The DoorKeeper guards the entry at a (FLAT) repository. It does so by running a SIP (Submission Information Package) through a sequence of actions, when one of them fails the SIP should not be allowed into the repository.
Some actions depend on some (patched) libraries which are not available in a Maven repository:
- https://github.com/menzowindhouwer/fedora-cargo-plugin.git
- https://github.com/menzowindhouwer/fedora-client.git
- https://github.com/meertensinstituut/EPICify.git
$ git clone https://github.com/menzowindhouwer/fedora-cargo-plugin.git
$ cd fedora-cargo-plugin
$ mvn clean install
$ cd ..
$ git clone https://github.com/menzowindhouwer/fedora-client.git
$ cd fedora-client
$ mvn clean install
$ cd ..
$ git clone https://github.com/meertensinstituut/EPICify.git
$ cd EPICify
$ mvn clean install
$ cd ..
$ git clone https://github.com/TLA-FLAT/DoorKeeper.git
$ cd DoorKeeper
$ mvn clean install
fedora-client might fail when running mvn clean install
. If you get the following error or a similar test related error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.14:test
You should run mvn -DskipTests clean install
.
If you get the following error or a similar port related error:
Port number 8009 (defined with the property cargo.tomcat.ajp.port) is in use.
You should turn off tomcat server before running mvn by running supervisorctl stop tomcat
. After running mvn, you can start tomcat again by running supervisorctl start tomcat
.
The DoorKeeper can be executed from the command line. But can also be embedded in a servlet (UPCOMMING: ServiceFlat).
$ java -jar target/doorkeeper.jar -?
INF: doorkeeper <OPTIONS> <workflow FILE> (<param>=<value>)*
INF: where <OPTIONS> are:
INF: -f <action> : from this action (name) (optional)
INF: -t <action> : to this action (name) (optional)
The actions to be executed are specified in a workflow XML file. Its structure reflects the basic workflow:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<config>
<!-- global properties -->
</config>
<init>
<!-- action flow to initialize the workflow (will be executed always) -->
</init>
<main>
<!-- main action flow to be executed (execution can be partial based on from/to options) -->
</main>
<exception>
<!-- action flow to be executed when the main action flow threw an exception -->
</exception>
<final>
<!-- action flow to tear down the workflow (will be executed always) -->
</final>
</flow>
The purpose of the configuration section is to specify global properties. These can be imported from the "environment", specified in the worflow file, or provided by the host application, e.g., the command line tool or a servlet.
<config>
<import class="nl.mpi.tla.flat.deposit.context.Environment" prefix="env-"/>
<import class="nl.mpi.tla.flat.deposit.context.SystemProperties" prefix="sys-"/>
<property name="home" value="/app/flat" uniq="true"/>
<property name="base" value="{$home}/deposit" uniq="true"/>
<property name="bag" value="{$base}/bags/{$sip}" uniq="true"/>
...
</config>
In this example environment variables are imported with the prefix env-
, e.g., env-HOME
, and Java system properties with the prefix sys-
. An import is handled by a Java class (indicated by the class
attribute), which are dynamically loaded, i.e., its easy to add a new one. An import class needs to implement the nl.mpi.tla.flat.deposit.context.ImportPropertiesInterface
interface and be available in the Java classpath.
Properties have a name and a value. Within curly braces ({}
inspired by XSLT's AVTs) an XPath 2.0 expression can be used. Previously declared properties are available as variables in these expressions and one can use the rich set of XPath 2.0 functions and operators if any processing is required. If needed its even possible to use and add extension functions (see SaxonExtensionFunctions.java
for some examples). The uniq
attribute is used to indicate if a property should be unique, i.e., not be declared again and if this does happen an error will be raised.
The other sections of the workflow file contain declarations of action invocations:
<init>
<action name="log setup" class="nl.mpi.tla.flat.deposit.action.WorkspaceLogSetup">
<parameter name="dir" value="{$work}/logs"/>
</action>
<action name="check workspace" class="nl.mpi.tla.flat.deposit.action.SIPLoad">
<parameter name="sip" value="{$work}/metadata/record.cmdi"/>
</action>
</init>
An action is implemented by a class (indicated by the class
attribute), which should implement the nl.mpi.tla.flat.deposit.action.ActionInterface
interface or, more conveniently, subclass the nl.mpi.tla.flat.deposit.action.AbstractAction
abstract class and be available on the Java classpath. Many examples are available in src/main/java/nl/mpi/tla/flat/deposit/action.
The action invocation will receive the specified parameters. A parameter is specified similarily to the properties in the configuration section. The values can potentially be constructed dynamically, i.e., by using the AVTs. The variables available in the AVTs are the global properties, i.e., not any parameters (from previously run actions).
This section contains a list of currently available actions. They are not listed in alfabetical order, but in more in the order they would make sense in a workflow. Most of them are generic, but others are repostory or even institute specific and are likely to move to an own repository in the future.
parameter | default | cardinality | notes |
---|---|---|---|
dir |
./logs |
? | directory will be created if it doesn't exist already |
Will create a logback configuration that will create two log files for the workflow in the specified directory:
devel.log
: contains any log message issues during the worflow executionuser-log-events.xml
: contains any INFO, WARN and ERROR log messages (to get wellformed XML access this log file using theuser-log.xml
wrapper)
NOTES
- best be used a the first action in the
init
section of the workflow - a Mapped Diagnoctic Context (MDC) is created so only the log messages of the thread running the workflow end up in the log files.
- see WorkspaceLogCleanup (mandatory, later)
parameter | default | cardinality | notes |
---|---|---|---|
sip |
./metadata/record.cmdi |
? |
Load a CMD record as a SIP.
NOTES:
- best be used in the
init
section of the workflow, so the SIP is loaded even if only some of the main actions are requested - the DoorKeeper interacts with a SIP through the
nl.mpi.tla.flat.deposit.sip.SIPInterface
interface, so its possible to use other SIP specifications than CMDI
parameter | default | cardinality | notes |
---|---|---|---|
dir |
./resources |
? | directory will be created if it doesn't exist already |
prefix |
foo |
? | handle prefix |
Copies (remote) resources into the working directory.
TODO:
- limit the remote download locations
- limit the directories in which local resouces can live, so one can't submit a SIP that would create a security leak
- check that all resources are available and accessible
parameter | default | cardinality | notes |
---|---|---|---|
schemaCache |
./cache |
? | directory will be created if it doesn't exist already |
rules |
? | should point to a Schematron file |
Validate the SIP document against its XML Schema, which should be specified in a @xsi:schemaLocation
. Optionally additional validation can be done against a set of Schematron rules. Validation errors will lead to failure of the action. Both errors and warnings will be logged.
NOTES:
- checks any XML document against its schema, so needs a Schematron rule to check that the file has actually the right type!
parameter | default | cardinality | notes |
---|---|---|---|
fitsService |
1 | ||
mimetypes |
1 | should point to a valid mimetypes file |
FITS is a library (also accessable via a command line tool or servlet) to identify, validate and extract technical metadata for a wide range of file formats. This action will identify and validate all resources in the SIP against a FITS server. The identified MIME type of a resource is checked against the specified list of allowed MIME types.
NOTES:
- if the MIME type is faulty specified by the SIP a warning will be issued and the faulty MIME type overwritten
<?xml version="1.0" encoding="UTF-8"?>
<mimetypes>
<mimetype value="application/pdf"/>
<mimetype value="text/plain"/>
<mimetype value="image/jpg"/>
</mimetypes>
parameter | default | cardinality | notes |
---|---|---|---|
resourcesDir |
1 | directory will be created if it doesn't exist already | |
policyFile |
1 | should point to a valid policy file | |
xpathDatasetName |
1 | XPath 2.0 expression into the SIP XML specification |
Move resources that match the rules in the policy file to a subdirectory, dynamically named using the xpathDatasetName
in the (persistent) resource directory.
<?xml version="1.0" encoding="UTF-8"?>
<persistence-policies>
<persistence-policy property="mimetype" regex="^.+/pdf$" target="{$dataset_name}/pdf"/>
<persistence-policy property="mimetype" regex="^text/.+$" target="{$dataset_name}/text"/>
<default-persistence-policy target="{$dataset_name}/default"/>
</persistence-policies>
NOTES:
- the action could be extended to match additional (technical) properties of a resource
parameter | default | cardinality | notes |
---|---|---|---|
prefix |
1 |
Assigns handles to the SIP and its resources.
NOTES:
- the handles are not created by this action!
- see EPICHandleCreation (mandatory, later)
TODO:
- validate that the assigned handle doesn't exist yet (how can we "reserve" a handle globally?)
parameter | default | cardinality | notes |
---|---|---|---|
policy |
./metadata/policy.n3 |
? | should point to a valid WebAccessControl file |
dir |
./acl |
? | directory will be created if it doesn't exist already |
Converts a WebAccessControl file into a set of XACML policies, i.e., one for each resource in the SIP, in the specified directory. It will also extract the user profile of the owner into an owner.xml
in the specified directory. This profile can be used by subsequent actions that need info on the owner.
The policy file should be based on the WebAccessControl W3C proposal. Here are some common patterns:
- a public SIP
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
# make the whole SIP public
[acl:accessTo <sip>; acl:mode acl:Read; acl:agentClass foaf:Agent].
#give the owner read and write access
[acl:accessTo <sip>; acl:mode acl:Read, acl:Write; acl:agent <#owner>].
# the owner
<#owner> a foaf:Person ;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "[email protected]"].
- a private SIP with a public resource
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
# make a specific resource (identified by the ID of the ResourceProxy) in the SIP public
[acl:accessTo <sip#h1>; acl:mode acl:Read; acl:agentClass foaf:Agent].
# give the owner read and write access
[acl:accessTo <sip>; acl:mode acl:Read, acl:Write; acl:agent <#owner>].
# the owner
<#owner> a foaf:Person ;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "[email protected]"].
- a private SIP with a shared resource
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
# make a specific resource (identified by the ID of the ResourceProxy) in the SIP accessible to a specific user
[acl:accessTo <sip#h1>; acl:mode acl:Read; acl:agent <#other1>].
# a colleague
<#other1> a foaf:Person ;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "[email protected]"].
# give the owner read and write access
[acl:accessTo <sip>; acl:mode acl:Read, acl:Write; acl:agent <#owner>].
# the owner
<#owner> a foaf:Person ;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "[email protected]"].
- an academic SIP
@prefix acl: <http://www.w3.org/ns/auth/acl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
# make the whole SIP available to academics
[acl:accessTo <sip>; acl:mode acl:Read; acl:agentClass <#academic>].
#give the owner read and write access
[acl:accessTo <sip>; acl:mode acl:Read, acl:Write; acl:agent <#owner>].
# academics (= the drupal role of 'authenticated user')
<#academic> a foaf:Group;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "authenticated user"].
# the owner
<#owner> a foaf:Person ;
foaf:account [foaf:accountServiceHomepage <#flat>; foaf:accountName "[email protected]"].
<user>
<name>[email protected]</name>
</user>
parameter | default | cardinality | notes |
---|---|---|---|
owner |
1 | the user profile of the owner | |
fedoraConfig |
1 | path to a valid Fedora Commons configuration | |
cmd2fox |
1 | should point to a valid XSLT 2.0 stylesheet | |
jar_cmd2fox |
? | used to resolve the include of jar:cmd2fox.xsl, which is the main cmd2fox.xsl embedded in LAT2FOX, should point to a valid XSLT 2.0 stylesheet. Not needed when the cmd2fox XSL doesn't use this include! | |
dir |
./fox |
? | directory will be created if it doesn't exist already |
policies |
* | should point to directories containing valid XACML policy files (see ACL) | |
management |
* | should point to directories containing managenent files | |
icons |
/app/flat/icons |
? | directory where the icons are found |
collections-map |
? | a collections map to dynamically determine the collection the SIP is a member of, if there are no explicit memberships in the SIP itself | |
oai-include-eval |
true() |
? | XPath 2.0 expression to determine if a SIP should be available via OAI-PMH |
always-collection-eval |
false() |
? | XPath 2.0 expression to determine if a SIP should always get the islandora:collectionCModel , if false this only happens when a SIP already refers to other SIPs |
always-compound-eval |
false() |
? | XPath 2.0 expression to determine if a SIP should always get the islandora:compoundCModel , if false this only happens when a SIP contains resources |
Uses the XSLT stylesheets, where (optionally) jar_cmd2fox
is included into cmd2fox
as jar:cmd2fox.xsl
, to convert the SIP XML specification into a set of FOXML files, which are stored into the specified directory.
If a policy file exists for the SIP and/or a resource in one of the policies directories it will be included in the FOXML.
If a management file exists for the SIP its included in the MGMT datastream. This stream is meant to contain collection management specific info, e.g., curation notes, and is only accessible for users with a data manager or administrator role.
NOTES:
- for a SIP a specific access policy based on its Fedora ID (+
.xml
) is looked for, if it doesn't exist it fallsback todefault-cmd-policy.xml
or evendefault-policy.xml
- for a resource a specific access policy based on its Fedora ID (+
.xml
) is looked for, if it doesn't exist it fallsback todefault-resource-policy.xml
or evendefault-policy.xml
- for a SIP a specific management file based on its Fedora ID (+
.xml
) is looked for - a management file should be a valid Java XML properties file
- see ACL (optional, earlier)
- see FedoraInteract (mandatory, later)
TODO:
- should be less CMDI/
jar:cmd2fox.xsl
specific, e.g., the documented parameter behaviour depends actually on the XSLT used - hide away
relations
Each collection in the collections map contains an XPath 2.0 expression, which is evaluated against the SIP. If the evaluation returns true the SIP is a potential member of that collection. If it actually will be is determined by the mode:
first
: the SIP becomes a member of the first collectionall
(default): the SIP becomes a member of all the collections
When there is no potential collection the, optional, default collection is taken or the SIP becomes a member of the fallback islandora:compound_collection
collection.
<map xmlns:cmd="http://www.clarin.eu/cmd/" mode="all">
<default pid="lat:collection_meertens"/>
<!--
Papieren collecties: 0-1000,
Digitale collecties: 1001-1999 en 3000-e.v.,
Audio collecties: 2000 – 2999.
-->
<collection pid="lat:collection_paper">
<xpath>exists(/cmd:CMD/cmd:Components/cmd:MeertensCollection/cmd:CoreCollectionInformation
[number(cmd:collectionID) le 1000])</xpath>
</collection>
<collection pid="lat:collection_digital">
<xpath>exists(/cmd:CMD/cmd:Components/cmd:MeertensCollection/cmd:CoreCollectionInformation
[(number(cmd:collectionID) ge 1001 and number(cmd:collectionID) le 1999) or (number(cmd:collectionID) ge 3000)])</xpath>
</collection>
<collection pid="lat:collection_audio">
<xpath>exists(/cmd:CMD/cmd:Components/cmd:MeertensCollection/cmd:CoreCollectionInformation
[number(cmd:collectionID) ge 2000 and number(cmd:collectionID) le 2999])</xpath>
</collection>
<!-- CLARIN-NL -->
<!-- - DBD -->
<collection pid="hdl:10744/cff73032-1005-4347-a1f0-e840793822cd">
<xpath>exists(/cmd:CMD/cmd:Components/cmd:DBD)</xpath>
<policy type="resource">public-resource-policy.xml</policy>
</collection>
<!-- - NEHOL -->
<collection pid="hdl:10744/e0e0253e-94d9-4d1f-90a8-4ad2464ed794">
<xpath>exists(/cmd:CMD/cmd:Components/(cmd:lat-corpus|cmd:lat-session))</xpath>
<policy type="resource">public-resource-policy.xml</policy>
</collection>
<!-- - D-LUCEA -->
<collection pid="hdl:10744/dcd5f7ad-da56-4a73-9f57-510a628879ba">
<xpath>exists(/cmd:CMD/cmd:Components/(cmd:collection|cmd:lucea))</xpath>
<policy type="resource">public-resource-policy.xml</policy>
</collection>
<!-- Roots of Ethnolect -->
<collection pid="hdl:10744/682ea992-b567-4c02-8f94-8291d8610ef5">
<xpath>exists(/cmd:CMD/cmd:Components/cmd:EthnolectConversation)</xpath>
</collection>
</map>
parameter | default | cardinality | notes |
---|---|---|---|
dir |
1 | ||
bags |
1 | ||
creator |
? | ||
audience |
? | ||
accessRights |
? |
Creates an EASY Bag for this SIP for a backup deposit to DANS via SWORD.
NOTES:
- the FOXML file is used to pick up the Dublin Core metadata generated before
- this just creates the ZIPped BAG, the actual upload to DANS is a separate (batch) process
parameter | default | cardinality | notes |
---|---|---|---|
user |
1 | an user profile | |
fedoraConfig |
1 | path to a valid Fedora Commons configuration | |
userFedoraConfig |
1 | path to the to be created user-specific Fedora Commons configuration | |
drupal |
1 | Drupal directory where Islandora is installed | |
drush |
1 | path to the drush command |
Looks up the Drupal (hashed) password of the user and creates a Fedora Commons configuration that allows to login as that user and thus actions take place with permissions of this user and the user will associated with them in the audit trail.
NOTES:
- see FedoraInteract (optional, later)
<FedoraCommons>
<localServer>https://localhost:8443/fedora</localServer>
<publicServer>http://localhost/flat</publicServer>
<userName>fedoraAdmin</userName>
<userPass>fedora</userPass>
<trustStore>/opt/jssecacerts</trustStore>
<trustStorePass>changeit</trustStorePass>
</FedoraCommons>
parameter | default | cardinality | notes |
---|---|---|---|
dir |
./fox |
? | directory will be created if it doesn't exist already |
prefix |
1 | path to a valid Fedora Commons configuration | |
new-pid-eval |
? | XPath 2.0 expression to determine if a new PID should be assigned to a collection |
Updates the CMD collection to which the SIP should belong, if a new PID is assigned to this collection it will also update its parent CMD collection (and so on to potentially the root collection)
NOTES:
- see FedoraInteract (optional, later)
parameter | default | cardinality | notes |
---|---|---|---|
fedoraConfig |
1 | path to a valid Fedora Commons configuration | |
dir |
./fox |
? | |
namespace |
lat |
? |
Loads all the Digital Objects or datastreams from files in the specified directory and loads them into the specified Fedora Commons repository. After this the URLs for the datastreams to which the assigned handles can resolve are known.
Files that match the following pattern are expected to be FOXML files that describe a new Digital Object: ${namespace}_[A-Za-z0-9_]+\.xml
(basically <fid>.xml
with nasty characters replaced by _
)
Files that match the following pattern are expected to be updates of an existing data stream: ${namespace}_[A-Za-z0-9_]+\.[A-Z]+\.[A-Za-z0-9_]+
(basically <fid>.<dsid>.<ext>
with nasty characters replaced by _
)
NOTES:
- see FedoraUser (optional, earlier)
- see HandleAssignment (optional, earlier)
- see CreateFOX (mandatory, earlier)
- see UpdateCollections (optional, earlier)
- see EPICHandleCreation (optional, later)
TODO:
- validate the FOXML files
- make it possible to load the credentials from a separate file
parameter | default | cardinality | notes |
---|---|---|---|
fedoraConfig |
1 | path to a valid Fedora Commons configuration | |
epicConfig |
1 | should point to a valid EPIC config file |
Creates or updates the assigned handles for the SIP, its resources and collections and makes them redirect to the right datastreams stored in the Fedora Commons repository.
NOTES:
- to actually create handles the status in the EPIC configuration should be
production
, i.e., nottest
. - see HandleAssignment (mandatory, earlier)
- see FedoraInteract (mandatory, earlier)
<PIDService>
<hostName>www.pidconsortium.eu</hostName>
<URI>http://www.pidconsortium.eu/</URI>
<HandlePrefix>12345</HandlePrefix>
<userName>epic</userName>
<password>test</password>
<email>[email protected]</email>
<status>test</status>
</PIDService>
parameter | default | cardinality | notes |
---|---|---|---|
gsearchServer |
1 | ||
gsearchUser |
1 | ||
gsearchPassword |
1 |
Triggers indexing the deposited SIP using gsearch.
NOTES:
- see FedoraInteract (mandatory, earlier)
parameter | default | cardinality | notes |
---|---|---|---|
config |
1 | path to a Mail config file | |
subject |
1 | fixed part of the mail subject | |
template |
1 | path to a Mail exception template XSLT file | |
tmpl-bag |
1 | ||
tmpl-user |
1 |
Sends out emails on successful and/or failed Doorkeeper runs
<mailConfig>
<sendWhenSuccess>true</sendWhenSuccess> <!-- On successful ingest: true- email sent , false- No email sent -->
<sendOnFailedValidation>true</sendOnFailedValidation><!-- On an unsuccessful validation: true- email sent , false- No email sent -->
<server>mailhost.example.com</server>
<port>25</port>
<user></user>
<password></password>
<from>[email protected]</from>
<repo>[The Archive]</repo>
<to>[email protected]</to>
</mailConfig>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmd="http://www.clarin.eu/cmd/" xmlns:lat="http://lat.mpi.nl/" version="2.0">
<xsl:param name="bag"/>
<xsl:param name="sip"/>
<xsl:param name="user"/>
<xsl:param name="exception"/>
<xsl:param name="stacktrace"/>
<xsl:param name="repo"/>
<xsl:param name="outcome"/>
<xsl:param name="handle"/>
<xsl:output method="html" encoding="UTF-8"/>
<xsl:template match="/">
<p>
<b> <xsl:text> The result of the deposit: </xsl:text> </b>
<xsl:value-of select="$outcome"/>
<br/>
<xsl:if test="normalize-space($user)!=''">
<b><xsl:text> User: </xsl:text></b>
<xsl:value-of select="$user"/>
<br/>
</xsl:if>
<b><xsl:text> SIP: </xsl:text></b>
<xsl:value-of select="$sip"/>
<br/>
<xsl:variable name="localURI" select="(/cmd:CMD/cmd:Resources/cmd:ResourceProxyList/cmd:ResourceProxy/cmd:ResourceRef/@lat:localURI)[1]"/>
<xsl:if test="normalize-space($localURI)!=''">
<b> <xsl:text> Data Location: </xsl:text> </b>
<xsl:value-of select="replace(resolve-uri($localURI,base-uri()),'(.*)/.*','$1')"/>
<br/>
</xsl:if>
<xsl:if test="normalize-space($handle)!=''">
<b> <xsl:text> Handle: </xsl:text> </b>
<xsl:value-of select="$handle"/>
<br/>
</xsl:if>
</p>
<p>
<xsl:if test="normalize-space($exception)!=''">
<b><xsl:text>Exception: </xsl:text></b>
<xsl:value-of select="$exception"/>
<br/>
<br/>
<b><xsl:text>Detailed:</xsl:text></b>
<xsl:value-of select="$stacktrace"/>
</xsl:if>
</p>
</xsl:template>
</xsl:stylesheet>
parameter | default | cardinality | notes |
---|---|---|---|
props |
1 | should point to a valid properties file from the SWORD deposit of the processed SIP |
If the properties file is found (otherwise the action will pass by silently) the state.label
is updated to
FAILED
if the deposit has failed due to an exceptionREJECTED
if an action in the main workflow failedARCHIVED
if the workflow was succesful
NOTES:
- best be used as an action in the
final
section of the workflow
parameter | default | cardinality | notes |
---|
Will remove the active log setup, i.e., the MDC associated with the thread that executed the workflow.
NOTES:
- best be used as the last action in the
final
section of the workflow - see WorkspaceLogSetup (mandatory, earlier)
Here is a complete example taken from the FLAT DoorKeeper Docker setup:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:flat="java:nl.mpi.tla.flat">
<config>
<import class="nl.mpi.tla.flat.deposit.context.Environment" prefix="env-"/>
<import class="nl.mpi.tla.flat.deposit.context.SystemProperties" prefix="sys-"/>
<property name="fitsService" value="http://localhost:8080/fits/" uniq="true"/>
<property name="home" value="/app/flat" uniq="true"/>
<property name="base" value="{$home}/deposit" uniq="true"/>
<property name="bag" value="{$base}/bags/{$sip}" uniq="true"/>
<property name="work" value="{flat:findBagBase($bag)}" uniq="true"/>
<property name="easy" value="{$base}/easy" uniq="true"/>
<property name="epicPrefix" value="12345"/>
<property name="gsearchUser" value="fgsAdmin"/>
<property name="gsearchPassword" value="fgsAdmin"/>
<property name="gsearchServer" value="http://localhost:8080/fedoragsearch"/>
</config>
<init>
<action name="log setup" class="nl.mpi.tla.flat.deposit.action.WorkspaceLogSetup">
<parameter name="dir" value="{$work}/logs"/>
</action>
<action name="check workspace" class="nl.mpi.tla.flat.deposit.action.SIPLoad">
<parameter name="sip" value="{$work}/metadata/record.cmdi"/>
</action>
</init>
<main>
<action name="assemble package" class="nl.mpi.tla.flat.deposit.action.PackageAssembly">
<parameter name="dir" value="{$work}/resources"/>
<parameter name="prefix" value="{$epicPrefix}"/>
</action>
<action name="validate metadata" class="nl.mpi.tla.flat.deposit.action.Validate">
<parameter name="schemaCache" value="{$base}/cache/schemas"/>
<parameter name="rules" value="{$base}/policies/rules.sch"/>
</action>
<action name="validate resources" class="nl.mpi.tla.flat.deposit.action.FITS">
<parameter name="fitsService" value="{$fitsService}"/>
<parameter name="mimetypes" value="{$base}/policies/fits-mimetypes.xml"/>
</action>
<action name="persist resources" class="nl.mpi.tla.flat.deposit.action.Persist">
<parameter name="resourcesDir" value="{$work}/resources"/>
<parameter name="policyFile" value="{$base}/policies/persistence-policy.xml"/>
<parameter name="xpathDatasetName" value="replace(//*[name()='MdSelfLink'], 'hdl:{$epicPrefix}/','')"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.HandleAssignment">
<parameter name="prefix" value="{$epicPrefix}"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.ACL">
<parameter name="policy" value="{$work}/metadata/policy.n3"/>
<parameter name="dir" value="{$work}/acl"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.CreateFOX">
<parameter name="owner" value="{$work}/acl/owner.xml"/>
<parameter name="fedoraConfig" value="{$base}/policies/fedora-config.xml"/>
<parameter name="cmd2fox" value="{$base}/policies/cmd2dc.xsl"/>
<parameter name="jar_cmd2fox" value="{$base}/transforms/cmd2fox.xsl"/>
<parameter name="dir" value="{$work}/fox"/>
<parameter name="policies" value="{$work}/acl"/>
<parameter name="policies" value="{$home}/policies"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.EasyBag">
<parameter name="bags" value="{$easy}"/>
<parameter name="foxes" value="{$work}/fox"/>
<parameter name="creator" value="{$base}/policies/easy-bag-creator.xml"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.FedoraUser">
<parameter name="user" value="{$work}/acl/owner.xml"/>
<parameter name="fedoraConfig" value="{$base}/policies/fedora-config.xml"/>
<parameter name="userFedoraConfig" value="{$work}/acl/fedora-config.xml"/>
<parameter name="drupal" value="/var/www/html/flat"/>
<parameter name="drush" value="/var/www/composer/vendor/drush/drush/drush"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.UpdateCollections">
<parameter name="fedoraConfig" value="{$work}/acl/fedora-config.xml"/>
<parameter name="dir" value="{$work}/fox"/>
<parameter name="prefix" value="{$epicPrefix}"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.FedoraInteract">
<parameter name="fedoraConfig" value="{$work}/acl/fedora-config.xml"/>
<parameter name="dir" value="{$work}/fox"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.EPICHandleCreation">
<parameter name="fedoraConfig" value="{$base}/policies/fedora-config.xml"/>
<parameter name="epicConfig" value="{$base}/policies/epic-config.xml"/>
</action>
<action class="nl.mpi.tla.flat.deposit.action.Index">
<parameter name="gsearchServer" value="{$gsearchServer}"/>
<parameter name="gsearchUser" value="{$gsearchUser}"/>
<parameter name="gsearchPassword" value="{$gsearchPassword}"/>
</action>
</main>
<exception>
</exception>
<final>
<!--
<action class="nl.mpi.tla.flat.deposit.action.Mail">
<parameter name="config" value="{$base}/policies/mail-config.xml"/>
<parameter name="subject" value=": deposit for user "/>
<parameter name="template" value="{$base}/policies/mail-exception.xsl"/>
<parameter name="tmpl-bag" value="{$bag}"/>
<parameter name="tmpl-user" value="{if (sx:fileExists(concat('file:',$work,'/acl/owner.xml') cast as xs:anyURI)) then (doc(concat($work,'/acl/owner.xml'))/user/name) else ('')}"/>
</action>
-->
<action name="status" class="nl.mpi.tla.flat.deposit.action.UpdateSwordStatus">
<parameter name="props" value="{$work}/../../deposit.properties"/>
</action>
<action name="log teardown" class="nl.mpi.tla.flat.deposit.action.WorkspaceLogCleanup"/>
</final>
</flow>