active-fedora 2.3.7 → 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
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