active-fedora 2.3.7 → 2.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.rvmrc CHANGED
@@ -4,7 +4,7 @@
4
4
  # development environment upon cd'ing into the directory
5
5
 
6
6
  ruby_string="ree-1.8.7"
7
- gemset_name="active_fedora"
7
+ gemset_name="active_fedora_2.x"
8
8
 
9
9
  # Install rubies when used instead of only displaying a warning and exiting
10
10
  rvm_install_on_use_flag=1
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active-fedora (2.3.5)
5
- activeresource
4
+ active-fedora (2.3.7)
5
+ activeresource (< 3.0.0)
6
6
  equivalent-xml
7
7
  facets
8
8
  mediashelf-loggable
9
9
  mime-types (>= 1.16)
10
10
  multipart-post (= 1.1.2)
11
+ net-http-persistent
11
12
  nokogiri
12
13
  om (>= 1.0)
13
14
  solr-ruby (>= 0.0.6)
@@ -38,6 +39,7 @@ GEM
38
39
  mime-types (1.16)
39
40
  mocha (0.9.12)
40
41
  multipart-post (1.1.2)
42
+ net-http-persistent (2.1)
41
43
  nokogiri (1.5.0)
42
44
  om (1.4.0)
43
45
  mediashelf-loggable
@@ -1,3 +1,10 @@
1
+ 2.3.8
2
+
3
+ HYDRA-670 -- Use persistent http connections
4
+ Don't set log level to error by default
5
+ Benchmark fedora and solr queries
6
+
7
+
1
8
  2.3.7
2
9
 
3
10
  HYDRA-650 -- Fixed relationship inheritance (Rick Johnson)
@@ -22,10 +22,11 @@ Gem::Specification.new do |s|
22
22
  s.add_dependency('nokogiri')
23
23
  s.add_dependency('om', '>= 1.0')
24
24
  s.add_dependency('solrizer', '>1.0.0')
25
- s.add_dependency("activeresource")
25
+ s.add_dependency("activeresource", "<3.0.0")
26
26
  s.add_dependency("mediashelf-loggable")
27
27
  s.add_dependency("equivalent-xml")
28
28
  s.add_dependency("facets")
29
+ s.add_dependency("net-http-persistent")
29
30
  s.add_development_dependency("yard")
30
31
  s.add_development_dependency("RedCloth") # for RDoc formatting
31
32
  s.add_development_dependency("rake")
@@ -68,7 +68,6 @@ module ActiveFedora #:nodoc:
68
68
  # 2. If it does not find a solr.yml and the fedora.yml contains a solr url, it will raise an configuration error
69
69
  # 3. If it does not find a solr.yml and the fedora.yml does not contain a solr url, it will look in: +Rails.root+/config, +current working directory+/config, then the solr.yml shipped with gem
70
70
  def self.init( options={} )
71
- logger.level = Logger::ERROR if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
72
71
  # Make config_options into a Hash if nil is passed in as the value
73
72
  options = {} if options.nil?
74
73
 
@@ -4,6 +4,7 @@ require 'active_fedora/semantic_node'
4
4
  require "solrizer"
5
5
  require 'nokogiri'
6
6
  require "loggable"
7
+ require 'benchmark'
7
8
 
8
9
  SOLR_DOCUMENT_ID = "id" unless (defined?(SOLR_DOCUMENT_ID) && !SOLR_DOCUMENT_ID.nil?)
9
10
  ENABLE_SOLR_UPDATES = true unless defined?(ENABLE_SOLR_UPDATES)
@@ -122,8 +123,12 @@ module ActiveFedora
122
123
  # Refreshes the object's info from Fedora
123
124
  # Note: Currently just registers any new datastreams that have appeared in fedora
124
125
  def refresh
125
- inner_object.load_attributes_from_fedora
126
- @datastreams = datastreams_in_fedora.merge(datastreams_in_memory)
126
+ ms = 1000 * Benchmark.realtime do
127
+ inner_object.load_attributes_from_fedora
128
+ @datastreams = datastreams_in_fedora.merge(datastreams_in_memory)
129
+ end
130
+ logger.debug "refreshing #{pid} took #{ms} ms"
131
+ @datastreams
127
132
  end
128
133
 
129
134
  #Deletes a Base object, also deletes the info indexed in Solr, and
@@ -945,11 +950,17 @@ module ActiveFedora
945
950
  def update_index
946
951
  if defined?( Solrizer::Fedora::Solrizer )
947
952
  #logger.info("Trying to solrize pid: #{pid}")
948
- solrizer = Solrizer::Fedora::Solrizer.new
949
- solrizer.solrize( self )
953
+ ms = 1000 * Benchmark.realtime do
954
+ solrizer = Solrizer::Fedora::Solrizer.new
955
+ solrizer.solrize( self )
956
+ end
957
+ logger.debug "solrize for #{pid} took #{ms} ms"
950
958
  else
951
959
  #logger.info("Trying to update solr for pid: #{pid}")
952
- SolrService.instance.conn.update(self.to_solr)
960
+ ms = 1000 * Benchmark.realtime do
961
+ SolrService.instance.conn.update(self.to_solr)
962
+ end
963
+ logger.debug "solr update for #{pid} took #{ms} ms"
953
964
  end
954
965
  end
955
966
 
@@ -1090,17 +1101,23 @@ module ActiveFedora
1090
1101
 
1091
1102
  # Pushes the object and all of its new or dirty datastreams into Fedora
1092
1103
  def update
1093
- result = Fedora::Repository.instance.save(@inner_object)
1094
- datastreams_in_memory.each do |k,ds|
1095
- if ds.dirty? || ds.new_object?
1096
- if ds.class.included_modules.include?(ActiveFedora::MetadataDatastreamHelper) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
1097
- # if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.kind_of?(ActiveFedora::NokogiriDatastream) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
1098
- @metadata_is_dirty = true
1099
- end
1100
- result = ds.save
1101
- end
1104
+ result = nil
1105
+ ms = 1000 * Benchmark.realtime do
1106
+ result = Fedora::Repository.instance.save(@inner_object)
1107
+ end
1108
+ logger.debug "instance save for #{pid} took #{ms} ms"
1109
+ ms = 1000 * Benchmark.realtime do
1110
+ datastreams_in_memory.each do |k,ds|
1111
+ if ds.dirty? || ds.new_object?
1112
+ if ds.class.included_modules.include?(ActiveFedora::MetadataDatastreamHelper) || ds.instance_of?(ActiveFedora::RelsExtDatastream)
1113
+ @metadata_is_dirty = true
1114
+ end
1115
+ result = ds.save
1116
+ end
1117
+ end
1118
+ refresh
1102
1119
  end
1103
- refresh
1120
+ logger.debug "datastream save for #{pid} took #{ms} ms"
1104
1121
  return result
1105
1122
  end
1106
1123
 
@@ -21,6 +21,7 @@ module ActiveFedora
21
21
  #set this Datastream's content
22
22
  def content=(content)
23
23
  self.blob = content
24
+ self.dirty = true
24
25
  end
25
26
 
26
27
  def self.delete(parent_pid, dsid)
@@ -14,7 +14,8 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
14
14
  alias_method(:om_term_values, :term_values) unless method_defined?(:om_term_values)
15
15
  alias_method(:om_update_values, :update_values) unless method_defined?(:om_update_values)
16
16
 
17
- attr_accessor :ng_xml, :internal_solr_doc
17
+ attr_accessor :internal_solr_doc
18
+ attr_reader :ng_xml
18
19
 
19
20
  #constructor, calls up to ActiveFedora::Datastream's constructor
20
21
  def initialize(attrs=nil)
@@ -43,22 +44,22 @@ class ActiveFedora::NokogiriDatastream < ActiveFedora::Datastream
43
44
  Nokogiri::XML::Document.parse("<xml/>")
44
45
  end
45
46
 
46
- # class << self
47
- # from_xml_original = self.instance_method(:from_xml)
48
- #
49
- # define_method(:from_xml, xml, tmpl=self.new) do
50
- # from_xml_original.bind(self).call(xml, tmpl)
51
- # tmpl.send(:dirty=, false)
52
- # end
53
- #
54
- # # def from_xml_custom(xml, tmpl=self.new)
55
- # # from_xml_original(xml, tmpl)
56
- # # tmpl.send(:dirty=, false)
57
- # # end
58
- # #
59
- # # alias_method :from_xml_original, :from_xml
60
- # # alias_method :from_xml, :from_xml_custom
61
- # end
47
+ def ng_xml=(new_xml)
48
+ case new_xml
49
+ when Nokogiri::XML::Document, Nokogiri::XML::Element, Nokogiri::XML::Node
50
+ @ng_xml = new_xml
51
+ when String
52
+ @ng_xml = Nokogiri::XML::Document.parse(new_xml)
53
+ else
54
+ raise TypeError, "You passed a #{new_xml.class} into the ng_xml of the #{self.dsid} datastream. NokogiriDatastream.ng_xml= only accepts Nokogiri::XML::Document, Nokogiri::XML::Element, Nokogiri::XML::Node, or raw XML (String) as inputs."
55
+ end
56
+ self.dirty = true
57
+ end
58
+
59
+ def content=(content)
60
+ super
61
+ self.ng_xml = Nokogiri::XML::Document.parse(content)
62
+ end
62
63
 
63
64
 
64
65
  def to_xml(xml = self.ng_xml)
@@ -65,6 +65,13 @@ module ActiveFedora
65
65
  return uri.gsub(/(:)/, '\\:')
66
66
  end
67
67
 
68
+ # Escapes these characters
69
+ # + - || ! ( ) { } [ ] ^ " ~ * ? : \
70
+ # See: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters
71
+ def self.escape_characters_for_query(value)
72
+ value.gsub(/([\#\+\-\|\{\}\^\"\~\*\:\>\<\?\(\)\[\]\+\!\\])/) {|v| "\\#{v}"}
73
+ end
74
+
68
75
 
69
76
  end #SolrService
70
77
  class SolrNotInitialized < StandardError;end
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "2.3.7"
2
+ VERSION = "2.3.8"
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require "base64"
2
2
  gem 'multipart-post'
3
3
  require 'net/http/post/multipart'
4
+ require 'net/http/persistent'
4
5
  require 'cgi'
5
6
  require "mime/types"
6
7
  require 'net/http'
@@ -46,6 +47,9 @@ module Fedora
46
47
  # 409 Conflict
47
48
  class ResourceConflict < ClientError; end # :nodoc:
48
49
 
50
+ # 415 Unsupported Media Type
51
+ class UnsupportedMediaType < ClientError; end # :nodoc:
52
+
49
53
  # 5xx Server Error
50
54
  class ServerError < ConnectionError; end # :nodoc:
51
55
 
@@ -60,6 +64,23 @@ module Fedora
60
64
  # This class is used by ActiveResource::Base to interface with REST
61
65
  # services.
62
66
  class Connection
67
+
68
+ CLASSES = [
69
+ Net::HTTP::Delete,
70
+ Net::HTTP::Get,
71
+ Net::HTTP::Head,
72
+ Net::HTTP::Post,
73
+ Net::HTTP::Put
74
+ ].freeze
75
+
76
+ MIME_TYPES = {
77
+ :binary => "application/octet-stream",
78
+ :json => "application/json",
79
+ :xml => "text/xml",
80
+ :none => "text/plain"
81
+ }.freeze
82
+
83
+
63
84
  attr_reader :site, :surrogate
64
85
  attr_accessor :format
65
86
 
@@ -78,84 +99,102 @@ module Fedora
78
99
  @surrogate=surrogate
79
100
  end
80
101
 
102
+ ##
103
+ # Perform an HTTP Delete, Head, Get, Post, or Put.
104
+
105
+ CLASSES.each do |clazz|
106
+ verb = clazz.to_s.split("::").last.downcase
107
+
108
+ define_method verb do |*args|
109
+ path = args[0]
110
+ params = args[1] || {}
111
+
112
+ response_for clazz, path, params
113
+ end
114
+ end
115
+
81
116
  # Set URI for remote service.
82
117
  def site=(site)
83
118
  @site = site.is_a?(URI) ? site : URI.parse(site)
84
119
  end
85
120
 
86
- # Execute a GET request.
87
- # Used to get (find) resources.
88
- def get(path, headers = {})
89
- format.decode(request(:get, path, build_request_headers(headers)).body)
90
- end
91
-
92
- # Execute a DELETE request (see HTTP protocol documentation if unfamiliar).
93
- # Used to delete resources.
94
- def delete(path, headers = {})
95
- request(:delete, path, build_request_headers(headers))
96
- end
97
121
 
122
+ private
98
123
 
124
+ # Makes request to remote service.
125
+ def response_for(clazz, path, params)
126
+ logger.debug "#{clazz} #{path}"
127
+ request = clazz.new path
128
+ request.body = params[:body]
99
129
 
100
- def raw_get(path, headers = {})
101
- request(:get, path, build_request_headers(headers))
102
- end
103
- def post(path, body='', headers={})
104
- do_method(:post, path, body, headers)
105
- end
106
- def put( path, body='', headers={})
107
- do_method(:put, path, body, headers)
130
+ handle_request request, params[:upload], params[:type], params[:headers] || {}
108
131
  end
109
132
 
110
- private
111
- def do_method(method, path, body = '', headers = {})
112
- meth_map={:put=>Net::HTTP::Put::Multipart, :post=>Net::HTTP::Post::Multipart}
113
- raise "undefined method: #{method}" unless meth_map.has_key? method
114
- headers = build_request_headers(headers)
115
- if body.respond_to?(:read)
116
- if body.respond_to?(:original_filename?)
117
- filename = File.basename(body.original_filename)
118
- io = UploadIO.new(body, mime_type,filename)
119
- elsif body.path
120
- filename = File.basename(body.path)
121
- else
122
- filename="NOFILE"
123
- end
124
- mime_types = MIME::Types.of(filename)
125
- mime_type ||= mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
126
-
127
- io = nil
128
- if body.is_a?(File)
129
- io = UploadIO.new(body.path,mime_type)
130
- else
131
- io =UploadIO.new(body, mime_type, filename)
132
- end
133
133
 
134
- req = meth_map[method].new(path, {:file=>io}, headers)
135
- multipart_request(req)
134
+ def handle_request request, upload, type, headers
135
+ handle_uploads request, upload, type
136
+ handle_headers request, upload, type, headers
137
+ result = http.request self.site, request
138
+ handle_response(result)
139
+ end
140
+
141
+ ##
142
+ # Handle chunked uploads.
143
+ #
144
+ # +request+: A Net::HTTP request Object.
145
+ # +upload+: A Hash with the following keys:
146
+ # +:file+: The file to be HTTP chunked uploaded.
147
+ # +:headers+: A Hash containing additional HTTP headers.
148
+ # +:type+: A Symbol with the mime_type.
149
+
150
+ def handle_uploads request, upload, type
151
+ return unless upload
152
+ io = nil
153
+ if upload[:file].is_a?(File)
154
+ io = File.open upload[:file].path
136
155
  else
137
- request(method, path, body.to_s, headers)
156
+ io = upload[:file]
138
157
  end
158
+
159
+ request.body_stream = io
139
160
  end
140
- def multipart_request(req)
141
- result = nil
142
- result = http.start do |conn|
143
- conn.read_timeout=60600 #these can take a while
144
- conn.request(req)
161
+
162
+
163
+ def handle_headers request, upload, type, headers
164
+ request.basic_auth(self.site.user, self.site.password) if self.site.user
165
+
166
+ request.add_field "Accept", mime_type(type)
167
+ request.add_field "Content-Type", mime_type(type) if requires_content_type? request
168
+
169
+ headers.merge! chunked_headers upload
170
+ headers.each do |header, value|
171
+ request[header] = value
145
172
  end
146
- handle_response(result)
173
+ end
174
+
175
+ ##
176
+ # Setting of chunked upload headers.
177
+ #
178
+ # +upload+: A Hash with the following keys:
179
+ # +:file+: The file to be HTTP chunked uploaded.
180
+
181
+ def chunked_headers upload
182
+ return {} unless upload
147
183
 
184
+ chunked_headers = {
185
+ "Content-Type" => mime_type(:binary),
186
+ "Transfer-Encoding" => "chunked"
187
+ }.merge upload[:headers] || {}
148
188
  end
149
189
 
150
- # Makes request to remote service.
151
- def request(method, path, *arguments)
152
- result = http.send(method, path, *arguments)
153
- handle_response(result)
190
+ def requires_content_type? request
191
+ [Net::HTTP::Post, Net::HTTP::Put].include? request.class
154
192
  end
155
193
 
156
194
  # Handles response and error codes from remote service.
157
195
  def handle_response(response)
158
196
  message = "Error from Fedora: #{response.body}"
197
+ logger.debug "Response: #{response.code}"
159
198
  case response.code.to_i
160
199
  when 301,302
161
200
  raise(Redirection.new(response))
@@ -173,6 +212,8 @@ module Fedora
173
212
  raise(MethodNotAllowed.new(response, message))
174
213
  when 409
175
214
  raise(ResourceConflict.new(response, message))
215
+ when 415
216
+ raise UnsupportedMediaType.new(response, message)
176
217
  when 422
177
218
  raise(ResourceInvalid.new(response, message))
178
219
  when 423...500
@@ -184,35 +225,30 @@ module Fedora
184
225
  end
185
226
  end
186
227
 
228
+ def mime_type type
229
+ if type.kind_of? String
230
+ type
231
+ else
232
+ MIME_TYPES[type] || MIME_TYPES[:xml]
233
+ end
234
+ end
235
+
187
236
  # Creates new Net::HTTP instance for communication with
188
237
  # remote service and resources.
189
238
  def http
190
- http = Net::HTTP.new(@site.host, @site.port)
239
+ return @http if @http
240
+ @http = Net::HTTP::Persistent.new#(@site)
191
241
  if(@site.is_a?(URI::HTTPS))
192
- http.use_ssl = true
193
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
242
+ @http.use_ssl = true
243
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
194
244
 
195
245
  if (defined?(SSL_CLIENT_CERT_FILE) && !SSL_CLIENT_CERT_FILE.nil? && defined?(SSL_CLIENT_KEY_FILE) && !SSL_CLIENT_KEY_FILE.nil? && defined?(SSL_CLIENT_KEY_PASS) && !SSL_CLIENT_KEY_PASS.nil?)
196
- http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
197
- http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
246
+ @http.cert = OpenSSL::X509::Certificate.new( File.read(SSL_CLIENT_CERT_FILE) )
247
+ @http.key = OpenSSL::PKey::RSA.new( File.read(SSL_CLIENT_KEY_FILE), SSL_CLIENT_KEY_PASS )
198
248
  end
199
249
  end
200
- http
250
+ @http
201
251
  end
202
252
 
203
- def default_header
204
- @default_header ||= { 'Content-Type' => format.mime_type }
205
- end
206
-
207
- # Builds headers for request to remote service.
208
- def build_request_headers(headers)
209
- headers.merge!({"From"=>surrogate}) if @surrogate
210
- authorization_header.update(default_header).update(headers)
211
- end
212
-
213
- # Sets authorization header; authentication information is pulled from credentials provided with site URI.
214
- def authorization_header
215
- (@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
216
- end
217
253
  end
218
254
  end
@@ -59,7 +59,7 @@ module Fedora
59
59
 
60
60
  # Fetch the raw content of either a fedora object or datastream
61
61
  def fetch_content(object_uri)
62
- response = connection.raw_get("#{url_for(object_uri)}?format=xml")
62
+ response = connection.get("#{url_for(object_uri)}?format=xml")
63
63
  StringResponse.new(response.body, response.content_type)
64
64
  end
65
65
 
@@ -95,7 +95,7 @@ module Fedora
95
95
  params[:sessionToken] = options[:sessionToken] if options[:sessionToken]
96
96
  includes = fields.inject("") { |s, f| s += "&#{f}=true"; s }
97
97
 
98
- convert_xml(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}"))
98
+ convert_xml(XmlFormat.decode(connection.get("#{fedora_url.path}/objects?#{params.to_fedora_query}#{includes}").body))
99
99
  end
100
100
 
101
101
  # Retrieve an object from fedora and load it as an instance of the given model/class
@@ -103,10 +103,14 @@ module Fedora
103
103
  # @param pid of the Fedora object to retrieve and deserialize
104
104
  # @param klazz the Model whose deserialize method the object's FOXML will be passed into
105
105
  def find_model(pid, klazz)
106
- obj = self.find_objects("pid=#{pid}").first
107
- if obj.nil?
108
- raise ActiveFedora::ObjectNotFoundError, "The repository does not have an object with pid #{pid}. The repository URL is #{self.base_url}"
106
+ obj = nil
107
+ ms = 1000 * Benchmark.realtime do
108
+ obj = self.find_objects("pid=#{pid}").first
109
+ if obj.nil?
110
+ raise ActiveFedora::ObjectNotFoundError, "The repository does not have an object with pid #{pid}. The repository URL is #{self.base_url}"
111
+ end
109
112
  end
113
+ logger.debug "loading #{pid} took #{ms} ms"
110
114
  doc = Nokogiri::XML::Document.parse(obj.object_xml)
111
115
  klazz.deserialize(doc)
112
116
  end
@@ -132,7 +136,7 @@ module Fedora
132
136
  case object
133
137
  when Fedora::FedoraObject
134
138
  pid = (object.pid ? object : 'new')
135
- response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, object.blob)
139
+ response = connection.post("#{url_for(pid)}?" + object.attributes.to_fedora_query, :body=>object.blob)
136
140
  if response.code == '201'
137
141
  object.pid = extract_pid(response)
138
142
  object.new_object = false
@@ -142,10 +146,14 @@ module Fedora
142
146
  end
143
147
  when Fedora::Datastream
144
148
  raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
145
- extra_headers = {}
146
- extra_headers['Content-Type'] = object.attributes[:mimeType] if object.attributes[:mimeType]
147
- response = connection.post("#{url_for(object)}?" + object.attributes.to_fedora_query,
148
- object.blob, extra_headers)
149
+ headers = {}
150
+ headers[:type] = object.attributes[:mimeType] if object.attributes[:mimeType]
151
+ if object.blob.respond_to? :read
152
+ headers[:upload] = {:file=>object.blob}
153
+ else
154
+ headers[:body]=object.blob
155
+ end
156
+ response = connection.post("#{url_for(object)}?" + object.attributes.to_fedora_query, headers)
149
157
  if response.code == '201'
150
158
  object.new_object = false
151
159
  true
@@ -170,7 +178,13 @@ module Fedora
170
178
  response.code == '200' || '307'
171
179
  when Fedora::Datastream
172
180
  raise ArgumentError, "Missing dsID attribute" if object.dsid.nil?
173
- response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query, object.blob)
181
+ headers = {}
182
+ if object.blob.respond_to? :read
183
+ headers[:upload] = {:file=>object.blob}
184
+ else
185
+ headers[:body]=object.blob
186
+ end
187
+ response = connection.put("#{url_for(object)}?" + object.attributes.to_fedora_query, headers)
174
188
  response.code == '200' || '201'
175
189
  return response.code
176
190
  else
@@ -225,7 +239,7 @@ module Fedora
225
239
  content_to_ingest = content_to_ingest.read
226
240
  end
227
241
 
228
- connection.post(url,content_to_ingest)
242
+ connection.post(url, :body=>content_to_ingest)
229
243
  end
230
244
 
231
245
  # Fetch the given object using custom method. This is used to fetch other aspects of a fedora object,
@@ -245,11 +259,11 @@ module Fedora
245
259
  end
246
260
 
247
261
  extra_params.delete(:format) if method == :export
248
- connection.raw_get("#{url_for(object)}#{path}?#{extra_params.to_fedora_query}").body
262
+ connection.get("#{url_for(object)}#{path}?#{extra_params.to_fedora_query}").body
249
263
  end
250
264
 
251
265
  def describe_repository
252
- result_body = connection.raw_get("#{fedora_url.path}/describe?xml=true").body
266
+ result_body = connection.get("#{fedora_url.path}/describe?xml=true").body
253
267
  XmlSimple.xml_in(result_body)
254
268
  end
255
269
 
@@ -140,6 +140,8 @@ end
140
140
  describe Fedora::Repository, "find_objects" do
141
141
  before(:all) do
142
142
  Fedora::Repository.register(ActiveFedora.fedora_config[:url])
143
+ @mock_response = mock("Response")
144
+ @mock_response.stubs(:body).returns(sample_response_xml)
143
145
  end
144
146
 
145
147
  def fields_to_s(fields)
@@ -156,31 +158,33 @@ describe Fedora::Repository, "find_objects" do
156
158
 
157
159
  it "should include all fields by default" do
158
160
  when_find_objects('label~Image*') { |conn|
159
- conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
161
+ conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
160
162
  }
161
163
  end
162
164
 
163
165
  it "should include all fields when :include => :all " do
164
166
  when_find_objects('label~Image*', :include => :all) { |conn|
165
- conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
167
+ conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
166
168
  }
167
169
  end
168
170
 
169
171
  it "should fetch results with limit" do
170
172
  when_find_objects('label~Image*', :limit => 10) { |conn|
171
- conn.expects(:get).with('/fedora/objects?maxResults=10&query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS))
173
+ conn.expects(:get).with('/fedora/objects?maxResults=10&query=label%7EImage%2A&resultFormat=xml' + fields_to_s(Fedora::ALL_FIELDS)).returns(@mock_response)
172
174
  }
173
175
  end
174
176
 
175
177
  it "should fetch results with some fields but not :pid" do
176
178
  when_find_objects('label~Image*', :select => [:label, :mDate]) { |conn|
177
- conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate]))
179
+ conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).returns(@mock_response)
180
+
178
181
  }
179
182
  end
180
183
 
181
184
  it "should fetch results with some fields with :pid" do
182
185
  when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
183
- conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate]))
186
+ conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).returns(@mock_response)
187
+
184
188
  }
185
189
  end
186
190
 
@@ -203,7 +207,7 @@ describe Fedora::Repository, "find_objects" do
203
207
  it "should convert xml response with 0 objectFields into array of FedoraObject" do
204
208
  objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
205
209
  conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
206
- returns(Fedora::XmlFormat.decode(sample_response_xml))
210
+ returns(@mock_response)
207
211
  }
208
212
 
209
213
  objects.session_token.should == 'aToken'
@@ -213,7 +217,7 @@ describe Fedora::Repository, "find_objects" do
213
217
  it "should return FedoraObjects with new_object set to false" do
214
218
  objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
215
219
  conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
216
- returns(Fedora::XmlFormat.decode(sample_response_xml))
220
+ returns(@mock_response)
217
221
  }
218
222
  objects.each do |obj|
219
223
  obj.should_not be_new_object
@@ -224,7 +228,7 @@ describe Fedora::Repository, "find_objects" do
224
228
  it "should convert xml response with single objectFields into array of FedoraObject" do
225
229
  objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
226
230
  conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
227
- returns(Fedora::XmlFormat.decode(sample_response_xml(1)))
231
+ returns(@mock_response)
228
232
  }
229
233
 
230
234
  objects.session_token.should == 'aToken'
@@ -234,9 +238,10 @@ describe Fedora::Repository, "find_objects" do
234
238
  end
235
239
 
236
240
  it "should convert xml response 2 objectFields into array of FedoraObject" do
241
+ @mock_response.stubs(:body).returns(sample_response_xml(2))
237
242
  objects = when_find_objects('label~Image*', :select => [:pid, :label, :mDate]) { |conn|
238
243
  conn.expects(:get).with('/fedora/objects?query=label%7EImage%2A&resultFormat=xml' + fields_to_s([:pid, :label, :mDate])).
239
- returns(Fedora::XmlFormat.decode(sample_response_xml(2)))
244
+ returns(@mock_response)
240
245
  }
241
246
 
242
247
  objects.session_token.should == 'aToken'
@@ -14,6 +14,8 @@ end
14
14
  ENV["RAILS_ENV"] ||= 'test'
15
15
  RAILS_ENV = ENV["RAILS_ENV"]
16
16
 
17
+ logger.level = Logger::WARN if logger.respond_to? :level ###MediaShelf StubLogger doesn't have a level= method
18
+
17
19
  $:.unshift(File.dirname(__FILE__) + '/../lib')
18
20
  Dir[File.join(File.dirname(__FILE__)+'/../lib/')+'**/*.rb'].each{|x| require x unless x.match(/railtie.rb$/)}
19
21
  $VERBOSE=nil
@@ -2,24 +2,24 @@ require File.join( File.dirname(__FILE__), "../spec_helper" )
2
2
 
3
3
  require 'active_resource'
4
4
  require 'fedora/repository'
5
-
6
- describe Fedora::Connection do
7
- it "should be creatable w/ a surrogate id" do
8
- c = Fedora::Connection.new('http://127.0.0.1/fedora', 'fubar', 'bob')
9
- c.site.to_s.should == "http://127.0.0.1/fedora"
10
- c.format.should == 'fubar'
11
- c.surrogate.should == 'bob'
12
- end
13
- it "should set a from header if surrogate defined." do
14
- c = Fedora::Connection.new('http://127.0.0.1/fedora', ActiveResource::Formats[:xml], 'bob')
15
- h = Hash.new
16
- r= c.send(:build_request_headers,h)
17
- r['From'].should == 'bob'
18
- end
19
- it "should not set a from header if surrogate undefined." do
20
- c = Fedora::Connection.new('http://127.0.0.1/fedora' )
21
- h = Hash.new
22
- r= c.send(:build_request_headers,h)
23
- r['From'].should be_nil
24
- end
25
- end
5
+ ### Removed by Justin 2011-9-23
6
+ # describe Fedora::Connection do
7
+ # it "should be creatable w/ a surrogate id" do
8
+ # c = Fedora::Connection.new('http://127.0.0.1/fedora', 'fubar', 'bob')
9
+ # c.site.to_s.should == "http://127.0.0.1/fedora"
10
+ # c.format.should == 'fubar'
11
+ # c.surrogate.should == 'bob'
12
+ # end
13
+ # it "should set a from header if surrogate defined." do
14
+ # c = Fedora::Connection.new('http://127.0.0.1/fedora', ActiveResource::Formats[:xml], 'bob')
15
+ # h = Hash.new
16
+ # r= c.send(:build_request_headers,h)
17
+ # r['From'].should == 'bob'
18
+ # end
19
+ # it "should not set a from header if surrogate undefined." do
20
+ # c = Fedora::Connection.new('http://127.0.0.1/fedora' )
21
+ # h = Hash.new
22
+ # r= c.send(:build_request_headers,h)
23
+ # r['From'].should be_nil
24
+ # end
25
+ # end
@@ -60,6 +60,17 @@ describe ActiveFedora::Datastream do
60
60
  end
61
61
  end
62
62
 
63
+ describe '.content=' do
64
+ it "should update the content and ng_xml, marking the datastream as dirty" do
65
+ sample_xml = "<foo><xmlelement/></foo>"
66
+ @test_datastream.should_not be_dirty
67
+ @test_datastream.blob.should_not be_equivalent_to(sample_xml)
68
+ @test_datastream.content = sample_xml
69
+ @test_datastream.should be_dirty
70
+ @test_datastream.blob.should be_equivalent_to(sample_xml)
71
+ end
72
+ end
73
+
63
74
  describe ".dirty?" do
64
75
  it "should return the value of the @dirty attribute" do
65
76
  @test_datastream.dirty.should equal(@test_datastream.dirty?)
@@ -10,7 +10,7 @@ describe ActiveFedora::NokogiriDatastream do
10
10
  :empty_field => {:values => {}}
11
11
  }
12
12
  @sample_xml = XmlSimple.xml_in("<fields><coverage>coverage1</coverage><coverage>coverage2</coverage><creation_date>fake-date</creation_date><mydate>fake-date</mydate><publisher>publisher1</publisher></fields>")
13
-
13
+ @sample_raw_xml = "<foo><xmlelement/></foo>"
14
14
  @solr_doc = {"id"=>"hydrange_article1","name_role_roleTerm_t"=>["creator","submitter","teacher"],"name_0_role_t"=>"\r\ncreator\r\nsubmitter\r\n","name_1_role_t"=>"\r\n teacher \r\n","name_0_role_0_roleTerm_t"=>"creator","name_0_role_1_roleTerm_t"=>"submitter","name_1_role_0_roleTerm_t"=>["teacher"]}
15
15
  end
16
16
 
@@ -35,8 +35,8 @@ describe ActiveFedora::NokogiriDatastream do
35
35
  test_ds1.ng_xml.to_xml.should == "<?xml version=\"1.0\"?>\n<xml>\n <foo/>\n</xml>\n"
36
36
  end
37
37
  it "should initialize from #xml_template if no xml is provided" do
38
- ActiveFedora::NokogiriDatastream.expects(:xml_template).returns("fake template")
39
- ActiveFedora::NokogiriDatastream.new.ng_xml.should == "fake template"
38
+ ActiveFedora::NokogiriDatastream.expects(:xml_template).returns("<fake template/>")
39
+ ActiveFedora::NokogiriDatastream.new.ng_xml.should be_equivalent_to("<fake template/>")
40
40
  end
41
41
  end
42
42
 
@@ -234,6 +234,32 @@ describe ActiveFedora::NokogiriDatastream do
234
234
  end
235
235
  end
236
236
 
237
+ describe '.content=' do
238
+ it "should update the content and ng_xml, marking the datastream as dirty" do
239
+ @test_ds.should_not be_dirty
240
+ @test_ds.blob.should_not be_equivalent_to(@sample_raw_xml)
241
+ @test_ds.ng_xml.to_xml.should_not be_equivalent_to(@sample_raw_xml)
242
+ @test_ds.content = @sample_raw_xml
243
+ @test_ds.should be_dirty
244
+ @test_ds.blob.should be_equivalent_to(@sample_raw_xml)
245
+ @test_ds.ng_xml.to_xml.should be_equivalent_to(@sample_raw_xml)
246
+ end
247
+ end
248
+
249
+ describe 'ng_xml=' do
250
+ it "should parse raw xml for you" do
251
+ @test_ds.ng_xml.to_xml.should_not be_equivalent_to(@sample_raw_xml)
252
+ @test_ds.ng_xml = @sample_raw_xml
253
+ @test_ds.ng_xml.class.should == Nokogiri::XML::Document
254
+ @test_ds.ng_xml.to_xml.should be_equivalent_to(@sample_raw_xml)
255
+ end
256
+ it "should mark the datastream as dirty" do
257
+ @test_ds.should_not be_dirty
258
+ @test_ds.ng_xml = @sample_raw_xml
259
+ @test_ds.should be_dirty
260
+ end
261
+ end
262
+
237
263
  describe '.to_xml' do
238
264
  it "should provide .to_xml" do
239
265
  @test_ds.should respond_to(:to_xml)
@@ -99,14 +99,14 @@ describe Fedora::Repository do
99
99
  it "should post the provided xml or file to fedora" do
100
100
  foxml = fixture("test_12.foxml.xml").read
101
101
  connection = Fedora::Repository.instance.send(:connection)
102
- connection.expects(:post).with("/fedora/objects/new",foxml)
102
+ connection.expects(:post).with("/fedora/objects/new",:body=>foxml)
103
103
  Fedora::Repository.instance.ingest(foxml)
104
104
  end
105
105
  it "should accept a file as its input" do
106
106
  foxml_file = fixture("test_12.foxml.xml")
107
107
  foxml = fixture("test_12.foxml.xml").read
108
108
  connection = Fedora::Repository.instance.send(:connection)
109
- connection.expects(:post).with("/fedora/objects/new",foxml)
109
+ connection.expects(:post).with("/fedora/objects/new",:body=>foxml)
110
110
  Fedora::Repository.instance.ingest(foxml_file)
111
111
  end
112
112
  end
@@ -84,4 +84,11 @@ describe ActiveFedora::SolrService do
84
84
  end
85
85
  end
86
86
 
87
+ describe "escape_characters_for_query" do
88
+ it "should escape the Solr special characters" do
89
+ test_val = '# + - || ! ( ) { } [ ] ^ " ~ * ? : \\'
90
+ expected_result = '\\# \\+ \\- \\|\\| \\! \\( \\) \\{ \\} \\[ \\] \\^ \\" \\~ \\* \\? \\: \\\\'
91
+ ActiveFedora::SolrService.escape_characters_for_query(test_val).should == expected_result
92
+ end
93
+ end
87
94
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-fedora
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 3
9
- - 7
10
- version: 2.3.7
9
+ - 8
10
+ version: 2.3.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Zumwalt
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-09-02 00:00:00 -05:00
19
+ date: 2011-09-23 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -133,12 +133,14 @@ dependencies:
133
133
  requirement: &id008 !ruby/object:Gem::Requirement
134
134
  none: false
135
135
  requirements:
136
- - - ">="
136
+ - - <
137
137
  - !ruby/object:Gem::Version
138
- hash: 3
138
+ hash: 7
139
139
  segments:
140
+ - 3
140
141
  - 0
141
- version: "0"
142
+ - 0
143
+ version: 3.0.0
142
144
  type: :runtime
143
145
  version_requirements: *id008
144
146
  - !ruby/object:Gem::Dependency
@@ -184,7 +186,7 @@ dependencies:
184
186
  type: :runtime
185
187
  version_requirements: *id011
186
188
  - !ruby/object:Gem::Dependency
187
- name: yard
189
+ name: net-http-persistent
188
190
  prerelease: false
189
191
  requirement: &id012 !ruby/object:Gem::Requirement
190
192
  none: false
@@ -195,10 +197,10 @@ dependencies:
195
197
  segments:
196
198
  - 0
197
199
  version: "0"
198
- type: :development
200
+ type: :runtime
199
201
  version_requirements: *id012
200
202
  - !ruby/object:Gem::Dependency
201
- name: RedCloth
203
+ name: yard
202
204
  prerelease: false
203
205
  requirement: &id013 !ruby/object:Gem::Requirement
204
206
  none: false
@@ -212,7 +214,7 @@ dependencies:
212
214
  type: :development
213
215
  version_requirements: *id013
214
216
  - !ruby/object:Gem::Dependency
215
- name: rake
217
+ name: RedCloth
216
218
  prerelease: false
217
219
  requirement: &id014 !ruby/object:Gem::Requirement
218
220
  none: false
@@ -226,7 +228,7 @@ dependencies:
226
228
  type: :development
227
229
  version_requirements: *id014
228
230
  - !ruby/object:Gem::Dependency
229
- name: rcov
231
+ name: rake
230
232
  prerelease: false
231
233
  requirement: &id015 !ruby/object:Gem::Requirement
232
234
  none: false
@@ -240,7 +242,7 @@ dependencies:
240
242
  type: :development
241
243
  version_requirements: *id015
242
244
  - !ruby/object:Gem::Dependency
243
- name: solrizer-fedora
245
+ name: rcov
244
246
  prerelease: false
245
247
  requirement: &id016 !ruby/object:Gem::Requirement
246
248
  none: false
@@ -254,7 +256,7 @@ dependencies:
254
256
  type: :development
255
257
  version_requirements: *id016
256
258
  - !ruby/object:Gem::Dependency
257
- name: jettywrapper
259
+ name: solrizer-fedora
258
260
  prerelease: false
259
261
  requirement: &id017 !ruby/object:Gem::Requirement
260
262
  none: false
@@ -268,9 +270,23 @@ dependencies:
268
270
  type: :development
269
271
  version_requirements: *id017
270
272
  - !ruby/object:Gem::Dependency
271
- name: rspec
273
+ name: jettywrapper
272
274
  prerelease: false
273
275
  requirement: &id018 !ruby/object:Gem::Requirement
276
+ none: false
277
+ requirements:
278
+ - - ">="
279
+ - !ruby/object:Gem::Version
280
+ hash: 3
281
+ segments:
282
+ - 0
283
+ version: "0"
284
+ type: :development
285
+ version_requirements: *id018
286
+ - !ruby/object:Gem::Dependency
287
+ name: rspec
288
+ prerelease: false
289
+ requirement: &id019 !ruby/object:Gem::Requirement
274
290
  none: false
275
291
  requirements:
276
292
  - - <
@@ -282,11 +298,11 @@ dependencies:
282
298
  - 0
283
299
  version: 2.0.0
284
300
  type: :development
285
- version_requirements: *id018
301
+ version_requirements: *id019
286
302
  - !ruby/object:Gem::Dependency
287
303
  name: mocha
288
304
  prerelease: false
289
- requirement: &id019 !ruby/object:Gem::Requirement
305
+ requirement: &id020 !ruby/object:Gem::Requirement
290
306
  none: false
291
307
  requirements:
292
308
  - - ">="
@@ -298,11 +314,11 @@ dependencies:
298
314
  - 8
299
315
  version: 0.9.8
300
316
  type: :development
301
- version_requirements: *id019
317
+ version_requirements: *id020
302
318
  - !ruby/object:Gem::Dependency
303
319
  name: ruby-debug
304
320
  prerelease: false
305
- requirement: &id020 !ruby/object:Gem::Requirement
321
+ requirement: &id021 !ruby/object:Gem::Requirement
306
322
  none: false
307
323
  requirements:
308
324
  - - ">="
@@ -312,7 +328,7 @@ dependencies:
312
328
  - 0
313
329
  version: "0"
314
330
  type: :development
315
- version_requirements: *id020
331
+ version_requirements: *id021
316
332
  description: ActiveFedora provides for creating and managing objects in the Fedora Repository Architecture.
317
333
  email:
318
334
  - matt.zumwalt@yourmediashelf.com