}\r
\r
@Override\r
-- public ClientResponse<String> updateWorkflow(String csid, PoxPayloadOut xmlPayload) {\r
-- return getProxy().updateWorkflow(csid, xmlPayload.getBytes());\r
++ public ClientResponse<String> updateWorkflowWithTransition(String csid, String workflowTransition) {\r
++ return getProxy().updateWorkflowWithTransition(csid, workflowTransition);\r
} \r
\r
/*\r
@Path("/{vcsid}/items/{csid}")\r
ClientResponse<String> readItem(@PathParam("vcsid") String vcsid,\r
@PathParam("csid") String csid,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
//(U)pdate Item\r
@PUT\r
ClientResponse<AuthorityRefDocList> getReferencingObjects(\r
@PathParam("csid") String parentcsid,\r
@PathParam("itemcsid") String itemcsid,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
// List Item Authority References\r
@GET\r
@GET\r
@Path("/urn:cspace:name({name})")\r
ClientResponse<String> readByName(@PathParam("name") String name,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
/*\r
* Item subresource methods\r
@Path("/{vcsid}/items/urn:cspace:name({specifier})")\r
ClientResponse<String> readNamedItem(@PathParam("vcsid") String vcsid,\r
@PathParam("specifier") String specifier,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
//(R)ead Item In Named Authority\r
@GET\r
@Path("/urn:cspace:name({specifier})/items/{csid}")\r
ClientResponse<String> readItemInNamedAuthority(@PathParam("specifier") String specifier,\r
@PathParam("csid") String csid,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
//(R)ead Named Item In Named Authority\r
@GET\r
@Path("/urn:cspace:name({specifier})/items/urn:cspace:name({itemspecifier})")\r
ClientResponse<String> readNamedItemInNamedAuthority(@PathParam("specifier") String specifier, \r
@PathParam("itemspecifier") String itemspecifier,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
/*\r
* Item subresource List methods\r
@PathParam("csid") String vcsid,\r
@QueryParam (IQueryManager.SEARCH_TYPE_PARTIALTERM) String partialTerm,\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
// List Items for a named authority matching a partial term or keywords.\r
@GET\r
@PathParam("specifier") String specifier,\r
@QueryParam (IQueryManager.SEARCH_TYPE_PARTIALTERM) String partialTerm,\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
/*\r
* Workflow related methods\r
*/
public ClientResponse<String> getWorkflow(String csid);
-- public ClientResponse<String> updateWorkflow(String csid, PoxPayloadOut xmlPayload);
++ public ClientResponse<String> updateWorkflowWithTransition(String csid, String workflowTransition);
/**
* Gets the authority refs.
@GET\r
@Produces({"application/xml"})\r
ClientResponse<AbstractCommonList> readIncludeDeleted(\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
@Override\r
@GET\r
@Produces({"application/xml"})\r
ClientResponse<AbstractCommonList> keywordSearchIncludeDeleted(\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
@Override\r
@GET\r
@Produces({ "application/xml" })\r
ClientResponse<AbstractCommonList> advancedSearchIncludeDeleted(\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_AS) String whereClause,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
}\r
@Path("/{csid}")\r
ClientResponse<String> readIncludeDeleted(\r
@PathParam("csid") String csid,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
// (U)pdate\r
@PUT\r
@GET\r
@Produces({ "application/xml" })\r
ClientResponse<LT> readIncludeDeleted(\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
/**\r
* Keyword search.\r
* \r
* @param keywords\r
* keywords on which to search\r
-- * @param includeDeleted\r
++ * @param workflowState\r
* @return the client response\r
*/\r
@GET\r
@Produces({ "application/xml" })\r
ClientResponse<LT> keywordSearchIncludeDeleted(\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
@GET\r
@Produces({ "application/xml" })\r
ClientResponse<LT> advancedSearchIncludeDeleted(\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_AS) String whereClause,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
}\r
@PUT\r
@Produces({"application/xml"})\r
@Consumes({"application/xml"}) \r
-- @Path("{csid}" + WorkflowClient.SERVICE_PATH)\r
-- ClientResponse<String> updateWorkflow(@PathParam("csid") String csid, byte[] xmlPayload);\r
++ @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}")\r
++ ClientResponse<String> updateWorkflowWithTransition(@PathParam("csid") String csid, @PathParam("transition") String transition);\r
\r
/*\r
* (R)read List operations\r
int existingTestCreated = allResourceIdsCreated.size(); // assumption is that no other test created records were soft deleted
String csid = allResourceIdsCreated.get(existingTestCreated - 1); //0-based index to get the last one added
this.setupUpdate();
-- this.updateLifeCycleState(testName, csid, WorkflowClient.WORKFLOWSTATE_DELETED);
++ this.updateLifeCycleState(testName, csid, WorkflowClient.WORKFLOWTRANSITION_DELETE, WorkflowClient.WORKFLOWSTATE_DELETED);
//
// Read the list of existing non-deleted records
//
int existingTestCreated = allResourceIdsCreated.size(); // assumption is that no other test created records were soft deleted
String csid = allResourceIdsCreated.get(existingTestCreated - 1); //0-based index to get the last one added
this.setupUpdate();
-- this.updateLifeCycleState(testName, csid, WorkflowClient.WORKFLOWSTATE_DELETED);
++ this.updateLifeCycleState(testName, csid, WorkflowClient.WORKFLOWTRANSITION_DELETE, WorkflowClient.WORKFLOWSTATE_DELETED);
//
// Search for the newly-created records, excluding the soft deleted record.
@SuppressWarnings("rawtypes")
-- protected void updateLifeCycleState(String testName, String resourceId, String lifeCycleState) throws Exception {
++ protected void updateLifeCycleState(String testName, String resourceId, String workflowTransition, String lifeCycleState) throws Exception {
//
// Read the existing object
//
// Perform the update
//
WorkflowCommon updatedWorkflowCommons = null;
-- res = client.updateWorkflow(resourceId, output);
++ res = client.updateWorkflowWithTransition(resourceId, workflowTransition);
try {
assertStatusCode(res, testName);
PoxPayloadIn input = new PoxPayloadIn(res.getEntity());
//
// Workflow states
//
++ public static final String WORKFLOWTRANSITION_UNDELETE = "undelete";
++ public static final String WORKFLOWTRANSITION_DELETE = "delete";
public static final String WORKFLOWSTATE_DELETED = "deleted";
-- public static final String WORKFLOWSTATE_PROJECT = "project";
- public static final String WORKFLOWSTATE_APPROVED = "approved";
- public static final String WORKFLOWSTATE_APPROVED = "approved";
++
++ public static final String WORKFLOWSTATE_ACTIVE = "active";
++
++ public static final String WORKFLOWTRANSITION_LOCK = "lock";
++ public static final String WORKFLOWSTATE_LOCKED = "locked";
+ //
+ // DocumentHandler passed properties
+ //
+ public static final String TRANSITION_ID = "transition_id";
//
// Service Query Params
//
-- public static final String WORKFLOW_QUERY_NONDELETED = "wf_deleted";
++ public static final String WORKFLOW_QUERY_NONDELETED = "wf_deleted";
++ public static final String WORKFLOWSTATE_QUERY = "wf_deleted";
@Override
<client-class>org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl</client-class>
<properties>
<types:item><types:key>pageSizeDefault</types:key><types:value>40</types:value></types:item>
++ <types:item><types:key>refreshAuthZOnStartup</types:key><types:value>true</types:value></types:item>
</properties>
</repository-client>
<types:key>authRef</types:key>
<types:value>taxonomicIdentGroupList/*/institution</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>annotationGroupList/*/annotationAuthor</types:value>
</types:item>
<!-- Object Identification Information group -->
<!-- There are currently no authority term references in this group -->
<!-- Object Description Information group -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentActivities|contentActivity</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentConcepts|contentConcept</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Subject authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentEventNameGroupList/*/contentEventName</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentEventNameGroupList/*/contentEventNameType</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentOrganizations|contentOrganization</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept OR Subject authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentOtherGroupList/*/contentOther</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentOtherGroupList/*/contentOtherType</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <!-- Uncomment when People authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentPeoples|contentPeople</types:value>
- </types:item>
+ </types:item
+ -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>contentPersons|contentPerson</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>textualInscriptionGroupList/*/inscriptionContentInscriber</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>textualInscriptionGroupList/*/inscriptionContentMethod</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>nonTextualInscriptionGroupList/*/inscriptionDescriptionInscriber</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>nonTextualInscriptionGroupList/*/inscriptionDescriptionMethod</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>materialGroupList/*/material</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>materialGroupList/*/materialSource</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>styles|style</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>objectComponentGroupList/*/objectComponentName</types:value>
</types:item>
+ -->
+
<!-- Object Production Information group -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>objectProductionOrganizationGroupList/*/objectProductionOrganization</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when People authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>objectProductionPeopleGroupList/*/objectProductionPeople</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>objectProductionPersonGroupList/*/objectProductionPerson</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>assocOrganizationGroupList/*/assocOrganization</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when People authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>assocPeopleGroupList/*/assocPeople</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ -->
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>assocPersonGroupList/*/assocPerson</types:value>
</types:item>
<!-- Object Viewer's Contribution Information group -->
<!-- There are currently no authority term references in this group -->
<!-- Reference Information group -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Citation authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>referenceGroupList/*/reference</types:value>
- </types:item>
+ </types:item
+ -->
<!-- Object Collection Information group -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>fieldCollectionPlace</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>fieldCollectors|fieldCollector</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Collecting Event authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>fieldColEventNames|fieldColEventName</types:value>
</types:item>
<types:key>termRef</types:key>
<types:value>assocActivityGroupList/*/assocActivity</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
- <types:key>termRef</types:key>
+ <types:key>authRef</types:key>
<types:value>assocConceptGroupList/*/assocConcept</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>termRef</types:key>
<types:value>assocCulturalContextGroupList/*/assocCulturalContext</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>fieldCollectors|fieldCollector</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Collecting Event authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
- <types:value>fieldCollectionEventNames|fieldCollectionEventName</types:value>
- </types:item>
+ <types:value>fieldCollectionEventNames|fieldCollectionEventName</types:value>
+ </types:item>
+ -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>valuer</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>rightsHolder</types:value>
</types:item>
- <!-- Subject Authority field -->
+ <!-- Uncomment when Subject authority is implemented in Services -->
+ <!--
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>subjectList|subject</types:value>
- </types:item>
+ </types:item
+ -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>measuredPartGroupList/*/dimensionSubGroupList/*/measuredBy</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>foundingPlace</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>groups|group</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>deathPlace</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Concept authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>groups|group</types:value>
</types:item>
<types:key>authRef</types:key>
<types:value>schoolsOrStyles|schoolOrStyle</types:value>
</types:item>
+ -->
<!-- Fields containing term list / controlled vocabulary references -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>termRef</types:key>
<types:value>salutation</types:value>
</types:item>
</tenant:serviceBindings>
<!-- end taxon service meta-data -->
- <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/conceptauthorities/*/workflow/</service:uriPath>
- <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/conceptauthorities/*/items/*/workflow/</service:uriPath>
+ <!-- begin conceptauthority service meta-data -->
+ <tenant:serviceBindings id="Conceptauthorities" name="Conceptauthorities" type="utility" version="0.1">
- <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
++ <service:uriPath xmlns:service="http://collectionspace.org/services/config/service">/conceptauthorities/*/workflow/</service:uriPath>
++ <service:uriPath xmlns:service="http://collectionspace.org/services/config/service">/conceptauthorities/*/items/*/workflow/</service:uriPath>
+ <!-- other URI paths through which this service could be accessed -->
+ <!--
- <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
- <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.concept.nuxeo.ConceptAuthorityDocumentModelHandler</service:documentHandler>
- <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/common/service">
++ <service:uriPath xmlns:service='http://collectionspace.org/services/config/service'>
+ /conceptauthorities/*/items/
+ </service:uriPath>
+ -->
- <service:initHandler xmlns:service="http://collectionspace.org/services/common/service">
++ <service:repositoryDomain xmlns:service="http://collectionspace.org/services/config/service">default-domain</service:repositoryDomain>
++ <service:documentHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.concept.nuxeo.ConceptAuthorityDocumentModelHandler</service:documentHandler>
++ <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/config/service">
+ <service:params>
+ <service:ListResultsFields>
+ <service:ListResultField>
+ <service:element>displayName</service:element>
+ <service:xpath>displayName</service:xpath>
+ </service:ListResultField>
+ <service:ListResultField>
+ <service:element>refName</service:element>
+ <service:xpath>refName</service:xpath>
+ </service:ListResultField>
+ <service:ListResultField>
+ <service:element>shortIdentifier</service:element>
+ <service:xpath>shortIdentifier</service:xpath>
+ </service:ListResultField>
+ <service:ListResultField>
+ <service:element>vocabType</service:element>
+ <service:xpath>vocabType</service:xpath>
+ </service:ListResultField>
+ </service:ListResultsFields>
+ </service:params>
+ </service:DocHandlerParams>
- <service:object xmlns:service="http://collectionspace.org/services/common/service" id="1" name="Conceptauthority" version="0.1">
++ <service:initHandler xmlns:service="http://collectionspace.org/services/config/service">
+ <service:classname>org.collectionspace.services.common.init.AddIndices</service:classname>
+ <service:params>
+ <service:field>
+ <service:table>conceptauthorities_common</service:table>
+ <service:col>displayname</service:col>
+ </service:field>
+ <service:field>
+ <service:table>conceptauthorities_common</service:table>
+ <service:col>shortidentifier</service:col>
+ </service:field>
+ </service:params>
+ </service:initHandler>
- <service:xmlContent namespaceURI="http://collectionspace.org/services/common/system" schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd" />
++ <service:object xmlns:service="http://collectionspace.org/services/config/service" id="1" name="Conceptauthority" version="0.1">
+ <service:part id="0" control_group="Managed" versionable="true" auditable="false" label="conceptauthorities-system" updated="" order="0">
+ <service:content contentType="application/xml">
- <service:repositoryDomain xmlns:service="http://collectionspace.org/services/common/service">default-domain</service:repositoryDomain>
- <service:documentHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.concept.nuxeo.ConceptDocumentModelHandler</service:documentHandler>
- <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/common/service">
++ <service:xmlContent namespaceURI="http://collectionspace.org/services/config/system" schemaLocation="http://collectionspace.org/services/config/system http://collectionspace.org/services/config/system/system-response.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="conceptauthorities_common" updated="" order="1">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/concept" schemaLocation="http://collectionspace.org/services/concept http://services.collectionspace.org/concept/conceptauthorities_common.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="2" control_group="Managed" versionable="true" auditable="false" label="collectionspace_core" updated="" order="2">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/collectionspace_core/" schemaLocation="http://collectionspace.org/collectionspace_core/ http://services.collectionspace.org/collectionspace_core.xsd" />
+ </service:content>
+ </service:part>
+ </service:object>
+ </tenant:serviceBindings>
+ <!-- end conceptauthority service meta-data -->
+
+ <!-- begin concept service meta-data.
+ Note there is no Concept service, but there is a
+ Repository workspace so we have to configure that.
+ -->
+ <tenant:serviceBindings id="Concepts" name="Concepts" type="authority" version="0.1">
- <service:validatorHandler xmlns:service="http://collectionspace.org/services/common/service">org.collectionspace.services.concept.nuxeo.ConceptValidatorHandler</service:validatorHandler>
- <service:initHandler xmlns:service="http://collectionspace.org/services/common/service">
++ <service:repositoryDomain xmlns:service="http://collectionspace.org/services/config/service">default-domain</service:repositoryDomain>
++ <service:documentHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.concept.nuxeo.ConceptDocumentModelHandler</service:documentHandler>
++ <service:DocHandlerParams xmlns:service="http://collectionspace.org/services/config/service">
+ <service:params>
+ <service:ListResultsFields>
+ <!-- Omit the standard AuthorityItem items (they are handled by the code) -->
+ <service:ListResultField>
+ <service:element>termType</service:element>
+ <service:xpath>termType</service:xpath>
+ </service:ListResultField>
+ </service:ListResultsFields>
+ </service:params>
+ </service:DocHandlerParams>
- <service:properties xmlns:service="http://collectionspace.org/services/common/service">
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
++ <service:validatorHandler xmlns:service="http://collectionspace.org/services/config/service">org.collectionspace.services.concept.nuxeo.ConceptValidatorHandler</service:validatorHandler>
++ <service:initHandler xmlns:service="http://collectionspace.org/services/config/service">
+ <service:classname>org.collectionspace.services.common.init.AddIndices</service:classname>
+ <service:params>
+ <service:field>
+ <service:table>concepts_common</service:table>
+ <service:col>inauthority</service:col>
+ </service:field>
+ <service:field>
+ <service:table>concepts_common</service:table>
+ <service:col>displayname</service:col>
+ </service:field>
+ <service:field>
+ <service:table>concepts_common</service:table>
+ <service:col>shortidentifier</service:col>
+ </service:field>
+ </service:params>
+ </service:initHandler>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
++ <service:properties xmlns:service="http://collectionspace.org/services/config/service">
++ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>objectNameProperty</types:key>
+ <types:value>displayName</types:value>
+ </types:item>
- <service:object xmlns:service="http://collectionspace.org/services/common/service" id="1" name="Conceptitem" version="0.1">
++ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>objectNumberProperty</types:key>
+ <types:value>shortIdentifier</types:value>
+ </types:item>
+ </service:properties>
- <service:xmlContent namespaceURI="http://collectionspace.org/services/common/system" schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd" />
++ <service:object xmlns:service="http://collectionspace.org/services/config/service" id="1" name="Conceptitem" version="0.1">
+ <service:part id="0" control_group="Managed" versionable="true" auditable="false" label="concepts-system" updated="" order="0">
+ <service:content contentType="application/xml">
- <service:properties xmlns:service="http://collectionspace.org/services/common/service">
++ <service:xmlContent namespaceURI="http://collectionspace.org/services/config/system" schemaLocation="http://collectionspace.org/services/config/system http://collectionspace.org/services/config/system/system-response.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="1" control_group="Managed" versionable="true" auditable="false" label="concepts_common" updated="" order="1">
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
++ <service:properties xmlns:service="http://collectionspace.org/services/config/service">
+ <!-- Fields containing term list / controlled vocabulary references -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
++ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>termRef</types:key>
+ <types:value>recordType</types:value>
+ </types:item>
++ <types:item xmlns:types="http://collectionspace.org/services/config/types">
+ <types:key>termRef</types:key>
+ <types:value>termStatus</types:value>
+ </types:item>
+ </service:properties>
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/services/concept" schemaLocation="http://collectionspace.org/services/concept http://services.collectionspace.org/concept/concepts_common.xsd" />
+ </service:content>
+ </service:part>
+ <service:part id="2" control_group="Managed" versionable="true" auditable="false" label="collectionspace_core" updated="" order="2">
+ <service:content contentType="application/xml">
+ <service:xmlContent namespaceURI="http://collectionspace.org/collectionspace_core/" schemaLocation="http://collectionspace.org/collectionspace_core/ http://services.collectionspace.org/collectionspace_core.xsd" />
+ </service:content>
+ </service:part>
+ </service:object>
+ </tenant:serviceBindings>
+ <!-- end concept service meta-data -->
+
<!-- begin acquisition service meta-data -->
<tenant:serviceBindings id="Acquisitions" name="Acquisitions" type="procedure" version="0.1">
- <service:uriPath xmlns:service="http://collectionspace.org/services/common/service">/acquisitions/*/workflow/</service:uriPath>
+ <service:uriPath xmlns:service="http://collectionspace.org/services/config/service">/acquisitions/*/workflow/</service:uriPath>
<!-- other URI paths through which this service could be accessed -->
<!--
- <service:uriPath xmlns:service='http://collectionspace.org/services/common/service'>
+ <service:uriPath xmlns:service='http://collectionspace.org/services/config/service'>
/acquisitions/*/authorityrefs/
</service:uriPath>
-->
<types:key>authRef</types:key>
<types:value>acquisitionSources|acquisitionSource</types:value>
</types:item>
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <!-- Uncomment when Collecting Event authority is implemented in Services -->
+ <!--
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>authRef</types:key>
<types:value>fieldCollectionEventNames|fieldCollectionEventName</types:value>
</types:item>
+ -->
<!-- Fields containing term list / controlled vocabulary references -->
- <types:item xmlns:types="http://collectionspace.org/services/common/types">
+ <types:item xmlns:types="http://collectionspace.org/services/config/types">
<types:key>termRef</types:key>
<types:value>acquisitionFundingList/*/acquisitionFundingCurrency</types:value>
</types:item>
package org.collectionspace.services.common.authorization_mgt;\r
\r
+ import java.sql.Connection;\r
+ import java.sql.PreparedStatement;\r
+ import java.sql.ResultSet;\r
+ import java.sql.SQLException;\r
+ import java.sql.Statement;\r
+ import java.util.ArrayList;\r
+ import java.util.Date;\r
+ import java.util.HashMap;\r
+ import java.util.Hashtable;\r
+ import java.util.List;\r
+ import java.util.UUID;\r
+ \r
+ import javax.naming.NamingException;\r
+ import javax.persistence.EntityManager;\r
+ import javax.persistence.EntityManagerFactory;\r
+ \r
+ import org.collectionspace.services.authorization.AuthZ;\r
+ import org.collectionspace.services.authorization.CSpaceAction;\r
+ import org.collectionspace.services.authorization.PermissionException;\r
+ import org.collectionspace.services.authorization.PermissionRole;\r
+ import org.collectionspace.services.authorization.PermissionRoleRel;\r
+ import org.collectionspace.services.authorization.PermissionValue;\r
+ import org.collectionspace.services.authorization.Role;\r
+ import org.collectionspace.services.authorization.RoleValue;\r
+ import org.collectionspace.services.authorization.SubjectType;\r
+ import org.collectionspace.services.authorization.URIResourceImpl;\r
+ import org.collectionspace.services.authorization.perms.ActionType;\r
+ import org.collectionspace.services.authorization.perms.EffectType;\r
+ import org.collectionspace.services.authorization.perms.Permission;\r
+ import org.collectionspace.services.authorization.perms.PermissionAction;\r
+ \r
+ import org.collectionspace.services.client.RoleClient;\r
+ import org.collectionspace.services.client.workflow.WorkflowClient;\r
+ import org.collectionspace.services.common.config.ServiceConfigUtils;\r
+ import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
++import org.collectionspace.services.common.context.ServiceBindingUtils;\r
+ import org.collectionspace.services.common.document.DocumentHandler;\r
+ import org.collectionspace.services.common.profile.Profiler;\r
+ import org.collectionspace.services.common.security.SecurityUtils;\r
+ import org.collectionspace.services.common.storage.DatabaseProductType;\r
+ import org.collectionspace.services.common.storage.JDBCTools;\r
+ import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;\r
+ import org.collectionspace.services.config.service.ServiceBindingType;\r
+ import org.collectionspace.services.config.tenant.TenantBindingType;\r
+ \r
+ import org.collectionspace.services.lifecycle.Lifecycle;\r
+ import org.collectionspace.services.lifecycle.TransitionDef;\r
+ import org.collectionspace.services.lifecycle.TransitionDefList;\r
+ \r
+ //import org.mortbay.log.Log;\r
+ import org.slf4j.Logger;\r
+ import org.slf4j.LoggerFactory;\r
+ \r
+ import org.springframework.security.acls.model.AlreadyExistsException;\r
+ \r
+ \r
public class AuthorizationCommon {\r
+ \r
++ final public static String REFRESH_AUTZ_PROP = "refreshAuthZOnStartup";\r
+ //\r
+ // ActionGroup labels/constants\r
+ //\r
+ \r
+ // for READ-WRITE\r
+ final public static String ACTIONGROUP_CRUDL_NAME = "CRUDL";\r
+ final public static ActionType[] ACTIONSET_CRUDL = {ActionType.CREATE, ActionType.READ, ActionType.UPDATE, ActionType.DELETE, ActionType.SEARCH};\r
+ // for READ-ONLY\r
+ final public static String ACTIONGROUP_RL_NAME = "RL";\r
+ final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};\r
+ \r
+ /*\r
+ * Inner class to deal with predefined ADMIN and READER action groupds\r
+ */\r
+ public class ActionGroup {\r
+ String name;\r
+ ActionType[] actions;\r
+ }\r
+ \r
+ static ActionGroup ACTIONGROUP_CRUDL;\r
+ static ActionGroup ACTIONGROUP_RL;\r
+ \r
+ // A static block to initialize the predefined action groups\r
+ static {\r
+ AuthorizationCommon ac = new AuthorizationCommon();\r
+ // For admin\r
+ ACTIONGROUP_CRUDL = ac.new ActionGroup();\r
+ ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;\r
+ ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;\r
+ // For reader\r
+ ACTIONGROUP_RL = ac.new ActionGroup();\r
+ ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;\r
+ ACTIONGROUP_RL.actions = ACTIONSET_RL;\r
+ \r
+ }\r
+ \r
+ final static Logger logger = LoggerFactory.getLogger(AuthorizationCommon.class);\r
+ \r
+ //\r
+ // The "super" role has a predefined ID of "0" and a tenant ID of "0";\r
+ //\r
+ final public static String ROLE_ADMINISTRATOR = "ADMINISTRATOR";\r
+ final public static String ROLE_ADMINISTRATOR_ID = "0";\r
+ final public static String ADMINISTRATOR_TENANT_ID = "0";\r
+ \r
+ final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";\r
+ final public static String ROLE_TENANT_READER = "TENANT_READER";\r
+ \r
+ public static final String TENANT_ADMIN_ACCT_PREFIX = "admin@"; \r
+ public static final String TENANT_READER_ACCT_PREFIX = "reader@"; \r
+ public static final String ROLE_PREFIX = "ROLE_"; \r
+ public static final String SPRING_ADMIN_ROLE = "ROLE_SPRING_ADMIN"; \r
+ public static final String TENANT_ADMIN_ROLE_SUFFIX = "_TENANT_ADMINISTRATOR"; \r
+ public static final String TENANT_READER_ROLE_SUFFIX = "_TENANT_READER"; \r
+ public static final String DEFAULT_ADMIN_PASSWORD = "Administrator";\r
+ public static final String DEFAULT_READER_PASSWORD = "reader";\r
\r
public static String ROLE_SPRING_ADMIN_ID = "-1";\r
- public static String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN"; \r
+ public static String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";\r
+ \r
+ public static Role getRole(String tenantId, String displayName) {\r
+ Role role = null;\r
+ \r
+ String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);\r
+ role = AuthorizationStore.getRoleByName(roleName, tenantId);\r
+ \r
+ return role;\r
+ }\r
+ \r
+ public static Role getRole(EntityManager em, String tenantId, String displayName) {\r
+ Role role = null;\r
+ \r
+ String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);\r
+ role = AuthorizationStore.getRoleByName(em, roleName, tenantId);\r
+ \r
+ return role;\r
+ }\r
+ \r
+ \r
+ public static Role createRole(String tenantId, String name, String description) {\r
+ return createRole(tenantId, name, description, false /* mutable by default */);\r
+ }\r
+ \r
+ public static Role createRole(String tenantId, String name, String description, boolean immutable) {\r
+ Role role = new Role();\r
+ \r
+ role.setCreatedAtItem(new Date());\r
+ role.setDisplayName(name);\r
+ String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, name); \r
+ role.setRoleName(roleName);\r
+ String id = UUID.randomUUID().toString(); //FIXME: The qualified role name should be unique enough to use as an ID/key\r
+ role.setCsid(id);\r
+ role.setDescription(description);\r
+ role.setTenantId(tenantId);\r
+ if (immutable == true) {\r
+ role.setMetadataProtection(RoleClient.IMMUTABLE);\r
+ role.setPermsProtection(RoleClient.IMMUTABLE);\r
+ }\r
+ \r
+ return role;\r
+ }\r
+ \r
+ /**\r
+ * Add permission to the Spring Security tables\r
+ * with assumption that resource is of type URI\r
+ * @param permission configuration\r
+ */\r
+ public static void addPermissionsForUri(Permission perm,\r
+ PermissionRole permRole) throws PermissionException {\r
+ //\r
+ // First check the integrity of the incoming arguments.\r
+ //\r
+ if (!perm.getCsid().equals(permRole.getPermission().get(0).getPermissionId())) {\r
+ throw new IllegalArgumentException("permission ids do not"\r
+ + " match for role=" + permRole.getRole().get(0).getRoleName()\r
+ + " with permissionId=" + permRole.getPermission().get(0).getPermissionId()\r
+ + " for permission with csid=" + perm.getCsid());\r
+ }\r
+ \r
+ List<String> principals = new ArrayList<String>(); \r
+ for (RoleValue roleValue : permRole.getRole()) {\r
+ principals.add(roleValue.getRoleName());\r
+ }\r
+ List<PermissionAction> permActions = perm.getAction();\r
+ for (PermissionAction permAction : permActions) {\r
+ try {\r
+ CSpaceAction action = URIResourceImpl.getAction(permAction.getName()); \r
+ URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
+ perm.getResourceName(), action);\r
+ boolean grant = perm.getEffect().equals(EffectType.PERMIT) ? true : false;\r
+ AuthZ.get().addPermissions(uriRes, principals.toArray(new String[0]), grant);//CSPACE-4967\r
+ } catch (PermissionException e) {\r
+ //\r
+ // Only throw the exception if it is *not* an already-exists exception\r
+ //\r
+ if (e.getCause() instanceof AlreadyExistsException == false) {\r
+ throw e;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ private static Connection getConnection() throws NamingException, SQLException {\r
+ return JDBCTools.getConnection(JDBCTools.CSPACE_REPOSITORY_NAME);\r
+ }\r
+ \r
+ /*\r
+ * Spring security seems to require that all of our role names start\r
+ * with the ROLE_PREFIX string.\r
+ */\r
+ public static String getQualifiedRoleName(String tenantId, String name) {\r
+ String result = name;\r
+ \r
+ String qualifiedName = ROLE_PREFIX + tenantId.toUpperCase() + "_" + name.toUpperCase(); \r
+ if (name.equals(qualifiedName) == false) {\r
+ result = qualifiedName;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static ActionGroup getActionGroup(String actionGroupStr) {\r
+ ActionGroup result = null;\r
+ \r
+ if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_CRUDL_NAME)) {\r
+ result = ACTIONGROUP_CRUDL;\r
+ } else if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_RL_NAME)) {\r
+ result = ACTIONGROUP_RL;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ public static Permission createPermission(String tenantId,\r
+ String resourceName,\r
+ String description,\r
+ String actionGroupStr) {\r
+ Permission result = null;\r
+ \r
+ ActionGroup actionGroup = getActionGroup(actionGroupStr);\r
+ result = createPermission(tenantId, resourceName, description, actionGroup);\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static Permission createPermission(String tenantId,\r
+ String resourceName,\r
+ String description,\r
+ ActionGroup actionGroup) {\r
+ // String id = UUID.randomUUID().toString(); //FIXME: Could this be something like a refname instead of a UUID?\r
+ String id = tenantId\r
+ + "-" + resourceName\r
+ + "-" + actionGroup.name;\r
+ Permission perm = new Permission();\r
+ perm.setCsid(id);\r
+ perm.setDescription(description);\r
+ perm.setCreatedAtItem(new Date());\r
+ perm.setResourceName(resourceName.toLowerCase().trim());\r
+ perm.setEffect(EffectType.PERMIT);\r
+ perm.setTenantId(tenantId);\r
+ \r
+ perm.setActionGroup(actionGroup.name);\r
+ ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();\r
+ perm.setAction(pas);\r
+ for (ActionType actionType : actionGroup.actions) {\r
+ PermissionAction permAction = createPermissionAction(perm, actionType);\r
+ pas.add(permAction);\r
+ }\r
+ \r
+ return perm;\r
+ }\r
+ \r
+ private static Permission createWorkflowPermission(TenantBindingType tenantBinding,\r
+ ServiceBindingType serviceBinding,\r
+ TransitionDef transitionDef,\r
+ ActionGroup actionGroup)\r
+ {\r
+ Permission result = null;\r
+ String workFlowServiceSuffix;\r
+ String transitionName;\r
+ if (transitionDef != null) {\r
+ transitionName = transitionDef.getName();\r
+ workFlowServiceSuffix = WorkflowClient.SERVICE_AUTHZ_SUFFIX;\r
+ } else {\r
+ transitionName = ""; //since the transitionDef was null, we're assuming that this is the base workflow permission to be created \r
+ workFlowServiceSuffix = WorkflowClient.SERVICE_PATH;\r
+ }\r
+ \r
+ String tenantId = tenantBinding.getId();\r
+ String resourceName = "/"\r
+ + serviceBinding.getName().toLowerCase().trim()\r
+ + workFlowServiceSuffix\r
+ + transitionName;\r
+ String description = "A generated workflow permission for actiongroup " + actionGroup.name;\r
+ result = createPermission(tenantId, resourceName, description, actionGroup);\r
+ \r
+ if (logger.isDebugEnabled() == true) {\r
+ logger.debug("Generated a workflow permission: "\r
+ + result.getResourceName()\r
+ + ":" + transitionName\r
+ + ":" + "tenant id=" + result.getTenantId()\r
+ + ":" + actionGroup.name);\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ private static PermissionRole createPermissionRole(EntityManager em,\r
+ Permission permission,\r
+ Role role,\r
+ boolean enforceTenancy) throws Exception\r
+ {\r
+ PermissionRole permRole = new PermissionRole();\r
+ // Check to see if the tenant ID of the permission and the tenant ID of the role match\r
+ boolean tenantIdsMatch = role.getTenantId().equalsIgnoreCase(permission.getTenantId());\r
+ if (tenantIdsMatch == false && enforceTenancy == false) {\r
+ tenantIdsMatch = true; // If we don't need to enforce tenancy then we'll just consider them matched.\r
+ }\r
+ \r
+ if (tenantIdsMatch == true) {\r
+ permRole.setSubject(SubjectType.ROLE);\r
+ //\r
+ // Set of the permission value list of the permrole\r
+ //\r
+ List<PermissionValue> permValues = new ArrayList<PermissionValue>();\r
+ PermissionValue permValue = new PermissionValue();\r
+ permValue.setPermissionId(permission.getCsid());\r
+ permValue.setResourceName(permission.getResourceName().toLowerCase());\r
+ permValue.setActionGroup(permission.getActionGroup());\r
+ permValues.add(permValue);\r
+ permRole.setPermission(permValues);\r
+ //\r
+ // Set of the role value list of the permrole\r
+ //\r
+ List<RoleValue> roleValues = new ArrayList<RoleValue>();\r
+ RoleValue rv = new RoleValue();\r
+ // This needs to use the qualified name, not the display name\r
+ rv.setRoleName(role.getRoleName());\r
+ rv.setRoleId(role.getCsid());\r
+ roleValues.add(rv);\r
+ permRole.setRole(roleValues);\r
+ } else {\r
+ String errMsg = "The tenant ID of the role: " + role.getTenantId()\r
+ + " did not match the tenant ID of the permission: " + permission.getTenantId();\r
+ throw new Exception(errMsg);\r
+ }\r
+ \r
+ return permRole;\r
+ }\r
+ \r
+ \r
+ /*\r
+ * FIXME: REM - This method is way too big -over 300 lines! We need to break it up into\r
+ * smaller, discrete, sub-methods.\r
+ */\r
+ public static void createDefaultAccounts(TenantBindingConfigReaderImpl tenantBindingConfigReader) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("ServiceMain.createDefaultAccounts starting...");\r
+ }\r
+ \r
+ Hashtable<String, TenantBindingType> tenantBindings =\r
+ tenantBindingConfigReader.getTenantBindings();\r
+ Hashtable<String, String> tenantInfo = new Hashtable<String, String>();\r
+ for (TenantBindingType tenantBinding : tenantBindings.values()) {\r
+ String tId = tenantBinding.getId();\r
+ String tName = tenantBinding.getName();\r
+ tenantInfo.put(tId, tName);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts found configured tenant id: "+tId+" name: "+tName);\r
+ }\r
+ }\r
+ Connection conn = null;\r
+ PreparedStatement pstmt = null;\r
+ Statement stmt = null;\r
+ // TODO - need to put in tests for existence first.\r
+ // We could just look for the accounts per tenant up front, and assume that\r
+ // the rest is there if the accounts are.\r
+ // Could add a sql script to remove these if need be - Spring only does roles, \r
+ // and we're not touching that, so we could safely toss the \r
+ // accounts, users, account-tenants, account-roles, and start over.\r
+ try {\r
+ conn = getConnection();\r
+ // First find or create the tenants\r
+ String queryTenantSQL = \r
+ "SELECT id,name FROM tenants";\r
+ stmt = conn.createStatement();\r
+ ResultSet rs = stmt.executeQuery(queryTenantSQL);\r
+ ArrayList<String> existingTenants = new ArrayList<String>();\r
+ while (rs.next()) {\r
+ String tId = rs.getString("id");\r
+ String tName = rs.getString("name");\r
+ if(tenantInfo.containsKey(tId)) {\r
+ existingTenants.add(tId);\r
+ if(!tenantInfo.get(tId).equalsIgnoreCase(tName)) {\r
+ logger.warn("Configured name for tenant: "\r
+ +tId+" in repository: "+tName\r
+ +" does not match config'd name: "+ tenantInfo.get(tId));\r
+ }\r
+ }\r
+ }\r
+ rs.close();\r
+ \r
+ String insertTenantSQL = \r
+ "INSERT INTO tenants (id,name,created_at) VALUES (?,?, now())";\r
+ pstmt = conn.prepareStatement(insertTenantSQL); // create a statement\r
+ for(String tId : tenantInfo.keySet()) {\r
+ if(existingTenants.contains(tId)) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts: tenant exists (skipping): "\r
+ +tenantInfo.get(tId));\r
+ }\r
+ continue;\r
+ }\r
+ pstmt.setString(1, tId); // set id param\r
+ pstmt.setString(2, tenantInfo.get(tId)); // set name param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts adding entry for tenant: "+tId);\r
+ }\r
+ pstmt.executeUpdate();\r
+ }\r
+ pstmt.close();\r
+ // Second find or create the users\r
+ String queryUserSQL = \r
+ "SELECT username FROM users WHERE username LIKE '"\r
+ +TENANT_ADMIN_ACCT_PREFIX+"%' OR username LIKE '"\r
+ +TENANT_READER_ACCT_PREFIX+"%'";\r
+ rs = stmt.executeQuery(queryUserSQL);\r
+ ArrayList<String> usersInRepo = new ArrayList<String>();\r
+ while (rs.next()) {\r
+ String uName = rs.getString("username");\r
+ usersInRepo.add(uName);\r
+ }\r
+ rs.close();\r
+ String insertUserSQL = \r
+ "INSERT INTO users (username,passwd, created_at)"\r
+ +" VALUES (?,?, now())";\r
+ pstmt = conn.prepareStatement(insertUserSQL); // create a statement\r
+ for(String tName : tenantInfo.values()) {\r
+ String adminAcctName = getDefaultAdminUserID(tName);\r
+ if(!usersInRepo.contains(adminAcctName)) {\r
+ String secEncPasswd = SecurityUtils.createPasswordHash(\r
+ adminAcctName, DEFAULT_ADMIN_PASSWORD);\r
+ pstmt.setString(1, adminAcctName); // set username param\r
+ pstmt.setString(2, secEncPasswd); // set passwd param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts adding user: "\r
+ +adminAcctName+" for tenant: "+tName);\r
+ }\r
+ pstmt.executeUpdate();\r
+ } else if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts: user: "+adminAcctName\r
+ +" already exists - skipping.");\r
+ }\r
+ \r
+ \r
+ String readerAcctName = getDefaultReaderUserID(tName);\r
+ if(!usersInRepo.contains(readerAcctName)) {\r
+ String secEncPasswd = SecurityUtils.createPasswordHash(\r
+ readerAcctName, DEFAULT_READER_PASSWORD);\r
+ pstmt.setString(1, readerAcctName); // set username param\r
+ pstmt.setString(2, secEncPasswd); // set passwd param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts adding user: "\r
+ +readerAcctName+" for tenant: "+tName);\r
+ }\r
+ pstmt.executeUpdate();\r
+ } else if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts: user: "+readerAcctName\r
+ +" already exists - skipping.");\r
+ }\r
+ }\r
+ pstmt.close();\r
+ // Third, create the accounts. Assume that if the users were already there,\r
+ // then the accounts were as well\r
+ String insertAccountSQL = \r
+ "INSERT INTO accounts_common "\r
+ + "(csid, email, userid, status, screen_name, metadata_protection, roles_protection, created_at) "\r
+ + "VALUES (?,?,?,'ACTIVE',?, 'immutable', 'immutable', now())";\r
+ Hashtable<String, String> tenantAdminAcctCSIDs = new Hashtable<String, String>();\r
+ Hashtable<String, String> tenantReaderAcctCSIDs = new Hashtable<String, String>();\r
+ pstmt = conn.prepareStatement(insertAccountSQL); // create a statement\r
+ for(String tId : tenantInfo.keySet()) {\r
+ String tName = tenantInfo.get(tId);\r
+ String adminCSID = UUID.randomUUID().toString();\r
+ tenantAdminAcctCSIDs.put(tId, adminCSID);\r
+ String adminAcctName = getDefaultAdminUserID(tName);\r
+ if(!usersInRepo.contains(adminAcctName)) {\r
+ pstmt.setString(1, adminCSID); // set csid param\r
+ pstmt.setString(2, adminAcctName); // set email param (bogus)\r
+ pstmt.setString(3, adminAcctName); // set userid param\r
+ pstmt.setString(4, "Administrator");// set screen name param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts adding account: "\r
+ +adminAcctName+" for tenant: "+tName);\r
+ }\r
+ pstmt.executeUpdate();\r
+ } else if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts: user: "+adminAcctName\r
+ +" already exists - skipping account generation.");\r
+ }\r
+ \r
+ String readerCSID = UUID.randomUUID().toString(); \r
+ tenantReaderAcctCSIDs.put(tId, readerCSID);\r
+ String readerAcctName = getDefaultReaderUserID(tName);\r
+ if(!usersInRepo.contains(readerAcctName)) {\r
+ pstmt.setString(1, readerCSID); // set csid param\r
+ pstmt.setString(2, readerAcctName); // set email param (bogus)\r
+ pstmt.setString(3, readerAcctName); // set userid param\r
+ pstmt.setString(4, "Reader"); // set screen name param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts adding account: "\r
+ +readerAcctName+" for tenant: "+tName);\r
+ }\r
+ pstmt.executeUpdate();\r
+ } else if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts: user: "+readerAcctName\r
+ +" already exists - skipping account creation.");\r
+ }\r
+ }\r
+ pstmt.close();\r
+ // Fourth, bind accounts to tenants. Assume that if the users were already there,\r
+ // then the accounts were bound to tenants correctly\r
+ String insertAccountTenantSQL;\r
+ DatabaseProductType databaseProductType = JDBCTools.getDatabaseProductType();\r
+ if (databaseProductType == DatabaseProductType.MYSQL) {\r
+ insertAccountTenantSQL =\r
+ "INSERT INTO accounts_tenants (TENANTS_ACCOUNTSCOMMON_CSID,tenant_id) "\r
+ + " VALUES(?, ?)";\r
+ } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
+ insertAccountTenantSQL =\r
+ "INSERT INTO accounts_tenants (HJID, TENANTS_ACCOUNTSCOMMON_CSID,tenant_id) "\r
+ + " VALUES(nextval('hibernate_sequence'), ?, ?)";\r
+ } else {\r
+ throw new Exception("Unrecognized database system.");\r
+ }\r
+ pstmt = conn.prepareStatement(insertAccountTenantSQL); // create a statement\r
+ for(String tId : tenantInfo.keySet()) {\r
+ String tName = tenantInfo.get(tId);\r
+ if(!usersInRepo.contains(getDefaultAdminUserID(tName))) {\r
+ String adminAcct = tenantAdminAcctCSIDs.get(tId);\r
+ pstmt.setString(1, adminAcct); // set acct CSID param\r
+ pstmt.setString(2, tId); // set tenant_id param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding account id: "\r
+ +adminAcct+" to tenant id: "+tId);\r
+ }\r
+ pstmt.executeUpdate();\r
+ }\r
+ if(!usersInRepo.contains(getDefaultReaderUserID(tName))) {\r
+ String readerAcct = tenantReaderAcctCSIDs.get(tId);\r
+ pstmt.setString(1, readerAcct); // set acct CSID param\r
+ pstmt.setString(2, tId); // set tenant_id param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding account id: "\r
+ +readerAcct+" to tenant id: "+tId);\r
+ }\r
+ pstmt.executeUpdate();\r
+ }\r
+ }\r
+ pstmt.close();\r
+ // Fifth, fetch and save the default roles\r
+ String springAdminRoleCSID = null;\r
+ String querySpringRole = \r
+ "SELECT csid from roles WHERE rolename='"+SPRING_ADMIN_ROLE+"'";\r
+ rs = stmt.executeQuery(querySpringRole);\r
+ if(rs.next()) {\r
+ springAdminRoleCSID = rs.getString(1);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts found Spring Admin role: "\r
+ +springAdminRoleCSID);\r
+ }\r
+ } else {\r
+ String insertSpringAdminRoleSQL =\r
+ "INSERT INTO roles (csid, rolename, displayName, rolegroup, created_at, tenant_id) "\r
+ + "VALUES ('-1', 'ROLE_SPRING_ADMIN', 'SPRING_ADMIN', 'Spring Security Administrator', now(), '0')";\r
+ stmt.executeUpdate(insertSpringAdminRoleSQL);\r
+ springAdminRoleCSID = "-1";\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts CREATED Spring Admin role: "\r
+ +springAdminRoleCSID);\r
+ }\r
+ }\r
+ rs.close();\r
+ String getRoleCSIDSql =\r
+ "SELECT csid from roles WHERE tenant_id=? and rolename=?";\r
+ pstmt = conn.prepareStatement(getRoleCSIDSql); // create a statement\r
+ rs = null;\r
+ Hashtable<String, String> tenantAdminRoleCSIDs = new Hashtable<String, String>();\r
+ Hashtable<String, String> tenantReaderRoleCSIDs = new Hashtable<String, String>();\r
+ for(String tId : tenantInfo.keySet()) {\r
+ pstmt.setString(1, tId); // set tenant_id param\r
+ pstmt.setString(2, getDefaultAdminRole(tId)); // set rolename param\r
+ rs = pstmt.executeQuery();\r
+ // extract data from the ResultSet\r
+ if(!rs.next()) {\r
+ throw new RuntimeException("Cannot find role: "+getDefaultAdminRole(tId)\r
+ +" for tenant id: "+tId+" in roles!");\r
+ }\r
+ String tenantAdminRoleCSID = rs.getString(1);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts found role: "\r
+ +getDefaultAdminRole(tId)+"("+tenantAdminRoleCSID\r
+ +") for tenant id: "+tId);\r
+ }\r
+ tenantAdminRoleCSIDs.put(tId, tenantAdminRoleCSID);\r
+ pstmt.setString(1, tId); // set tenant_id param\r
+ pstmt.setString(2, getDefaultReaderRole(tId)); // set rolename param\r
+ rs.close();\r
+ rs = pstmt.executeQuery();\r
+ // extract data from the ResultSet\r
+ if(!rs.next()) {\r
+ throw new RuntimeException("Cannot find role: "+getDefaultReaderRole(tId)\r
+ +" for tenant id: "+tId+" in roles!");\r
+ }\r
+ String tenantReaderRoleCSID = rs.getString(1);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts found role: "\r
+ +getDefaultReaderRole(tId)+"("+tenantReaderRoleCSID\r
+ +") for tenant id: "+tId);\r
+ }\r
+ tenantReaderRoleCSIDs.put(tId, tenantReaderRoleCSID);\r
+ rs.close();\r
+ }\r
+ pstmt.close();\r
+ // Sixth, bind the accounts to roles. If the users already existed,\r
+ // we'll assume they were set up correctly.\r
+ String insertAccountRoleSQL;\r
+ if (databaseProductType == DatabaseProductType.MYSQL) {\r
+ insertAccountRoleSQL =\r
+ "INSERT INTO accounts_roles(account_id, user_id, role_id, role_name, created_at)"\r
+ +" VALUES(?, ?, ?, ?, now())";\r
+ } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
+ insertAccountRoleSQL =\r
+ "INSERT INTO accounts_roles(HJID, account_id, user_id, role_id, role_name, created_at)"\r
+ +" VALUES(nextval('hibernate_sequence'), ?, ?, ?, ?, now())";\r
+ } else {\r
+ throw new Exception("Unrecognized database system.");\r
+ }\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding accounts to roles with SQL:\n"\r
+ +insertAccountRoleSQL);\r
+ }\r
+ pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement\r
+ for(String tId : tenantInfo.keySet()) {\r
+ String adminUserId = getDefaultAdminUserID(tenantInfo.get(tId));\r
+ if(!usersInRepo.contains(adminUserId)) {\r
+ String adminAcct = tenantAdminAcctCSIDs.get(tId);\r
+ String adminRoleId = tenantAdminRoleCSIDs.get(tId);\r
+ pstmt.setString(1, adminAcct); // set acct CSID param\r
+ pstmt.setString(2, adminUserId); // set user_id param\r
+ pstmt.setString(3, adminRoleId); // set role_id param\r
+ pstmt.setString(4, getDefaultAdminRole(tId)); // set rolename param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding account: "\r
+ +adminUserId+" to Admin role("+adminRoleId\r
+ +") for tenant id: "+tId);\r
+ }\r
+ pstmt.executeUpdate();\r
+ // Now add the Spring Admin Role to the admin accounts\r
+ pstmt.setString(3, springAdminRoleCSID); // set role_id param\r
+ pstmt.setString(4, SPRING_ADMIN_ROLE); // set rolename param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding account: "\r
+ +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);\r
+ }\r
+ pstmt.executeUpdate();\r
+ }\r
+ String readerUserId = getDefaultReaderUserID(tenantInfo.get(tId));\r
+ if(!usersInRepo.contains(readerUserId)) {\r
+ String readerAcct = tenantReaderAcctCSIDs.get(tId);\r
+ String readerRoleId = tenantReaderRoleCSIDs.get(tId);\r
+ pstmt.setString(1, readerAcct); // set acct CSID param\r
+ pstmt.setString(2, readerUserId); // set user_id param\r
+ pstmt.setString(3, readerRoleId); // set role_id param\r
+ pstmt.setString(4, getDefaultReaderRole(tId)); // set rolename param\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createDefaultAccounts binding account: "\r
+ +readerUserId+" to Reader role("+readerRoleId\r
+ +") for tenant id: "+tId);\r
+ }\r
+ pstmt.executeUpdate();\r
+ }\r
+ }\r
+ pstmt.close();\r
+ stmt.close();\r
+ } catch (RuntimeException rte) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Exception in createDefaultAccounts: "+\r
+ rte.getLocalizedMessage());\r
+ logger.debug(rte.getStackTrace().toString());\r
+ }\r
+ throw rte;\r
+ } catch (SQLException sqle) {\r
+ // SQLExceptions can be chained. We have at least one exception, so\r
+ // set up a loop to make sure we let the user know about all of them\r
+ // if there happens to be more than one.\r
+ if (logger.isDebugEnabled()) {\r
+ SQLException tempException = sqle;\r
+ while (null != tempException) {\r
+ logger.debug("SQL Exception: " + sqle.getLocalizedMessage());\r
+ tempException = tempException.getNextException();\r
+ }\r
+ logger.debug(sqle.getStackTrace().toString());\r
+ }\r
+ throw new RuntimeException("SQL problem in createDefaultAccounts: ", sqle);\r
+ } catch (Exception e) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Exception in createDefaultAccounts: "+\r
+ e.getLocalizedMessage());\r
+ }\r
+ } finally {\r
+ try {\r
+ if(conn!=null)\r
+ conn.close();\r
+ if(pstmt!=null)\r
+ pstmt.close();\r
+ if(stmt!=null)\r
+ stmt.close();\r
+ } catch (SQLException sqle) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("SQL Exception closing statement/connection: "\r
+ + sqle.getLocalizedMessage());\r
+ }\r
+ }\r
+ } \r
+ }\r
+ \r
+ private static String getDefaultAdminRole(String tenantId) {\r
+ return ROLE_PREFIX+tenantId+TENANT_ADMIN_ROLE_SUFFIX;\r
+ }\r
+ \r
+ private static String getDefaultReaderRole(String tenantId) {\r
+ return ROLE_PREFIX+tenantId+TENANT_READER_ROLE_SUFFIX;\r
+ }\r
+ \r
+ private static String getDefaultAdminUserID(String tenantName) {\r
+ return TENANT_ADMIN_ACCT_PREFIX+tenantName;\r
+ }\r
+ \r
+ private static String getDefaultReaderUserID(String tenantName) {\r
+ return TENANT_READER_ACCT_PREFIX+tenantName;\r
+ }\r
+ \r
+ static public PermissionAction createPermissionAction(Permission perm,\r
+ ActionType actionType) {\r
+ PermissionAction pa = new PermissionAction();\r
+ \r
+ CSpaceAction action = URIResourceImpl.getAction(actionType);\r
+ URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
+ perm.getResourceName(), action);\r
+ pa.setName(actionType);\r
+ pa.setObjectIdentity(uriRes.getHashedId().toString());\r
+ pa.setObjectIdentityResource(uriRes.getId());\r
+ \r
+ return pa;\r
+ }\r
+ \r
+ static public PermissionAction update(Permission perm, PermissionAction permAction) {\r
+ PermissionAction pa = new PermissionAction();\r
+ \r
+ CSpaceAction action = URIResourceImpl.getAction(permAction.getName());\r
+ URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
+ perm.getResourceName(), action);\r
+ pa.setObjectIdentity(uriRes.getHashedId().toString());\r
+ pa.setObjectIdentityResource(uriRes.getId());\r
+ \r
+ return pa;\r
+ }\r
+ \r
+ private static TransitionDefList getTransitionDefList(TenantBindingType tenantBinding, ServiceBindingType serviceBinding) {\r
+ TransitionDefList result = null;\r
+ try {\r
+ String serviceObjectName = serviceBinding.getObject().getName();\r
+ DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance(\r
+ tenantBinding, serviceBinding);\r
+ Lifecycle lifecycle = docHandler.getLifecycle(serviceObjectName);\r
+ if (lifecycle != null) {\r
+ result = lifecycle.getTransitionDefList();\r
+ }\r
+ } catch (Exception e) {\r
+ // Ignore this exception and return an empty non-null TransitionDefList\r
+ }\r
+ \r
+ if (result == null) {\r
+ logger.warn("Could not retrieve a lifecycle transition definition list from: "\r
+ + serviceBinding.getName()\r
+ + " with tenant ID = "\r
+ + tenantBinding.getId()); \r
+ // return an empty list \r
+ result = new TransitionDefList();\r
+ } else {\r
+ logger.debug("Successfully etrieved a lifecycle transition definition list from: "\r
+ + serviceBinding.getName()\r
+ + " with tenant ID = "\r
+ + tenantBinding.getId());\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
- public static void createDefaultPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception\r
++ public static void createDefaultPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception //FIXME: REM - 4/11/2012 - Rename to createWorkflowPermissions\r
+ {\r
+ AuthZ.get().login(); //login to Spring Security manager\r
+ \r
+ EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);\r
+ EntityManager em = null;\r
+ \r
+ try {\r
+ em = emf.createEntityManager();\r
+ \r
+ Role superRole = AuthorizationCommon.getRole(em, ADMINISTRATOR_TENANT_ID, ROLE_ADMINISTRATOR);\r
+ Hashtable<String, TenantBindingType> tenantBindings =\r
+ tenantBindingConfigReader.getTenantBindings();\r
+ for (String tenantId : tenantBindings.keySet()) {\r
+ TenantBindingType tenantBinding = tenantBindings.get(tenantId);\r
+ Role adminRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_ADMINISTRATOR);\r
+ Role readonlyRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_READER);\r
+ for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {\r
- try {\r
- em.getTransaction().begin();\r
- //\r
- // For the default admin role, create the base workflow (aka, "/workflow" permissions for the service.\r
- Permission baseAdminPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_CRUDL);\r
- persist(em, baseAdminPerm, adminRole, true);\r
- //\r
- // For the default read-only role, create the base workflow (aka, "/workflow" permissions for the service.\r
- Permission baseReadonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_RL);\r
- persist(em, baseReadonlyPerm, readonlyRole, true); \r
- //\r
- // Next, create a permission for each workflow transition supported by the service's document type.\r
- //\r
- TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);\r
- for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {\r
++ String prop = ServiceBindingUtils.getPropertyValue(serviceBinding, REFRESH_AUTZ_PROP);\r
++ if (prop == null ? true : Boolean.parseBoolean(prop)) {\r
++ try {\r
++ em.getTransaction().begin();\r
+ //\r
- // Create the permission for the admin role\r
- Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_CRUDL);\r
- persist(em, adminPerm, adminRole, true);\r
++ // For the default admin role, create the base workflow (aka, "/workflow" permissions for the service.\r
++ Permission baseAdminPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_CRUDL);\r
++ persist(em, baseAdminPerm, adminRole, true);\r
+ //\r
- // Create the permission for the read-only role\r
- Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_RL);\r
- \r
- Profiler profiler = new Profiler(AuthorizationCommon.class, 1);\r
- profiler.start("createDefaultPermissions started:" + readonlyPerm.getCsid());\r
- persist(em, readonlyPerm, readonlyRole, true); // Persist/store the permission and permrole records and related Spring Security info\r
- profiler.stop();\r
- logger.debug("Finished full perm generation for "\r
- + ":" + tenantBinding.getId()\r
- + ":" + serviceBinding.getName()\r
- + ":" + transitionDef.getName()\r
- + ":" + ACTIONGROUP_RL\r
- + ":" + profiler.getCumulativeTime()); \r
- /*\r
++ // For the default read-only role, create the base workflow (aka, "/workflow" permissions for the service.\r
++ Permission baseReadonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_RL);\r
++ persist(em, baseReadonlyPerm, readonlyRole, true); \r
+ //\r
- // Create the permission for the super-admin role. Note we use the same "adminPerm" instance we used for the "adminPermRole" instance\r
++ // Next, create a permission for each workflow transition supported by the service's document type.\r
+ //\r
- persist(em, adminPerm, superRole, false);\r
- */\r
++ TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);\r
++ for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {\r
++ //\r
++ // Create the permission for the admin role\r
++ Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_CRUDL);\r
++ persist(em, adminPerm, adminRole, true);\r
++ //\r
++ // Create the permission for the read-only role\r
++ Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_RL);\r
++ \r
++ Profiler profiler = new Profiler(AuthorizationCommon.class, 1);\r
++ profiler.start("createDefaultPermissions started:" + readonlyPerm.getCsid());\r
++ persist(em, readonlyPerm, readonlyRole, true); // Persist/store the permission and permrole records and related Spring Security info\r
++ profiler.stop();\r
++ logger.debug("Finished full perm generation for "\r
++ + ":" + tenantBinding.getId()\r
++ + ":" + serviceBinding.getName()\r
++ + ":" + transitionDef.getName()\r
++ + ":" + ACTIONGROUP_RL\r
++ + ":" + profiler.getCumulativeTime()); \r
++ /*\r
++ //\r
++ // Create the permission for the super-admin role. Note we use the same "adminPerm" instance we used for the "adminPermRole" instance\r
++ //\r
++ persist(em, adminPerm, superRole, false);\r
++ */\r
++ }\r
++ em.getTransaction().commit();\r
++ } catch (IllegalStateException e) {\r
++ logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.\r
+ }\r
- em.getTransaction().commit();\r
- } catch (IllegalStateException e) {\r
- logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.\r
++ } else {\r
++ logger.warn("AuthZ refresh service binding property is set to FALSE so default roles and permissions will NOT be refreshed.");\r
+ }\r
+ }\r
+ }\r
+ em.close();\r
+ } catch (Exception e) {\r
+ if (em != null && em.getTransaction().isActive()) {\r
+ em.getTransaction().rollback();\r
+ }\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Caught exception and rolling back permission creation: ", e);\r
+ }\r
+ throw e;\r
+ } finally {\r
+ if (em != null) {\r
+ JpaStorageUtils.releaseEntityManagerFactory(emf);\r
+ }\r
+ }\r
+ }\r
+ \r
+ private static PermissionRoleRel findPermRoleRel(EntityManager em, String permissionId, String RoleId) {\r
+ PermissionRoleRel result = null;\r
+ \r
+ try {\r
+ String whereClause = "where permissionId = :id and roleId = :roleId";\r
+ HashMap<String, Object> params = new HashMap<String, Object>();\r
+ params.put("id", permissionId);\r
+ params.put("roleId", RoleId); \r
+ \r
+ result = (PermissionRoleRel) JpaStorageUtils.getEntity(em,\r
+ PermissionRoleRel.class.getCanonicalName(), whereClause, params);\r
+ } catch (Exception e) {\r
+ //Do nothing. Will return null;\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ /*\r
+ * Persists the Permission, PermissionRoleRel, and Spring Security table entries all in one transaction\r
+ */\r
+ private static void persist(EntityManager em, Permission permission, Role role, boolean enforceTenancy) throws Exception {\r
+ AuthorizationStore authzStore = new AuthorizationStore();\r
+ // First persist the Permission record\r
+ authzStore.store(em, permission);\r
+ \r
+ // If the PermRoleRel doesn't already exists then relate the permission and the role in a new PermissionRole (the service payload)\r
+ // Create a PermissionRoleRel (the database relation table for the permission and role)\r
+ PermissionRoleRel permRoleRel = findPermRoleRel(em, permission.getCsid(), role.getCsid());\r
+ if (permRoleRel == null) {\r
+ PermissionRole permRole = createPermissionRole(em, permission, role, enforceTenancy);\r
+ List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();\r
+ PermissionRoleUtil.buildPermissionRoleRel(em, permRole, SubjectType.ROLE, permRoleRels, false /*not for delete*/);\r
+ for (PermissionRoleRel prr : permRoleRels) {\r
+ authzStore.store(em, prr);\r
+ }\r
+ Profiler profiler = new Profiler(AuthorizationCommon.class, 2);\r
+ profiler.start();\r
+ // Add a corresponding entry in the Spring Security Tables\r
+ addPermissionsForUri(permission, permRole);\r
+ profiler.stop();\r
+ logger.debug("Finished full perm generation for "\r
+ + ":" + permission.getTenantId()\r
+ + ":" + permission.getResourceName()\r
+ + ":" + ACTIONGROUP_RL\r
+ + ":" + profiler.getCumulativeTime());\r
+ }\r
+ \r
+ }\r
\r
}\r
import java.util.ArrayList;\r
import java.util.List;\r
import java.util.Map;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
\r
import org.collectionspace.services.common.config.PropertyItemUtils;\r
- import org.collectionspace.services.common.service.ObjectPartType;\r
- import org.collectionspace.services.common.service.ServiceBindingType;\r
- import org.collectionspace.services.common.service.ServiceObjectType;\r
- import org.collectionspace.services.common.tenant.TenantBindingType;\r
- import org.collectionspace.services.common.types.PropertyItemType;\r
- import org.collectionspace.services.common.types.PropertyType;\r
+ import org.collectionspace.services.config.service.ObjectPartType;\r
+ import org.collectionspace.services.config.service.ServiceBindingType;\r
+ import org.collectionspace.services.config.service.ServiceObjectType;\r
+ import org.collectionspace.services.config.types.PropertyItemType;\r
+ import org.collectionspace.services.config.types.PropertyType;\r
import org.collectionspace.services.nuxeo.util.NuxeoUtils;\r
import org.nuxeo.ecm.core.api.ClientException;\r
import org.nuxeo.ecm.core.api.DocumentModel;\r
* @return an identifier for the transition required to
* place the document in that workflow state.
*/
++ @Deprecated
private String getTransitionFromState(String state) {
String result = TRANSITION_UNKNOWN;
// destination workflow state and the set of allowable state transitions.
if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
-- result = TRANSITION_DELETE;
-- } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_APPROVED)) {
-- result = TRANSITION_APPROVE;
-- } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
-- result = TRANSITION_UNDELETE;
++ result = WorkflowClient.WORKFLOWTRANSITION_DELETE;
++ } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_ACTIVE)) {
++ result = WorkflowClient.WORKFLOWTRANSITION_UNDELETE; //FIXME, could also be transition WORKFLOWTRANSITION_UNLOCK
++ } else if (state.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_LOCKED)) {
++ result = WorkflowClient.WORKFLOWTRANSITION_LOCK;
} else {
logger.warn("An attempt was made to transition a document to an unknown workflow state = "
+ state);
public final static String COLLECTIONSPACE_CORE_UPDATED_AT = "updatedAt";
public final static String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy";
public final static String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy";
+ public final static String COLLECTIONSPACE_CORE_WORKFLOWSTATE = "workflowState";
+ /*
+ * Map Nuxeo's life cycle object to our JAX-B based life cycle object
+ */
+ private Lifecycle createCollectionSpaceLifecycle(org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle) {
+ Lifecycle result = null;
+
+ if (nuxeoLifecyle != null) {
+ //
+ // Copy the life cycle's name
+ result = new Lifecycle();
+ result.setName(nuxeoLifecyle.getName());
+
+ // We currently support only one initial state, so take the first one from Nuxeo
+ Collection<String> initialStateNames = nuxeoLifecyle.getInitialStateNames();
+ result.setDefaultInitial(initialStateNames.iterator().next());
+
+ // Next, we copy the state and corresponding transition lists
+ StateList stateList = new StateList();
+ List<State> states = stateList.getState();
+ Collection<org.nuxeo.ecm.core.lifecycle.LifeCycleState> nuxeoStates = nuxeoLifecyle.getStates();
+ for (org.nuxeo.ecm.core.lifecycle.LifeCycleState nuxeoState : nuxeoStates) {
+ State tempState = new State();
+ tempState.setDescription(nuxeoState.getDescription());
+ tempState.setInitial(nuxeoState.isInitial());
+ tempState.setName(nuxeoState.getName());
+ // Now get the list of transitions
+ TransitionList transitionList = new TransitionList();
+ List<String> transitions = transitionList.getTransition();
+ Collection<String> nuxeoTransitions = nuxeoState.getAllowedStateTransitions();
+ for (String nuxeoTransition : nuxeoTransitions) {
+ transitions.add(nuxeoTransition);
+ }
+ tempState.setTransitionList(transitionList);
+ states.add(tempState);
+ }
+ result.setStateList(stateList);
+
+ // Finally, we create the transition definitions
+ TransitionDefList transitionDefList = new TransitionDefList();
+ List<TransitionDef> transitionDefs = transitionDefList.getTransitionDef();
+ Collection<org.nuxeo.ecm.core.lifecycle.LifeCycleTransition> nuxeoTransitionDefs = nuxeoLifecyle.getTransitions();
+ for (org.nuxeo.ecm.core.lifecycle.LifeCycleTransition nuxeoTransitionDef : nuxeoTransitionDefs) {
+ TransitionDef tempTransitionDef = new TransitionDef();
+ tempTransitionDef.setDescription(nuxeoTransitionDef.getDescription());
+ tempTransitionDef.setDestinationState(nuxeoTransitionDef.getDestinationStateName());
+ tempTransitionDef.setName(nuxeoTransitionDef.getName());
+ transitionDefs.add(tempTransitionDef);
+ }
+ result.setTransitionDefList(transitionDefList);
+ }
+
+ return result;
+ }
+
+ /*
+ * Returns the the life cycle definition of the related Nuxeo document type for this handler.
+ * (non-Javadoc)
+ * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle()
+ */
+ @Override
+ public Lifecycle getLifecycle() {
+ Lifecycle result = null;
+
+ String docTypeName = null;
+ try {
+ docTypeName = this.getServiceContext().getDocumentType();
+ result = getLifecycle(docTypeName);
+ } catch (Exception e) {
+ if (logger.isTraceEnabled() == true) {
+ logger.trace("Could not retrieve lifecycle definition for Nuxeo doctype: " + docTypeName);
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ * Returns the the life cycle definition of the related Nuxeo document type for this handler.
+ * (non-Javadoc)
+ * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle(java.lang.String)
+ */
+ @Override
+ public Lifecycle getLifecycle(String docTypeName) {
+ org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle;
+ Lifecycle result = null;
+
+ try {
+ LifeCycleService lifeCycleService = null;
+ try {
+ lifeCycleService = NXCore.getLifeCycleService();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ String lifeCycleName;
+ lifeCycleName = lifeCycleService.getLifeCycleNameFor(docTypeName);
+ nuxeoLifecyle = lifeCycleService.getLifeCycleByName(lifeCycleName);
+
+ result = createCollectionSpaceLifecycle(nuxeoLifecyle);
+ // result = (Lifecycle)FileTools.getJaxbObjectFromFile(Lifecycle.class, "default-lifecycle.xml");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ logger.error("Could not retreive life cycle information for Nuxeo doctype: " + docTypeName, e);
+ }
+
+ return result;
+ }
+
/*
* We're using the "name" field of Nuxeo's DocumentModel to store
* the CSID.
*/
package org.collectionspace.services.nuxeo.client.java;
--import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
@GET
@Produces({"application/xml"})
ClientResponse<DimensionsCommonList> readIncludeDeleted(
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
@Override
@GET
@Produces({"application/xml"})
ClientResponse<DimensionsCommonList> keywordSearchIncludeDeleted(
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
}
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.api.ZipTools;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
- import org.collectionspace.services.common.tenant.RepositoryDomainType;
- import org.collectionspace.services.common.tenant.TenantBindingType;
+import org.collectionspace.services.common.context.MultipartServiceContextFactory;
+import org.collectionspace.services.common.context.ServiceContextFactory;
-import org.collectionspace.authentication.AuthN;
-
+ import org.collectionspace.services.config.tenant.RepositoryDomainType;
+ import org.collectionspace.services.config.tenant.TenantBindingType;
+import org.collectionspace.services.imports.ImportsCommon;
import org.collectionspace.services.imports.nuxeo.ImportCommand;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.xml.sax.InputSource;
-package org.collectionspace.services.imports.nuxeo;
-
-import java.io.File;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.collectionspace.services.nuxeo.client.java.NuxeoClientEmbedded;
-import org.collectionspace.services.nuxeo.client.java.NuxeoConnectorEmbedded;
-import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
-import org.nuxeo.ecm.core.io.DocumentPipe;
-import org.nuxeo.ecm.core.io.DocumentReader;
-import org.nuxeo.ecm.core.io.DocumentWriter;
-import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl;
-import org.nuxeo.ecm.core.io.impl.plugins.DocumentModelWriter;
-// we use our own override of this: import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader;
-
-// based loosely on package org.nuxeo.ecm.shell.commands.io.ImportCommand;
-public class ImportCommand {
- private static final Log logger = LogFactory.getLog(ImportCommand.class);
-
- public String run(String src, String dest) throws Exception {
- File file = new File(src);
- ///cspace way of configuring client and auth:
- NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
- RepositoryInstance repoSession = client.openRepository();
- try {
- return importTree(repoSession, file, dest);
- } finally {
-// repository.close();
- client.releaseRepository(repoSession);
- }
- }
-
- String importTree(RepositoryInstance repository, File file, String toPath) throws Exception {
- DocumentReader reader = null;
- DocumentWriter writer = null;
- String dump = "NO RESULTS";
- try {
- System.out.println("importTree reading file: "+file+(file!=null ? " exists? "+file.exists() : " file param is null"));
- reader = new LoggedXMLDirectoryReader(file); //our overload of XMLDirectoryReader.
- writer = new DocumentModelWriter(repository, toPath, 10);
- DocumentPipe pipe = new DocumentPipeImpl(10);
- // pipe.addTransformer(transformer);
- pipe.setReader(reader);
- pipe.setWriter(writer);
- pipe.run();
- } finally {
- if (reader != null) {
- reader.close();
- dump = ((LoggedXMLDirectoryReader)reader).report();
- }
- if (writer != null) {
- writer.close();
- }
- }
- return dump;
- }
+package org.collectionspace.services.imports.nuxeo;\r
+\r
+import java.io.File;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.TreeSet;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
- import org.collectionspace.services.client.PoxPayloadIn;\r
- import org.collectionspace.services.client.PoxPayloadOut;\r
- import org.collectionspace.services.common.context.ServiceContext;\r
+import org.collectionspace.services.nuxeo.client.java.NuxeoClientEmbedded;\r
+import org.collectionspace.services.nuxeo.client.java.NuxeoConnectorEmbedded;\r
- import org.collectionspace.services.nuxeo.util.NuxeoUtils;\r
+import org.nuxeo.ecm.core.api.DocumentModel;\r
+import org.nuxeo.ecm.core.api.DocumentRef;\r
+import org.nuxeo.ecm.core.api.repository.RepositoryInstance;\r
+import org.nuxeo.ecm.core.io.DocumentPipe;\r
+import org.nuxeo.ecm.core.io.DocumentReader;\r
+import org.nuxeo.ecm.core.io.DocumentTranslationMap;\r
+import org.nuxeo.ecm.core.io.DocumentWriter;\r
+import org.nuxeo.ecm.core.io.impl.DocumentPipeImpl;\r
+import org.nuxeo.ecm.core.io.impl.plugins.DocumentModelWriter;\r
+// we use our own override of this: import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader;\r
+\r
+// based loosely on package org.nuxeo.ecm.shell.commands.io.ImportCommand;\r
+public class ImportCommand {\r
+ private static final Log logger = LogFactory.getLog(ImportCommand.class);\r
+\r
+ public String run(String src, String dest) throws Exception {\r
+ File file = new File(src);\r
+ ///cspace way of configuring client and auth:\r
+ NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();\r
+ RepositoryInstance repoSession = client.openRepository();\r
+ try {\r
+ return importTree(repoSession, file, dest);\r
+ } catch (Exception e) {\r
+ throw e;\r
+ } finally {\r
+// repository.close();\r
+ client.releaseRepository(repoSession);\r
+ }\r
+ }\r
+\r
+ String importTree(RepositoryInstance repoSession, File file, String toPath) throws Exception {\r
+ DocumentReader reader = null;\r
+ DocumentWriter writer = null;\r
+ DocumentModel docModel = null;\r
+ DocumentRef keyDocRef, valueDocRef;\r
+ String docType;\r
+ StringBuffer dump = new StringBuffer();\r
+ Map<String,Integer> recordsImportedForDocType = new HashMap<String,Integer>();\r
+ Integer numRecordsImportedForDocType = new Integer(0);\r
+ int totalRecordsImported = 0;\r
+ try {\r
+ System.out.println("importTree reading file: "+file+(file!=null ? " exists? "+file.exists() : " file param is null"));\r
+ reader = new LoggedXMLDirectoryReader(file); //our overload of XMLDirectoryReader.\r
+ writer = new DocumentModelWriter(repoSession, toPath, 10);\r
+ DocumentPipe pipe = new DocumentPipeImpl(10);\r
+ // pipe.addTransformer(transformer);\r
+ pipe.setReader(reader);\r
+ pipe.setWriter(writer);\r
+ // FIXME: pipe.run() appears to return at least one type\r
+ // of Exception that is logged but not thrown; this is a\r
+ // potential workaround\r
+ DocumentTranslationMap dtm = pipe.run();\r
+ Map<DocumentRef,DocumentRef> documentRefs = dtm.getDocRefMap();\r
+ dump.append("<importedRecords>");\r
+ for (Map.Entry entry: documentRefs.entrySet()) {\r
+ keyDocRef = (DocumentRef) entry.getKey();\r
+ valueDocRef = (DocumentRef) entry.getValue();\r
+ if (keyDocRef == null || valueDocRef == null) {\r
+ continue;\r
+ }\r
+ // System.out.println("value="+entry.getValue());\r
+ // System.out.println("key="+entry.getKey());\r
+\r
+ docModel = repoSession.getDocument((DocumentRef) entry.getValue());\r
+ // System.out.println("value doctype="+docModel.getDocumentType().toString());\r
+\r
+ dump.append("<importedRecord>");\r
+ docModel = repoSession.getDocument(valueDocRef);\r
+ docType = docModel.getDocumentType().getName();\r
+ // System.out.println(docType);\r
+ dump.append("<doctype>"+docType+"</doctype>");\r
+ dump.append("<csid>"+keyDocRef.toString()+"</csid>");\r
+ dump.append("</importedRecord>");\r
+ // System.out.println(dump.toString());\r
+ if (recordsImportedForDocType.containsKey(docType)) {\r
+ numRecordsImportedForDocType = (Integer) recordsImportedForDocType.get(docType);\r
+ numRecordsImportedForDocType = Integer.valueOf(numRecordsImportedForDocType.intValue() + 1);\r
+ recordsImportedForDocType.put(docType, numRecordsImportedForDocType);\r
+ } else {\r
+ recordsImportedForDocType.put(docType, 1);\r
+ }\r
+ totalRecordsImported++;\r
+ }\r
+ dump.append("</importedRecords>");\r
+ } catch (Exception e) {\r
+ throw e;\r
+ } finally {\r
+ dump.append("<totalRecordsImported>"+totalRecordsImported+"</totalRecordsImported>");\r
+ dump.append("<numRecordsImportedByDocType>");\r
+ TreeSet<String> keys = new TreeSet<String>(recordsImportedForDocType.keySet());\r
+ for (String key : keys) {\r
+ dump.append("<docType>"+key+"</docType>");\r
+ dump.append("<numRecords>"+recordsImportedForDocType.get(key).intValue()+"</numRecords>");\r
+ }\r
+ dump.append("</numRecordsImportedByDocType>");\r
+ if (reader != null) {\r
+ dump.append("<report>"+(((LoggedXMLDirectoryReader)reader).report())+"</report>");\r
+ reader.close();\r
+ }\r
+ if (writer != null) {\r
+ writer.close();\r
+ }\r
+ }\r
+ return dump.toString();\r
+ }\r
}
- package org.collectionspace.services.imports.nuxeo;\r
- \r
- import java.io.BufferedInputStream;\r
- import java.io.File;\r
- import java.io.FileFilter;\r
- import java.io.FileInputStream;\r
- import java.io.IOException;\r
- import java.util.ArrayList;\r
- import java.util.List;\r
- \r
- import org.dom4j.Document;\r
- import org.dom4j.DocumentException;\r
- import org.dom4j.io.SAXReader;\r
- import org.nuxeo.common.utils.FileTreeIterator;\r
- import org.nuxeo.common.utils.FileUtils;\r
- import org.nuxeo.common.utils.Path;\r
- import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob;\r
- import org.nuxeo.ecm.core.io.ExportConstants;\r
- import org.nuxeo.ecm.core.io.ExportedDocument;\r
- import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader;\r
- import org.nuxeo.ecm.core.io.impl.ExportedDocumentImpl;\r
- import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader;\r
- import org.nuxeo.runtime.services.streaming.FileSource;\r
- \r
- public class LoggedXMLDirectoryReader extends AbstractDocumentReader {\r
- \r
- protected Document loadXML(File file) throws IOException {\r
- String filename = file.getCanonicalPath();\r
- System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename);\r
- BufferedInputStream in = null;\r
- try {\r
- in = new BufferedInputStream(new FileInputStream(file));\r
- System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: DONE");\r
- reportList.add("READ: "+filename);\r
- return new SAXReader().read(in);\r
- } catch (DocumentException e) {\r
- IOException ioe = new IOException("Failed to read file document "\r
- + file + ": " + e.getMessage());\r
- ioe.setStackTrace(e.getStackTrace());\r
- System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: ERROR");\r
- reportList.add("ERROR: "+filename);\r
- throw ioe;\r
- } finally {\r
- if (in != null) {\r
- in.close();\r
- }\r
- }\r
- }\r
- \r
- private File source;\r
- \r
- private FileTreeIterator iterator;\r
- \r
- public LoggedXMLDirectoryReader(String sourcePath) {\r
- this(new File(sourcePath));\r
- }\r
- \r
- public LoggedXMLDirectoryReader(File source) {\r
- this.source = source;\r
- iterator = new FileTreeIterator(source);\r
- iterator.setFilter(new FileFilter() {\r
- public boolean accept(File pathname) {\r
- return pathname.isDirectory();\r
- }\r
- });\r
- }\r
- \r
- public Object getSource() {\r
- return source;\r
- }\r
- \r
- public void setSource(File source) {\r
- this.source = source;\r
- }\r
- \r
- public void close() {\r
- source = null;\r
- iterator = null;\r
- }\r
- \r
- private List<String> reportList = new ArrayList<String>();\r
- public String report(){\r
- StringBuffer result = new StringBuffer();\r
- for (String s: reportList){\r
- result.append(s).append("\r\n");\r
- }\r
- return result.toString();\r
- }\r
- \r
- \r
- @Override\r
- public ExportedDocument read() throws IOException {\r
- if (iterator.hasNext()) {\r
- File dir = iterator.next();\r
- if (dir == null) {\r
- return null;\r
- }\r
- // read document files\r
- ExportedDocument xdoc = new ExportedDocumentImpl();\r
- for (File file : dir.listFiles()) {\r
- if (file.isFile()) {\r
- String name = file.getName();\r
- if (ExportConstants.DOCUMENT_FILE.equals(name)) {\r
- Document doc = loadXML(file);\r
- xdoc.setDocument(doc);\r
- Path relPath = computeRelativePath(dir);\r
- xdoc.setPath(relPath);\r
- reportList.add(relPath.toString());\r
- } else if (name.endsWith(".xml")) {\r
- xdoc.putDocument(\r
- FileUtils.getFileNameNoExt(file.getName()),\r
- loadXML(file));\r
- } else { // presume a blob\r
- xdoc.putBlob(file.getName(), new StreamingBlob(\r
- new FileSource(file)));\r
- }\r
- }\r
- }\r
- return xdoc;\r
- }\r
- return null;\r
- }\r
- \r
- /*NXP-1688 Rux: the path was somehow left over when migrated from\r
- core 1.3.4 to 1.4.0. Pull back.*/\r
- private Path computeRelativePath(File file) {\r
- /*NXP-2507 Rux: preserve directory structure with slashes instead OS name separator*/\r
- String subPathS =\r
- file.getAbsolutePath().substring(source.getAbsolutePath().length());\r
- subPathS = subPathS.replace(File.separatorChar, '/');\r
- return new Path(subPathS);\r
- }\r
- \r
+ package org.collectionspace.services.imports.nuxeo;
+
+ import java.io.BufferedInputStream;
+ import java.io.File;
+ import java.io.FileFilter;
+ import java.io.FileInputStream;
+ import java.io.IOException;
+ import java.util.ArrayList;
+ import java.util.List;
+
+ import org.dom4j.Document;
+ import org.dom4j.DocumentException;
+ import org.dom4j.io.SAXReader;
+ import org.nuxeo.common.utils.FileTreeIterator;
+ import org.nuxeo.common.utils.FileUtils;
+ import org.nuxeo.common.utils.Path;
+ import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob;
+ import org.nuxeo.ecm.core.io.ExportConstants;
+ import org.nuxeo.ecm.core.io.ExportedDocument;
+ import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader;
+ import org.nuxeo.ecm.core.io.impl.ExportedDocumentImpl;
-import org.nuxeo.ecm.core.io.impl.plugins.XMLDirectoryReader;
+ import org.nuxeo.runtime.services.streaming.FileSource;
+
+ public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
+
+ protected Document loadXML(File file) throws IOException {
+ String filename = file.getCanonicalPath();
+ System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename);
+ BufferedInputStream in = null;
+ try {
+ in = new BufferedInputStream(new FileInputStream(file));
+ System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: DONE");
+ reportList.add("READ: "+filename);
+ return new SAXReader().read(in);
+ } catch (DocumentException e) {
+ IOException ioe = new IOException("Failed to read file document "
+ + file + ": " + e.getMessage());
+ ioe.setStackTrace(e.getStackTrace());
+ System.out.println("~~~~~~~~~~~~~~~~~~~ LoggedXMLDirectoryReader :: "+filename+" :: ERROR");
+ reportList.add("ERROR: "+filename);
+ throw ioe;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+ }
+
+ private File source;
+
+ private FileTreeIterator iterator;
+
+ public LoggedXMLDirectoryReader(String sourcePath) {
+ this(new File(sourcePath));
+ }
+
+ public LoggedXMLDirectoryReader(File source) {
+ this.source = source;
+ iterator = new FileTreeIterator(source);
+ iterator.setFilter(new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+ }
+
+ public Object getSource() {
+ return source;
+ }
+
+ public void setSource(File source) {
+ this.source = source;
+ }
+
+ public void close() {
+ source = null;
+ iterator = null;
+ }
+
+ private List<String> reportList = new ArrayList<String>();
+ public String report(){
+ StringBuffer result = new StringBuffer();
+ for (String s: reportList){
+ result.append(s).append("\r\n");
+ }
+ return result.toString();
+ }
+
+
+ @Override
+ public ExportedDocument read() throws IOException {
+ if (iterator.hasNext()) {
+ File dir = iterator.next();
+ if (dir == null) {
+ return null;
+ }
+ // read document files
+ ExportedDocument xdoc = new ExportedDocumentImpl();
+ for (File file : dir.listFiles()) {
+ if (file.isFile()) {
+ String name = file.getName();
+ if (ExportConstants.DOCUMENT_FILE.equals(name)) {
+ Document doc = loadXML(file);
+ xdoc.setDocument(doc);
+ Path relPath = computeRelativePath(dir);
+ xdoc.setPath(relPath);
+ reportList.add(relPath.toString());
+ } else if (name.endsWith(".xml")) {
+ xdoc.putDocument(
+ FileUtils.getFileNameNoExt(file.getName()),
+ loadXML(file));
+ } else { // presume a blob
+ xdoc.putBlob(file.getName(), new StreamingBlob(
+ new FileSource(file)));
+ }
+ }
+ }
+ return xdoc;
+ }
+ return null;
+ }
+
+ /*NXP-1688 Rux: the path was somehow left over when migrated from
+ core 1.3.4 to 1.4.0. Pull back.*/
+ private Path computeRelativePath(File file) {
+ /*NXP-2507 Rux: preserve directory structure with slashes instead OS name separator*/
+ String subPathS =
+ file.getAbsolutePath().substring(source.getAbsolutePath().length());
+ subPathS = subPathS.replace(File.separatorChar, '/');
+ return new Path(subPathS);
+ }
+
}
@GET
@Produces({"application/xml"})
ClientResponse<AbstractCommonList> readIncludeDeleted(
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
@Override
@GET
@Produces({"application/xml"})
ClientResponse<AbstractCommonList> keywordSearchIncludeDeleted(
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
@GET
@Produces({"application/xml"})
@GET\r
@Produces({"application/xml"})\r
ClientResponse<NotesCommonList> readIncludeDeleted(\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted); \r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState); \r
\r
@Override\r
@GET\r
@Produces({"application/xml"})\r
ClientResponse<NotesCommonList> keywordSearchIncludeDeleted(\r
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,\r
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);\r
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);\r
\r
/*\r
//(C)reate\r
@GET
@Produces({"application/xml"})
ClientResponse<RelationsCommonList> readIncludeDeleted(
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
@Override
@GET
@Produces({"application/xml"})
ClientResponse<RelationsCommonList> keywordSearchIncludeDeleted(
@QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords,
-- @QueryParam(WorkflowClient.WORKFLOW_QUERY_NONDELETED) String includeDeleted);
++ @QueryParam(WorkflowClient.WORKFLOWSTATE_QUERY) String workflowState);
@GET
@Produces({"application/xml"})
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.ResourceBase;
--import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.api.RefName;
import org.collectionspace.services.common.api.Tools;
-
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.context.ServiceBindingUtils;
import org.collectionspace.services.common.document.DocumentNotFoundException;
++import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.document.InvalidDocumentException;
import org.collectionspace.services.common.relation.RelationJAXBSchema;
import org.collectionspace.services.common.relation.nuxeo.RelationConstants;
-import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
-import org.collectionspace.services.common.context.ServiceBindingUtils;
import org.collectionspace.services.common.context.ServiceContext;
--import org.collectionspace.services.common.repository.RepositoryClient;
--import org.collectionspace.services.common.repository.RepositoryClientFactory;
- import org.collectionspace.services.common.service.ServiceBindingType;
-
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
-
import org.collectionspace.services.relation.RelationsCommon;
import org.collectionspace.services.relation.RelationsCommonList;
import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
++import org.collectionspace.services.relation.RelationsDocListItem;
// HACK HACK HACK
import org.collectionspace.services.client.PersonAuthorityClient;
import org.collectionspace.services.client.OrgAuthorityClient;
import org.collectionspace.services.client.LocationAuthorityClient;
-import org.collectionspace.services.client.PlaceAuthorityClient;
import org.collectionspace.services.client.TaxonomyAuthorityClient;
+import org.collectionspace.services.client.PlaceAuthorityClient;
+import org.collectionspace.services.client.ConceptAuthorityClient;
--import org.collectionspace.services.common.document.DocumentWrapper;
- import org.collectionspace.services.jaxb.AbstractCommonList;
+ import org.collectionspace.services.config.service.ServiceBindingType;
-import org.collectionspace.services.jaxb.AbstractCommonList;
import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl;
--import org.collectionspace.services.relation.RelationsDocListItem;
-
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
@Override
public void update(String testName) throws Exception {
setupUpdate();
-- updateLifeCycleState(testName, knownResourceId, WorkflowClient.WORKFLOWSTATE_APPROVED);
++ updateLifeCycleState(testName, knownResourceId, WorkflowClient.WORKFLOWTRANSITION_DELETE, WorkflowClient.WORKFLOWSTATE_DELETED);
}
@Override