dor-services 2.2.4 → 4.4.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/bin/dor-indexer +108 -0
- data/bin/dor-indexerd +73 -0
- data/bin/nokogiri +19 -0
- data/bin/rake +19 -0
- data/bin/ruby_noexec_wrapper +14 -0
- data/bin/solrizer +19 -0
- data/bin/solrizerd +19 -0
- data/config/certs/README +1 -0
- data/config/config_defaults.yml +62 -0
- data/config/dev_console_env.rb.example +67 -0
- data/config/predicate_mappings.yml +55 -0
- data/lib/dor-services.rb +152 -19
- data/lib/dor/config.rb +133 -35
- data/lib/dor/datastreams/administrative_metadata_ds.rb +84 -0
- data/lib/dor/datastreams/content_metadata_ds.rb +337 -0
- data/lib/dor/datastreams/datastream_spec_solrizer.rb +18 -0
- data/lib/dor/datastreams/default_object_rights_ds.rb +52 -0
- data/lib/dor/datastreams/desc_metadata_ds.rb +39 -0
- data/lib/{datastreams → dor/datastreams}/embargo_metadata_ds.rb +25 -20
- data/lib/{datastreams → dor/datastreams}/events_ds.rb +14 -9
- data/lib/dor/datastreams/identity.xsl +8 -0
- data/lib/dor/datastreams/identity_metadata_ds.rb +112 -0
- data/lib/dor/datastreams/role_metadata_ds.rb +51 -0
- data/lib/dor/datastreams/simple_dublin_core_ds.rb +45 -0
- data/lib/dor/datastreams/version_metadata_ds.rb +214 -0
- data/lib/dor/datastreams/workflow_definition_ds.rb +113 -0
- data/lib/dor/datastreams/workflow_ds.rb +103 -0
- data/lib/dor/exceptions.rb +0 -1
- data/lib/dor/migrations/content_metadata_ds/change_content_type.rb +7 -0
- data/lib/dor/migrations/identifiable/assert_adminPolicy.rb +9 -0
- data/lib/dor/migrations/identifiable/fix_model_assertions.rb +13 -0
- data/lib/dor/migrations/identifiable/record_remediation.rb +18 -0
- data/lib/dor/migrations/identifiable/uriify_augmented_contentlocation_refs.rb +18 -0
- data/lib/dor/migrations/identifiable/uriify_contentlocation_refs.rb +18 -0
- data/lib/dor/migrations/processable/unify_workflows.rb +17 -0
- data/lib/dor/migrations/versionable/add_missing_version_md.rb +9 -0
- data/lib/dor/models/admin_policy_object.rb +16 -0
- data/lib/dor/models/assembleable.rb +14 -0
- data/lib/dor/models/collection.rb +14 -0
- data/lib/dor/models/contentable.rb +227 -0
- data/lib/dor/models/describable.rb +194 -0
- data/lib/dor/models/discoverable.rb +66 -0
- data/lib/dor/models/editable.rb +267 -0
- data/lib/dor/models/embargoable.rb +97 -0
- data/lib/dor/models/eventable.rb +12 -0
- data/lib/dor/models/governable.rb +162 -0
- data/lib/dor/models/identifiable.rb +211 -0
- data/lib/dor/models/item.rb +44 -0
- data/lib/dor/models/itemizable.rb +66 -0
- data/lib/dor/{mods2dc.xslt → models/mods2dc.xslt} +39 -12
- data/lib/dor/models/preservable.rb +50 -0
- data/lib/dor/models/processable.rb +229 -0
- data/lib/dor/models/publishable.rb +74 -0
- data/lib/dor/models/set.rb +12 -0
- data/lib/dor/models/shelvable.rb +27 -0
- data/lib/dor/models/upgradable.rb +74 -0
- data/lib/dor/models/versionable.rb +94 -0
- data/lib/dor/models/workflow_object.rb +54 -0
- data/lib/dor/services/cleanup_service.rb +47 -0
- data/lib/dor/services/digital_stacks_service.rb +55 -0
- data/lib/dor/services/merge_service.rb +96 -0
- data/lib/dor/{metadata_handlers → services/metadata_handlers}/catalog_handler.rb +0 -2
- data/lib/dor/{metadata_handlers → services/metadata_handlers}/mdtoolkit_handler.rb +0 -2
- data/lib/dor/{metadata_service.rb → services/metadata_service.rb} +1 -3
- data/lib/dor/services/registration_service.rb +181 -0
- data/lib/dor/services/sdr_ingest_service.rb +181 -0
- data/lib/dor/services/search_service.rb +131 -0
- data/lib/dor/services/suri_service.rb +32 -0
- data/lib/dor/services/technical_metadata_service.rb +226 -0
- data/lib/dor/{tei2dc.xslt → services/tei2dc.xslt} +0 -0
- data/lib/dor/utils/ng_tidy.rb +37 -0
- data/lib/dor/utils/predicate_patch.rb +23 -0
- data/lib/dor/utils/solr_doc_helper.rb +9 -0
- data/lib/dor/utils/utc_date_field_mapper.rb +7 -0
- data/lib/dor/version.rb +3 -0
- data/lib/dor/workflow/document.rb +131 -0
- data/lib/dor/workflow/graph.rb +166 -0
- data/lib/dor/workflow/process.rb +99 -0
- data/lib/gsearch/demoFoxmlToSolr.xslt +340 -122
- data/lib/tasks/dor.rake +39 -0
- metadata +494 -384
- data/lib/datastreams/content_metadata_ds.rb +0 -12
- data/lib/datastreams/identity_metadata_ds.rb +0 -28
- data/lib/datastreams/ng_tidy.rb +0 -19
- data/lib/datastreams/simple_dublin_core_ds.rb +0 -23
- data/lib/datastreams/workflow_definition_ds.rb +0 -105
- data/lib/datastreams/workflow_ds.rb +0 -16
- data/lib/dor/admin_policy_object.rb +0 -11
- data/lib/dor/base.rb +0 -81
- data/lib/dor/cleanup_service.rb +0 -32
- data/lib/dor/digital_stacks_service.rb +0 -82
- data/lib/dor/druid_utils.rb +0 -41
- data/lib/dor/embargo.rb +0 -41
- data/lib/dor/item.rb +0 -141
- data/lib/dor/provenance_metadata_service.rb +0 -65
- data/lib/dor/registration_service.rb +0 -87
- data/lib/dor/rsolr.rb +0 -27
- data/lib/dor/sdr_ingest_service.rb +0 -117
- data/lib/dor/search_service.rb +0 -86
- data/lib/dor/suri_service.rb +0 -37
- data/lib/dor/workflow_object.rb +0 -13
- data/lib/dor/workflow_service.rb +0 -111
- data/lib/xml_models/foxml.rb +0 -261
- data/lib/xml_models/identity_metadata/dublin_core.rb +0 -119
- data/lib/xml_models/identity_metadata/identity_metadata.rb +0 -288
@@ -1,12 +0,0 @@
|
|
1
|
-
class ContentMetadataDS < ActiveFedora::NokogiriDatastream
|
2
|
-
|
3
|
-
def public_xml
|
4
|
-
result = self.ng_xml.clone
|
5
|
-
result.xpath('/contentMetadata/resource[not(file[(@deliver="yes" or @publish="yes")])]').each { |n| n.remove }
|
6
|
-
result.xpath('/contentMetadata/resource/file[not(@deliver="yes" or @publish="yes")]').each { |n| n.remove }
|
7
|
-
result.xpath('/contentMetadata/resource/file').xpath('@preserve|@shelve|@publish|@deliver').each { |n| n.remove }
|
8
|
-
result.xpath('/contentMetadata/resource/file/checksum').each { |n| n.remove }
|
9
|
-
result
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
class IdentityMetadataDS < ActiveFedora::NokogiriDatastream
|
2
|
-
|
3
|
-
set_terminology do |t|
|
4
|
-
t.root(:path=>"identityMetadata", :xmlns => '')
|
5
|
-
t.objectId(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
6
|
-
t.objectType(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
7
|
-
t.objectLabel(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
8
|
-
t.citationCreator(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
9
|
-
t.sourceId(:index_as=>[:searchable, :displayable, :facetable, :sortable], :attributes=>{:type=>"source"}, :required=>:true, :type=>:string, :namespace_prefix => nil )
|
10
|
-
t.otherId(:index_as=>[:searchable, :displayable, :facetable, :sortable], :attributes=>{:type=>"name"}, :required=>:true, :type=>:string, :namespace_prefix => nil )
|
11
|
-
t.agreementId(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
12
|
-
t.tag(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
13
|
-
t.citationTitle(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
14
|
-
t.objectCreator(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
15
|
-
t.adminPolicy(:index_as=>[:searchable, :displayable, :facetable, :sortable], :required=>:true, :type=>:string, :namespace_prefix => nil )
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.xml_template
|
19
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
20
|
-
xml.identityMetadata {
|
21
|
-
xml.citationTitle
|
22
|
-
xml.objectCreator
|
23
|
-
}
|
24
|
-
end
|
25
|
-
return builder.doc
|
26
|
-
end #self.xml_template
|
27
|
-
|
28
|
-
end #class
|
data/lib/datastreams/ng_tidy.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
class Nokogiri::XML::Text
|
2
|
-
|
3
|
-
def normalize
|
4
|
-
self.content =~ /\S/ ? self.content.gsub(/\s+/,' ').strip : self.content
|
5
|
-
end
|
6
|
-
|
7
|
-
def normalize!
|
8
|
-
self.content = self.normalize
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
class Nokogiri::XML::Node
|
14
|
-
|
15
|
-
def normalize_text!
|
16
|
-
self.xpath('//text()').each { |t| t.normalize! }
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
class SimpleDublinCoreDs < ActiveFedora::NokogiriDatastream
|
2
|
-
|
3
|
-
set_terminology do |t|
|
4
|
-
t.root(:path=>"dc", :xmlns=>"http://www.openarchives.org/OAI/2.0/oai_dc/", :schema=>"http://cosimo.stanford.edu/standards/oai_dc/v2/oai_dc.xsd", :namespace_prefix => 'oai_dc')
|
5
|
-
t.title(:index_as=>[:searchable, :displayable, :facetable, :sortable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
|
6
|
-
t.creator(:index_as=>[:searchable, :displayable, :facetable, :sortable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
|
7
|
-
t.identifier(:index_as=>[:searchable, :displayable, :sortable], :xmlns => "http://purl.org/dc/elements/1.1/", :namespace_prefix => 'dc')
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.xml_template
|
11
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
12
|
-
xml.dc(:xmlns=>"http://www.openarchives.org/OAI/2.0/oai_dc/",
|
13
|
-
'xmlns:dc'=>'http://purl.org/dc/elements/1.1/') {
|
14
|
-
xml['dc'].title
|
15
|
-
xml['dc'].creator
|
16
|
-
xml['dc'].identifier
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
return builder.doc
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
class WorkflowProcess
|
2
|
-
|
3
|
-
def initialize(workflow, node)
|
4
|
-
@workflow = workflow
|
5
|
-
@node = node
|
6
|
-
end
|
7
|
-
|
8
|
-
def name
|
9
|
-
@node['name']
|
10
|
-
end
|
11
|
-
|
12
|
-
def sequence
|
13
|
-
@node['sequence']
|
14
|
-
end
|
15
|
-
|
16
|
-
def lifecycle
|
17
|
-
@node['lifecycle']
|
18
|
-
end
|
19
|
-
|
20
|
-
def label
|
21
|
-
@node.at_xpath('label/text()').to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
def prerequisites
|
25
|
-
@node.xpath('prereq').collect do |p|
|
26
|
-
if (p['repository'].nil? and p['workflow'].nil?) or (p['repository'] == workflow.repository and p['workflow'] == workflow.name)
|
27
|
-
p.text.to_s
|
28
|
-
else
|
29
|
-
[(p['repository'] or workflow.repository),(p['workflow'] or workflow.name),p.text.to_s].join(':')
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
class WorkflowDefinitionDs < ActiveFedora::NokogiriDatastream
|
37
|
-
|
38
|
-
define_template :process do |builder,workflow,name,seq,label,lifecycle,prereqs|
|
39
|
-
attrs = {:name => name}
|
40
|
-
attrs[:sequence] = seq unless seq.nil?
|
41
|
-
attrs[:lifecycle] = lifecycle unless lifecycle.nil?
|
42
|
-
builder.process(attrs) do |node|
|
43
|
-
prereqs.each do |prereq|
|
44
|
-
(repo,wf,prereq_name) = prereq.split(/:/)
|
45
|
-
if prereq_name.nil?
|
46
|
-
prereq_name = repo
|
47
|
-
repo = nil
|
48
|
-
end
|
49
|
-
if (repo == workflow.repository and wf = workflow.name)
|
50
|
-
repo = nil
|
51
|
-
wf = nil
|
52
|
-
end
|
53
|
-
attrs = (repo.nil? and wf.nil?) ? {} : { :repository => repo, :workflow => wf }
|
54
|
-
node.prereq(attrs) { node.text prereq_name }
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def add_process(name, seq, label, lifecycle, prereqs)
|
60
|
-
add_child_node(ng_xml.at_xpath('/workflow'), :process, self, name, seq, label, lifecycle, prereqs)
|
61
|
-
end
|
62
|
-
|
63
|
-
def processes
|
64
|
-
ng_xml.xpath('/workflow/process').collect do |node|
|
65
|
-
WorkflowProcess.new(self, node)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def name
|
70
|
-
ng_xml.at_xpath('/workflow/@id').to_s
|
71
|
-
end
|
72
|
-
|
73
|
-
def repository
|
74
|
-
ng_xml.at_xpath('/workflow/@repository').to_s
|
75
|
-
end
|
76
|
-
|
77
|
-
def configuration
|
78
|
-
result = {
|
79
|
-
'repository' => repository,
|
80
|
-
'name' => name
|
81
|
-
}
|
82
|
-
processes.each_pair do |process_name,process|
|
83
|
-
result[process_name] = {
|
84
|
-
'prerequisites' => process.prerequisites.collect { |p| p.name }
|
85
|
-
}
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def configuration=(hash)
|
90
|
-
ng_xml = Nokogiri::XML(%{<workflow id="#{hash['name']}" repository="#{hash['repository']}"/>})
|
91
|
-
i = 0
|
92
|
-
hash.each_pair do |k,v|
|
93
|
-
if v.is_a?(Hash)
|
94
|
-
add_process(k,i+=1,nil,nil,v['prerequisite'])
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def to_yaml
|
100
|
-
s = StringIO.new('')
|
101
|
-
YAML.dump(self.configuration, s)
|
102
|
-
s.string
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
class WorkflowDs < ActiveFedora::NokogiriDatastream
|
2
|
-
|
3
|
-
set_terminology do |t|
|
4
|
-
t.root(:path=>"workflow", :xmlns => '', :namespace_prefix => nil)
|
5
|
-
t.workflowId(:path=>{:attribute => "id"}, :index_as => [:displayable, :facetable])
|
6
|
-
t.process(:path=>'process', :namespace_prefix => nil) {
|
7
|
-
t._name(:path=>{:attribute=>"name"}, :index_as => [:displayable, :facetable, :sortable])
|
8
|
-
t.status(:path=>{:attribute=>"status"}, :index_as => [:displayable, :facetable, :sortable])
|
9
|
-
t.timestamp(:path=>{:attribute=>"datetime"}, :index_as => [:searchable, :sortable])
|
10
|
-
t.elapsed(:path=>{:attribute=>"elapsed"})
|
11
|
-
t.lifecycle(:path=>{:attribute=>"lifecycle"}, :index_as => [:displayable, :facetable, :sortable])
|
12
|
-
t.attempts(:path=>{:attribute=>"attempts"})
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module Dor
|
2
|
-
|
3
|
-
class AdminPolicyObject < Base
|
4
|
-
|
5
|
-
has_metadata :name => "administrativeMetadata", :type => ActiveFedora::NokogiriDatastream
|
6
|
-
has_metadata :name => "roleMetadata", :type => ActiveFedora::NokogiriDatastream
|
7
|
-
has_metadata :name => "defaultObjectRights", :type => ActiveFedora::NokogiriDatastream
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
data/lib/dor/base.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'active_fedora'
|
2
|
-
require 'datastreams/identity_metadata_ds'
|
3
|
-
require 'datastreams/simple_dublin_core_ds'
|
4
|
-
require 'datastreams/workflow_ds'
|
5
|
-
require 'dor/suri_service'
|
6
|
-
|
7
|
-
module Dor
|
8
|
-
|
9
|
-
class Base < ::ActiveFedora::Base
|
10
|
-
|
11
|
-
attr_reader :workflows
|
12
|
-
|
13
|
-
has_metadata :name => "DC", :type => SimpleDublinCoreDs
|
14
|
-
has_metadata :name => "RELS-EXT", :type => ActiveFedora::RelsExtDatastream
|
15
|
-
has_metadata :name => "identityMetadata", :type => IdentityMetadataDS
|
16
|
-
|
17
|
-
# Make a random (and harmless) API-M call to get gsearch to reindex the object
|
18
|
-
def self.touch(*pids)
|
19
|
-
client = Dor::Config.fedora.client
|
20
|
-
pids.collect { |pid|
|
21
|
-
response = client["objects/#{pid}/datastreams/DC?dsState=A&ignoreContent=true"].put('', :content_type => 'text/xml')
|
22
|
-
response.code
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.get_foxml(pid, interpolate_refs = false)
|
27
|
-
foxml = Nokogiri::XML(Dor::Config.fedora.client["objects/#{pid}/objectXML"].get)
|
28
|
-
if interpolate_refs
|
29
|
-
external_refs = foxml.xpath('//foxml:contentLocation[contains(@REF,"/workflows/")]')
|
30
|
-
external_refs.each do |ref|
|
31
|
-
begin
|
32
|
-
external_doc = Nokogiri::XML(RestClient.get(ref['REF']))
|
33
|
-
external_root = external_doc.root
|
34
|
-
ref.replace('<foxml:xmlContent/>').first.add_child(external_doc.root)
|
35
|
-
external_root.traverse { |node| node.namespace = nil }
|
36
|
-
rescue
|
37
|
-
ref.remove
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
return foxml
|
42
|
-
end
|
43
|
-
|
44
|
-
def initialize(attrs = {})
|
45
|
-
unless attrs[:pid]
|
46
|
-
attrs = attrs.merge!({:pid=>Dor::SuriService.mint_id})
|
47
|
-
@new_object=true
|
48
|
-
else
|
49
|
-
@new_object = attrs[:new_object] == false ? false : true
|
50
|
-
end
|
51
|
-
@inner_object = Fedora::FedoraObject.new(attrs)
|
52
|
-
@datastreams = {}
|
53
|
-
@workflows = {}
|
54
|
-
configure_defined_datastreams
|
55
|
-
end
|
56
|
-
|
57
|
-
def identity_metadata
|
58
|
-
if self.datastreams.has_key?('identityMetadata')
|
59
|
-
IdentityMetadata.from_xml(self.datastreams['identityMetadata'].content)
|
60
|
-
else
|
61
|
-
nil
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Self-aware datastream builders
|
66
|
-
def build_datastream(datastream, force = false)
|
67
|
-
ds = datastreams[datastream]
|
68
|
-
if force or ds.new_object? or (ds.content.to_s.empty?)
|
69
|
-
proc = "build_#{datastream}_datastream".to_sym
|
70
|
-
content = self.send(proc, ds)
|
71
|
-
ds.save
|
72
|
-
end
|
73
|
-
return ds
|
74
|
-
end
|
75
|
-
|
76
|
-
def reindex
|
77
|
-
Dor::SearchService.reindex(self.pid)
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
data/lib/dor/cleanup_service.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'lyber-utils'
|
3
|
-
|
4
|
-
module Dor
|
5
|
-
class CleanupService
|
6
|
-
Config.declare(:cleanup) do
|
7
|
-
local_workspace_root '/dor/workspace'
|
8
|
-
local_export_home '/dor/export'
|
9
|
-
end
|
10
|
-
|
11
|
-
# Delete all workspace and export entities for the druid
|
12
|
-
# @param [LyberCore::Robots::WorkItem]
|
13
|
-
def self.cleanup(dor_item)
|
14
|
-
druid = dor_item.pid
|
15
|
-
workspace_dir = Druid.new(druid).path(Config.cleanup.local_workspace_root)
|
16
|
-
self.remove_entry(workspace_dir)
|
17
|
-
bag_dir = File.join(Config.cleanup.local_export_home, druid)
|
18
|
-
self.remove_entry(bag_dir)
|
19
|
-
tarfile = "#{bag_dir}.tar"
|
20
|
-
self.remove_entry(tarfile)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Deleta a filesystem entry
|
24
|
-
# @param [String]
|
25
|
-
def self.remove_entry(entry)
|
26
|
-
FileUtils.remove_entry(entry) if File.exist?(entry)
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'tempfile'
|
2
|
-
require 'systemu'
|
3
|
-
|
4
|
-
module Dor
|
5
|
-
class DigitalStacksService
|
6
|
-
|
7
|
-
Config.declare(:stacks) do
|
8
|
-
document_cache_storage_root nil
|
9
|
-
document_cache_host nil
|
10
|
-
document_cache_user nil
|
11
|
-
|
12
|
-
storage_root '/stacks'
|
13
|
-
host nil
|
14
|
-
user nil
|
15
|
-
|
16
|
-
local_workspace_root '/dor'
|
17
|
-
end
|
18
|
-
|
19
|
-
# TODO copied from lyber-core, but didn't want to create circular dependency for between gems for this one method
|
20
|
-
# Executes a system command in a subprocess.
|
21
|
-
# The method will return stdout from the command if execution was successful.
|
22
|
-
# The method will raise an exception if if execution fails.
|
23
|
-
# The exception's message will contain the explaination of the failure.
|
24
|
-
# @param [String] command the command to be executed
|
25
|
-
# @return [String] stdout from the command if execution was successful
|
26
|
-
def self.execute(command)
|
27
|
-
status, stdout, stderr = systemu(command)
|
28
|
-
if (status.exitstatus != 0)
|
29
|
-
raise stderr
|
30
|
-
end
|
31
|
-
return stdout
|
32
|
-
rescue
|
33
|
-
msg = "Command failed to execute: [#{command}] caused by <STDERR =\n#{stderr.split($/).join("\n")}>"
|
34
|
-
msg << "\nSTDOUT =\n#{stdout.split($/).join("\n")}" if (stdout && (stdout.length > 0))
|
35
|
-
raise msg
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.druid_tree(druid)
|
39
|
-
Druid.new(druid).path
|
40
|
-
rescue
|
41
|
-
nil
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.transfer_to_document_store(id, content, filename)
|
45
|
-
path = self.druid_tree(id)
|
46
|
-
raise "Invalid druid: #{id}" if(path.nil?)
|
47
|
-
|
48
|
-
# create the remote directory in the document cache
|
49
|
-
remote_document_cache_dir = File.join(Config.stacks.document_cache_storage_root, path)
|
50
|
-
command = "ssh #{Config.stacks.document_cache_user}@#{Config.stacks.document_cache_host} mkdir -p #{remote_document_cache_dir}"
|
51
|
-
self.execute(command)
|
52
|
-
|
53
|
-
# create a temp file containing the content and copy the contents to the remote document cache
|
54
|
-
Tempfile.open(filename) do |tf|
|
55
|
-
tf.write(content)
|
56
|
-
tf.flush
|
57
|
-
command = "scp \"#{tf.path}\" #{Config.stacks.document_cache_user}@#{Config.stacks.document_cache_host}:#{remote_document_cache_dir}/#{filename}"
|
58
|
-
self.execute(command)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.shelve_to_stacks(id, files)
|
63
|
-
path = self.druid_tree(id)
|
64
|
-
raise "Invalid druid: #{id}" if(path.nil?)
|
65
|
-
|
66
|
-
# create the remote directory on the digital stacks
|
67
|
-
remote_storage_dir = File.join(Config.stacks.storage_root, path)
|
68
|
-
command = "ssh #{Config.stacks.user}@#{Config.stacks.host} mkdir -p #{remote_storage_dir}"
|
69
|
-
self.execute(command)
|
70
|
-
|
71
|
-
# copy the contents for the given object from the local workspace directory to the remote directory
|
72
|
-
local_storage_dir = File.join(Config.stacks.local_workspace_root, path)
|
73
|
-
files.each do |file|
|
74
|
-
command = "scp \"#{local_storage_dir}/#{file}\" #{Config.stacks.user}@#{Config.stacks.host}:#{remote_storage_dir}"
|
75
|
-
self.execute(command)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
data/lib/dor/druid_utils.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
class Druid
|
2
|
-
attr_accessor :druid
|
3
|
-
|
4
|
-
DRUID_PATTERN = /^(?:druid:)?([a-z]{2})(\d{3})([a-z]{2})(\d{4})$/
|
5
|
-
def initialize(druid)
|
6
|
-
if druid !~ DRUID_PATTERN
|
7
|
-
raise ArgumentError, "Invalid DRUID: #{druid}"
|
8
|
-
end
|
9
|
-
@druid = druid
|
10
|
-
end
|
11
|
-
|
12
|
-
def id
|
13
|
-
@druid.scan(/^(?:druid:)?(.+)$/).flatten.last
|
14
|
-
end
|
15
|
-
|
16
|
-
def tree
|
17
|
-
@druid.scan(DRUID_PATTERN).flatten
|
18
|
-
end
|
19
|
-
|
20
|
-
def path(base=nil)
|
21
|
-
File.join(*([base,tree].compact))
|
22
|
-
end
|
23
|
-
|
24
|
-
def mkdir(base)
|
25
|
-
FileUtils.mkdir_p(path(base))
|
26
|
-
end
|
27
|
-
|
28
|
-
def rmdir(base)
|
29
|
-
parts = tree
|
30
|
-
while parts.length > 0
|
31
|
-
dir = File.join(base, *parts)
|
32
|
-
begin
|
33
|
-
FileUtils.rm(File.join(dir,'.DS_Store'), :force => true)
|
34
|
-
FileUtils.rmdir(dir)
|
35
|
-
rescue Errno::ENOTEMPTY
|
36
|
-
break
|
37
|
-
end
|
38
|
-
parts.pop
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|