]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
Merge branch 'CSPACE-4964' back to trunk. Includes work in the service layer for...
authorRichard Millet <remillet@berkeley.edu>
Wed, 11 Apr 2012 21:45:56 +0000 (14:45 -0700)
committerRichard Millet <remillet@berkeley.edu>
Wed, 11 Apr 2012 21:45:56 +0000 (14:45 -0700)
34 files changed:
1  2 
services/JaxRsServiceProvider/pom.xml
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java
services/client/src/main/java/org/collectionspace/services/client/AbstractServiceClientImpl.java
services/client/src/main/java/org/collectionspace/services/client/AuthorityProxy.java
services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClient.java
services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceCommonListPoxProxy.java
services/client/src/main/java/org/collectionspace/services/client/CollectionSpacePoxProxy.java
services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceProxy.java
services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java
services/client/src/main/java/org/collectionspace/services/client/workflow/WorkflowClient.java
services/common/src/main/cspace/config/services/service-config.xml
services/common/src/main/cspace/config/services/tenants/lifesci/tenant-bindings.delta.xml
services/common/src/main/cspace/config/services/tenants/tenant-bindings-proto.xml
services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java
services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java
services/common/src/main/java/org/collectionspace/services/common/workflow/service/nuxeo/WorkflowDocumentModelHandler.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java
services/dimension/client/src/main/java/org/collectionspace/services/client/DimensionProxy.java
services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java
services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java
services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java
services/movement/client/src/main/java/org/collectionspace/services/client/MovementProxy.java
services/note/client/src/main/java/org/collectionspace/services/client/NoteProxy.java
services/pom.xml
services/relation/client/src/main/java/org/collectionspace/services/client/RelationProxy.java
services/relation/service/pom.xml
services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationDocumentModelHandler.java
services/servicegroup/service/src/main/java/org/collectionspace/services/servicegroup/nuxeo/ServiceGroupDocumentModelHandler.java
services/workflow/client/src/test/java/org/collectionspace/services/client/test/WorkflowServiceTest.java

Simple merge
index f898152a32dbe9891084eb88fba32ff51349ce3a,f898152a32dbe9891084eb88fba32ff51349ce3a..377fb551a6f089a57cb0874ce2daaeae409d47c9
@@@ -430,8 -430,8 +430,8 @@@ public abstract class AbstractServiceCl
      }\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
index 52493c81e12b4251d9e3ab31b0b29ccc6782f4d0,52493c81e12b4251d9e3ab31b0b29ccc6782f4d0..178f1409c121610f2e46ee1b65c7f311674d8fe7
@@@ -37,7 -37,7 +37,7 @@@ public interface AuthorityProxy extend
      @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
@@@ -64,7 -64,7 +64,7 @@@
      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
@@@ -82,7 -82,7 +82,7 @@@
      @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
index 668a8664d719fdc8c92acfb033d214f9c6cd2fe3,668a8664d719fdc8c92acfb033d214f9c6cd2fe3..7652020a16a1aa94bae3c4927a10f4f9a07da351
@@@ -193,7 -193,7 +193,7 @@@ public interface CollectionSpaceClient<
       */
      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.
index 6ca1698449828ec64a995932ae032ffa69b9c34c,6ca1698449828ec64a995932ae032ffa69b9c34c..6ee3dfd7f2d25f7b1f505ed7c0fdf3b04c4dba8a
@@@ -16,19 -16,19 +16,19 @@@ public interface CollectionSpaceCommonL
        @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
index e09c6f538b064f7eb4a4b8d95934e0bcca1ad7f0,e09c6f538b064f7eb4a4b8d95934e0bcca1ad7f0..0e760ba4e49aee10c35b31808462b4aa7c6be613
@@@ -30,7 -30,7 +30,7 @@@ public interface CollectionSpacePoxProx
        @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
index 21df5873a983c84407b042b59a9f1e176c820e04,21df5873a983c84407b042b59a9f1e176c820e04..18acc9eced1323d7e97efb663f4782a07a14593c
@@@ -67,8 -67,8 +67,8 @@@ public interface CollectionSpaceProxy<C
      @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
index 2a1edf9adb9da1419580433ea70d3d34420f9e92,2a1edf9adb9da1419580433ea70d3d34420f9e92..510ad38f2c7478d5366d866a33f87262a40c6220
@@@ -530,7 -530,7 +530,7 @@@ public abstract class AbstractServiceTe
              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());
index 4e5ddc2eb6cea4241ddbb648a80e0b99b97df821,6db639d37d84d893e50cd68c1dbe3733fdc22357..c3ea8854ebc5fb1eb11328174813b771a2d41dd8
@@@ -39,13 -39,17 +39,23 @@@ public class WorkflowClient extends Abs
        //
        // 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
index 06b54323877e596ae324d66bdda57e62aa2f6947,890fa00c457f9f4def528f60890fccec42de10b8..d4d669e4b39d657fdc32ae7d4f68f5089c5d39c8
@@@ -26,6 -26,6 +26,7 @@@
          <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>
  
index 3de2dde8a9db3e565887099e0cb9ac5a96675a76,e24cf4664f0f9a5d0de120c9d276900e492902c8..b9c0a76e31c7a54b65634ac542f39b2c87163ce6
@@@ -40,8 -40,7 +40,8 @@@
                                                <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>
index 9d99add93a5a50a2981d6571b38907d0cdf5fb2f,fd1b92a706e0c6cabd195aa3253e3fc7ead2e454..82464e5b0ea0883b9b91a286a64878178412f06b
                          <!-- 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>
index 62ac660e8ff48c72ee816092ef2591e0211f2f05,bf4113d02fb238af47d3cdb7672d75e164dc5f57..c5221920695a390866c3cff97cb733f67311ddd5
  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
index 9d6afc82d53ac0c7f24efcedfed517a1425442ba,934a90cacef77b5ca24848f9d948f783705be96b..58de69b16d7a57110102e16d0ff371d28bd59ba1
@@@ -3,17 -3,13 +3,16 @@@ package org.collectionspace.services.co
  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
index 59b3348000b3679390224e1c548ba24f8cad9622,29f297b5929e4431f535645e91504ee878ee242d..f4d12ae6e5b2391fcd99f60f76974aec9bb172fb
@@@ -118,6 -113,6 +113,7 @@@ public class WorkflowDocumentModelHandl
       * @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);
index fd43e68efdac6e3ecfd2eb989fc02f64dc56ae2f,9fb971bd5aec83c2b9532576f2ae84eede430a15..e9a2d8ebe989e41f47a544fd0043d25d2549764f
@@@ -71,8 -78,115 +78,116 @@@ public abstract class DocumentModelHand
      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.
index 2bb8aa96adf7aeab734713cbcb82cc9f001bff4d,2bb8aa96adf7aeab734713cbcb82cc9f001bff4d..113ea8fe6ae3e2cd2270ae596afc3274326fcfe9
@@@ -17,7 -17,7 +17,6 @@@
   */
  package org.collectionspace.services.nuxeo.client.java;
  
--import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.List;
index f8d729dc97aaf7bf500db047337677e7bee11be4,f8d729dc97aaf7bf500db047337677e7bee11be4..b3a848674a457c0f45d38ba6eb7c41482f356d95
@@@ -25,12 -25,12 +25,12 @@@ public interface DimensionProxy extend
        @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);
  }
index 8fe6b217f375c339e0c0b6f7cb8965d005d83a3b,75109b400e031a7e1ebb9a66634d5f1b181b9d76..b55710945bbd38f8d1c33cf827c66273f556398d
@@@ -35,14 -32,12 +35,14 @@@ import org.collectionspace.services.com
  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;
index 255ba79f760854e0230bf8c63905c03c7d9876f0,37b23919efda524dd4d5b00ff48c9d8328e7deec..11f2cb54a4f51d52c0a3958d4dd95c3cb9e0278b
 -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
  }
index 125976ff291482899a803f1e59160534692b921b,36f0a3ebe86259013b892fb05b6432c2949ab099..6d2ed5713e2112d81fb385bf42e0beafe4121521
- 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);
+     }
  }
index 3c8ed92ff5d715408324aff257c4b1e1beb4c1a9,3c8ed92ff5d715408324aff257c4b1e1beb4c1a9..3fc883d2a09e5840f52636ac1dfaa5a9aa2227d4
@@@ -55,14 -55,14 +55,14 @@@ public interface MovementProxy extends 
        @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"})
index f2402c629d7faef969cb958eaff88c0b4192a1cf,f2402c629d7faef969cb958eaff88c0b4192a1cf..d0669f1e85e8ad501fa382fef3e1cb1d4eb4abd4
@@@ -31,14 -31,14 +31,14 @@@ public interface NoteProxy extends Coll
        @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
Simple merge
index e642644ec78a1bdf99c092be4cd805a971f69776,e642644ec78a1bdf99c092be4cd805a971f69776..eeb1cf73dfb5a66b802ae9adf8cc2ec2b9534451
@@@ -28,14 -28,14 +28,14 @@@ public interface RelationProxy extends 
        @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"})
Simple merge
index b3614f2f9665e928a1ff055d09168edf49d197fa,0405bbb8e3f1934b4b4e175aed30d66898fe7c4a..a14a6294bb58b93d325129c27fc0c1ed22af73e0
@@@ -29,38 -29,41 +29,34 @@@ import java.util.Iterator
  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;
index 387685ee44eca3f211e6b4abb1a2b28591b52957,387685ee44eca3f211e6b4abb1a2b28591b52957..44f115c505ca97be98d2fc1b7271981b6e9056fe
@@@ -105,7 -105,7 +105,7 @@@ public class WorkflowServiceTest extend
      @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