spdocgen 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +26 -0
- data/lib/spdocgen.rb +15 -0
- data/lib/spdocgen/configuration.rb +31 -0
- data/lib/spdocgen/document.rb +13 -0
- data/lib/spdocgen/document_set.rb +23 -0
- data/lib/spdocgen/download_request.rb +15 -0
- data/lib/spdocgen/download_response.rb +12 -0
- data/lib/spdocgen/protocol.rb +80 -0
- data/lib/spdocgen/render_request.rb +76 -0
- data/lib/spdocgen/render_response.rb +17 -0
- data/lib/spdocgen/status_request.rb +11 -0
- data/lib/spdocgen/status_response.rb +74 -0
- data/lib/spdocgen/version.rb +4 -0
- data/spdocgen.gemspec +21 -0
- data/spec/config.yml +4 -0
- data/spec/download_request_spec.rb +34 -0
- data/spec/render_request_spec.rb +94 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/status_request_spec.rb +89 -0
- data/spec/test_server.rb +52 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
metadata.gz: c2f64220f543247a047013d39dc6cebee4390b8fcc531b67cd5e8a86073298a4f401b0c7fd6abe97894a736f9449219c04460dc631a99a6f492942c8d5c4acfa
|
4
|
+
data.tar.gz: ee878ee4a4a915378cb266ed2b1f0cd0cbd36a4086ced6178a020dc199288a198966da9a96c0285178fb1d5d328e7e084e57dc0211ef0e3328bba69039fdccbf
|
5
|
+
SHA1:
|
6
|
+
metadata.gz: f084863ea5fc6784ac2bf2a57e800d6cddcf4a1b
|
7
|
+
data.tar.gz: 72ba51d7f0976b343ed747a95abcf96751fdf8d7
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Software Projects
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# SP Docgen for Ruby
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'spdocgen'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install spdocgen
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'net/ssh/authentication/methods/password'
|
4
|
+
require 'net/scp'
|
5
|
+
require 'highline/import'
|
6
|
+
|
7
|
+
task :push => :build do
|
8
|
+
def upload(ssh)
|
9
|
+
filename = "spdocgen-#{SPDocgen::VERSION}.gem"
|
10
|
+
print "Uploading #{filename}..."
|
11
|
+
u = ssh.scp.upload("pkg/#{filename}", "/var/www/rubygems/gems/#{filename}") do
|
12
|
+
print '.'
|
13
|
+
end
|
14
|
+
u.wait
|
15
|
+
puts
|
16
|
+
ssh.exec! '/usr/local/rvm/bin/gem generate_index --directory=/var/www/rubygems'
|
17
|
+
end
|
18
|
+
|
19
|
+
opts = Net::SSH.configuration_for('sp43.sp.local')
|
20
|
+
begin
|
21
|
+
Net::SSH.start('sp43.sp.local', 'rubygems', :auth_methods => %w[publickey]) {|o| upload(o)}
|
22
|
+
rescue
|
23
|
+
password = ask("rubygems@sp43.sp.local's password: ") { |q| q.echo = false }
|
24
|
+
Net::SSH.start('sp43.sp.local', 'rubygems', :password => password) {|o| upload(o)}
|
25
|
+
end
|
26
|
+
end
|
data/lib/spdocgen.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "spdocgen/version"
|
2
|
+
|
3
|
+
module SPDocgen
|
4
|
+
autoload :Configuration, 'spdocgen/configuration'
|
5
|
+
autoload :Document, 'spdocgen/document'
|
6
|
+
autoload :DocumentSet, 'spdocgen/document_set'
|
7
|
+
autoload :Protocol, 'spdocgen/protocol'
|
8
|
+
|
9
|
+
autoload :DownloadRequest, 'spdocgen/download_request'
|
10
|
+
autoload :DownloadResponse, 'spdocgen/download_response'
|
11
|
+
autoload :RenderRequest, 'spdocgen/render_request'
|
12
|
+
autoload :RenderResponse, 'spdocgen/render_response'
|
13
|
+
autoload :StatusRequest, 'spdocgen/status_request'
|
14
|
+
autoload :StatusResponse, 'spdocgen/status_response'
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SPDocgen
|
2
|
+
class Configuration
|
3
|
+
class <<self
|
4
|
+
attr_accessor :configuration_file
|
5
|
+
|
6
|
+
def current
|
7
|
+
env = nil
|
8
|
+
env = Rails.env if defined? Rails
|
9
|
+
env ||= ENV['RAILS_ENV']
|
10
|
+
env ||= ENV['RACK_ENV']
|
11
|
+
raise 'Unable to determine environment' if env.nil?
|
12
|
+
|
13
|
+
c = read
|
14
|
+
raise "Environment not defined in SPDocgen configuration: #{env}" if c[env].nil?
|
15
|
+
(c['global'] || {}).merge(c[env])
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def read
|
21
|
+
if defined? Rails
|
22
|
+
self.configuration_file ||= File.join(Rails.root, 'config', 'spdocgen.yml')
|
23
|
+
elsif self.configuration_file.nil?
|
24
|
+
raise 'Unable to determine a default location for SPDocgen configuration'
|
25
|
+
end
|
26
|
+
|
27
|
+
@configuration ||= YAML.load_file(self.configuration_file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SPDocgen
|
2
|
+
class DocumentSet
|
3
|
+
attr_reader :xmlns, :data_sources
|
4
|
+
attr_accessor :documents
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@xmlns = {}
|
8
|
+
@data_sources = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def all_data_sources
|
12
|
+
mapped = (data_sources + documents.collect(&:data_sources).flatten).inject({}) do |map, ds|
|
13
|
+
map[ds.id] = ds
|
14
|
+
map
|
15
|
+
end
|
16
|
+
mapped.values.sort_by(&:id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def all_xmlns
|
20
|
+
documents.inject(@xmlns){|map, doc| map.merge(doc.xmlns)}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SPDocgen
|
2
|
+
class DownloadResponse
|
3
|
+
attr_accessor :body, :content_type, :content_encoding, :content_disposition
|
4
|
+
|
5
|
+
def initialize(body, content_type, content_encoding, content_disposition)
|
6
|
+
self.body = body
|
7
|
+
self.content_type = content_type
|
8
|
+
self.content_encoding = content_encoding
|
9
|
+
self.content_disposition = content_disposition
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module SPDocgen
|
5
|
+
class Protocol
|
6
|
+
def self.instance
|
7
|
+
@instance ||= self.new Configuration.current
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@base_url = config['base_url']
|
12
|
+
@render_path = config['render_path']
|
13
|
+
@username = config['username']
|
14
|
+
@password = config['password']
|
15
|
+
|
16
|
+
url = URI.parse @base_url
|
17
|
+
@http = Net::HTTP.new url.host, url.port
|
18
|
+
@http.use_ssl = (url.scheme =~ /https/i)
|
19
|
+
|
20
|
+
@downloaders = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def download(parsed_uri)
|
24
|
+
with_downloader_for(parsed_uri) do |http|
|
25
|
+
req = Net::HTTP::Get.new parsed_uri.request_uri
|
26
|
+
req['Accept'] = '*/*'
|
27
|
+
req.basic_auth @username, @password
|
28
|
+
|
29
|
+
response = http.request(req)
|
30
|
+
|
31
|
+
raise "Unable to download: #{parsed_uri.to_s} .. Response was #{response.code} #{response.message} : #{response.body ? response.body : ''} - request is #{req.to_s}" unless response.is_a? Net::HTTPOK
|
32
|
+
|
33
|
+
SPDocgen::DownloadResponse.new response.body, response.content_type, response['content-encoding'], response['content-disposition']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def submit(xml)
|
38
|
+
request = Net::HTTP::Post.new render_url
|
39
|
+
request.body = xml
|
40
|
+
request['Content-Type'] = 'application/xml'
|
41
|
+
|
42
|
+
SPDocgen::RenderResponse.new do_request(request).body
|
43
|
+
end
|
44
|
+
|
45
|
+
def poll(uri)
|
46
|
+
request = Net::HTTP::Get.new uri
|
47
|
+
SPDocgen::StatusResponse.new do_request(request).body
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def http
|
53
|
+
@http.start unless @http.started?
|
54
|
+
@http
|
55
|
+
end
|
56
|
+
|
57
|
+
def render_url
|
58
|
+
URI.join(@base_url, @render_path).to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def with_downloader_for(u, &block)
|
62
|
+
host = u.class.new(u.scheme, nil, u.host, u.port, nil, '', nil, nil, nil, false).to_s
|
63
|
+
|
64
|
+
downloader = Net::HTTP.new(u.host, u.port)
|
65
|
+
downloader.use_ssl = (u.scheme =~ /https/i)
|
66
|
+
|
67
|
+
downloader.start(&block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_request(request)
|
71
|
+
request['Accept'] = 'application/xml'
|
72
|
+
request.basic_auth @username, @password
|
73
|
+
|
74
|
+
response = http.request request
|
75
|
+
raise 'Response did not contain XML' unless response.code == '200' and response['content-type'] =~ /xml/i
|
76
|
+
|
77
|
+
response
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module SPDocgen
|
4
|
+
class RenderRequest
|
5
|
+
attr_accessor :metadata, :xml
|
6
|
+
|
7
|
+
def initialize(document_set)
|
8
|
+
raise "Document set should inherit from #{DocumentSet.name}" unless document_set.is_a? DocumentSet
|
9
|
+
raise "Documents should inherit from #{Document.name}" unless document_set.documents.all?{|doc| doc.is_a? Document}
|
10
|
+
|
11
|
+
@document_set = document_set
|
12
|
+
@xmlns = {
|
13
|
+
'xmlns:dgr' => 'http://www.sp.com.au/docgen/schemas/wsh',
|
14
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
|
15
|
+
}.merge(document_set.all_xmlns)
|
16
|
+
|
17
|
+
raise 'XML namespace definitions should start with xmlns:' unless @xmlns.keys.all?{|k| k.start_with? 'xmlns:'}
|
18
|
+
|
19
|
+
@metadata = {}
|
20
|
+
if document_set.respond_to? :metadata
|
21
|
+
@metadata = document_set.metadata
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
raise 'Already built' if @xml
|
27
|
+
raise 'No data sources' if @document_set.nil? or @document_set.documents.nil? or @document_set.documents.empty?
|
28
|
+
|
29
|
+
builder = Nokogiri::XML::Builder.new :encoding => 'utf-8' do |xml|
|
30
|
+
# Clients that treat this as a real builder sometimes need to call 'tag!'
|
31
|
+
# That's ok.
|
32
|
+
def xml.tag!(*args, &bl)
|
33
|
+
# Handle reserved names correctly
|
34
|
+
name = args.shift + '_'
|
35
|
+
send name, *args, &bl
|
36
|
+
end
|
37
|
+
|
38
|
+
xml.DocGenRequest @xmlns do
|
39
|
+
# See http://stackoverflow.com/questions/1829425/creating-an-xml-document-with-a-namespaced-root-element-with-nokogiri-builder
|
40
|
+
xml.parent.namespace = xml.parent.namespace_definitions.find{|ns| ns.prefix == 'dgr'}
|
41
|
+
dgr = xml['dgr']
|
42
|
+
dgr.MetaData do
|
43
|
+
self.metadata.each do |k,v|
|
44
|
+
dgr.MetaDataEntry do
|
45
|
+
dgr.Key k
|
46
|
+
dgr.Value v
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
dgr.SharedXmlDataSources do
|
52
|
+
@document_set.all_data_sources.each do |data_source|
|
53
|
+
dgr.SharedXmlDataSource 'sharedXmlDataSourceId' => data_source.id do
|
54
|
+
data_source.build(xml)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
dgr.DocumentRequests do
|
60
|
+
@document_set.documents.each do |document|
|
61
|
+
document.build(xml)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
@xml = builder.to_xml
|
68
|
+
end
|
69
|
+
|
70
|
+
def submit
|
71
|
+
raise 'Request needs to be built first' unless @xml
|
72
|
+
|
73
|
+
SPDocgen::Protocol.instance.submit @xml
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module SPDocgen
|
4
|
+
class RenderResponse
|
5
|
+
attr_reader :uuid, :uri
|
6
|
+
|
7
|
+
def initialize(xml)
|
8
|
+
document = Nokogiri::XML.parse(xml, nil, 'UTF-8')
|
9
|
+
raise 'Not a render response' unless document.root.name == 'RenderResponse'
|
10
|
+
|
11
|
+
@uuid = document.xpath('/RenderResponse/Uuid').text
|
12
|
+
@uri = document.xpath('/RenderResponse/StatusUri').text
|
13
|
+
|
14
|
+
raise "Invalid render response #{xml}" unless !@uuid.blank? && !@uri.blank?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module SPDocgen
|
4
|
+
class StatusResponse
|
5
|
+
#<StatusResponse>
|
6
|
+
#<DocGenRequestStatuses>
|
7
|
+
#<DocGenRequestStatus>
|
8
|
+
#<Uuid>9f576898-8d74-432e-80b8-dacbaf8d7bf6</Uuid>
|
9
|
+
#<State>Failed</State>
|
10
|
+
#<DocumentRequests>
|
11
|
+
#<DocumentRequest ServerId='5614' ClientId='b3b98dc0-449c-012f-238b-0026b92085d1' State='Timeout'>
|
12
|
+
#<Documents></Documents>
|
13
|
+
#</DocumentRequest>
|
14
|
+
#</DocumentRequests>
|
15
|
+
#</DocGenRequestStatus>
|
16
|
+
#</DocGenRequestStatuses>
|
17
|
+
#</StatusResponse>
|
18
|
+
def initialize(xml)
|
19
|
+
document = Nokogiri::XML.parse(xml, nil, 'UTF-8')
|
20
|
+
raise 'Not a render response' unless document.root.name == 'StatusResponse'
|
21
|
+
|
22
|
+
document.xpath('/StatusResponse/DocGenRequestStatuses/DocGenRequestStatus').each do |node|
|
23
|
+
uuid = node.xpath('Uuid').text
|
24
|
+
state = node.xpath('State').text
|
25
|
+
requests = node.xpath('DocumentRequests/DocumentRequest').collect do |req|
|
26
|
+
documents = req.xpath('Documents/Document').collect do |doc|
|
27
|
+
name = doc.xpath('Name')
|
28
|
+
uri = doc.xpath('Uri')
|
29
|
+
metadata = doc.xpath('MetaDataEntries/MetaDataEntry').inject({}) do |map,md|
|
30
|
+
map[md.xpath('Key').text] = md.xpath('Value').text
|
31
|
+
map
|
32
|
+
end
|
33
|
+
|
34
|
+
{
|
35
|
+
:reference => doc['Reference'],
|
36
|
+
:num_pages => doc['NumPages'].to_i,
|
37
|
+
:name => name.text,
|
38
|
+
:uri => uri.text,
|
39
|
+
:metadata => metadata
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
{
|
44
|
+
:server_id => req['ServerId'],
|
45
|
+
:request_guid => req['ClientId'],
|
46
|
+
:state => req['State'],
|
47
|
+
:documents => documents
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
record_status uuid, state, requests
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def uuids
|
56
|
+
@uuids ||= []
|
57
|
+
end
|
58
|
+
|
59
|
+
def status(uuid)
|
60
|
+
@status ||= {}
|
61
|
+
@status[uuid] ||= {}
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def record_status(uuid, state, requests)
|
66
|
+
self.uuids << uuid
|
67
|
+
self.status(uuid).merge!(
|
68
|
+
:uuid => uuid,
|
69
|
+
:state => state,
|
70
|
+
:requests => requests
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/spdocgen.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'spdocgen/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "spdocgen"
|
8
|
+
gem.version = SPDocgen::VERSION
|
9
|
+
gem.authors = ["Shaun Mangelsdorf"]
|
10
|
+
gem.email = ["smangelsdorf@sp.com.au"]
|
11
|
+
gem.description = %q{Ruby client library for rendering and downloading documents from SP Docgen}
|
12
|
+
gem.summary = %q{SP Docgen client library}
|
13
|
+
gem.homepage = "http://sp.docgen.net.au"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'nokogiri'
|
21
|
+
end
|
data/spec/config.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SPDocgen::DownloadRequest do
|
4
|
+
subject do
|
5
|
+
SPDocgen::DownloadRequest.new server.url('/download/file.txt')
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'downloads the file' do
|
9
|
+
server.response = [200, {'content-type' => 'text/plain'}, "test file"]
|
10
|
+
|
11
|
+
response = subject.download
|
12
|
+
response.should be_a SPDocgen::DownloadResponse
|
13
|
+
response.body.should == "test file"
|
14
|
+
response.content_type.should == 'text/plain'
|
15
|
+
response.content_encoding.should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'includes the content encoding' do
|
19
|
+
server.response = [200, {'content-type' => 'text/plain', 'content-encoding' => 'gzip'}, "test file"]
|
20
|
+
|
21
|
+
response = subject.download
|
22
|
+
response.should be_a SPDocgen::DownloadResponse
|
23
|
+
response.body.should == "test file"
|
24
|
+
response.content_type.should == 'text/plain'
|
25
|
+
response.content_encoding.should == 'gzip'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'includes the content disposition' do
|
29
|
+
server.response = [200, {'content-type' => 'text/plain', 'content-disposition' => 'attachment; filename=test.txt'}, 'test file']
|
30
|
+
response = subject.download
|
31
|
+
response.should be_a SPDocgen::DownloadResponse
|
32
|
+
response.content_disposition.should == 'attachment; filename=test.txt'
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'uuid'
|
4
|
+
|
5
|
+
describe SPDocgen::RenderRequest do
|
6
|
+
class TestDocumentSet < SPDocgen::DocumentSet
|
7
|
+
end
|
8
|
+
|
9
|
+
class BadTestDocument < SPDocgen::Document
|
10
|
+
end
|
11
|
+
class TestDocument < SPDocgen::Document
|
12
|
+
def build(xml)
|
13
|
+
xml.DocumentRequest 'test-xml'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
class NamespaceDocument < SPDocgen::Document
|
17
|
+
def initialize
|
18
|
+
super
|
19
|
+
xmlns['xmlns:test'] = 'http://example.org/test'
|
20
|
+
end
|
21
|
+
|
22
|
+
def build(xml)
|
23
|
+
xml.DocumentRequest do
|
24
|
+
xml['test'].TestXml
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
before :each do
|
30
|
+
@uuid = UUID.generate
|
31
|
+
end
|
32
|
+
|
33
|
+
subject do
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should reject document sets of the wrong type' do
|
37
|
+
lambda {
|
38
|
+
set = Object.new
|
39
|
+
SPDocgen::RenderRequest.new set
|
40
|
+
}.should raise_error(RuntimeError, /should inherit from/)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should reject documents of the wrong type' do
|
44
|
+
lambda {
|
45
|
+
set = TestDocumentSet.new
|
46
|
+
set.documents = [Object.new]
|
47
|
+
SPDocgen::RenderRequest.new set
|
48
|
+
}.should raise_error(RuntimeError, /should inherit from/)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should not build a bad implementation' do
|
52
|
+
set = TestDocumentSet.new
|
53
|
+
set.documents = [BadTestDocument.new]
|
54
|
+
req = SPDocgen::RenderRequest.new set
|
55
|
+
lambda {
|
56
|
+
req.build
|
57
|
+
}.should raise_error(RuntimeError, /does not define/)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should build' do
|
61
|
+
set = TestDocumentSet.new
|
62
|
+
set.documents = [TestDocument.new]
|
63
|
+
req = SPDocgen::RenderRequest.new set
|
64
|
+
req.build
|
65
|
+
req.xml.should match /test-xml/
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should build with namespaces' do
|
69
|
+
set = TestDocumentSet.new
|
70
|
+
set.documents = [NamespaceDocument.new]
|
71
|
+
req = SPDocgen::RenderRequest.new set
|
72
|
+
req.build
|
73
|
+
req.xml.should match /<test:TestXml\/>/
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should submit' do
|
77
|
+
server.response = [200, {'content-type' => 'application/xml'}, %{
|
78
|
+
<RenderResponse>
|
79
|
+
<Uuid>#{@uuid}</Uuid>
|
80
|
+
<StatusUri>#{server.url("/status/#{@uuid}")}</StatusUri>
|
81
|
+
</RenderResponse>
|
82
|
+
}]
|
83
|
+
|
84
|
+
set = TestDocumentSet.new
|
85
|
+
set.documents = [TestDocument.new]
|
86
|
+
req = SPDocgen::RenderRequest.new set
|
87
|
+
req.build
|
88
|
+
|
89
|
+
response = req.submit
|
90
|
+
response.should be_a SPDocgen::RenderResponse
|
91
|
+
response.uuid.should == @uuid
|
92
|
+
response.uri.should end_with @uuid
|
93
|
+
end
|
94
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'spdocgen'
|
5
|
+
require 'test_server'
|
6
|
+
|
7
|
+
require 'tempfile'
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.add_setting :server
|
12
|
+
config.add_setting :spdocgen_configuration
|
13
|
+
|
14
|
+
config.server = SPDocgen::TestServer.new
|
15
|
+
config.server.start
|
16
|
+
|
17
|
+
config.include SPDocgen::TestServerHelper
|
18
|
+
|
19
|
+
config.before :suite do
|
20
|
+
ENV['RACK_ENV'] = 'test'
|
21
|
+
|
22
|
+
yml = Tempfile.new(['spdocgen-config', '.yml'])
|
23
|
+
template = YAML.load_file File.join(File.dirname(__FILE__), 'config.yml')
|
24
|
+
template['test'].merge!('base_url' => config.server.base_url)
|
25
|
+
yml.write YAML.dump(template)
|
26
|
+
yml.close
|
27
|
+
|
28
|
+
config.spdocgen_configuration = yml
|
29
|
+
SPDocgen::Configuration.configuration_file = yml.path
|
30
|
+
end
|
31
|
+
|
32
|
+
config.after :suite do
|
33
|
+
config.spdocgen_configuration.unlink
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'uuid'
|
4
|
+
|
5
|
+
describe SPDocgen::StatusRequest do
|
6
|
+
subject do
|
7
|
+
SPDocgen::StatusRequest.new server.url('/download/file.txt')
|
8
|
+
end
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@request = UUID.generate
|
12
|
+
@uuid = UUID.generate
|
13
|
+
end
|
14
|
+
|
15
|
+
def status_response(state, request_state, documents)
|
16
|
+
doc_xml = documents.collect do |doc|
|
17
|
+
%{<Document Reference='#{doc[:reference]}' NumPages='#{doc[:num_pages] || 1}'>
|
18
|
+
<Name>#{doc[:name]}</Name>
|
19
|
+
<Uri>#{doc[:uri]}</Uri>
|
20
|
+
<MetaDataEntries>
|
21
|
+
<MetaDataEntry>
|
22
|
+
<Key>test</Key>
|
23
|
+
<Value>this is a test</Value>
|
24
|
+
</MetaDataEntry>
|
25
|
+
</MetaDataEntries>
|
26
|
+
</Document>}
|
27
|
+
end.join('')
|
28
|
+
|
29
|
+
%{<StatusResponse>
|
30
|
+
<DocGenRequestStatuses>
|
31
|
+
<DocGenRequestStatus>
|
32
|
+
<Uuid>#{@uuid}</Uuid>
|
33
|
+
<State>#{state}</State>
|
34
|
+
<DocumentRequests>
|
35
|
+
<DocumentRequest ServerId='1' ClientId='#{@request}' State='#{request_state}'>
|
36
|
+
<Documents>#{doc_xml}</Documents>
|
37
|
+
</DocumentRequest>
|
38
|
+
</DocumentRequests>
|
39
|
+
</DocGenRequestStatus>
|
40
|
+
</DocGenRequestStatuses>
|
41
|
+
</StatusResponse>
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'polls for status' do
|
46
|
+
response_body = status_response('Failed', 'Timeout', [])
|
47
|
+
server.response = [200, {'content-type' => 'application/xml'}, response_body]
|
48
|
+
response = subject.poll
|
49
|
+
|
50
|
+
response.should be_a SPDocgen::StatusResponse
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'determines a request has failed' do
|
54
|
+
response_body = status_response('Failed', 'Timeout', [])
|
55
|
+
server.response = [200, {'content-type' => 'application/xml'}, response_body]
|
56
|
+
response = subject.poll
|
57
|
+
|
58
|
+
response.status(@uuid)[:state].should == 'Failed'
|
59
|
+
req_status = response.status(@uuid)[:requests].first
|
60
|
+
req_status[:request_guid].should == @request
|
61
|
+
req_status[:state].should == 'Timeout'
|
62
|
+
req_status[:documents].should be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'determines a request has succeeded' do
|
66
|
+
doc_uuid = UUID.generate
|
67
|
+
|
68
|
+
documents = []
|
69
|
+
documents << {:reference => doc_uuid, :num_pages => 5, :name => 'Test.file', :uri => server.url('/test.file')}
|
70
|
+
|
71
|
+
response_body = status_response('Completed', 'Completed', documents)
|
72
|
+
server.response = [200, {'content-type' => 'application/xml'}, response_body]
|
73
|
+
response = subject.poll
|
74
|
+
|
75
|
+
response.status(@uuid)[:state].should == 'Completed'
|
76
|
+
req_status = response.status(@uuid)[:requests].first
|
77
|
+
req_status[:request_guid].should == @request
|
78
|
+
req_status[:state].should == 'Completed'
|
79
|
+
req_status[:documents].should_not be_empty
|
80
|
+
|
81
|
+
doc_status = req_status[:documents].first
|
82
|
+
doc_status[:name].should == 'Test.file'
|
83
|
+
doc_status[:uri].should end_with '/test.file'
|
84
|
+
doc_status[:reference].should == doc_uuid
|
85
|
+
doc_status[:num_pages].should == 5
|
86
|
+
doc_status[:metadata].should_not be_empty
|
87
|
+
doc_status[:metadata]['test'].should == 'this is a test'
|
88
|
+
end
|
89
|
+
end
|
data/spec/test_server.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rack'
|
3
|
+
require 'rack/handler/thin'
|
4
|
+
|
5
|
+
module SPDocgen
|
6
|
+
class TestServer
|
7
|
+
attr_accessor :env, :response
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@host = '127.0.0.1'
|
11
|
+
@port = find_available_port
|
12
|
+
end
|
13
|
+
|
14
|
+
def base_url
|
15
|
+
"http://#{@host}:#{@port}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def url(path)
|
19
|
+
URI.join(base_url, path).to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
self.env = env
|
24
|
+
response.tap{self.response = nil}
|
25
|
+
end
|
26
|
+
|
27
|
+
def start
|
28
|
+
@thread = Thread.new do
|
29
|
+
Rack::Handler::Thin.run self, :Host => @host, :Port => @port do |server|
|
30
|
+
@server = server
|
31
|
+
end
|
32
|
+
end
|
33
|
+
sleep(0.1) until @server and @server.running?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Stolen from Capybara
|
39
|
+
def find_available_port
|
40
|
+
server = TCPServer.new(@host, 0)
|
41
|
+
server.addr[1]
|
42
|
+
ensure
|
43
|
+
server.close if server
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module TestServerHelper
|
48
|
+
def server
|
49
|
+
RSpec.configuration.server
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spdocgen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shaun Mangelsdorf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2015-11-20 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- &id002
|
20
|
+
- ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
type: :runtime
|
24
|
+
version_requirements: *id001
|
25
|
+
description: Ruby client library for rendering and downloading documents from SP Docgen
|
26
|
+
email:
|
27
|
+
- smangelsdorf@sp.com.au
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- .gitignore
|
36
|
+
- Gemfile
|
37
|
+
- LICENSE.txt
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- lib/spdocgen.rb
|
41
|
+
- lib/spdocgen/configuration.rb
|
42
|
+
- lib/spdocgen/document.rb
|
43
|
+
- lib/spdocgen/document_set.rb
|
44
|
+
- lib/spdocgen/download_request.rb
|
45
|
+
- lib/spdocgen/download_response.rb
|
46
|
+
- lib/spdocgen/protocol.rb
|
47
|
+
- lib/spdocgen/render_request.rb
|
48
|
+
- lib/spdocgen/render_response.rb
|
49
|
+
- lib/spdocgen/status_request.rb
|
50
|
+
- lib/spdocgen/status_response.rb
|
51
|
+
- lib/spdocgen/version.rb
|
52
|
+
- spdocgen.gemspec
|
53
|
+
- spec/config.yml
|
54
|
+
- spec/download_request_spec.rb
|
55
|
+
- spec/render_request_spec.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
- spec/status_request_spec.rb
|
58
|
+
- spec/test_server.rb
|
59
|
+
homepage: http://sp.docgen.net.au
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
metadata: {}
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- *id002
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- *id002
|
75
|
+
requirements: []
|
76
|
+
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.0.11
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: SP Docgen client library
|
82
|
+
test_files:
|
83
|
+
- spec/config.yml
|
84
|
+
- spec/download_request_spec.rb
|
85
|
+
- spec/render_request_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
- spec/status_request_spec.rb
|
88
|
+
- spec/test_server.rb
|