]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-221: Refactor persistence of AuthN/AuthZ entities to support better transaction...
authorremillet <remillet@yahoo.com>
Fri, 29 Dec 2017 22:24:24 +0000 (14:24 -0800)
committerremillet <remillet@yahoo.com>
Fri, 29 Dec 2017 22:24:24 +0000 (14:24 -0800)
37 files changed:
services/account/client/src/main/java/org/collectionspace/services/client/AccountFactory.java
services/account/client/src/main/java/org/collectionspace/services/client/AccountRoleFactory.java
services/account/jaxb/src/main/resources/accounts_common.xsd
services/account/pstore/src/main/resources/db/postgresql/account.sql
services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
services/account/service/src/main/java/org/collectionspace/services/account/AccountRoleSubResource.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountRoleDocumentHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantStorageClient.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/csidp/UserStorageClient.java
services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/RoleServiceTest.java
services/authorization-mgt/import/src/main/java/org/collectionspace/ImportAuthz.java
services/authorization-mgt/import/src/main/java/org/collectionspace/services/authorization/driver/AuthorizationSeedDriver.java
services/authorization-mgt/import/src/main/java/org/collectionspace/services/authorization/importer/AuthorizationGen.java
services/authorization-mgt/import/src/main/java/org/collectionspace/services/authorization/importer/AuthorizationSeed.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/RoleResource.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/RoleDocumentHandler.java
services/authorization/jaxb/src/main/resources/authorization_common.xsd
services/common/src/main/java/org/collectionspace/services/authorization/PermissionResource.java
services/common/src/main/java/org/collectionspace/services/authorization/PermissionRoleSubResource.java
services/common/src/main/java/org/collectionspace/services/authorization/storage/AuthorizationDelegate.java
services/common/src/main/java/org/collectionspace/services/authorization/storage/PermissionDocumentHandler.java
services/common/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleDocumentHandler.java
services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java
services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java
services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java
services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationStore.java
services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/PermissionRoleUtil.java
services/common/src/main/java/org/collectionspace/services/common/context/RemoteServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/storage/TransactionContext.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JPATransactionContext.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaRelationshipStorageClient.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java

index e464c8ff4867aba9cb30369ead41d4d033e8373f..756f46d07c8b8637b57b9e875d68d9a286764f19 100644 (file)
@@ -29,6 +29,7 @@ import java.util.List;
 import java.util.UUID;
 import org.collectionspace.services.account.AccountTenant;
 import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.authorization.AccountValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -102,4 +103,14 @@ public class AccountFactory {
 
     }
 
+   static public AccountValue createAccountValue(AccountsCommon accountsCommon) {
+       AccountValue result = new AccountValue();
+       
+       result.setAccountId(accountsCommon.getCsid());
+       result.setScreenName(accountsCommon.getScreenName());
+       result.setUserId(accountsCommon.getUserId());
+
+       return result;
+   }
+   
 }
index 0e4d758a1ee84380617198dbc08d46ce35d0a789..e8b207d2baca458885d77e5443c0833114d54dbf 100644 (file)
@@ -26,10 +26,15 @@ package org.collectionspace.services.client;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
+
+import org.collectionspace.services.account.AccountsCommon;
 import org.collectionspace.services.authorization.AccountRole;
 import org.collectionspace.services.authorization.AccountValue;
 import org.collectionspace.services.authorization.SubjectType;
+
 import org.collectionspace.services.authorization.RoleValue;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,30 +48,30 @@ public class AccountRoleFactory {
  /**
      * Creates the account role instance.
      *
-     * @param pv the pv
-     * @param rvs the rvs
-     * @param usePermId the use perm id
+     * @param accountValue the pv
+     * @param roleValueList the rvs
+     * @param useAccountId the use perm id
      * @param useRoleId the use role id
      * @return the account role
      */
-    static public AccountRole createAccountRoleInstance(AccountValue pv,
-            Collection<RoleValue> rvs,
-            boolean usePermId,
+    static public AccountRole createAccountRoleInstance(AccountValue accountValue,
+            Collection<RoleValue> roleValueList,
+            boolean useAccountId,
             boolean useRoleId) {
 
         AccountRole accRole = new AccountRole();
         //service consume is not required to provide subject as it is determined
         //from URI used
         accRole.setSubject(SubjectType.ROLE);
-        if (usePermId) {
+        if (useAccountId) {
             ArrayList<AccountValue> pvs = new ArrayList<AccountValue>();
-            pvs.add(pv);
+            pvs.add(accountValue);
             accRole.setAccount(pvs);
         }
         if (useRoleId) {
             //FIXME is there a better way?
             ArrayList<RoleValue> rvas = new ArrayList<RoleValue>();
-            for (RoleValue rv : rvs) {
+            for (RoleValue rv : roleValueList) {
                 rvas.add(rv);
             }
             accRole.setRole(rvas);
@@ -75,5 +80,51 @@ public class AccountRoleFactory {
         return accRole;
     }
 
+    /*
+     * Convert the Account service's RoleValue list to the AuthZ RoleValue list we need
+     */
+    static public AccountRole createAccountRoleInstance(AccountsCommon accountsCommon,
+            Collection<org.collectionspace.services.account.RoleValue> roleValueList,
+            boolean useAccountId,
+            boolean useRoleId) {
+       
+       Collection<RoleValue> authzRoleValueList = new ArrayList<RoleValue>();
+       if (roleValueList != null && roleValueList.size() > 0) {
+               for (org.collectionspace.services.account.RoleValue rv : roleValueList) {
+                       RoleValue authzRoleValue = new RoleValue();
+                       authzRoleValue.setDisplayName(rv.getDisplayName());
+                       authzRoleValue.setRoleId(rv.getRoleId());
+                       authzRoleValue.setRoleName(rv.getRoleName());
+                       authzRoleValue.setRoleRelationshipId(rv.getRoleRelationshipId());
+                       authzRoleValue.setTenantId(rv.getTenantId());
+                       authzRoleValueList.add(authzRoleValue);
+               }
+       }
 
+               AccountValue accountValue = AccountFactory.createAccountValue(accountsCommon);
+        return AccountRoleFactory.createAccountRoleInstance(accountValue, authzRoleValueList, useAccountId, useRoleId);
+    }
+    
+    /**
+     * Converts a standard RoleValue list to the type needed by the Account resource.
+     * @param roleValueList
+     * @return
+     */
+    static public List<org.collectionspace.services.account.RoleValue> convert(List<RoleValue> roleValueList) {
+       List<org.collectionspace.services.account.RoleValue> result = new ArrayList<org.collectionspace.services.account.RoleValue>();
+       
+       if (roleValueList != null && roleValueList.size() > 0) {
+               for (RoleValue rv : roleValueList) {
+                       org.collectionspace.services.account.RoleValue accountRoleValue = new org.collectionspace.services.account.RoleValue();
+                       accountRoleValue.setDisplayName(rv.getDisplayName());
+                       accountRoleValue.setRoleId(rv.getRoleId());
+                       accountRoleValue.setRoleName(rv.getRoleName());
+                       accountRoleValue.setRoleRelationshipId(rv.getRoleRelationshipId());
+                       accountRoleValue.setTenantId(rv.getTenantId());
+                       result.add(accountRoleValue);
+               }
+       }
+       
+       return result;
+    }
 }
index cdd208f3a96945cbb0a9a9e0ed1e050321cd0700..51a1e908381f054fa23b6b0aa764fee967ad5c1a 100644 (file)
@@ -54,6 +54,9 @@
                 <xs:appinfo>
                     <hj:entity>
                         <orm:table name="accounts_common">
+                               <orm:unique-constraint>
+                                   <orm:column-name>userid</orm:column-name>
+                                   </orm:unique-constraint>
                         </orm:table>
                     </hj:entity>
                 </xs:appinfo>
                         </xs:appinfo>
                     </xs:annotation>
                 </xs:element>
+                <xs:element name="role" type="ns:role_value" minOccurs="1" maxOccurs="unbounded"/>
             </xs:sequence>
             <xs:attribute name="csid" type="xs:string">
                 <xs:annotation>
         </xs:complexType>
     </xs:element>
 
+    <xs:complexType name="role_value" >
+        <xs:annotation>
+            <xs:documentation>
+                RoleValue is used relationships
+            </xs:documentation>
+            <xs:appinfo>
+                <hj:ignored/>
+            </xs:appinfo>
+        </xs:annotation>
+        <xs:sequence>
+               <xs:element name="roleRelationshipId" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="roleId" type="xs:string" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="roleName" type="xs:string" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="displayName" type="xs:string" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="tenantId" type="xs:string" minOccurs="1" maxOccurs="1"/>
+        </xs:sequence>
+    </xs:complexType>
+    
     <!-- This is the base class for paginated lists -->
     <xs:complexType name="abstractCommonList">
         <xs:annotation>
index 74f75df2385427e2afa5b023c2af392bc7cc28fc..307e9b0e0fd5c9030c662f9f35051585bc85a570 100644 (file)
@@ -3,7 +3,7 @@ DROP TABLE IF EXISTS accounts_common CASCADE;
 DROP TABLE IF EXISTS accounts_tenants CASCADE;
 DROP TABLE IF EXISTS tenants CASCADE;
 DROP SEQUENCE IF EXISTS hibernate_sequence;
-create table accounts_common (csid varchar(128) not null, created_at timestamp not null, email varchar(255) not null, mobile varchar(255), person_ref_name varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, updated_at timestamp, userid varchar(128) not null, metadata_protection varchar(255), roles_protection varchar(255), primary key (csid));
+create table accounts_common (csid varchar(128) not null, created_at timestamp not null, email varchar(255) not null, mobile varchar(255), person_ref_name varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, updated_at timestamp, userid varchar(128) not null, metadata_protection varchar(255), roles_protection varchar(255), primary key (csid), unique (userid));
 create table accounts_tenants (HJID int8 not null, tenant_id varchar(128) not null, TENANTS_ACCOUNTS_COMMON_CSID varchar(128), primary key (HJID));
 create table tenants (id varchar(128) not null, created_at timestamp not null, name varchar(255) not null, config_md5hash varchar(255), authorities_initialized boolean not null, disabled boolean not null, updated_at timestamp, primary key (id));
 alter table accounts_tenants add constraint FKFDA649B05A9CEEB5 foreign key (TENANTS_ACCOUNTS_COMMON_CSID) references accounts_common;
index 38e67812881a82726f48d2e920495891da3f02bf..d7a86fb48d876ae3ddccd00af637e03c38d0d14b 100644 (file)
@@ -68,7 +68,6 @@ import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -111,12 +110,14 @@ public class AccountResource extends SecurityResourceBase {
         return AccountsCommon.class;
     }
 
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public ServiceContextFactory<AccountsCommon, AccountsCommon> getServiceContextFactory() {
         return (ServiceContextFactory<AccountsCommon, AccountsCommon>) RemoteServiceContextFactory.get();
     }
 
-    @Override
+    @SuppressWarnings("rawtypes")
+       @Override
     public StorageClient getStorageClient(ServiceContext ctx) {
         //FIXME use ctx to identify storage client
         return storageClient;
@@ -445,26 +446,34 @@ public class AccountResource extends SecurityResourceBase {
     public Response deleteAccount(@Context UriInfo uriInfo, @PathParam("csid") String csid) {
         logger.debug("deleteAccount with csid=" + csid);
         ensureCSID(csid, ServiceMessages.DELETE_FAILED);
+        
         try {
                AccountsCommon account = (AccountsCommon)get(csid, AccountsCommon.class);
             // If marked as metadata immutable, do not delete
-            if(AccountClient.IMMUTABLE.equals(account.getMetadataProtection())) {
+            if (AccountClient.IMMUTABLE.equals(account.getMetadataProtection())) {
                 Response response =
                        Response.status(Response.Status.FORBIDDEN).entity("Account: "+csid+" is immutable.").type("text/plain").build();
                 return response;
             }
-            //FIXME ideally the following two ops should be in the same tx CSPACE-658
-            //delete all relationships
-            AccountRoleSubResource subResource = new AccountRoleSubResource("accounts/accountroles");
-            subResource.deleteAccountRole(csid, SubjectType.ROLE);
+            //
+            // We need to delete the account and the account/role relationships in a
+            // single transaction
+            //
             ServiceContext<AccountsCommon, AccountsCommon> ctx = createServiceContext((AccountsCommon) null,
                     AccountsCommon.class, uriInfo);
-            getStorageClient(ctx).delete(ctx, csid);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            ctx.openConnection();
+            try {
+                   AccountRoleSubResource subResource = new AccountRoleSubResource("accounts/accountroles");
+                   subResource.deleteAccountRole(ctx, csid, SubjectType.ROLE);
+                   getStorageClient(ctx).delete(ctx, csid);
+            } finally {
+               ctx.closeConnection();
+            }
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid);
         }
 
+        return Response.status(HttpResponseCodes.SC_OK).build();        
     }
 
     @POST
@@ -473,7 +482,7 @@ public class AccountResource extends SecurityResourceBase {
             @PathParam("csid") String accCsid,
             AccountRole input) {
         if (method != null) {
-            if ("delete".equalsIgnoreCase(method)) {
+            if ("delete".equalsIgnoreCase(method)) { // How would this ever be true?
                 return deleteAccountRole(accCsid, input);
             }
         }
@@ -482,14 +491,14 @@ public class AccountResource extends SecurityResourceBase {
         try {
                AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
             // If marked as roles immutable, do not create
-            if(AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
+            if (AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
                 Response response =
                        Response.status(Response.Status.FORBIDDEN).entity("Roles for Account: "+accCsid+" are immutable.").type("text/plain").build();
                 return response;
             }
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
-            String accrolecsid = subResource.createAccountRole(input, SubjectType.ROLE);
+            String accrolecsid = subResource.createAccountRole((ServiceContext)null, input, SubjectType.ROLE);
             UriBuilder path = UriBuilder.fromResource(AccountResource.class);
             path.path(accCsid + "/accountroles/" + accrolecsid);
             Response response = Response.created(path.build()).build();
@@ -511,7 +520,7 @@ public class AccountResource extends SecurityResourceBase {
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
             //get relationships for an account
-            result = subResource.getAccountRoleRel(accCsid, SubjectType.ROLE, accrolecsid);
+            result = subResource.getAccountRoleRel((ServiceContext)null, accCsid, SubjectType.ROLE, accrolecsid);
          } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, accCsid);
         }
@@ -526,14 +535,16 @@ public class AccountResource extends SecurityResourceBase {
         logger.debug("getAccountRole with accCsid=" + accCsid);
         ensureCSID(accCsid, ServiceMessages.GET_FAILED+ "accountroles account ");
         AccountRole result = null;
+        
         try {
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
             //get relationships for an account
-            result = subResource.getAccountRole(accCsid, SubjectType.ROLE);
+            result = subResource.getAccountRole((ServiceContext)null, accCsid, SubjectType.ROLE);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, accCsid);
         }
+        
         checkResult(result, accCsid, ServiceMessages.GET_FAILED);
         return result;
     }
@@ -542,6 +553,7 @@ public class AccountResource extends SecurityResourceBase {
     @Path("{csid}/accountperms")
     public AccountPermission getAccountPerm(@PathParam("csid") String accCsid) {
         logger.debug("getAccountPerm with accCsid=" + accCsid);
+        
         ensureCSID(accCsid, ServiceMessages.GET_FAILED+ "getAccountPerm account ");
         AccountPermission result = null;
         try {
@@ -550,12 +562,14 @@ public class AccountResource extends SecurityResourceBase {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, accCsid);
         }
         checkResult(result, accCsid, ServiceMessages.GET_FAILED);
+        
         return result;
     }
 
     public Response deleteAccountRole(String accCsid, AccountRole input) {
         logger.debug("deleteAccountRole with accCsid=" + accCsid);
         ensureCSID(accCsid, ServiceMessages.DELETE_FAILED+ "accountroles account ");
+        
         try {
                AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
             // If marked as roles immutable, do not delete
@@ -567,11 +581,12 @@ public class AccountResource extends SecurityResourceBase {
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
             //delete all relationships for an account
-            subResource.deleteAccountRole(accCsid, SubjectType.ROLE, input);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            subResource.deleteAccountRole((ServiceContext)null, accCsid, SubjectType.ROLE, input);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, accCsid);
         }
+        
+        return Response.status(HttpResponseCodes.SC_OK).build();
     }
 
     @DELETE
@@ -579,10 +594,11 @@ public class AccountResource extends SecurityResourceBase {
     public Response deleteAccountRole(@PathParam("csid") String accCsid) {
         logger.debug("deleteAccountRole: All roles related to account with accCsid=" + accCsid);
         ensureCSID(accCsid, ServiceMessages.DELETE_FAILED+ "accountroles account ");
+        
         try {
             // If marked as roles immutable, do not delete
                AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
-            if(AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
+            if (AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
                 Response response =
                        Response.status(Response.Status.FORBIDDEN).entity("Roles for Account: "+accCsid+" are immutable.").type("text/plain").build();
                 return response;
@@ -590,10 +606,12 @@ public class AccountResource extends SecurityResourceBase {
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
             //delete all relationships for an account
-            subResource.deleteAccountRole(accCsid, SubjectType.ROLE);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            subResource.deleteAccountRole((ServiceContext)null, accCsid, SubjectType.ROLE);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, accCsid);
         }
+        
+        return Response.status(HttpResponseCodes.SC_OK).build();
+
     }
 }
index 811df57b699ce202bd86e39ddbea1ac170651c1c..9d3dce195650dfba7a2ad4cae2d5aaac37955d2d 100644 (file)
@@ -30,21 +30,19 @@ import javax.persistence.PersistenceException;
 
 import org.collectionspace.authentication.AuthN;
 import org.collectionspace.services.account.storage.AccountRoleDocumentHandler;
-//import org.collectionspace.services.authorization.AccountRolesList;
-//import org.collectionspace.services.authorization.AccountRolesList.AccountRoleListItem;
 import org.collectionspace.services.authorization.AccountRole;
 import org.collectionspace.services.authorization.AccountRoleRel;
 import org.collectionspace.services.authorization.Role;
 import org.collectionspace.services.authorization.RoleValue;
 import org.collectionspace.services.authorization.SubjectType;
 
-import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
 import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
 import org.collectionspace.services.common.context.RemoteServiceContextFactory;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextFactory;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.storage.StorageClient;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaRelationshipStorageClient;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 import org.collectionspace.services.common.context.ServiceContextProperties;
@@ -56,6 +54,7 @@ import org.slf4j.LoggerFactory;
  * AccountRoleSubResource is used to manage account-role relationship
  * @author
  */
+@SuppressWarnings("rawtypes")
 public class AccountRoleSubResource
 //        extends AbstractCollectionSpaceResourceImpl<AccountRole, AccountRolesList> {
        extends AbstractCollectionSpaceResourceImpl<AccountRole, AccountRole> {
@@ -108,9 +107,9 @@ public class AccountRoleSubResource
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.CollectionSpaceResource#getServiceContextFactory()
      */
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public ServiceContextFactory<AccountRole, AccountRole> getServiceContextFactory() {
-//    public ServiceContextFactory<AccountRole, AccountRolesList> getServiceContextFactory() {
         return RemoteServiceContextFactory.get();
     }
 
@@ -124,9 +123,21 @@ public class AccountRoleSubResource
      * 
      * @throws Exception the exception
      */
-    private ServiceContext<AccountRole, AccountRole> createServiceContext(AccountRole input,
+    private ServiceContext<AccountRole, AccountRole> createServiceContext(
+               ServiceContext parentCtx, 
+               AccountRole input,
             SubjectType subject) throws Exception {
         ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(input);
+       JPATransactionContext parentTransactionContext = parentCtx != null ? (JPATransactionContext)parentCtx.getCurrentTransactionContext() : null;
+       //
+       // If the parent context has an active JPA connection then we'll use it.
+       //
+       if (parentTransactionContext != null) {
+               ctx.setTransactionContext(parentTransactionContext);
+       }
+        //
+       // Set other context values
+       //
         ctx.setDocumentType(AccountRole.class.getPackage().getName()); //persistence unit
         ctx.setProperty(ServiceContextProperties.ENTITY_NAME, AccountRoleRel.class.getName());
         ctx.setProperty(ServiceContextProperties.ENTITY_CLASS, AccountRoleRel.class);
@@ -162,7 +173,7 @@ public class AccountRoleSubResource
      * @return
      * @throws Exception
      */
-    public String createAccountRole(AccountRole input, SubjectType subject)
+    public String createAccountRole(ServiceContext parentCtx, AccountRole input, SubjectType subject)
             throws Exception {
        
        //
@@ -185,7 +196,7 @@ public class AccountRoleSubResource
        // The Spring role relationship may already exist, if it does then we'll get a PersistenceException that
        // we'll just ignore.
        try {
-               ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(input, subject);
+               ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
                DocumentHandler handler = createDocumentHandler(ctx);        
                getStorageClient(ctx).create(ctx, handler);
        } catch (PersistenceException e) {
@@ -202,7 +213,7 @@ public class AccountRoleSubResource
        // Now we'll add the account relationships for the original incoming roles.
        //
        input.setRole(inputRoleValues);
-        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(input, subject);
+        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
         DocumentHandler handler = createDocumentHandler(ctx);        
         String bogusCsid = getStorageClient(ctx).create(ctx, handler);
         
@@ -217,14 +228,14 @@ public class AccountRoleSubResource
      * @return
      * @throws Exception
      */
-    public AccountRole getAccountRole(
+    public AccountRole getAccountRole(ServiceContext parentCtx,
             String csid, SubjectType subject) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("getAccountRole with csid=" + csid);
         }
         AccountRole result = null;
-        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext((AccountRole) null, subject);
+        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole) null, subject);
         DocumentHandler handler = createDocumentHandler(ctx);
         getStorageClient(ctx).get(ctx, csid, handler);
         result = (AccountRole) ctx.getOutput();
@@ -241,27 +252,19 @@ public class AccountRoleSubResource
      * @return the account role
      * @throws Exception the exception
      */
-    public AccountRoleRel getAccountRoleRel(String csid,
+    public AccountRoleRel getAccountRoleRel(
+               ServiceContext parentCtx,
+               String csid,
                SubjectType subject,
                String accountRoleCsid) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("getAccountRole with csid=" + csid);
         }
-//        AccountRolesList result = new AccountRolesList();
-        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext((AccountRole) null, subject);
+        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole)null, subject);
         AccountRoleDocumentHandler handler = (AccountRoleDocumentHandler)createDocumentHandler(ctx);
         handler.setAccountRoleCsid(accountRoleCsid);
-        //getStorageClient(ctx).get(ctx, csid, handler);
         AccountRoleRel accountRoleRel = (AccountRoleRel)JpaStorageUtils.getEntity(new Long(accountRoleCsid).longValue(), AccountRoleRel.class);
-//        List<AccountRoleListItem> accountRoleList = result.getAccountRoleListItems();
-//        AccountRoleListItem listItem = new AccountRoleListItem();
-//        // fill the item
-//        listItem.setCsid(accountRoleRel.getHjid().toString());
-//        listItem.setRoleId(accountRoleRel.getRoleId());
-//        listItem.setRoleName(accountRoleRel.getRoleName());
-        // add item to result list
-//        result = (AccountRolesList) ctx.getOutput();
         
         return accountRoleRel;
     }
@@ -273,14 +276,16 @@ public class AccountRoleSubResource
      * @param subject the subject
      * @throws Exception the exception
      */
-    public void x_deleteAccountRole(String csid,
+    public void x_deleteAccountRole(
+               ServiceContext parentCtx,
+               String csid,
             SubjectType subject) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("deleteAccountRole with csid=" + csid);
         }
-        AccountRole toDelete = getAccountRole(csid, subject);
-        deleteAccountRole(csid, subject, toDelete);
+        AccountRole toDelete = getAccountRole(parentCtx, csid, subject);
+        deleteAccountRole(parentCtx, csid, subject, toDelete);
     }
     
     /**
@@ -291,13 +296,15 @@ public class AccountRoleSubResource
      * @return
      * @throws Exception
      */
-    public void deleteAccountRole(String csid,
+    public void deleteAccountRole(
+               ServiceContext parentCtx,
+               String csid,
             SubjectType subject) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("deleteAccountRole with csid=" + csid);
         }
-        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext((AccountRole) null, subject);
+        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole) null, subject);
         getStorageClient(ctx).delete(ctx, csid);
     }
 
@@ -310,10 +317,12 @@ public class AccountRoleSubResource
      * @return
      * @throws Exception
      */
-    public void deleteAccountRole(String csid, SubjectType subject, AccountRole input)
+       public void deleteAccountRole(
+               ServiceContext parentCtx,
+               String csid, SubjectType subject, AccountRole input)
             throws Exception {
 
-        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(input, subject);
+        ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
         DocumentHandler handler = createDocumentHandler(ctx);
         getStorageClient(ctx).delete(ctx, csid, handler);
     }
index 1c7d796f7c8e944c5ca58485853be723575fa86f..daa2245cc241e12ed00d6e096fa143a12e834f72 100644 (file)
@@ -32,9 +32,15 @@ import org.collectionspace.services.account.AccountTenant;
 import org.collectionspace.services.account.AccountsCommon;
 import org.collectionspace.services.account.AccountsCommonList;
 import org.collectionspace.services.account.AccountListItem;
+import org.collectionspace.services.account.AccountRoleSubResource;
 import org.collectionspace.services.account.Status;
-
+import org.collectionspace.services.authorization.AccountRole;
+import org.collectionspace.services.authorization.AccountValue;
+import org.collectionspace.services.authorization.SubjectType;
+import org.collectionspace.services.account.RoleValue;
 import org.collectionspace.services.client.AccountClient;
+import org.collectionspace.services.client.AccountFactory;
+import org.collectionspace.services.client.AccountRoleFactory;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentFilter;
@@ -50,7 +56,7 @@ import org.slf4j.LoggerFactory;
  * @author 
  */
 public class AccountDocumentHandler
-        extends JpaDocumentHandler<AccountsCommon, AccountsCommonList, AccountsCommon, List> {
+        extends JpaDocumentHandler<AccountsCommon, AccountsCommonList, AccountsCommon, List<AccountsCommon>> {
 
     private final Logger logger = LoggerFactory.getLogger(AccountDocumentHandler.class);
     private AccountsCommon account;
@@ -73,9 +79,32 @@ public class AccountDocumentHandler
         AccountsCommon accountFound = wrapDoc.getWrappedObject();
         AccountsCommon accountReceived = getCommonPart();
         // If marked as metadata immutable, do not do update
-        if(!AccountClient.IMMUTABLE.equals(accountFound.getMetadataProtection())) {
+        if (!AccountClient.IMMUTABLE.equals(accountFound.getMetadataProtection())) {
                merge(accountReceived, accountFound);
         }
+        //
+        // Update the accountroles if supplied
+        //
+        List<RoleValue> roleValueList = accountReceived.getRole();
+        if (roleValueList != null && roleValueList.size() > 0) {
+                       AccountRoleSubResource subResource = 
+                                       new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
+                       //
+                       // First, delete the exist accountroles
+                       //
+                       subResource.deleteAccountRole(getServiceContext(), accountFound.getCsid(), SubjectType.ROLE);
+                       //
+                       // Next, create the new accountroles
+                       //
+                       AccountRole accountRole = AccountRoleFactory.createAccountRoleInstance(accountFound, 
+                                       roleValueList, true, true);
+                       String accountRoleCsid = subResource.createAccountRole(getServiceContext(), accountRole, SubjectType.ROLE);
+                       //
+                       // Finally, set the updated role list in the result
+                       //
+                       AccountRole newAccountRole = subResource.getAccountRole(getServiceContext(), accountFound.getCsid(), SubjectType.ROLE);
+                       accountFound.setRole(AccountRoleFactory.convert(newAccountRole.getRole()));
+        }
     }
 
     /**
@@ -116,6 +145,17 @@ public class AccountDocumentHandler
         return to;
     }
 
+    @Override
+    public void completeCreate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
+       AccountsCommon accountsCommon = wrapDoc.getWrappedObject();
+       List<RoleValue> roleValueList = account.getRole();
+       if (roleValueList != null && roleValueList.size() > 0) {
+               AccountRoleSubResource subResource = new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
+               AccountRole accountRole = AccountRoleFactory.createAccountRoleInstance(accountsCommon, roleValueList, true, true);
+                       String accountRoleCsid = subResource.createAccountRole(this.getServiceContext(), accountRole, SubjectType.ROLE);
+       }
+    }
+    
     @Override
     public void completeUpdate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
         AccountsCommon upAcc = wrapDoc.getWrappedObject();
@@ -131,7 +171,7 @@ public class AccountDocumentHandler
     }
 
     @Override
-    public void handleGetAll(DocumentWrapper<List> wrapDoc) throws Exception {
+    public void handleGetAll(DocumentWrapper<List<AccountsCommon>> wrapDoc) throws Exception {
         AccountsCommonList accList = extractCommonPartList(wrapDoc);
         setCommonPartList(accList);
         getServiceContext().setOutput(getCommonPartList());
@@ -152,7 +192,7 @@ public class AccountDocumentHandler
 
     @Override
     public AccountsCommonList extractCommonPartList(
-            DocumentWrapper<List> wrapDoc)
+            DocumentWrapper<List<AccountsCommon>> wrapDoc)
             throws Exception {
 
        AccountsCommonList accList = this.extractPagingInfo(new AccountsCommonList(), wrapDoc);
index d6ee4c05ebec4c8e86a83b7d789c5c053585e8ad..9ea09060917ab084da3490891cb0fdf0ce77065c 100644 (file)
@@ -202,6 +202,11 @@ public class AccountRoleDocumentHandler
 //        return result;
     }
 
+    @Override
+    public void prepareCreate() throws Exception {
+       // Ensure the roles exist
+    }
+    
     public void fillCommonPart(AccountRole ar,
                DocumentWrapper<List<AccountRoleRel>> wrapDoc,
                boolean handleDelete)
index ea517d1a2433f28f0e1ba6cb400a981e44e8cdea..ffdf5398de82321a842b2acd0cb86dca8cb70c6a 100644 (file)
@@ -25,8 +25,6 @@ package org.collectionspace.services.account.storage;
 
 import java.util.Date;
 import java.util.HashMap;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
 
 import org.collectionspace.services.account.AccountsCommon;
 import org.collectionspace.services.account.storage.csidp.UserStorageClient;
@@ -41,6 +39,7 @@ import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.DocumentWrapperImpl;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
@@ -54,6 +53,7 @@ import org.slf4j.LoggerFactory;
  * are used where possible to permorme the persistence operations atomically.
  * @author 
  */
+@SuppressWarnings({ "rawtypes", "unchecked" })
 public class AccountStorageClient extends JpaStorageClientImpl {
 
     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
@@ -62,63 +62,51 @@ public class AccountStorageClient extends JpaStorageClientImpl {
     public AccountStorageClient() {
     }
 
-    @Override
+       @Override
     public String create(ServiceContext ctx,
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
-
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "AccountStorageClient.create : ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "AccountStorageClient.create: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
-        AccountsCommon account = (AccountsCommon) handler.getCommonPart();
+       String result = null;
+       
+       AccountsCommon account = null;
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
+            account = (AccountsCommon) handler.getCommonPart();
             handler.prepare(Action.CREATE);
             DocumentWrapper<AccountsCommon> wrapDoc =
                     new DocumentWrapperImpl<AccountsCommon>(account);
             handler.handle(Action.CREATE, wrapDoc);
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            //if userid and password are given, add to default id provider
-            if (account.getUserId() != null &&
-                    isForCSIdP(account.getPassword())) {
-                User user = userStorageClient.create(account.getUserId(),
-                        account.getPassword());
-                em.persist(user);
+            jpaConnectionContext.beginTransaction();
+            //
+            // If userid and password are given, add to default id provider
+            //
+            if (account.getUserId() != null && isForCSpaceIdentityProvider(account.getPassword())) {
+                User user = userStorageClient.create(account.getUserId(), account.getPassword());
+                   jpaConnectionContext.persist(user);         
             }
-//            if (accountReceived.getTenant() != null) {
-//                UserTenant ut = createTenantAssoc(accountReceived);
-//                em.persist(ut);
-//            }
+
             account.setCreatedAtItem(new Date());
-            em.persist(account);
-            em.getTransaction().commit();
+            jpaConnectionContext.persist(account);             
+
             handler.complete(Action.CREATE, wrapDoc);
-            return (String) JaxbUtils.getValue(account, "getCsid");
+            jpaConnectionContext.commitTransaction();
+
+            result = (String)JaxbUtils.getValue(account, "getCsid");
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw bre;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             boolean uniqueConstraint = false;
-            if (userStorageClient.get(em, account.getUserId()) != null) {
+            if (userStorageClient.get(ctx, account.getUserId()) != null) {
                 //might be unique constraint violation
                 uniqueConstraint = true;
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            
+               jpaConnectionContext.markForRollback();
+
             if (uniqueConstraint) {
                 String msg = "UserId exists. Non unique userId=" + account.getUserId();
                 logger.error(msg);
@@ -126,28 +114,21 @@ public class AccountStorageClient extends JpaStorageClientImpl {
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
+        
+        return result;
     }
 
     @Override
     public void get(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "get: ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "get: handler is missing");
-        }
         DocumentFilter docFilter = handler.getDocumentFilter();
         if (docFilter == null) {
             docFilter = handler.createDocumentFilter();
         }
 
+        JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
         try {
             handler.prepare(Action.GET);
             Object o = null;
@@ -156,7 +137,7 @@ public class AccountStorageClient extends JpaStorageClientImpl {
             params.put("csid", id);
             params.put("tenantId", ctx.getTenantId());
 
-            o = JpaStorageUtils.getEntity(
+            o = JpaStorageUtils.getEntity(jpaTransactionContext, 
                     "org.collectionspace.services.account.AccountsCommon", whereClause, params);
             if (null == o) {
                 String msg = "could not find entity with id=" + id;
@@ -172,64 +153,50 @@ public class AccountStorageClient extends JpaStorageClientImpl {
                 logger.debug("Caught exception ", e);
             }
             throw new DocumentException(e);
+        } finally {
+               ctx.closeConnection();
         }
+        
     }
 
     @Override
     public void update(ServiceContext ctx, String id, DocumentHandler handler)
             throws BadRequestException, DocumentNotFoundException,
             DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "AccountStorageClient.update : ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "AccountStorageClient.update: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
         try {
+            jpaConnectionContext.beginTransaction();
+
             handler.prepare(Action.UPDATE);
             AccountsCommon accountReceived = (AccountsCommon) handler.getCommonPart();
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            AccountsCommon accountFound = getAccount(em, id);
+            AccountsCommon accountFound = getAccount(jpaConnectionContext, id);
             checkAllowedUpdates(accountReceived, accountFound);
             //if userid and password are given, add to default id provider
             // Note that this ignores the immutable flag, as we allow
             // password changes.
-            if (accountReceived.getUserId() != null
-                    && isForCSIdP(accountReceived.getPassword())) {
-                userStorageClient.update(em,
+            if (accountReceived.getUserId() != null && isForCSpaceIdentityProvider(accountReceived.getPassword())) {
+                userStorageClient.update(jpaConnectionContext,
                         accountReceived.getUserId(),
                         accountReceived.getPassword());
             }
             DocumentWrapper<AccountsCommon> wrapDoc =
                     new DocumentWrapperImpl<AccountsCommon>(accountFound);
             handler.handle(Action.UPDATE, wrapDoc);
-            em.getTransaction().commit();
             handler.complete(Action.UPDATE, wrapDoc);
+
+            jpaConnectionContext.commitTransaction();
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw bre;
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
-            if (logger.isDebugEnabled()) {
-                logger.debug("Caught exception ", e);
-            }
+               jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -241,54 +208,38 @@ public class AccountStorageClient extends JpaStorageClientImpl {
         if (logger.isDebugEnabled()) {
             logger.debug("deleting entity with id=" + id);
         }
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "AccountStorageClient.delete : ctx is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+        
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
         try {
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-
-            AccountsCommon accountFound = getAccount(em, id);
-            em.getTransaction().begin();
+            AccountsCommon accountFound = getAccount(jpaConnectionContext, id);
+            jpaConnectionContext.beginTransaction();
             //if userid gives any indication about the id provider, it should
             //be used to avoid  delete
-            userStorageClient.delete(em, accountFound.getUserId());
-            em.remove(accountFound);
-            em.getTransaction().commit();
-
+            userStorageClient.delete(jpaConnectionContext, accountFound.getUserId());
+            jpaConnectionContext.remove(accountFound);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
-    private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
-        AccountsCommon accountFound = em.find(AccountsCommon.class, id);
+    private AccountsCommon getAccount(JPATransactionContext jpaConnectionContext, String id) throws DocumentNotFoundException {
+        AccountsCommon accountFound = (AccountsCommon) jpaConnectionContext.find(AccountsCommon.class, id);
         if (accountFound == null) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
             String msg = "could not find account with id=" + id;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
         }
+        
         return accountFound;
     }
 
@@ -311,7 +262,7 @@ public class AccountStorageClient extends JpaStorageClientImpl {
      * @param bpass
      * @return
      */
-    private boolean isForCSIdP(byte[] bpass) {
+    private boolean isForCSpaceIdentityProvider(byte[] bpass) {
         return bpass != null && bpass.length > 0;
     }
 //    private UserTenant createTenantAssoc(AccountsCommon accountReceived) {
index 438e9495f055a64f67b201e70b0569db45ed0963..bec10d722e9f03635a286406fb9804242cc6b37a 100644 (file)
@@ -102,6 +102,10 @@ public class AccountValidatorHandler implements ValidatorHandler {
                     invalid = true;
                     msgBldr.append("\nuserId : missing");
                 }
+                if (account.getPassword() == null || account.getPassword().length == 0) {
+                    invalid = true;
+                    msgBldr.append("\npassword : missing");
+                }                
                 if (account.getEmail() == null || account.getEmail().isEmpty()) {
                     invalid = true;
                     msgBldr.append("\nemail : missing");
index 6822527f60b7cd3896a939d5e6a107b842e10317..da43ba6940ad90fd39b2fe35fbe0b124b920d6f7 100644 (file)
@@ -25,8 +25,7 @@ package org.collectionspace.services.account.storage;
 
 import java.util.Date;
 import java.util.HashMap;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
+
 import org.collectionspace.services.account.Tenant;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.BadRequestException;
@@ -38,6 +37,7 @@ import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.DocumentWrapperImpl;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
@@ -51,6 +51,7 @@ import org.slf4j.LoggerFactory;
  * are used where possible to perform the persistence operations atomically.
  * @author 
  */
+@SuppressWarnings({"rawtypes", "unchecked"})
 public class TenantStorageClient extends JpaStorageClientImpl {
 
     private final Logger logger = LoggerFactory.getLogger(TenantStorageClient.class);
@@ -58,41 +59,28 @@ public class TenantStorageClient extends JpaStorageClientImpl {
     public TenantStorageClient() {
     }
 
-    @Override
+       @Override
     public String create(ServiceContext ctx,
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
-
-       /*
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "TenantStorageClient.create : ctx is missing");
-        }
-        */
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "TenantStorageClient.create: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+        String result = null;
+               
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         Tenant tenant = (Tenant) handler.getCommonPart();
         try {
             handler.prepare(Action.CREATE);
             DocumentWrapper<Tenant> wrapDoc =
                     new DocumentWrapperImpl<Tenant>(tenant);
             handler.handle(Action.CREATE, wrapDoc);
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
+            jpaConnectionContext.beginTransaction();
             tenant.setCreatedAtItem(new Date());
-            em.persist(tenant);
-            em.getTransaction().commit();
+            jpaConnectionContext.persist(tenant);
             handler.complete(Action.CREATE, wrapDoc);
-            return (String) JaxbUtils.getValue(tenant, "getId");
+            jpaConnectionContext.commitTransaction();
+            
+            result = (String)JaxbUtils.getValue(tenant, "getId");
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw bre;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
@@ -100,16 +88,14 @@ public class TenantStorageClient extends JpaStorageClientImpl {
             }
             boolean uniqueConstraint = false;
             try {
-               if(em.find(Tenant.class, tenant.getId()) != null) {
+               if(jpaConnectionContext.find(Tenant.class, tenant.getId()) != null) {
                        //might be unique constraint violation
                        uniqueConstraint = true;
                } 
             } catch(Exception ignored) {
                //Ignore - we just care if exists
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             if (uniqueConstraint) {
                 String msg = "TenantId exists. Non unique tenantId=" + tenant.getId();
                 logger.error(msg);
@@ -117,31 +103,21 @@ public class TenantStorageClient extends JpaStorageClientImpl {
             }
             throw new DocumentException(e);
         } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
+        
+        return result;
     }
 
-        @Override
+       @Override
     public void get(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
-        /*
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "get: ctx is missing");
-        } 
-        */
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "get: handler is missing");
-        }
         DocumentFilter docFilter = handler.getDocumentFilter();
         if (docFilter == null) {
             docFilter = handler.createDocumentFilter();
         }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
             handler.prepare(Action.GET);
             Object o = null;
@@ -152,10 +128,7 @@ public class TenantStorageClient extends JpaStorageClientImpl {
             o = JpaStorageUtils.getEntity(
                     "org.collectionspace.services.account.Tenant", whereClause, params);
             if (null == o) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
-                String msg = "could not find entity with id=" + id;
+                String msg = "Could not find entity with id=" + id;
                 throw new DocumentNotFoundException(msg);
             }
             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
@@ -169,9 +142,7 @@ public class TenantStorageClient extends JpaStorageClientImpl {
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -179,50 +150,35 @@ public class TenantStorageClient extends JpaStorageClientImpl {
     public void update(ServiceContext ctx, String id, DocumentHandler handler)
             throws BadRequestException, DocumentNotFoundException,
             DocumentException {
-        /*
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "TenantStorageClient.update : ctx is missing");
-        }
-         */
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "TenantStorageClient.update: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
             handler.prepare(Action.UPDATE);
+            
             Tenant tenantReceived = (Tenant) handler.getCommonPart();
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            Tenant tenantFound = getTenant(em, id);
+            jpaConnectionContext.beginTransaction();
+            Tenant tenantFound = getTenant(jpaConnectionContext, id);
             checkAllowedUpdates(tenantReceived, tenantFound);
             DocumentWrapper<Tenant> wrapDoc =
                     new DocumentWrapperImpl<Tenant>(tenantFound);
             handler.handle(Action.UPDATE, wrapDoc);
-            em.getTransaction().commit();
             handler.complete(Action.UPDATE, wrapDoc);
+            
+            jpaConnectionContext.commitTransaction();
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw bre;
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
+               jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -234,53 +190,35 @@ public class TenantStorageClient extends JpaStorageClientImpl {
         if (logger.isDebugEnabled()) {
             logger.debug("deleting entity with id=" + id);
         }
-        /*
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "TenantStorageClient.delete : ctx is missing");
-        }
-        */
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
-        try {
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-
-            Tenant tenantFound = getTenant(em, id);
-            em.getTransaction().begin();
-            em.remove(tenantFound);
-            em.getTransaction().commit();
 
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
+        try {
+            Tenant tenantFound = getTenant(jpaConnectionContext, id);
+            jpaConnectionContext.beginTransaction();
+            jpaConnectionContext.remove(tenantFound);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
-    private Tenant getTenant(EntityManager em, String id) throws DocumentNotFoundException {
-        Tenant tenantFound = em.find(Tenant.class, id);
+    private Tenant getTenant(JPATransactionContext jpaConnectionContext, String id) throws DocumentNotFoundException {
+        Tenant tenantFound = (Tenant) jpaConnectionContext.find(Tenant.class, id);
         if (tenantFound == null) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
             String msg = "could not find account with id=" + id;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
         }
+        
         return tenantFound;
     }
 
index 2345ec102ac3e694c69cc25261385854ab850195..b274c21bc2c645cad3b14515219d0b2125fc0ddc 100644 (file)
 package org.collectionspace.services.account.storage.csidp;
 
 import java.util.Date;
-import javax.persistence.EntityManager;
 import javax.persistence.Query;
+
 import org.collectionspace.services.authentication.User;
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.security.SecurityUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,18 +71,35 @@ public class UserStorageClient {
      * @param em EntityManager
      * @param userId
      */
-    public User get(EntityManager em, String userId) throws DocumentNotFoundException {
-        User userFound = em.find(User.class, userId);
+    public User get(JPATransactionContext jpaTransactionContext, String userId) throws DocumentNotFoundException {
+        User userFound = (User) jpaTransactionContext.find(User.class, userId);
         if (userFound == null) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
-            String msg = "could not find user with userId=" + userId;
+            String msg = "Could not find user with userId=" + userId;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
         }
+        
         return userFound;
     }
+    
+    @SuppressWarnings("rawtypes")
+       public User get(ServiceContext ctx, String userId) throws DocumentNotFoundException, TransactionException {
+       User userFound = null;
+       
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();
+       try {
+               userFound = (User) jpaConnectionContext.find(User.class, userId);
+               if (userFound == null) {
+                   String msg = "could not find user with userId=" + userId;
+                   logger.error(msg);
+                   throw new DocumentNotFoundException(msg);
+               }
+       } finally {
+               ctx.closeConnection();
+       }
+        
+        return userFound;
+    }    
 
     /**
      * updateUser for given userId
@@ -86,16 +107,16 @@ public class UserStorageClient {
      * @param userId
      * @param password
      */
-    public void update(EntityManager em, String userId, byte[] password)
+    public void update(JPATransactionContext jpaTransactionContext, String userId, byte[] password)
             throws DocumentNotFoundException, Exception {
-        User userFound = get(em, userId);
+        User userFound = get(jpaTransactionContext, userId);
         if (userFound != null) {
             userFound.setPasswd(getEncPassword(userId, password));
             userFound.setUpdatedAtItem(new Date());
             if (logger.isDebugEnabled()) {
                 logger.debug("updated user=" + JaxbUtils.toString(userFound, User.class));
             }
-            em.persist(userFound);
+            jpaTransactionContext.persist(userFound);
         }
     }
 
@@ -105,7 +126,7 @@ public class UserStorageClient {
      * @param userId
      * @throws Exception if user for given userId not found
      */
-    public void delete(EntityManager em, String userId)
+    public void delete(JPATransactionContext jpaTransactionContext, String userId)
             throws DocumentNotFoundException, Exception {
         //if userid gives any indication about the id provider, it should
         //be used to avoid the following approach
@@ -113,13 +134,10 @@ public class UserStorageClient {
         usrDelStr.append(User.class.getCanonicalName());
         usrDelStr.append(" WHERE username = :username");
         //TODO: add tenant id
-        Query usrDel = em.createQuery(usrDelStr.toString());
+        Query usrDel = jpaTransactionContext.createQuery(usrDelStr.toString());
         usrDel.setParameter("username", userId);
         int usrDelCount = usrDel.executeUpdate();
         if (usrDelCount != 1) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
             String msg = "could not find user with username=" + userId;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
index b6a9b0c6f941e6ad289995231b712bd9237b4e4c..9ac0801ea8d492e77354f1d38f2f29eb5104cc3f 100644 (file)
@@ -231,7 +231,7 @@ public class RoleServiceTest extends AbstractServiceTestImpl<RolesList, Role, Ro
                // Store the ID returned from this create operation
                // for additional tests below.
                knownResourceId = extractId(res);
-               //allResourceIdsCreated.add(knownResourceId);
+               //allResourceIdsCreated.add(knownResourceId);  //FIXME: 
                if (logger.isDebugEnabled()) {
                    logger.debug(testName + ": knownResourceId=" + knownResourceId);
                }
index c939cd8ba40e2c6d156b96eae3cb00676836e925..af8445eed7671dd25f7f0f0715ea20beab480120 100644 (file)
@@ -35,6 +35,8 @@ import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.collectionspace.services.authorization.driver.AuthorizationSeedDriver;
+import org.collectionspace.services.common.document.TransactionException;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -137,11 +139,12 @@ public class ImportAuthz {
     //
     // Create our AuthZ metadata
     //
-    public static void main(String[] args) {
+    public static void main(String[] args) throws TransactionException {
 
         Options options = createOptions();
 
         CommandLineParser parser = new GnuParser();
+        JPATransactionContext jpaTransactionContext = new JPATransactionContext();
         try {
             // parse the command line arguments
             CommandLine line = parser.parse(options, args);
@@ -160,20 +163,24 @@ public class ImportAuthz {
             //
             AuthorizationSeedDriver driver = new AuthorizationSeedDriver(
                     user, password, tenantBinding, exportDir);
-            driver.generate();
+               jpaTransactionContext.beginTransaction();
+            driver.generate(jpaTransactionContext);
             logger.info("Finished processing all tenant bindings files and generating all AuthN/AuthZ metadata.");
             //
             // If the "-g" option was set, then we will NOT seed the AuthZ tables.  Instead, we'll
             // just merge the prototypical tenant bindings and generate the permissions XML output
             //
             if (generateOnly(generate_only) == false) {
-               driver.seed();
+               driver.seed(jpaTransactionContext);
             } else {
                logError("WARNING: '-g' was set to 'true' so AuthZ tables were ***NOT*** seeded.");
             }
+            jpaTransactionContext.commitTransaction();
         } catch (ParseException exp) {
+               jpaTransactionContext.markForRollback();
                logError("Parsing failed.  Reason: " + exp.getMessage());
         } catch (Exception e) {
+               jpaTransactionContext.markForRollback();
                logError("Error : " + e.getMessage());
                logError(MSG_SEPARATOR);
             printUsage(System.err);
@@ -181,6 +188,8 @@ public class ImportAuthz {
             logError("Import failed: ");
             logInitialErrorCauseMsg(e);
             System.exit(1);
+        } finally {
+               jpaTransactionContext.close();
         }
     }
 }
index 9b597be1b29e717978f352af512344e011f8d638..b54b8e50d8c18ac29cf54c5162b6bfb3829b432a 100644 (file)
@@ -43,6 +43,8 @@ import org.collectionspace.services.authorization.importer.AuthorizationSeed;
 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
 import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;
 import org.collectionspace.services.common.authorization_mgt.PermissionRoleUtil;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
 import org.hibernate.exception.ConstraintViolationException;
@@ -111,12 +113,12 @@ public class AuthorizationSeedDriver {
 
     }
 
-    public void generate() {
+    public void generate(JPATransactionContext jpaTransactionContext) {
         try {
             authzGen = new AuthorizationGen();
             authzGen.initialize(tenantBindingFile);
-            authzGen.createDefaultRoles();
-            authzGen.createDefaultPermissions();
+            authzGen.createDefaultRoles(jpaTransactionContext);
+            authzGen.createDefaultPermissions(jpaTransactionContext);
             authzGen.associateDefaultPermissionsRoles();
             authzGen.exportDefaultRoles(exportDir + File.separator + ROLE_FILE);
             authzGen.exportDefaultPermissions(exportDir + File.separator + PERMISSION_FILE);
@@ -130,7 +132,7 @@ public class AuthorizationSeedDriver {
         }
     }
 
-    public void seed() {
+    public void seed(JPATransactionContext jpaTransactionContext) {
         TransactionStatus status = null;
         try {
                // Push all the authz info into the cspace DB tables -this include default roles, permissions, and permroles
@@ -139,9 +141,7 @@ public class AuthorizationSeedDriver {
             setupSpring();
             status = beginTransaction("seedData");
             AuthorizationSeed authzSeed = new AuthorizationSeed();
-            authzSeed.seedPermissions(authzGen.getDefaultPermissions(), authzGen.getDefaultPermissionRoles());
-//            authzSeed.seedPermissions(exportDir + File.separator + PERMISSION_FILE,
-//                    exportDir + File.separator + PERMISSION_ROLE_FILE);
+            authzSeed.seedPermissions(jpaTransactionContext, authzGen.getDefaultPermissions(), authzGen.getDefaultPermissionRoles());
             if (logger.isDebugEnabled()) {
                 logger.debug("Authorization seeding completed.");
             }
@@ -161,15 +161,22 @@ public class AuthorizationSeedDriver {
         }
     }
 
+    /**
+     * Setup of Spring Security context
+     */
     private void setupSpring() {
-
         ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
                 new String[]{SPRING_SECURITY_METADATA});
         login();
         System.setProperty("spring-beans-config", SPRING_SECURITY_METADATA);
+        //
         // authZ local not used but call to AuthZ.get() has side-effect of initializing our Spring Security context
+        //
         AuthZ authZ = AuthZ.get();
         txManager = (org.springframework.jdbc.datasource.DataSourceTransactionManager) appContext.getBean("transactionManager");
+        //
+        // debug
+        //
         if (logger.isDebugEnabled()) {
             logger.debug("Spring Security setup complete.");
         }
@@ -196,25 +203,22 @@ public class AuthorizationSeedDriver {
     }
 
     private void store() throws Exception {
-        EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_AUTHZ_PERSISTENCE_UNIT);
-        EntityManager em = null;
-
+        JPATransactionContext jpaTransactionContext = new JPATransactionContext((ServiceContext)null);
         try {
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
+               jpaTransactionContext.beginTransaction();
             
                AuthorizationStore authzStore = new AuthorizationStore();
                logger.info("Seeding Roles metadata to database.");
                for (Role role : authzGen.getDefaultRoles()) {
                        try {
-                               authzStore.store(em, role);
+                               authzStore.store(jpaTransactionContext, role);
                        } catch (Exception e) {
                                //
                                // If the role already exists, read it in and replace the instance
                                // we're trying to import with the exist one.  This will ensure that the rest
                                // of import uses the correct CSID.
                                if (e.getCause() instanceof ConstraintViolationException) {
-                                       Role existingRole = authzStore.getRoleByName(role.getRoleName(), role.getTenantId());
+                                       Role existingRole = authzStore.getRoleByName(jpaTransactionContext, role.getRoleName(), role.getTenantId());
                                        //
                                        role = existingRole;
                                }
@@ -223,36 +227,31 @@ public class AuthorizationSeedDriver {
        
                logger.info("Seeding Permissions metadata to database.");
                for (Permission perm : authzGen.getDefaultPermissions()) { //FIXME: REM - 3/27/2012 - If we change the CSID of permissions to something like a refname, then we need to check for existing perms just like we did above for roles
-                   authzStore.store(em, perm);
+                   authzStore.store(jpaTransactionContext, perm);
                }
        
                logger.info("Seeding Permissions/Roles relationships metadata to database.");
                List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
                for (PermissionRole pr : authzGen.getDefaultPermissionRoles()) {
                        String tenantId = getTenantId(pr);
-                   PermissionRoleUtil.buildPermissionRoleRel(em, pr, SubjectType.ROLE, permRoleRels, false /*not for delete*/, tenantId);
+                   PermissionRoleUtil.buildPermissionRoleRel(jpaTransactionContext, pr, SubjectType.ROLE, permRoleRels, false /*not for delete*/, tenantId);
                }
                for (PermissionRoleRel permRoleRel : permRoleRels) {
-                   authzStore.store(em, permRoleRel);
+                   authzStore.store(jpaTransactionContext, permRoleRel);
                }
        
-               em.getTransaction().commit();
-               em.close();
+               jpaTransactionContext.commitTransaction();
                if (logger.isInfoEnabled()) {
                    logger.info("All Authorization metadata persisted.");
                }
         } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception and rolling back permission creation: ", e);
             }
             throw e;
         } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+               jpaTransactionContext.close();
         }
     }
 
index 7ead5209534aba427144f8fea24ffab33206cabd..23510b009f7fdb274983608ac474fcca33dca95f 100644 (file)
@@ -46,6 +46,7 @@ import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon
 import org.collectionspace.services.common.config.ServicesConfigReaderImpl;
 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
 import org.collectionspace.services.common.security.SecurityUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.config.service.ServiceBindingType;
 import org.collectionspace.services.config.tenant.TenantBindingType;
 
@@ -109,7 +110,7 @@ public class AuthorizationGen {
      * @see initialize
      * @return
      */
-    public void createDefaultPermissions() {
+    public void createDefaultPermissions(JPATransactionContext jpaTransactionContext) {
         for (String tenantId : tenantBindings.keySet()) {
             List<Permission> adminPerms = createDefaultAdminPermissions(tenantId, AUTHZ_IS_ENTITY_PROXY);
             adminPermList.addAll(adminPerms);
@@ -129,7 +130,7 @@ public class AuthorizationGen {
      * @return
      */
     public List<Permission> createDefaultAdminPermissions(String tenantId, boolean isEntityProxy) {
-        ArrayList<Permission> apcList = new ArrayList<Permission>();
+        ArrayList<Permission> result = new ArrayList<Permission>();
         TenantBindingType tbinding = tenantBindings.get(tenantId);
         for (ServiceBindingType sbinding : tbinding.getServiceBindings()) {
 
@@ -138,22 +139,20 @@ public class AuthorizationGen {
                if (isEntityProxy == true) {
                        resourceName = SecurityUtils.getResourceEntity(resourceName);
                }
-            Permission perm = buildAdminPermission(tbinding.getId(),
-                    resourceName);
-            apcList.add(perm);
+            Permission perm = buildAdminPermission(tbinding.getId(), resourceName);
+            result.add(perm);
 
             //add permissions for alternate paths
             if (isEntityProxy == false) {
                    List<String> uriPaths = sbinding.getUriPath();
                    for (String uriPath : uriPaths) {
-                       perm = buildAdminPermission(tbinding.getId(),
-                               uriPath.toLowerCase());
-                       apcList.add(perm);
+                       perm = buildAdminPermission(tbinding.getId(), uriPath.toLowerCase());
+                       result.add(perm);
                    }
             }
         }
         
-        return apcList;
+        return result;
     }
 
     /**
@@ -248,20 +247,20 @@ public class AuthorizationGen {
      * createDefaultRoles creates default admin and reader roles
      * for each tenant found in the given tenant binding file
      */
-    public void createDefaultRoles() {
+    public void createDefaultRoles(JPATransactionContext jpaTransactionContext) {
         for (String tenantId : tenantBindings.keySet()) {
 
-            Role arole = buildTenantAdminRole(tenantId);
+            Role arole = buildTenantAdminRole(jpaTransactionContext, tenantId);
             adminRoles.add(arole);
 
-            Role rrole = buildTenantReaderRole(tenantId);
+            Role rrole = buildTenantReaderRole(jpaTransactionContext, tenantId);
             readerRoles.add(rrole);
         }
     }
 
-    private Role buildTenantAdminRole(String tenantId) {
+    private Role buildTenantAdminRole(JPATransactionContext jpaTransactionContext, String tenantId) {
        String type = "admin";
-        Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
+        Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);
         
         if (result == null) {
                // the role doesn't exist already, so we need to create it
@@ -272,9 +271,9 @@ public class AuthorizationGen {
         return result;
     }
 
-    private Role buildTenantReaderRole(String tenantId) {
+    private Role buildTenantReaderRole(JPATransactionContext jpaTransactionContext, String tenantId) {
        String type = "read only";
-        Role result = AuthorizationCommon.getRole(tenantId, AuthorizationCommon.ROLE_TENANT_READER);
+        Role result = AuthorizationCommon.getRole(jpaTransactionContext, tenantId, AuthorizationCommon.ROLE_TENANT_READER);
         
         if (result == null) {
                // the role doesn't exist already, so we need to create it
index fa59a890e3c6a67cc2742594011fe95eedbb77dc..bd849dc15ee98fcc6ec46c6831ec272afa84a9b1 100644 (file)
@@ -39,6 +39,7 @@ import org.collectionspace.services.authorization.PermissionRole;
 import org.collectionspace.services.authorization.perms.PermissionsList;
 import org.collectionspace.services.authorization.PermissionsRolesList;
 import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 
 /**
  * AuthorizationSeed seeds authorizations (permission, role) into authz provider database
@@ -55,7 +56,7 @@ public class AuthorizationSeed {
      * @param permRoleFileName permission role file name
      * @throws Exception
      */
-    public void seedPermissions(String permFileName, String permRoleFileName) throws Exception {
+    public void seedPermissions(JPATransactionContext jpaTransactionContext, String permFileName, String permRoleFileName) throws Exception {
         PermissionsRolesList permRoleList =
                 (PermissionsRolesList) fromFile(PermissionsRolesList.class,
                 permRoleFileName);
@@ -69,7 +70,7 @@ public class AuthorizationSeed {
                logger.debug("read permissions from " + permFileName);
            }
 
-        seedPermissions(permList, permRoleList);
+        seedPermissions(jpaTransactionContext, permList, permRoleList);
     }
 
     /**
@@ -78,10 +79,10 @@ public class AuthorizationSeed {
      * @param permRoleList
      * @throws Exception
      */
-    public void seedPermissions(PermissionsList permList, PermissionsRolesList permRoleList)
+    public void seedPermissions(JPATransactionContext jpaTransactionContext, PermissionsList permList, PermissionsRolesList permRoleList)
             throws Exception {
        
-       seedPermissions(permList.getPermission(), permRoleList.getPermissionRole());
+       seedPermissions(jpaTransactionContext, permList.getPermission(), permRoleList.getPermissionRole());
     }
     
     /**
@@ -90,7 +91,7 @@ public class AuthorizationSeed {
      * @param permRoleList
      * @throws Exception
      */
-    public void seedPermissions(List<Permission> permList, List<PermissionRole> permRoleList)
+    public void seedPermissions(JPATransactionContext jpaTransactionContext, List<Permission> permList, List<PermissionRole> permRoleList)
             throws Exception {
        if (logger.isInfoEnabled() == true) {
                logger.info("Started seeding Spring Security Tables...");
index cf9283c38f674c9ae8a3c469fe73301a3594ab79..bde34a397b74a6463adbc1eb09725d936170f71b 100644 (file)
@@ -31,6 +31,7 @@ import org.collectionspace.services.common.context.RemoteServiceContextFactory;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextFactory;
 import org.collectionspace.services.common.storage.StorageClient;
+import org.collectionspace.services.common.storage.TransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
 import org.collectionspace.services.common.CSWebApplicationException;
 
@@ -55,6 +56,7 @@ import javax.ws.rs.core.UriInfo;
 @Path(RoleClient.SERVICE_PATH)
 @Consumes("application/xml")
 @Produces("application/xml")
+@SuppressWarnings("unchecked")
 public class RoleResource extends SecurityResourceBase {
 
     final Logger logger = LoggerFactory.getLogger(RoleResource.class);
@@ -106,16 +108,18 @@ public class RoleResource extends SecurityResourceBase {
             @PathParam("csid") String accCsid) {
         logger.debug("getAccountRole with accCsid=" + accCsid);
         ensureCSID(accCsid, ServiceMessages.GET_FAILED+ "accountroles role ");
+        
         AccountRole result = null;
         try {
             AccountRoleSubResource subResource =
                     new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
             //get relationships for a role
-            result = subResource.getAccountRole(accCsid, SubjectType.ACCOUNT);
+            result = subResource.getAccountRole((ServiceContext)null, accCsid, SubjectType.ACCOUNT);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, accCsid);
         }
         checkResult(result, accCsid, ServiceMessages.GET_FAILED);
+        
         return result;
     }
 
@@ -128,50 +132,65 @@ public class RoleResource extends SecurityResourceBase {
     @PUT
     @Path("{csid}")
     public Role updateRole(@PathParam("csid") String csid, Role theUpdate) {
+       Role result = null;
+       
         try {
                Role role = (Role)get(csid, Role.class);
                // If marked as metadata immutable, do not update
-               if(RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
+               if (RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
                    Response response = 
                        Response.status(Response.Status.FORBIDDEN).entity("Role: "+csid+" is immutable.").type("text/plain").build();
                 throw new CSWebApplicationException(response);
                }
-               return (Role)update(csid, theUpdate, Role.class);
+               result = (Role)update(csid, theUpdate, Role.class);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.UPDATE_FAILED, csid);
         }
+        
+        return result;
     }
 
-    @DELETE
+       @DELETE
     @Path("{csid}")
-    public Response deleteRole(@PathParam("csid") String csid) {
+    public Response deleteRole(@PathParam("csid") String csid, @Context UriInfo ui) {
         logger.debug("deleteRole with csid=" + csid);
         ensureCSID(csid, ServiceMessages.DELETE_FAILED + "deleteRole ");
 
         try {
-               Role role = (Role)get(csid, Role.class);
-            // If marked as metadata immutable, do not delete
-            if(RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
-                Response response = 
-                       Response.status(Response.Status.FORBIDDEN).entity("Role: "+csid+" is immutable.").type("text/plain").build();
-                return response;
-            }
-            //FIXME ideally the following three operations should be in the same tx CSPACE-658
-            //delete all relationships for this permission
-            PermissionRoleSubResource permRoleResource =
-                    new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
-            permRoleResource.deletePermissionRole(csid, SubjectType.PERMISSION);
-            //delete all the account/role relationships associate with this role
-            AccountRoleSubResource accountRoleResource =
-                new AccountRoleSubResource(AccountRoleSubResource.ROLE_ACCOUNTROLE_SERVICE);
-            accountRoleResource.deleteAccountRole(csid, SubjectType.ACCOUNT);
-            //finally, delete the role itself
             ServiceContext<Role, Role> ctx = createServiceContext((Role) null, Role.class);
-            ((JpaStorageClientImpl) getStorageClient(ctx)).deleteWhere(ctx, csid);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            ctx.openConnection(); // ensure we do all this in one transaction
+            try {
+                       Role role = (Role)get(csid, Role.class);
+                   // If marked as metadata immutable, do not delete
+                   if (RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
+                       Response response = 
+                               Response.status(Response.Status.FORBIDDEN).entity("Role: "+csid+" is immutable.").type("text/plain").build();
+                       return response;
+                   }
+                   //
+                   // delete all the permission/role relationships
+                   //
+                   PermissionRoleSubResource permRoleResource =
+                           new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
+                   permRoleResource.deletePermissionRole(ctx, csid, SubjectType.PERMISSION);
+                   //
+                   //delete all the account/role relationships associate with this role
+                   //
+                   AccountRoleSubResource accountRoleResource =
+                       new AccountRoleSubResource(AccountRoleSubResource.ROLE_ACCOUNTROLE_SERVICE);
+                   accountRoleResource.deleteAccountRole(ctx, csid, SubjectType.ACCOUNT);
+                   //
+                   //finally, delete the role itself
+                   //
+                   ((JpaStorageClientImpl) getStorageClient(ctx)).deleteWhere(ctx, csid);
+            } finally {
+               ctx.closeConnection();
+            }
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid);
         }
+        
+        return Response.status(HttpResponseCodes.SC_OK).build();
     }
 
     @POST
@@ -183,26 +202,29 @@ public class RoleResource extends SecurityResourceBase {
                 return deleteRolePermission(roleCsid, input);
             }
         }
+        
         logger.debug("createRolePermission with roleCsid=" + roleCsid);
         ensureCSID(roleCsid, ServiceMessages.PUT_FAILED + "permroles role ");
+        Response response = null;
         try {
                Role role = (Role)get(roleCsid, Role.class);
             // If marked as metadata immutable, do not delete
-            if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
-                Response response = 
+            if (RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+                response = 
                        Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
                 return response;
             }
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
-            String permrolecsid = subResource.createPermissionRole(input, SubjectType.PERMISSION);
+            String permrolecsid = subResource.createPermissionRole((ServiceContext)null, input, SubjectType.PERMISSION);
             UriBuilder path = UriBuilder.fromResource(RoleResource.class);
             path.path(roleCsid + "/permroles/" + permrolecsid);
-            Response response = Response.created(path.build()).build();
-            return response;
+            response = Response.created(path.build()).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, roleCsid);
         }
+
+        return response;
     }
 
     @GET
@@ -211,16 +233,18 @@ public class RoleResource extends SecurityResourceBase {
             @PathParam("csid") String roleCsid) {
         logger.debug("getRolePermission with roleCsid=" + roleCsid);
         ensureCSID(roleCsid, ServiceMessages.GET_FAILED + "permroles role ");
+        
         PermissionRole result = null;
         try {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
             //get relationships for a role
-            result = subResource.getPermissionRole(roleCsid, SubjectType.PERMISSION);
+            result = subResource.getPermissionRole((ServiceContext)null, roleCsid, SubjectType.PERMISSION);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, roleCsid);
         }
         checkResult(result, roleCsid, ServiceMessages.GET_FAILED);
+        
         return result;
     }
 
@@ -231,38 +255,44 @@ public class RoleResource extends SecurityResourceBase {
             @PathParam("id") String permrolecsid) {
         logger.debug("getRolePermission with roleCsid=" + roleCsid);
         ensureCSID(roleCsid, ServiceMessages.GET_FAILED + "permroles role ");
+        
         PermissionRoleRel result = null;
         try {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
             //get relationships for a role
-            result = subResource.getPermissionRoleRel(roleCsid, SubjectType.PERMISSION, permrolecsid);
+            result = subResource.getPermissionRoleRel((ServiceContext)null, roleCsid, SubjectType.PERMISSION, permrolecsid);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, roleCsid);
         }
         checkResult(result, roleCsid, ServiceMessages.GET_FAILED);
+        
         return result;
     }
 
     public Response deleteRolePermission(String roleCsid, PermissionRole input) {
         logger.debug("deleteRolePermission with roleCsid=" + roleCsid);
         ensureCSID(roleCsid, ServiceMessages.DELETE_FAILED + "permroles role ");
+        
+        Response result = null;
         try {
                Role role = (Role)get(roleCsid, Role.class);
             // If marked as metadata immutable, do not delete
-            if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
-                Response response = 
-                       Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
+            if (RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+                Response response = Response.status(Response.Status.FORBIDDEN).entity(
+                               "Role: "+roleCsid+" is immutable.").type("text/plain").build();
                 return response;
             }
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
             //delete all relationships for a permission
-            subResource.deletePermissionRole(roleCsid, SubjectType.PERMISSION, input);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            subResource.deletePermissionRole((ServiceContext)null, roleCsid, SubjectType.PERMISSION, input);
+            result = Response.status(HttpResponseCodes.SC_OK).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, roleCsid);
         }
+        
+        return result;
     }
 
     @DELETE
@@ -271,10 +301,11 @@ public class RoleResource extends SecurityResourceBase {
                @PathParam("csid") String roleCsid) {
         logger.debug("deleteRolePermission with roleCsid=" + roleCsid);
         ensureCSID(roleCsid, ServiceMessages.DELETE_FAILED + "permroles role ");
+        
         try {
                Role role = (Role)get(roleCsid, Role.class);
             // If marked as metadata immutable, do not delete
-            if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+            if (RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
                 Response response = 
                        Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
                 return response;
@@ -282,10 +313,11 @@ public class RoleResource extends SecurityResourceBase {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
             //delete all relationships for a permission
-            subResource.deletePermissionRole(roleCsid, SubjectType.PERMISSION);
-            return Response.status(HttpResponseCodes.SC_OK).build();
+            subResource.deletePermissionRole((ServiceContext)null, roleCsid, SubjectType.PERMISSION);            
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, roleCsid);
         }
+        
+        return Response.status(HttpResponseCodes.SC_OK).build();
     }
 }
index 77b3ca387fd9075de6be5b321bba5e88d0b21617..cd777062fac709394b6c5688f6319e02431bd33d 100644 (file)
@@ -27,7 +27,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
-import org.collectionspace.services.account.AccountsCommonList;
 import org.collectionspace.services.authorization.PermissionRole;
 import org.collectionspace.services.authorization.PermissionRoleSubResource;
 import org.collectionspace.services.authorization.PermissionValue;
@@ -40,13 +39,14 @@ import org.collectionspace.services.client.PermissionRoleFactory;
 import org.collectionspace.services.client.RoleClient;
 import org.collectionspace.services.client.RoleFactory;
 import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.JaxbUtils;
 import org.collectionspace.services.common.security.SecurityUtils;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
-import org.collectionspace.services.jaxb.AbstractCommonList;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,6 +54,7 @@ import org.slf4j.LoggerFactory;
  * Document handler for Role
  * @author 
  */
+@SuppressWarnings("unchecked")
 public class RoleDocumentHandler
                extends JpaDocumentHandler<Role, RolesList, Role, List<Role>> {
     private final Logger logger = LoggerFactory.getLogger(RoleDocumentHandler.class);
@@ -80,26 +81,11 @@ public class RoleDocumentHandler
         role.setCsid(id);
         // We do not allow creation of locked roles through the services.
         role.setMetadataProtection(null);
-        role.setPermsProtection(null);
+        role.setPermsProtection(null);        
     }
     
-    @Override
-    public void completeCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
-       Role role = wrapDoc.getWrappedObject();
-       List<PermissionValue> permValueList = role.getPermission();
-       if (permValueList != null && permValueList.size() > 0) {
-               // create and persist a permrole instance
-               // The caller of this method needs to ensure a valid and active EM (EntityManager) instance is in the Service context
-               RoleValue roleValue = RoleFactory.createRoleValueInstance(role);
-               PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
-                               permValueList, true, true);
-            PermissionRoleSubResource subResource =
-                    new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
-            String permrolecsid = subResource.createPermissionRole(permRole, SubjectType.PERMISSION);
-       }
-    }
-
-    @Override
+    @SuppressWarnings("rawtypes")
+       @Override
        public void handleUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
                Role roleFound = wrapDoc.getWrappedObject();
                Role roleReceived = getCommonPart();
@@ -112,25 +98,26 @@ public class RoleDocumentHandler
                //
                // Update perms is supplied.
                //
+               ServiceContext ctx = this.getServiceContext();
                List<PermissionValue> permValueList = roleReceived.getPermission();
-               if (permValueList != null) {
+               if (permValueList != null && permValueList.size() > 0) {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
             //
             // First, delete the existing permroles
             //
-            subResource.deletePermissionRole(roleFound.getCsid(), SubjectType.PERMISSION);
+            subResource.deletePermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
             //
             // Next, create the new permroles
             //
                RoleValue roleValue = RoleFactory.createRoleValueInstance(roleFound);
                PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
                                permValueList, true, true);            
-            subResource.createPermissionRole(permRole, SubjectType.PERMISSION);
+            subResource.createPermissionRole(ctx, permRole, SubjectType.PERMISSION);
             //
             // Finally, set the updated perm list in the result
             //
-            PermissionRole newPermRole = subResource.getPermissionRole(roleFound.getCsid(), SubjectType.PERMISSION);
+            PermissionRole newPermRole = subResource.getPermissionRole(ctx, roleFound.getCsid(), SubjectType.PERMISSION);
             roleFound.setPermission(newPermRole.getPermission());
                }
        }
@@ -168,6 +155,26 @@ public class RoleDocumentHandler
         
         return to;
     }
+    
+    @Override
+    public void completeCreate(DocumentWrapper<Role> wrapDoc) throws Exception {
+        Role role = wrapDoc.getWrappedObject();
+        //
+        // If there are perms in the payload, create the required role/perm relationships.
+        //
+       List<PermissionValue> permValueList = role.getPermission();
+       if (permValueList != null && permValueList.size() > 0) {
+               // create and persist a permrole instance
+               // The caller of this method needs to ensure a valid and active EM (EntityManager) instance is in the Service context
+               RoleValue roleValue = RoleFactory.createRoleValueInstance(role);
+               PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(SubjectType.PERMISSION, roleValue,
+                               permValueList, true, true);
+            PermissionRoleSubResource subResource =
+                    new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
+            subResource.createPermissionRole(getServiceContext(), permRole, SubjectType.PERMISSION);
+       }
+
+    }
 
     @Override
     public void completeUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
@@ -190,7 +197,7 @@ public class RoleDocumentHandler
         getServiceContext().setOutput(getCommonPartList());
     }
 
-    @Override
+       @Override
     public Role extractCommonPart(
             DocumentWrapper<Role> wrapDoc)
             throws Exception {
@@ -201,7 +208,7 @@ public class RoleDocumentHandler
         if (includePerms) {
                PermissionRoleSubResource permRoleResource =
                        new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
-               PermissionRole permRole = permRoleResource.getPermissionRole(role.getCsid(), SubjectType.PERMISSION);
+               PermissionRole permRole = permRoleResource.getPermissionRole(getServiceContext(), role.getCsid(), SubjectType.PERMISSION);
                role.setPermission(permRole.getPermission());
         }
     
index aedbb2ffc3a1b0d00361cf851d5635ac79a1f6f8..9eb30df733a8389d80529ec0614ffeb04eff6b24 100644 (file)
@@ -17,7 +17,7 @@
     xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
     xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
     xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
-    xmlns:ns="http://collectionspace.org/services/authorization"
+    xmlns:ans="http://collectionspace.org/services/authorization"
     xmlns="http://collectionspace.org/services/authorization"
     targetNamespace="http://collectionspace.org/services/authorization"
     version="0.1"
index 8256574206fd37c5356e5e85501677287505982f..4d84795971ebf03861de68d6b49fe4021f009c16 100644 (file)
@@ -38,6 +38,8 @@ import org.collectionspace.services.common.context.RemoteServiceContextFactory;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextFactory;
 import org.collectionspace.services.common.storage.StorageClient;
+import org.collectionspace.services.common.storage.TransactionContext;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
 import org.jboss.resteasy.util.HttpResponseCodes;
 import org.slf4j.Logger;
@@ -80,30 +82,31 @@ public class PermissionResource extends SecurityResourceBase {
         return Permission.class;
     }
 
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public ServiceContextFactory<Permission, Permission> getServiceContextFactory() {
         return RemoteServiceContextFactory.get();
     }
 
     @Override
-    public StorageClient getStorageClient(ServiceContext ctx) {
+    public StorageClient getStorageClient(@SuppressWarnings("rawtypes") ServiceContext ctx) {
         //FIXME use ctx to identify storage client
         return storageClient;
     }
 
     @POST
-    public Response createPermission(Permission input) {
-        return create(input);
+    public Response createPermission(JPATransactionContext jpaTransactionContext, Permission input) {
+        return create(jpaTransactionContext, input);
     }
     
-    public Permission createPermissionFromInstance(Permission input) {
+    public Permission createPermissionFromInstance(JPATransactionContext jpaTransactionContext, Permission input) {
        Permission result = null;
        
        String permCsid = null;
-       Response response = createPermission(input);
+       Response response = createPermission(jpaTransactionContext, input);
        if (response.getStatus() == Response.Status.CREATED.getStatusCode()) {
                permCsid = CollectionSpaceClientUtils.extractId(response);
-               result = getPermission(permCsid);
+               result = (Permission)get(jpaTransactionContext, permCsid, Permission.class);
        }
                
        return result;
@@ -133,33 +136,38 @@ public class PermissionResource extends SecurityResourceBase {
          return (Permission)update(csid, theUpdate, Permission.class);
     }
 
-    @DELETE
+    @SuppressWarnings("unchecked")
+       @DELETE
     @Path("{csid}")
-    public Response deletePermission(@PathParam("csid") String csid) {
+    public Response deletePermission(@PathParam("csid") String csid) throws Exception {
         logger.debug("deletePermission with csid=" + csid);
         ensureCSID(csid, ServiceMessages.DELETE_FAILED + "permission ");
+
+               ServiceContext<Permission, Permission> ctx = createServiceContext((Permission) null, Permission.class);
+        TransactionContext transactionContext = ctx.openConnection();
         try {
             //FIXME ideally the following two ops should be in the same tx CSPACE-658
             //delete all relationships for this permission
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
-            subResource.deletePermissionRole(csid, SubjectType.ROLE);
+            subResource.deletePermissionRole(ctx, csid, SubjectType.ROLE);
             //NOTE for delete permissions in the authz provider
             //at the PermissionRoleSubResource/DocHandler level, there is no visibility
             //if permission is deleted, so do it here, however,
             //this is a very dangerous operation as it deletes the Spring ACL instead of ACE(s)
             //the ACL might be needed for other ACEs roles...
-            AuthorizationDelegate.deletePermissions(csid);
+            AuthorizationDelegate.deletePermissions((JPATransactionContext)transactionContext, csid);
 
-            ServiceContext<Permission, Permission> ctx = createServiceContext((Permission) null, Permission.class);
             getStorageClient(ctx).delete(ctx, csid);
             return Response.status(HttpResponseCodes.SC_OK).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid);
+        } finally {
+               ctx.closeConnection();
         }
     }
 
-    @POST
+       @POST
     @Path("{csid}/permroles")
     public Response createPermissionRole(@QueryParam("_method") String method,
             @PathParam("csid") String permCsid,
@@ -174,7 +182,7 @@ public class PermissionResource extends SecurityResourceBase {
         try {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
-            String permrolecsid = subResource.createPermissionRole(input, SubjectType.ROLE);
+            String permrolecsid = subResource.createPermissionRole((ServiceContext<Permission, Permission>)null, input, SubjectType.ROLE);
             UriBuilder path = UriBuilder.fromResource(PermissionResource.class);
             path.path(permCsid + "/permroles/" + permrolecsid);
             Response response = Response.created(path.build()).build();
@@ -184,7 +192,7 @@ public class PermissionResource extends SecurityResourceBase {
         }
     }
 
-    @GET
+       @GET
     @Path("{csid}/permroles/{id}")
     public PermissionRoleRel getPermissionRole(
             @PathParam("csid") String permCsid,
@@ -196,7 +204,7 @@ public class PermissionResource extends SecurityResourceBase {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
             //get relationships for a permission
-            result = subResource.getPermissionRoleRel(permCsid, SubjectType.ROLE, permrolecsid);
+            result = subResource.getPermissionRoleRel((ServiceContext<Permission, Permission>)null, permCsid, SubjectType.ROLE, permrolecsid);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, permCsid);
         }
@@ -204,7 +212,7 @@ public class PermissionResource extends SecurityResourceBase {
         return result;
     }
 
-    @GET
+       @GET
     @Path("{csid}/permroles")
     public PermissionRole getPermissionRole(
             @PathParam("csid") String permCsid) {
@@ -215,7 +223,7 @@ public class PermissionResource extends SecurityResourceBase {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
             //get relationships for a permission
-            result = subResource.getPermissionRole(permCsid, SubjectType.ROLE);
+            result = subResource.getPermissionRole((ServiceContext<Permission, Permission>)null, permCsid, SubjectType.ROLE);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED, permCsid);
         }
@@ -230,7 +238,7 @@ public class PermissionResource extends SecurityResourceBase {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
             //delete all relationships for a permission
-            subResource.deletePermissionRole(permCsid, SubjectType.ROLE, input);
+            subResource.deletePermissionRole((ServiceContext<Permission, Permission>)null, permCsid, SubjectType.ROLE, input);
             return Response.status(HttpResponseCodes.SC_OK).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, permCsid);
@@ -247,7 +255,7 @@ public class PermissionResource extends SecurityResourceBase {
             PermissionRoleSubResource subResource =
                     new PermissionRoleSubResource(PermissionRoleSubResource.PERMISSION_PERMROLE_SERVICE);
             //delete all relationships for a permission
-            subResource.deletePermissionRole(permCsid, SubjectType.ROLE);
+            subResource.deletePermissionRole((ServiceContext<Permission, Permission>)null, permCsid, SubjectType.ROLE);
             return Response.status(HttpResponseCodes.SC_OK).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, permCsid);
index a410eb4d56355095fb1152e485e20cf8b091769c..4d02fd137199ee55bf998c650959c35904865ca1 100644 (file)
@@ -35,6 +35,7 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextFactory;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.storage.StorageClient;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaRelationshipStorageClient;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 import org.collectionspace.services.common.context.ServiceContextProperties;
@@ -46,6 +47,7 @@ import org.slf4j.LoggerFactory;
  * PermissionRoleSubResource is used to manage permission-role relationship
  * @author
  */
+@SuppressWarnings("rawtypes")
 public class PermissionRoleSubResource
         extends AbstractCollectionSpaceResourceImpl<PermissionRole, PermissionRole> {
 
@@ -97,7 +99,8 @@ public class PermissionRoleSubResource
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.CollectionSpaceResource#getServiceContextFactory()
      */
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public ServiceContextFactory<PermissionRole, PermissionRole> getServiceContextFactory() {
         return RemoteServiceContextFactory.get();
     }
@@ -112,9 +115,21 @@ public class PermissionRoleSubResource
      * 
      * @throws Exception the exception
      */
-    private ServiceContext<PermissionRole, PermissionRole> createServiceContext(PermissionRole input,
+    private ServiceContext<PermissionRole, PermissionRole> createServiceContext(
+               ServiceContext parentCtx,
+               PermissionRole input,
             SubjectType subject) throws Exception {
         ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(input);
+       JPATransactionContext parentTransactionContext = parentCtx != null ? (JPATransactionContext)parentCtx.getCurrentTransactionContext() : null;
+       //
+       // If the parent context has an active JPA connection then we'll use it.
+       //
+       if (parentTransactionContext != null) {
+               ctx.setTransactionContext(parentTransactionContext);
+       }
+        //
+       // Set other context values
+       //
         ctx.setDocumentType(PermissionRole.class.getPackage().getName()); //persistence unit
         ctx.setProperty(ServiceContextProperties.ENTITY_NAME, PermissionRoleRel.class.getName());
         ctx.setProperty(ServiceContextProperties.ENTITY_CLASS, PermissionRoleRel.class);
@@ -154,10 +169,10 @@ public class PermissionRoleSubResource
      * @return
      * @throws Exception
      */
-    public String createPermissionRole(PermissionRole input, SubjectType subject)
+    public String createPermissionRole(ServiceContext parentCtx, PermissionRole input, SubjectType subject)
             throws Exception {
 
-        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(input, subject);
+        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(parentCtx, input, subject);
         DocumentHandler handler = createDocumentHandler(ctx);
         return getStorageClient(ctx).create(ctx, handler);
     }
@@ -171,28 +186,22 @@ public class PermissionRoleSubResource
      * @return the permission role rel
      * @throws Exception the exception
      */
-    public PermissionRoleRel getPermissionRoleRel(String csid,
+    public PermissionRoleRel getPermissionRoleRel(
+               ServiceContext parentCtx,
+               String csid,
                SubjectType subject,
                String permissionRoleCsid) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("getAccountRole with csid=" + csid);
         }
-//        AccountRolesList result = new AccountRolesList();
-        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext((PermissionRole) null, subject);
+
+        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(parentCtx, (PermissionRole) null, subject);
         PermissionRoleDocumentHandler handler = (PermissionRoleDocumentHandler)createDocumentHandler(ctx);
         handler.setPermissionRoleCsid(permissionRoleCsid);
         //getStorageClient(ctx).get(ctx, csid, handler);
         PermissionRoleRel permissionRoleRel = (PermissionRoleRel)JpaStorageUtils.getEntity(
                        new Long(permissionRoleCsid).longValue(), PermissionRoleRel.class);
-//        List<AccountRoleListItem> accountRoleList = result.getAccountRoleListItems();
-//        AccountRoleListItem listItem = new AccountRoleListItem();
-//        // fill the item
-//        listItem.setCsid(accountRoleRel.getHjid().toString());
-//        listItem.setRoleId(accountRoleRel.getRoleId());
-//        listItem.setRoleName(accountRoleRel.getRoleName());
-        // add item to result list
-//        result = (AccountRolesList) ctx.getOutput();
         
         return permissionRoleRel;
     }
@@ -206,13 +215,15 @@ public class PermissionRoleSubResource
      * @throws Exception
      */
     public PermissionRole getPermissionRole(
-            String csid, SubjectType subject) throws Exception {
+               ServiceContext parentCtx,
+            String csid, 
+            SubjectType subject) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("getPermissionRole with csid=" + csid);
         }
         PermissionRole result = null;
-        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext((PermissionRole) null, subject);
+        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(parentCtx, (PermissionRole) null, subject);
         DocumentHandler handler = createDocumentHandler(ctx);
         getStorageClient(ctx).get(ctx, csid, handler);
         result = (PermissionRole) ctx.getOutput();
@@ -228,14 +239,15 @@ public class PermissionRoleSubResource
      * @return
      * @throws Exception
      */
-    public void deletePermissionRole(String csid,
+    public void deletePermissionRole(ServiceContext parentCtx,
+               String csid,
             SubjectType subject) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("deletePermissionRole with csid=" + csid);
         }
-        PermissionRole permRole = this.getPermissionRole(csid, subject);
-        this.deletePermissionRole(csid, subject, permRole);
+        PermissionRole permRole = this.getPermissionRole(parentCtx, csid, subject);
+        deletePermissionRole(parentCtx, csid, subject, permRole);
     }
 
     /**
@@ -247,13 +259,13 @@ public class PermissionRoleSubResource
      * @return
      * @throws Exception
      */
-    public void deletePermissionRole(String csid,
+       public void deletePermissionRole(ServiceContext parentCtx, String csid,
             SubjectType subject, PermissionRole input) throws Exception {
 
         if (logger.isDebugEnabled()) {
             logger.debug("deletePermissionRole(input) with csid=" + csid);
         }
-        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(input, subject);
+        ServiceContext<PermissionRole, PermissionRole> ctx = createServiceContext(parentCtx, input, subject);
         DocumentHandler handler = createDocumentHandler(ctx);
         getStorageClient(ctx).delete(ctx, csid, handler);
     }
index c8f863aab67e129970930086258cb23f8dca261c..0adcb0186b07de5b02679f68755e165cf34f437b 100644 (file)
@@ -44,6 +44,7 @@ import org.collectionspace.services.authorization.URIResourceImpl;
 import org.collectionspace.services.common.authorization_mgt.PermissionRoleUtil;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,25 +67,27 @@ public class AuthorizationDelegate {
      * @see PermissionRole
      */
     public static void addPermissions(ServiceContext ctx, PermissionRole pr) throws Exception {
+       JPATransactionContext jpaTransactionContext = (JPATransactionContext) ctx.getCurrentTransactionContext();
+       
         SubjectType subject = PermissionRoleUtil.getRelationSubject(ctx, pr);
         AuthZ authz = AuthZ.get();
         if (subject.equals(SubjectType.ROLE)) {
             PermissionValue pv = pr.getPermission().get(0);
-            Permission p = getPermission(pv.getPermissionId());
+            Permission p = getPermission(jpaTransactionContext, pv.getPermissionId());
             if (p == null) {
                 String msg = "addPermissions: No permission found for id=" + pv.getPermissionId();
                 logger.error(msg);
                 throw new DocumentNotFoundException(msg);
             }
             CSpaceResource[] resources = getResources(p);
-            String[] roles = getRoles(pr.getRole());
+            String[] roles = getRoles(jpaTransactionContext, pr.getRole());
             for (CSpaceResource res : resources) {
                 boolean grant = p.getEffect().equals(EffectType.PERMIT) ? true : false;
                 authz.addPermissions(res, roles, grant);
             }
         } else if (SubjectType.PERMISSION.equals(subject)) {
             RoleValue rv = pr.getRole().get(0);
-            Role r = getRole(rv.getRoleId());
+            Role r = getRole(jpaTransactionContext, rv.getRoleId());
             if (r == null) {
                 String msg = "addPermissions: No role found for id=" + rv.getRoleId();
                 logger.error(msg);
@@ -94,7 +97,7 @@ public class AuthorizationDelegate {
             // This needs to use the qualified name, not the display name
             String[] roles = {r.getRoleName()};
             for (PermissionValue pv : pr.getPermission()) {
-                Permission p = getPermission(pv.getPermissionId());
+                Permission p = getPermission(jpaTransactionContext, pv.getPermissionId());
                 if (p == null) {
                     String msg = "addPermissions: No permission found for id=" + pv.getPermissionId();
                     logger.error(msg);
@@ -118,20 +121,22 @@ public class AuthorizationDelegate {
      */
     public static void deletePermissions(ServiceContext ctx, PermissionRole pr)
             throws Exception {
+       JPATransactionContext jpaTransactionContext = (JPATransactionContext) ctx.getCurrentTransactionContext();
+
         SubjectType subject = PermissionRoleUtil.getRelationSubject(ctx, pr);
         AuthZ authz = AuthZ.get();
         if (subject.equals(SubjectType.ROLE)) {
                List<PermissionValue> permissionValues = pr.getPermission();
                if (permissionValues != null & permissionValues.size() > 0) {
                    PermissionValue pv = permissionValues.get(0);
-                   Permission p = getPermission(pv.getPermissionId());
+                   Permission p = getPermission(jpaTransactionContext, pv.getPermissionId());
                    if (p == null) {
                        String msg = "deletePermissions: No permission found for id=" + pv.getPermissionId();
                        logger.error(msg);
                        throw new DocumentNotFoundException(msg);
                    }
                    CSpaceResource[] resources = getResources(p);
-                   String[] roles = getRoles(pr.getRole());
+                   String[] roles = getRoles(jpaTransactionContext, pr.getRole());
                    for (CSpaceResource res : resources) {
                        authz.deletePermissions(res, roles);
                    }
@@ -140,7 +145,7 @@ public class AuthorizationDelegate {
                List<RoleValue> roleValues = pr.getRole();
                if (roleValues != null && roleValues.size() > 0) {
                    RoleValue rv = roleValues.get(0);
-                   Role r = getRole(rv.getRoleId());
+                   Role r = getRole(jpaTransactionContext, rv.getRoleId());
                    if (r == null) {
                        String msg = "deletePermissions: No role found for id=" + rv.getRoleId();
                        logger.error(msg);
@@ -150,7 +155,7 @@ public class AuthorizationDelegate {
                    // This needs to use the qualified name, not the display name
                    String[] roles = {r.getRoleName()}; 
                    for (PermissionValue pv : pr.getPermission()) {
-                       Permission p = getPermission(pv.getPermissionId());
+                       Permission p = getPermission(jpaTransactionContext, pv.getPermissionId());
                        if (p == null) {
                            String msg = "deletePermissions: No permission found for id=" + pv.getPermissionId();
                            logger.error(msg);
@@ -175,8 +180,8 @@ public class AuthorizationDelegate {
     //the Spring ACL instead of ACE(s) that is associated with each role
     //the ACL might be needed for other ACEs (including those for ROLE_ADMINISTRATOR,
     //ROLE_TENANT_ADMINISTRATOR, etc.)...
-    static public void deletePermissions(String permCsid) throws Exception {
-        Permission p = getPermission(permCsid);
+    static public void deletePermissions(JPATransactionContext jpaTransactionContext, String permCsid) throws Exception {
+        Permission p = getPermission(jpaTransactionContext, permCsid);
         if (p == null) {
             String msg = "deletePermissions: No permission found for id=" + permCsid;
             logger.error(msg);
@@ -202,11 +207,11 @@ public class AuthorizationDelegate {
      * @return string array with role names
      * @see RoleValue
      */
-    private static String[] getRoles(List<RoleValue> rvl)
+    private static String[] getRoles(JPATransactionContext jpaTransactionContext, List<RoleValue> rvl)
                throws DocumentNotFoundException {
         List<String> rvls = new ArrayList<String>();
         for (RoleValue rv : rvl) {
-            Role r = getRole(rv.getRoleId());
+            Role r = getRole(jpaTransactionContext, rv.getRoleId());
             if (r == null) {
                 String msg = "getRoles: No role found for id=" + rv.getRoleId();
                 logger.error(msg);
@@ -215,6 +220,7 @@ public class AuthorizationDelegate {
             }
             rvls.add(r.getRoleName());
         }
+        
         return rvls.toArray(new String[0]);
     }
 
@@ -242,17 +248,15 @@ public class AuthorizationDelegate {
         return rl.toArray(new CSpaceResource[0]);
     }
 
-    private static Permission getPermission(String permCsid)
+    private static Permission getPermission(JPATransactionContext jpaTransactionContext, String permCsid)
                throws DocumentNotFoundException {
-        Permission p = (Permission) JpaStorageUtils.getEntity(permCsid,
+        Permission p = (Permission) JpaStorageUtils.getEntity(jpaTransactionContext, permCsid,
                 Permission.class);
         return p;
     }
 
-    private static Role getRole(String roleCsid)
-               throws DocumentNotFoundException {
-        Role r = (Role) JpaStorageUtils.getEntity(roleCsid,
-                Role.class);
+    private static Role getRole(JPATransactionContext jpaTransactionContext, String roleCsid) throws DocumentNotFoundException {
+        Role r = (Role) JpaStorageUtils.getEntity(jpaTransactionContext, roleCsid, Role.class);
         return r;
     }
 
index 156ad27f6e592d188523fb34ab2b2b2af057361f..d618ea45389763ada0a4bb89fa5e26f45dd4cbdd 100644 (file)
@@ -28,25 +28,27 @@ import java.util.List;
 import java.util.UUID;
 
 import javax.persistence.EntityExistsException;
-import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 
+import org.collectionspace.services.client.PermissionClient;
+import org.collectionspace.services.client.PermissionClient.ActionCompare;
+
 import org.collectionspace.services.authorization.perms.ActionType;
 import org.collectionspace.services.authorization.CSpaceAction;
-import org.collectionspace.services.authorization.RolesList;
 import org.collectionspace.services.authorization.perms.Permission;
 import org.collectionspace.services.authorization.perms.PermissionAction;
 import org.collectionspace.services.authorization.perms.PermissionsList;
-import org.collectionspace.services.client.PermissionClient;
-import org.collectionspace.services.client.PermissionClient.ActionCompare;
 import org.collectionspace.services.authorization.URIResourceImpl;
-import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;
+
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentException;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.security.SecurityUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
@@ -57,6 +59,7 @@ import org.slf4j.LoggerFactory;
  * Document handler for Permission
  * @author 
  */
+@SuppressWarnings("rawtypes")
 public class PermissionDocumentHandler
                extends JpaDocumentHandler<Permission, PermissionsList, Permission, List<Permission>> {
 
@@ -132,12 +135,14 @@ public class PermissionDocumentHandler
         }
     }
     
-    private Permission findExistingPermission(EntityManager em, Permission perm) {
+       private Permission findExistingPermission(Permission perm) throws TransactionException {
        Permission result = null;
-               String tenantId = getServiceContext().getTenantId(); // we need a tenant ID 
-        
+       
+               ServiceContext ctx = getServiceContext();
+               String tenantId = ctx.getTenantId(); // we need a tenant ID 
+               JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
                try {
-               result = (Permission)JpaStorageUtils.getEntityByDualKeys(em
+               result = (Permission)JpaStorageUtils.getEntityByDualKeys(jpaTransactionContext
                                Permission.class.getName(),
                                PermissionStorageConstants.RESOURCE_NAME, perm.getResourceName(), 
                                PermissionStorageConstants.ACTION_GROUP, perm.getActionGroup(),
@@ -148,6 +153,8 @@ public class PermissionDocumentHandler
                                                perm.getResourceName(), perm.getActionGroup(), tenantId);
                                logger.trace(msg);
                        }
+               } finally {
+                       ctx.closeConnection();
                }
 
        return result;
@@ -158,10 +165,8 @@ public class PermissionDocumentHandler
        //
        // First check to see if an equivalent permission exists
        //
-       Permission permission = wrapDoc.getWrappedObject();
-       
-       EntityManager em = (EntityManager) this.getServiceContext().getProperty(AuthorizationStore.ENTITY_MANAGER_PROP_KEY);
-       Permission existingPermission = findExistingPermission(em, permission);
+       Permission permission = wrapDoc.getWrappedObject();     
+       Permission existingPermission = findExistingPermission(permission);
 
        if (existingPermission == null) {
                String id = UUID.randomUUID().toString();        
@@ -224,7 +229,8 @@ public class PermissionDocumentHandler
         return to;
     }
 
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public void completeUpdate(DocumentWrapper<Permission> wrapDoc) throws Exception {
         Permission upAcc = wrapDoc.getWrappedObject();
         getServiceContext().setOutput(upAcc);
@@ -234,14 +240,16 @@ public class PermissionDocumentHandler
         //new based on new actions and effect
     }
 
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public void handleGet(DocumentWrapper<Permission> wrapDoc) throws Exception {
         setCommonPart(extractCommonPart(wrapDoc));
         sanitize(getCommonPart());
         getServiceContext().setOutput(permission);
     }
 
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public void handleGetAll(DocumentWrapper<List<Permission>> wrapDoc) throws Exception {
         PermissionsList permissionsList = extractCommonPartList(wrapDoc);
         setCommonPartList(permissionsList);
index 990c732013fb78e2155f12155f113d58dcb4da21..392671bb6e5c9cfb55078b465009608c22a80af9 100644 (file)
@@ -26,8 +26,6 @@ package org.collectionspace.services.authorization.storage;
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
 import javax.persistence.NoResultException;
 
 import org.collectionspace.services.authorization.PermissionRole;
@@ -36,14 +34,18 @@ import org.collectionspace.services.authorization.PermissionValue;
 import org.collectionspace.services.authorization.PermissionsRolesList;
 import org.collectionspace.services.authorization.RoleValue;
 import org.collectionspace.services.authorization.SubjectType;
-import org.collectionspace.services.authorization.perms.Permission;
+
 import org.collectionspace.services.common.authorization_mgt.AuthorizationRoleRel;
 import org.collectionspace.services.common.authorization_mgt.PermissionRoleUtil;
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.document.TransactionException;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentFilter;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,12 +89,12 @@ public class PermissionRoleDocumentHandler
         filterOutExisting(wrapDoc);
     }
     
-    private boolean permRoleRelExists(EntityManager em, PermissionRoleRel permRoleRel) {
+    private boolean permRoleRelExists(JPATransactionContext jpaTransactionContext, PermissionRoleRel permRoleRel) throws TransactionException {
        boolean result = false;
        
        PermissionRoleRel queryResult = null;
        try {
-               queryResult = (PermissionRoleRel) JpaStorageUtils.getEntityByDualKeys(em
+               queryResult = (PermissionRoleRel) JpaStorageUtils.getEntityByDualKeys(jpaTransactionContext
                                PermissionRoleRel.class.getName(),
                                PermissionStorageConstants.PERMREL_ROLE_ID, permRoleRel.getRoleId(), 
                                PermissionStorageConstants.PERMREL_PERM_ID, permRoleRel.getPermissionId());
@@ -112,41 +114,33 @@ public class PermissionRoleDocumentHandler
      * @param wrapDoc
      * @throws Exception
      */
-    private void filterOutExisting(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+    @SuppressWarnings("rawtypes")
+       private void filterOutExisting(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
        List<PermissionRoleRel> permRoleRelList = wrapDoc.getWrappedObject();
        
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       ServiceContext ctx = getServiceContext();
+        JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
         try {
-            emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
+               jpaTransactionContext.beginTransaction();
             
             for (PermissionRoleRel permRoleRel : permRoleRelList) {
-               if (permRoleRelExists(em, permRoleRel) == true) {
+               if (permRoleRelExists(jpaTransactionContext, permRoleRel) == true) {
                        //
                        // Remove the item from the list since it already exists
                        //
                        permRoleRelList.remove(permRoleRel);
                }
             }
-            
-            em.getTransaction().commit();
-               em.close();            
+            jpaTransactionContext.commitTransaction();
         } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             throw e;
         } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
-
     }
 
     /* (non-Javadoc)
@@ -177,7 +171,8 @@ public class PermissionRoleDocumentHandler
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.document.AbstractDocumentHandlerImpl#handleGet(org.collectionspace.services.common.document.DocumentWrapper)
      */
-    @Override
+    @SuppressWarnings("unchecked")
+       @Override
     public void handleGet(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
         setCommonPart(extractCommonPart(wrapDoc));
         getServiceContext().setOutput(permissionRole);
@@ -263,7 +258,8 @@ public class PermissionRoleDocumentHandler
      * @param handleDelete the handle delete
      * @throws Exception the exception
      */
-    public void fillCommonPart(PermissionRole pr,
+    @SuppressWarnings("rawtypes")
+       public void fillCommonPart(PermissionRole pr,
                        DocumentWrapper<List<PermissionRoleRel>> wrapDoc,
                        boolean handleDelete)
             throws Exception {
@@ -276,8 +272,9 @@ public class PermissionRoleDocumentHandler
             //subject mismatch should have been checked during validation
         }
         
-        String tenantId = this.getServiceContext().getTenantId();
-        PermissionRoleUtil.buildPermissionRoleRel(pr, subject, prrl, handleDelete, tenantId);
+        ServiceContext ctx = this.getServiceContext();
+        String tenantId = ctx.getTenantId();
+        PermissionRoleUtil.buildPermissionRoleRel(ctx, pr, subject, prrl, handleDelete, tenantId);
     }
     
     /* (non-Javadoc)
index 9bf20714f3cd1410632300140a7e99045854025d..05f0c893df22c4cd58693a071201d296eafe0493 100644 (file)
@@ -3,35 +3,66 @@ package org.collectionspace.services.common;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentHandler;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
+@SuppressWarnings({ "unchecked", "rawtypes" })
 public abstract class SecurityResourceBase extends AbstractCollectionSpaceResourceImpl {
 
     final Logger logger = LoggerFactory.getLogger(SecurityResourceBase.class);
 
     public Response create(Object input) {
-            try {
-                ServiceContext ctx = createServiceContext(input, input.getClass());
-                DocumentHandler handler = createDocumentHandler(ctx);
-                String csid = getStorageClient(ctx).create(ctx, handler);
-                UriBuilder path = UriBuilder.fromResource(this.getClass());
-                path.path("" + csid);
-                Response response = Response.created(path.build()).build();
-                return response;
-            } catch (Exception e) {
-                throw bigReThrow(e, ServiceMessages.POST_FAILED+"create in "+this.getClass().getName());
-            }
+       Response response = null;
+       
+        try {
+            ServiceContext ctx = createServiceContext(input, input.getClass());
+            DocumentHandler handler = createDocumentHandler(ctx);
+            String csid = getStorageClient(ctx).create(ctx, handler);
+            UriBuilder path = UriBuilder.fromResource(this.getClass());
+            path.path("" + csid);
+            response = Response.created(path.build()).build();
+        } catch (Exception e) {
+            throw bigReThrow(e, ServiceMessages.POST_FAILED+"create in "+this.getClass().getName());
         }
+        
+        return response;
+    }
+    
+    public Response create(JPATransactionContext jpaTransactionContext, Object input) {
+       Response response = null;
+       
+        try {
+            ServiceContext ctx = createServiceContext(jpaTransactionContext, input, input.getClass());
+            DocumentHandler handler = createDocumentHandler(ctx);
+            String csid = getStorageClient(ctx).create(ctx, handler);
+            UriBuilder path = UriBuilder.fromResource(this.getClass());
+            path.path("" + csid);
+            response = Response.created(path.build()).build();
+        } catch (Exception e) {
+            throw bigReThrow(e, ServiceMessages.POST_FAILED+"create in "+this.getClass().getName());
+        }
+        
+        return response;
+    }    
+
+    private ServiceContext createServiceContext(JPATransactionContext jpaTransactionContext, Object input,
+                       Class<? extends Object> clazz) throws Exception {
+        ServiceContext result = createServiceContext(input, clazz);
+        
+        if (jpaTransactionContext != null) {
+                       result.setTransactionContext(jpaTransactionContext);
+        }
+        
+        return result;
+       }
 
-    public Object get(String csid, Class objectClass) {
+       public Object get(String csid, Class objectClass) {
        return get((UriInfo)null, csid, objectClass);
     }
 
@@ -50,8 +81,24 @@ public abstract class SecurityResourceBase extends AbstractCollectionSpaceResour
         checkResult(result, csid, ServiceMessages.GET_FAILED);
         return result;
     }
+    
+    public Object get(JPATransactionContext jpaTransactionContext, String csid, Class objectClass) {
+        logger.debug("get with csid=" + csid);
+        ensureCSID(csid, ServiceMessages.GET_FAILED + "csid");
+        Object result = null;
+        try {
+            ServiceContext ctx = createServiceContext(jpaTransactionContext, (Object) null, objectClass);   
+            DocumentHandler handler = createDocumentHandler(ctx);
+            getStorageClient(ctx).get(ctx, csid, handler);
+            result = ctx.getOutput();
+        } catch (Exception e) {
+            throw bigReThrow(e, ServiceMessages.GET_FAILED, csid);
+        }
+        checkResult(result, csid, ServiceMessages.GET_FAILED);
+        return result;
+    }    
 
-    public Object getList(UriInfo ui, Class objectClass) {
+       public Object getList(UriInfo ui, Class objectClass) {
         try {
             ServiceContext ctx = createServiceContext((Object) null, objectClass, ui);
             DocumentHandler handler = createDocumentHandler(ctx);
@@ -69,11 +116,11 @@ public abstract class SecurityResourceBase extends AbstractCollectionSpaceResour
         }
     }
 
-    public Object update(String csid, Object theUpdate, Class objectClass) {
+    public Object update(String csid, Object theUpdate, Class<?> objectClass) {
        return update((UriInfo)null, csid, theUpdate, objectClass);
     }
     
-    public Object update(UriInfo ui, String csid, Object theUpdate, Class objectClass) {
+       public Object update(UriInfo ui, String csid, Object theUpdate, Class objectClass) {
         if (logger.isDebugEnabled()) {
             logger.debug("updateRole with csid=" + csid);
         }
index 263e01774c64e4474890a6adbf42f05ebedf0460..901113619267f0e9726e63eda8d7ddc5653b10e6 100644 (file)
@@ -36,7 +36,7 @@ import org.collectionspace.services.common.init.AddIndices;
 import org.collectionspace.services.common.init.IInitHandler;
 import org.collectionspace.services.common.storage.DatabaseProductType;
 import org.collectionspace.services.common.storage.JDBCTools;
-
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.config.service.InitHandler.Params.Field;
 import org.collectionspace.services.config.ClientType;
 import org.collectionspace.services.config.ServiceConfig;
@@ -238,19 +238,23 @@ public class ServiceMain {
         // Create all the tenant records, default user accounts, roles, and permissions.  Since some of our "cspace" database config files
         // for Spring need to be created at build time, the "cspace" database already will be suffixed with the
         // correct 'cspaceInstanceId' so we don't need to pass it to the JDBCTools methods.
-        //        
+        //
+               JPATransactionContext jpaTransactionContext = new JPATransactionContext();
                try {
+                       jpaTransactionContext.beginTransaction();
                        DatabaseProductType databaseProductType = JDBCTools.getDatabaseProductType(JDBCTools.CSPACE_DATASOURCE_NAME,
                                        cspaceDatabaseName);            
-
                        AuthorizationCommon.createTenants(tenantBindingConfigReader, databaseProductType, cspaceDatabaseName);
-                       AuthorizationCommon.createDefaultWorkflowPermissions(tenantBindingConfigReader, databaseProductType, cspaceDatabaseName);
+                       AuthorizationCommon.createDefaultWorkflowPermissions(jpaTransactionContext, tenantBindingConfigReader, databaseProductType, cspaceDatabaseName);
                        AuthorizationCommon.createDefaultAccounts(tenantBindingConfigReader, databaseProductType, cspaceDatabaseName);
                        AuthorizationCommon.persistTenantBindingsMD5Hash(tenantBindingConfigReader, databaseProductType, cspaceDatabaseName);
+                       jpaTransactionContext.commitTransaction();
                } catch (Exception e) {
                        logger.error("Default create/update of tenants, accounts, roles and permissions setup failed with exception(s): " +
                                        e.getLocalizedMessage(), e);
                        throw e;
+               } finally {
+                       jpaTransactionContext.close();
                }
                //
                // Log tenant status -shows all tenants' info and active status.
index af328f7c1db706a8ede3cb174e009e575aa030c7..0280856499d1d63ce7b70e79424315583bab58af 100644 (file)
@@ -49,6 +49,7 @@ import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.security.SecurityUtils;
 import org.collectionspace.services.common.storage.DatabaseProductType;
 import org.collectionspace.services.common.storage.JDBCTools;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
 import org.collectionspace.services.config.service.ServiceBindingType;
@@ -68,7 +69,7 @@ import org.springframework.security.acls.model.AlreadyExistsException;
 
 public class AuthorizationCommon {
        
-       final public static String REFRESH_AUTZ_PROP = "refreshAuthZOnStartup";
+       final public static String REFRESH_AUTHZ_PROP = "refreshAuthZOnStartup";
        
        //
        // For token generation and password reset
@@ -162,20 +163,21 @@ public class AuthorizationCommon {
                return tenantConfigMD5HashTable.put(tenantId, md5hash);
        }       
        
-    public static Role getRole(String tenantId, String displayName) {
+       @Deprecated
+    public static Role xgetRole(String tenantId, String displayName) {
        Role role = null;
        
        String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
-       role = AuthorizationStore.getRoleByName(roleName, tenantId);
+       //role = AuthorizationStore.getRoleByName(roleName, tenantId);
         
         return role;
     }
     
-    public static Role getRole(EntityManager em, String tenantId, String displayName) {
+    public static Role getRole(JPATransactionContext jpaTransactionContext, String tenantId, String displayName) {
        Role role = null;
        
        String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
-       role = AuthorizationStore.getRoleByName(em, roleName, tenantId);
+       role = AuthorizationStore.getRoleByName(jpaTransactionContext, roleName, tenantId);
         
         return role;
     }
@@ -349,7 +351,7 @@ public class AuthorizationCommon {
        return result;
     }
     
-    private static PermissionRole createPermissionRole(EntityManager em,
+    private static PermissionRole createPermissionRole(
                Permission permission,
                Role role,
                boolean enforceTenancy) throws Exception
@@ -899,6 +901,7 @@ public class AuthorizationCommon {
     /*
      * Using the tenant bindings, ensure there are corresponding Tenant records (db columns).
      */
+    //FIXME: This code should be using JPA objects and JPATransactionContext, not raw SQL.
     public static void createTenants(
                TenantBindingConfigReaderImpl tenantBindingConfigReader,
                DatabaseProductType databaseProductType,
@@ -927,6 +930,14 @@ public class AuthorizationCommon {
                }
        }
     
+    /**
+     * 
+     * @param tenantBindingConfigReader
+     * @param databaseProductType
+     * @param cspaceDatabaseName
+     * @throws Exception
+     */
+    //FIXME: This code should be using the JPA objects and JPATransactionContext, not raw SQL.
     public static void createDefaultAccounts(
                TenantBindingConfigReaderImpl tenantBindingConfigReader,
                DatabaseProductType databaseProductType,
@@ -1084,7 +1095,9 @@ public class AuthorizationCommon {
         * @param cspaceDatabaseName
         * @throws Exception
         */
-    public static void createDefaultWorkflowPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader,
+    public static void createDefaultWorkflowPermissions(
+               JPATransactionContext jpaTransactionContext,
+               TenantBindingConfigReaderImpl tenantBindingConfigReader,
                DatabaseProductType databaseProductType, 
                String cspaceDatabaseName) throws Exception //FIXME: REM - 4/11/2012 - Rename to createWorkflowPermissions
     {
@@ -1092,12 +1105,7 @@ public class AuthorizationCommon {
 
        AuthZ.get().login(); //login to Spring Security manager
        
-        EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
-        EntityManager em = null;
-
         try {
-            em = emf.createEntityManager();
-
                Hashtable<String, TenantBindingType> tenantBindings = tenantBindingConfigReader.getTenantBindings();
                for (String tenantId : tenantBindings.keySet()) {
                        logger.info(String.format("Creating/verifying workflow permissions for tenant ID=%s.", tenantId));
@@ -1106,8 +1114,8 @@ public class AuthorizationCommon {
                                continue; // skip the rest of the loop and go to the next tenant
                        }
                        
-                       Role adminRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_ADMINISTRATOR);
-                       Role readonlyRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_READER);
+                       Role adminRole = AuthorizationCommon.getRole(jpaTransactionContext, tenantBinding.getId(), ROLE_TENANT_ADMINISTRATOR);
+                       Role readonlyRole = AuthorizationCommon.getRole(jpaTransactionContext, tenantBinding.getId(), ROLE_TENANT_READER);
                        
                        if (adminRole == null || readonlyRole == null) {
                                String msg = String.format("One or more of the required default CollectionSpace administrator roles is missing or was never created.  If you're setting up a new instance of CollectionSpace, shutdown the Tomcat server and run the 'ant import' command from the root/top level CollectionSpace 'Services' source directory.  Then try restarting Tomcat.");
@@ -1116,25 +1124,27 @@ public class AuthorizationCommon {
                        }
                        
                        for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {
-                               String prop = ServiceBindingUtils.getPropertyValue(serviceBinding, REFRESH_AUTZ_PROP);
+                               String prop = ServiceBindingUtils.getPropertyValue(serviceBinding, REFRESH_AUTHZ_PROP);
                                if (prop == null ? true : Boolean.parseBoolean(prop)) {
-                                               try {
-                                               em.getTransaction().begin();
+                                       try {
+                                               jpaTransactionContext.beginTransaction();
                                                TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);
                                                HashSet<String> transitionVerbList = getTransitionVerbList(tenantBinding, serviceBinding);
                                                for (String transitionVerb : transitionVerbList) {
                                                        //
                                                        // Create the permission for the admin role
                                                        Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionVerb, ACTIONGROUP_CRUDL);
-                                                       persist(em, adminPerm, adminRole, true, ACTIONGROUP_CRUDL);
+                                                       persist(jpaTransactionContext, adminPerm, adminRole, true, ACTIONGROUP_CRUDL);
                                                        //
                                                        // Create the permission for the read-only role
                                                        Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionVerb, ACTIONGROUP_RL);                                                      
-                                                       persist(em, readonlyPerm, readonlyRole, true, ACTIONGROUP_RL); // Persist/store the permission and permrole records and related Spring Security info
+                                                       persist(jpaTransactionContext, readonlyPerm, readonlyRole, true, ACTIONGROUP_RL); // Persist/store the permission and permrole records and related Spring Security info
                                                }
-                                               em.getTransaction().commit();
+                                               jpaTransactionContext.commitTransaction();
                                        } catch (IllegalStateException e) {
                                                logger.fine(e.getLocalizedMessage()); //We end up here if there is no document handler for the service -this is ok for some of the services.
+                                       } catch (Exception x) {
+                                               jpaTransactionContext.markForRollback();
                                        }
                                } else {
                                        logger.warning("AuthZ refresh service binding property is set to FALSE so default permissions will NOT be refreshed for: "
@@ -1142,17 +1152,10 @@ public class AuthorizationCommon {
                                }
                        }
                }
-            em.close();
        } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             logger.fine("Caught exception and rolling back permission creation: " + e.getMessage());
             throw e;
-        } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
         }
     }
     
@@ -1223,7 +1226,10 @@ public class AuthorizationCommon {
        return result;
     }
 
-       private static PermissionRoleRel findPermRoleRel(EntityManager em, String permissionId, String RoleId) {
+       private static PermissionRoleRel findPermRoleRel(
+                       JPATransactionContext jpaTransactionContext,
+                       String permissionId,
+                       String RoleId) {
        PermissionRoleRel result = null;
        
        try {
@@ -1232,7 +1238,7 @@ public class AuthorizationCommon {
                params.put("id", permissionId);
                params.put("roleId", RoleId);        
        
-               result = (PermissionRoleRel) JpaStorageUtils.getEntity(em,
+               result = (PermissionRoleRel) JpaStorageUtils.getEntity(jpaTransactionContext,
                                PermissionRoleRel.class.getCanonicalName(), whereClause, params);
        } catch (Exception e) {
                //Do nothing. Will return null;
@@ -1244,21 +1250,21 @@ public class AuthorizationCommon {
     /*
      * Persists the Permission, PermissionRoleRel, and Spring Security table entries all in one transaction
      */
-    private static void persist(EntityManager em, Permission permission, Role role, boolean enforceTenancy, ActionGroup actionGroup) throws Exception {
+    private static void persist(JPATransactionContext jpaTransactionContext, Permission permission, Role role, boolean enforceTenancy, ActionGroup actionGroup) throws Exception {
                AuthorizationStore authzStore = new AuthorizationStore();
                // First persist the Permission record
-               authzStore.store(em, permission);
+               authzStore.store(jpaTransactionContext, permission);
                
                // If the PermRoleRel doesn't already exists then relate the permission and the role in a new PermissionRole (the service payload)
                // Create a PermissionRoleRel (the database relation table for the permission and role)
-               PermissionRoleRel permRoleRel = findPermRoleRel(em, permission.getCsid(), role.getCsid());
+               PermissionRoleRel permRoleRel = findPermRoleRel(jpaTransactionContext, permission.getCsid(), role.getCsid());
                if (permRoleRel == null) {
-                       PermissionRole permRole = createPermissionRole(em, permission, role, enforceTenancy);
+                       PermissionRole permRole = createPermissionRole(permission, role, enforceTenancy);
                List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
-               PermissionRoleUtil.buildPermissionRoleRel(em, permRole, SubjectType.ROLE, permRoleRels,
+               PermissionRoleUtil.buildPermissionRoleRel(jpaTransactionContext, permRole, SubjectType.ROLE, permRoleRels,
                                false /*not for delete*/, role.getTenantId());
                for (PermissionRoleRel prr : permRoleRels) {
-                   authzStore.store(em, prr);
+                   authzStore.store(jpaTransactionContext, prr);
                }
                        Profiler profiler = new Profiler(AuthorizationCommon.class, 2);
                        profiler.start();
index be9c907af162b720cab4af925d50e3a4a0373c6f..6a4b72ac029007a6a076dafa6bdee24e85014867 100644 (file)
@@ -36,6 +36,7 @@ import org.collectionspace.services.authorization.PermissionRoleRel;
 import org.collectionspace.services.authorization.perms.Permission;
 import org.collectionspace.services.authorization.storage.RoleStorageConstants;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,11 +51,14 @@ public class AuthorizationStore {
     private final static String PERSISTENCE_UNIT = "org.collectionspace.services.authorization";
     public final static String ENTITY_MANAGER_PROP_KEY = EntityManager.class.getCanonicalName();
 
-    static public Role getRoleByName(String roleName, String tenantId) {
+    static public Role getRoleByName(
+               JPATransactionContext jpaTransactionContext,
+               String roleName, 
+               String tenantId) {
        Role theRole = null;
        
        try {
-               theRole = (Role)JpaStorageUtils.getEnityByKey(Role.class.getName(),
+               theRole = (Role)JpaStorageUtils.getEnityByKey(jpaTransactionContext, Role.class.getName(),
                                RoleStorageConstants.ROLE_NAME, roleName, tenantId);
        } catch (Throwable e) {
                if (logger.isTraceEnabled() == true) {
@@ -65,27 +69,14 @@ public class AuthorizationStore {
        return theRole;
     }
     
-    static public Role getRoleByName(EntityManager em, String roleName, String tenantId) {
-       Role theRole = null;
-       
-       try {
-               theRole = (Role)JpaStorageUtils.getEnityByKey(em, Role.class.getName(),
-                               RoleStorageConstants.ROLE_NAME, roleName, tenantId);
-       } catch (Throwable e) {
-               if (logger.isTraceEnabled() == true) {
-                       logger.trace("Could not retrieve role with name =" + roleName, e);
-               }
-       }
-       
-       return theRole;
-    }
-    
-    
-    static public PermissionRoleRel getPermRoleRel(EntityManager em, String permId, String roleId) {
+    static public PermissionRoleRel getPermRoleRel(
+               JPATransactionContext jpaTransactionContext,
+               String permId,
+               String roleId) {
        PermissionRoleRel permRoleRel = null;
        
        try {
-               permRoleRel = (PermissionRoleRel)JpaStorageUtils.getEntityByDualKeys(em
+               permRoleRel = (PermissionRoleRel)JpaStorageUtils.getEntityByDualKeys(jpaTransactionContext
                                PermissionRoleRel.class.getName(),
                                RoleStorageConstants.PERM_ROLE_REL_PERM_ID, permId, 
                                RoleStorageConstants.PERM_ROLE_REL_ROLE_ID, roleId);
@@ -155,27 +146,27 @@ public class AuthorizationStore {
         }
     }
     
-    private boolean exists(EntityManager em, Object entity) {
+    private boolean exists(JPATransactionContext jpaTransactionContext, Object entity) {
        boolean result = false;
        
        try {
-               if(entity instanceof Role) {
+               if (entity instanceof Role) {
                        // If find by name, exists
                        Role roleEntity = (Role)entity;
                        String roleName = roleEntity.getRoleName();
                        String tenantId = roleEntity.getTenantId();
-                       if(getRoleByName(em, roleName, tenantId)!=null) {
+                       if (getRoleByName(jpaTransactionContext, roleName, tenantId)!=null) {
                                result = true;
                        logger.trace("Role {} already exists in tenant {}.", roleName, tenantId);
                        } else {
                        logger.trace("Role {} does not exist in tenant {}.", roleName, tenantId);
                        }
-               } else if(entity instanceof PermissionRoleRel) {
+               } else if (entity instanceof PermissionRoleRel) {
                        // If find by name, exists
                        PermissionRoleRel permRoleEntity = (PermissionRoleRel)entity;
                        String roleId = permRoleEntity.getRoleId();
                        String permId = permRoleEntity.getPermissionId();
-                       if(getPermRoleRel(em, permId, roleId)!=null) {
+                       if (getPermRoleRel(jpaTransactionContext, permId, roleId) != null) {
                                result = true;
                        logger.trace("PermRoleRel for {}, {} already exists.", permId, roleId);
                        } else {
@@ -183,7 +174,7 @@ public class AuthorizationStore {
                        }
                } else {        // Default case; also best test for Permission
                        String csid = (String)JaxbUtils.getValue(entity, "getCsid");
-                       Object existingEntity = em.find(entity.getClass(), csid);
+                       Object existingEntity = jpaTransactionContext.find(entity.getClass(), csid);
                        if (existingEntity != null) {
                                result = true;
                        logger.trace("Entity with csid {} already exists.", csid);
@@ -197,11 +188,12 @@ public class AuthorizationStore {
        
        return result;
     }
+    
     /*
      * Use this method if you've already started a transaction with an EntityManager
      */
-    public String store(EntityManager em, Object entity) throws Exception {
-       boolean entityExists = exists(em, entity);
+    public String store(JPATransactionContext jpaTransactionContext, Object entity) throws Exception {
+       boolean entityExists = exists(jpaTransactionContext, entity);
        /* 
         * Logging moved to exists, for better detail
        if (entityExists == true) {
@@ -217,7 +209,7 @@ public class AuthorizationStore {
                // PLS: Question: why merge? what might be new to change, and is this really a good idea?
                // Shouldn't we define them once and leave them alone?
         } else {
-               em.persist(entity);
+               jpaTransactionContext.persist(entity);
         }
         
         // look for a CSID
index 27c374cdbc2ed8f31d07b613a0ef12aaba9c6e2e..d73f37656f94ff7e7d2ee2c9166d86ee41b1be97 100644 (file)
@@ -32,8 +32,10 @@ import javax.persistence.NoResultException;
 
 import org.collectionspace.services.common.document.DocumentException;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
+import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextProperties;
+import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
 import org.collectionspace.services.authorization.perms.ActionType;
@@ -102,7 +104,7 @@ public class PermissionRoleUtil {
      * @param prrl persistent entities built are inserted into this list
      * @param toDelete the to delete
      */
-    static public void buildPermissionRoleRel(EntityManager em
+    static public void buildPermissionRoleRel(JPATransactionContext jpaTransactionContext
                PermissionRole pr,
                SubjectType subject,
                List<PermissionRoleRel> prrl,
@@ -114,7 +116,7 @@ public class PermissionRoleUtil {
                if (permissionValues != null && permissionValues.size() > 0) {
                    PermissionValue pv = permissionValues.get(0);
                    for (RoleValue rv : pr.getRole()) {
-                       PermissionRoleRel prr = buildPermissonRoleRel(em, pv, rv, subject, handleDelete, tenantId);
+                       PermissionRoleRel prr = buildPermissonRoleRel(jpaTransactionContext, pv, rv, subject, handleDelete, tenantId);
                        prrl.add(prr);
                    }
                }
@@ -123,42 +125,34 @@ public class PermissionRoleUtil {
                if (roleValues != null && roleValues.size() > 0) {
                    RoleValue rv = roleValues.get(0);
                    for (PermissionValue pv : pr.getPermission()) {
-                       PermissionRoleRel prr = buildPermissonRoleRel(em, pv, rv, subject, handleDelete, tenantId);
+                       PermissionRoleRel prr = buildPermissonRoleRel(jpaTransactionContext, pv, rv, subject, handleDelete, tenantId);
                        prrl.add(prr);
                    }
                }
         }
     }
     
-    static public void buildPermissionRoleRel( 
+    static public void buildPermissionRoleRel(
+               ServiceContext ctx,
                PermissionRole pr,
                SubjectType subject,
                List<PermissionRoleRel> prrl,
                boolean handleDelete,
                String tenantId) throws Exception {
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       
+        JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
         try {
-            emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            
-            buildPermissionRoleRel(em, pr, subject, prrl, handleDelete, tenantId);
-            
-            em.getTransaction().commit();
-               em.close();            
+            jpaTransactionContext.beginTransaction();            
+            buildPermissionRoleRel(jpaTransactionContext, pr, subject, prrl, handleDelete, tenantId);
+            jpaTransactionContext.commitTransaction();
         } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             throw e;
         } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }    
 
@@ -166,7 +160,7 @@ public class PermissionRoleUtil {
      * Try to find a persisted Permission record using a PermissionValue instance.
      *
      */
-    static private Permission lookupPermission(EntityManager em, PermissionValue permissionValue, String tenantId) {
+    static private Permission lookupPermission(JPATransactionContext jpaTransactionContext, PermissionValue permissionValue, String tenantId) throws TransactionException {
        Permission result = null;
        
        String actionGroup = permissionValue.getActionGroup() != null ? permissionValue.getActionGroup().trim() : null;
@@ -177,7 +171,7 @@ public class PermissionRoleUtil {
        //
        if (permissionId != null && !permissionId.isEmpty()) {
                try {
-                       result = (Permission)JpaStorageUtils.getEntity(em, permissionId, Permission.class);
+                       result = (Permission)JpaStorageUtils.getEntity(jpaTransactionContext, permissionId, Permission.class);
                } catch (Throwable e) {
                        String msg = String.format("Searched for but couldn't find a permission with CSID='%s'.",
                                        permissionId);
@@ -189,7 +183,7 @@ public class PermissionRoleUtil {
                // If there was no permission ID, then we can try to find the permission with the resource name and action group tuple
                //
                try {
-                       result = (Permission)JpaStorageUtils.getEntityByDualKeys(em
+                       result = (Permission)JpaStorageUtils.getEntityByDualKeys(jpaTransactionContext
                                        Permission.class.getName(),
                                        PermissionStorageConstants.RESOURCE_NAME, permissionValue.getResourceName(), 
                                        PermissionStorageConstants.ACTION_GROUP, permissionValue.getActionGroup(),
@@ -217,14 +211,14 @@ public class PermissionRoleUtil {
      * @return the permission role rel
      * @throws DocumentException 
      */
-    static private PermissionRoleRel buildPermissonRoleRel(EntityManager em, PermissionValue permissionValue,
+    static private PermissionRoleRel buildPermissonRoleRel(JPATransactionContext jpaTransactionContext, PermissionValue permissionValue,
                RoleValue roleValue,
                SubjectType subject,
                boolean handleDelete,  // if 'true' then we're deleting not building a permission-role record
                String tenantId) throws DocumentException {
 
        PermissionRoleRel result = null;
-       Permission permission = lookupPermission(em, permissionValue, tenantId);
+       Permission permission = lookupPermission(jpaTransactionContext, permissionValue, tenantId);
        
        //
        // If we couldn't find an existing permission and we're not processing a DELETE request, we need to create
@@ -237,7 +231,7 @@ public class PermissionRoleUtil {
                permission.setEffect(EffectType.PERMIT); // By default, CollectionSpace currently (11/2017) supports only PERMIT
                List<PermissionAction> actionList = createPermActionList(permissionValue.getActionGroup());
                permission.setAction(actionList);
-               permission = createPermission(permission);
+               permission = createPermission(jpaTransactionContext, permission);
                if (permission == null) {
                        String errMsg = "Could not create new permission for new permission-role relationship.";
                        throw new DocumentException(errMsg);
@@ -278,11 +272,11 @@ public class PermissionRoleUtil {
         return result;
     }
 
-    private static Permission createPermission(Permission permission) {
+    private static Permission createPermission(JPATransactionContext jpaTransactionContext, Permission permission) {
                Permission result = null;
                
                PermissionResource permissionResource = new PermissionResource();  // Get the PermissionResource singleton instance (RESTEasy ensures it is a singleton)
-               result = permissionResource.createPermissionFromInstance(permission);
+               result = permissionResource.createPermissionFromInstance(jpaTransactionContext, permission);
                
                return result;
        }
index a1c1ebd7c14231e22f4fc5401293d997d48dd916..d10ab1caf3ae8d509ac06cdfa83902319bcfc5de 100644 (file)
@@ -61,8 +61,16 @@ public class RemoteServiceContextImpl<IT, OT>
     /** The output. */
     private OT output;
     /** The target of the HTTP request **/
-    JaxRsContext jaxRsContext;
     
+    //
+    // Reference count for things like JPA connections
+    //
+    private int transactionConnectionRefCount = 0;
+    
+    //
+    // RESTEasy context
+    //
+    JaxRsContext jaxRsContext;    
     ResourceMap resourceMap = null;
     
     @Override
@@ -255,42 +263,58 @@ public class RemoteServiceContextImpl<IT, OT>
        // Transaction management methods
        //
        
-       private TransactionContext getCurrentTransactionContext() {
+       @Override
+       public TransactionContext getCurrentTransactionContext() {
                return (TransactionContext) this.getProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY);
        }
 
        @Override
-       public void releaseConnection() throws TransactionException {
-               if (isTransactionContextShared() == true) {
-                       throw new TransactionException("Attempted to release a shared storage connection.  Only the originator can release the connection");
+       synchronized public void closeConnection() throws TransactionException {
+               if (transactionConnectionRefCount == 0) {
+                       throw new TransactionException("Attempted to release a connection that doesn't exist or has already been released.");
                }
-               
-               TransactionContext transactionCtx = getCurrentTransactionContext();             
-               if (transactionCtx != null) {
-                       transactionCtx.close();
-               this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, null);
+
+               if (isTransactionContextShared() == true) {
+                       //
+                       // If it's a shared connection, we can't close it.  Just reduce the refcount by 1
+                       //
+                       String warnMsg = "Attempted to release a shared storage connection.  Only the originator can release the connection";
+                       logger.warn(warnMsg);
+                       transactionConnectionRefCount--;
                } else {
-                       throw new TransactionException("Attempted to release a non-existent storage connection.  Transaction context missing from service context.");
+                       TransactionContext transactionCtx = getCurrentTransactionContext();
+                       if (transactionCtx != null) {
+                               if (--transactionConnectionRefCount == 0) {
+                                       transactionCtx.close();
+                               this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, null);
+                               }
+                       } else {
+                               throw new TransactionException("Attempted to release a non-existent storage connection.  Transaction context missing from service context.");
+                       }
                }
        }
 
        @Override
-       public TransactionContext openConnection() throws TransactionException {
+       synchronized public TransactionContext openConnection() throws TransactionException {
                TransactionContext result = getCurrentTransactionContext();
-               if (result != null) {
-                       throw new TransactionException("Attempted to open a new connection when a current connection is still part of the current service context.  The current connection must be closed with the releaseConnection() method.");
+               
+               if (result == null) {
+                       result = new JPATransactionContext(this);
+               this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, result);
                }
-
-               result = new JPATransactionContext(this);
-        this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, result);
-
+               transactionConnectionRefCount++;
+               
                return result;
        }
 
        @Override
-       public void setTransactionContext(TransactionContext transactionCtx) {
-               // TODO Auto-generated method stub
-               
+       public void setTransactionContext(TransactionContext transactionCtx) throws TransactionException {
+               TransactionContext currentTransactionCtx = this.getCurrentTransactionContext();
+               if (currentTransactionCtx == null) {
+                       setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, transactionCtx);
+               } else if (currentTransactionCtx != transactionCtx) {
+                       throw new TransactionException("Transaction context already set from service context.");
+               }
        }
 
        /**
index ccdf5c3b8414e4f0184c46739f7ee982a16ee140..36bb6a2a6f47fa4307e45b5928571eac04df2fe9 100644 (file)
@@ -423,17 +423,25 @@ public interface ServiceContext<IT, OT> {
        /**
         * 
         */
-       public void releaseConnection() throws TransactionException; // Assumes there's been a call to getConnection.
+       public void closeConnection() throws TransactionException; // Assumes there's been a call to getConnection.
        
        /**
+        * @throws TransactionException 
         * 
         */
-       public void setTransactionContext(TransactionContext transactionCtx); // For sharing a transaction context with another service context.
+       void setTransactionContext(TransactionContext transactionCtx) throws TransactionException; // For sharing a transaction context with another service context.
        
        /**
         * 
         */
        public boolean isTransactionContextShared() throws TransactionException;
+
+       /**
+        * 
+        * @return
+        */
+       TransactionContext getCurrentTransactionContext();
+
 }
 
 
index 41bf9a3a29f5215533eb7703eea7c00bca9283fb..3a1ca5e7d2d4d8058cbdc4d1977c9612c84b3bf2 100644 (file)
@@ -1,5 +1,7 @@
 package org.collectionspace.services.common.storage;
 
+import javax.persistence.Query;
+
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.TransactionException;
 
@@ -22,4 +24,14 @@ public abstract class TransactionContext {
        abstract public void commitTransaction() throws TransactionException;
 
        abstract public boolean isTransactionActive() throws TransactionException;
+
+       abstract public void persist(Object entity);
+
+       abstract public Object find(Class entityClass, Object primaryKey);
+       
+       abstract public Object find(Class entityClass, String id);
+       
+       abstract public Query createQuery(String qlString);
+       
+       abstract public void remove(Object entity);
 }
index 6e747f3190834a3064363e694b368ad59c7b4e4b..33045098dff631cd609cdfd22318ab0676932324 100644 (file)
@@ -2,26 +2,35 @@ package org.collectionspace.services.common.storage.jpa;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
 
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.storage.TransactionContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("rawtypes")
 public class JPATransactionContext extends TransactionContext {
+    /** The logger. */
+    private final Logger logger = LoggerFactory.getLogger(TransactionContext.class);
+
+       private int transactionRefCount = 0;
+       private Boolean commitSuccessful = null;
+       
        EntityManagerFactory emf;
        EntityManager em;
        
-       @SuppressWarnings("unused")
-       private JPATransactionContext() {
-               // Don't allow anyone to create an empty instance
-       }
-       
        public JPATransactionContext(ServiceContext ctx) {
         emf = JpaStorageUtils.getEntityManagerFactory();            
         em = emf.createEntityManager();
         this.ctx = ctx;
        }
+       
+       public JPATransactionContext() {
+        emf = JpaStorageUtils.getEntityManagerFactory();            
+        em = emf.createEntityManager();
+       }       
 
        protected EntityManagerFactory getEntityManagerFactory() {
                return emf;
@@ -38,7 +47,12 @@ public class JPATransactionContext extends TransactionContext {
        
        @Override
        public void markForRollback() {
-               em.getTransaction().setRollbackOnly();
+               if (em.getTransaction().isActive() == true) {
+                       em.getTransaction().setRollbackOnly();
+               } else {
+                       String msg = "Attemped to mark an inactive transaction for rollback.";
+                       logger.warn(msg);
+               }
        }
        
        @Override
@@ -54,13 +68,47 @@ public class JPATransactionContext extends TransactionContext {
        }
 
        @Override
-       public void beginTransaction() {
-        em.getTransaction().begin();    
+       synchronized public void beginTransaction() {
+               if (transactionRefCount == 0) {
+                       em.getTransaction().begin();
+               }
+        transactionRefCount++;
+       }
+       
+       @Override
+       public void persist(Object entity) {
+               em.persist(entity);
+       }
+       
+       @Override
+       public Object find(Class entityClass, Object primaryKey) {
+               return em.find(entityClass, primaryKey);
+       }
+       
+       @Override
+       public Object find(Class entityClass, String id) {
+               return em.find(entityClass, id);
+       }
+       
+       @Override
+       public Query createQuery(String qlString) {
+               return em.createQuery(qlString);
+       }
+       
+       @Override
+    public void remove(Object entity) {
+               em.remove(entity);
        }
 
        @Override
-       public void commitTransaction() {
-        em.getTransaction().commit();
+       public void commitTransaction() throws TransactionException {
+               if (transactionRefCount == 0) {
+               throw new JPATransactionException("There is no active transaction to commit.");
+               }
+               if (--transactionRefCount == 0) {
+                       em.getTransaction().commit();
+                       commitSuccessful = Boolean.TRUE;
+               }
        }
 
        @Override
index ad86f0088a0efe5165bdd0dc0b959cfd15da6638..368b17963b38a77ba7f61bdf377da714c07b5bce 100644 (file)
@@ -28,10 +28,7 @@ import org.collectionspace.services.common.context.ServiceContextProperties;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.UUID;
 
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
 import javax.persistence.NoResultException;
 import javax.persistence.PersistenceException;
 import javax.persistence.Query;
@@ -65,6 +62,7 @@ import org.slf4j.LoggerFactory;
  * delete deletes all subjects for the given object in relationship
  * @author 
  */
+@SuppressWarnings({ "rawtypes", "unchecked" })
 public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
 
     private final Logger logger = LoggerFactory.getLogger(JpaRelationshipStorageClient.class);
@@ -99,57 +97,44 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
      * @throws BadRequestException
      * @throws DocumentException
      */
-    @Override
+       @Override
     public String create(ServiceContext ctx,
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
-
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "create : ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "create: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       String result = null;
+       
+       JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();      
         try {
+            jpaTransactionContext.beginTransaction();
             handler.prepare(Action.CREATE);
             List<T> rl = new ArrayList<T>();
             DocumentWrapper<List<T>> wrapDoc =
                     new DocumentWrapperImpl<List<T>>(rl);
             handler.handle(Action.CREATE, wrapDoc);
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
             for (T r : rl) {
                 JaxbUtils.setValue(r, "setCreatedAtItem", Date.class, new Date());
-                em.persist(r);
+                jpaTransactionContext.persist(r);
             }
-            em.getTransaction().commit();
             handler.complete(Action.CREATE, wrapDoc);
-            return UUID.randomUUID().toString(); //filler, not useful
+            jpaTransactionContext.commitTransaction();
+            result = "-1"; // meaningless result
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             throw bre;
         } catch (PersistenceException pe) {
+               jpaTransactionContext.markForRollback();
                throw pe;
         } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             throw new DocumentException(e);
         } finally {
-            if (em != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
+        
+        return result;
     }
 
     /**
@@ -164,20 +149,14 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
     @Override
     public void get(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "get: ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "get: handler is missing");
-        }
+
         if (getObject(ctx, id) == null) {
             String msg = "get: "
                     + "could not find the object with id=" + id;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
         }
+        
         String objectId = getObjectId(ctx);
         if (logger.isDebugEnabled()) {
             logger.debug("get: using objectId=" + objectId);
@@ -190,8 +169,8 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
         if (docFilter == null) {
             docFilter = handler.createDocumentFilter();
         }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+        
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
             handler.prepare(Action.GET);
             StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
@@ -203,35 +182,27 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
             if ((null != where) && (where.length() > 0)) {
                 queryStrBldr.append(" AND " + where);
             }
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
+
             String queryStr = queryStrBldr.toString(); //for debugging
             if (logger.isDebugEnabled()) {
                 logger.debug("get: jql=" + queryStr.toString());
             }
-            Query q = em.createQuery(queryStr);
+            Query q = jpaConnectionContext.createQuery(queryStr);
             q.setParameter("objectId", id);
 
             List<T> rl = new ArrayList<T>();
+               jpaConnectionContext.beginTransaction();
             try {
-                //require transaction for get?
-                em.getTransaction().begin();
                 rl = q.getResultList();
-                em.getTransaction().commit();
             } catch (NoResultException nre) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
-                String msg = "get(1): "
-                        + " could not find relationships for object class="
+                String msg = "get(1): " + " could not find relationships for object class="
                         + objectClass.getName() + " id=" + id;
                 if (logger.isDebugEnabled()) {
                     logger.debug(msg, nre);
                 }
             }
             if (rl.size() == 0) {
-                String msg = "get(2): "
-                        + " could not find relationships for object class="
+                String msg = "get(2): " + " could not find relationships for object class="
                         + objectClass.getName() + " id=" + id;
                 if (logger.isDebugEnabled()) {
                     logger.debug(msg);
@@ -241,17 +212,17 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
                     new DocumentWrapperImpl<List<T>>(rl);
             handler.handle(Action.GET, wrapDoc);
             handler.complete(Action.GET, wrapDoc);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            throw de;
+               jpaConnectionContext.markForRollback();
         } catch (Exception e) {
+               jpaConnectionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
     
@@ -285,11 +256,11 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
      * @return the relationship
      * @throws DocumentNotFoundException the document not found exception
      */
-    private T getRelationship(EntityManager em, T relationship)
+    private T getRelationship(JPATransactionContext jpaTransactionContext, T relationship)
                throws DocumentNotFoundException {
        Long id = getId(relationship);
        
-        T relationshipFound = (T)em.find(relationship.getClass(), id);
+        T relationshipFound = (T)jpaTransactionContext.find(relationship.getClass(), id);
         if (relationshipFound == null) {
             String msg = "Could not find relationship with id=" + id;
             if (logger.isErrorEnabled() == true) {
@@ -297,6 +268,7 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
             }
             throw new DocumentNotFoundException(msg);
         }
+        
         return relationshipFound;
     }
 
@@ -313,16 +285,12 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
             throws DocumentNotFoundException,
             DocumentException {
 
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "delete : ctx is missing");
-        }
         if (getObject(ctx, id) == null) {
-            String msg = "delete : "
-                    + "could not find the object with id=" + id;
+            String msg = "delete : " + "could not find the object with id=" + id;
             logger.error(msg);
             throw new DocumentNotFoundException(msg);
         }
+        
         String objectId = getObjectId(ctx);
         if (logger.isDebugEnabled()) {
             logger.debug("delete: using objectId=" + objectId);
@@ -331,22 +299,20 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
         if (logger.isDebugEnabled()) {
             logger.debug("delete: using object class=" + objectClass.getName());
         }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+        
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
             StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
             String entityName = getEntityName(ctx);
             deleteStr.append(entityName);
             deleteStr.append(" WHERE " + objectId + " = :objectId");
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
             if (logger.isDebugEnabled()) {
                 logger.debug("delete: jql=" + deleteStr.toString());
             }
-            Query q = em.createQuery(deleteStr.toString());
+            Query q = jpaConnectionContext.createQuery(deleteStr.toString());
             q.setParameter("objectId", id);
             int rcount = 0;
-            em.getTransaction().begin();
+            jpaConnectionContext.beginTransaction();
             if (logger.isDebugEnabled() == true) {
                logger.debug(q.toString());
             }
@@ -355,20 +321,15 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
                 logger.debug("deleted " + rcount + " relationships for entity " + entityName
                         + " with objectId=" + objectId);
             }
-            em.getTransaction().commit();
-
+            jpaConnectionContext.commitTransaction();
         } catch (Exception e) {
+               jpaConnectionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -388,49 +349,32 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
             throws DocumentNotFoundException, DocumentException {
        boolean result = true;
        
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "delete : ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "delete : handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();      
         try {
+               jpaTransactionContext.beginTransaction();
             handler.prepare(Action.DELETE);
             List<T> rl = new ArrayList<T>();
-            DocumentWrapper<List<T>> wrapDoc =
-                    new DocumentWrapperImpl<List<T>>(rl);
+            DocumentWrapper<List<T>> wrapDoc = new DocumentWrapperImpl<List<T>>(rl);
             handler.handle(Action.DELETE, wrapDoc);
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            //the following could be much more efficient if done with a single
-            //sql/jql
+            //
+            //the following could be much more efficient if done with a single sql/jql
+            //
             for (T r : rl) {
-               em.remove(getRelationship(em, r));
+               jpaTransactionContext.remove(getRelationship(jpaTransactionContext, r));
             }
-            em.getTransaction().commit();
             handler.complete(Action.DELETE, wrapDoc); // Delete from the Spring Security tables.  Would be better if this was part of the earlier transaction.
+            jpaTransactionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaTransactionContext.markForRollback();
             throw de;
         } catch (Exception e) {
+               jpaTransactionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("delete(ctx, ix, handler): Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+               ctx.closeConnection();
         }
         
         return result;
@@ -443,9 +387,9 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
      */
     protected String getObjectId(ServiceContext ctx) {
         String objectId = (String) ctx.getProperty(ServiceContextProperties.OBJECT_ID);
+        
         if (objectId == null) {
-            String msg = ServiceContextProperties.OBJECT_ID
-                    + " property is missing in the context";
+            String msg = ServiceContextProperties.OBJECT_ID + " property is missing in the context";
             logger.error(msg);
             throw new IllegalArgumentException(msg);
         }
@@ -460,12 +404,13 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
      */
     protected Class getObjectClass(ServiceContext ctx) {
         Class objectClass = (Class) ctx.getProperty(ServiceContextProperties.OBJECT_CLASS);
+        
         if (objectClass == null) {
-            String msg = ServiceContextProperties.OBJECT_CLASS
-                    + " property is missing in the context";
+            String msg = ServiceContextProperties.OBJECT_CLASS + " property is missing in the context";
             logger.error(msg);
             throw new IllegalArgumentException(msg);
         }
+        
         return objectClass;
     }
 
@@ -478,6 +423,6 @@ public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
     protected Object getObject(ServiceContext ctx, String id)
                throws DocumentNotFoundException {
         Class objectClass = getObjectClass(ctx);
-        return JpaStorageUtils.getEntity(id, objectClass);
+        return JpaStorageUtils.getEntity((JPATransactionContext)ctx.getCurrentTransactionContext(), id, objectClass);
     }
 }
index 5ade3641c5a39a2846772ca4f8635c6eeb6f23c6..88367d02b8d82a34317dd63ccd7b0d5fdfc3a0f7 100644 (file)
@@ -20,15 +20,9 @@ package org.collectionspace.services.common.storage.jpa;
 import java.util.Date;
 import java.util.List;
 
-import javax.persistence.RollbackException;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import java.sql.BatchUpdateException;
-
 import javax.persistence.EntityExistsException;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
 import javax.persistence.Query;
+import javax.persistence.RollbackException;
 
 import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentException;
@@ -41,14 +35,12 @@ import org.collectionspace.services.common.document.DocumentWrapperImpl;
 import org.collectionspace.services.common.document.JaxbUtils;
 import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.storage.StorageClient;
+import org.collectionspace.services.common.storage.TransactionContext;
 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
-import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
 import org.collectionspace.services.common.context.ServiceContextProperties;
-import org.collectionspace.services.common.api.GregorianCalendarDateTimeUtils;
-import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;
 import org.collectionspace.services.common.context.ServiceContext;
-import org.collectionspace.services.common.query.QueryContext;
 import org.collectionspace.services.lifecycle.TransitionDef;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -105,77 +97,60 @@ public class JpaStorageClientImpl implements StorageClient {
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#create(org.collectionspace.services.common.context.ServiceContext, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+       @Override
     public String create(ServiceContext ctx,
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "create: ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "create: handler is missing");
-        }
-        
-       boolean rollbackTransaction = false;
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       String result = null;
+
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();
         try {
             handler.prepare(Action.CREATE);
             Object entity = handler.getCommonPart();
             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(entity);
             
-            emf = JpaStorageUtils.getEntityManagerFactory();            
-            em = emf.createEntityManager();
-            em.getTransaction().begin(); { //begin of transaction block            
-                   ctx.setProperty(AuthorizationStore.ENTITY_MANAGER_PROP_KEY, em);
-                   try {
-                       handler.handle(Action.CREATE, wrapDoc);
-                           JaxbUtils.setValue(entity, "setCreatedAtItem", Date.class, new Date());
-                           em.persist(entity);                 
-                   } catch (EntityExistsException ee) {
-                       //
-                       // We found an existing matching entity in the store, so we don't need to create one.  Just update the transient 'entity' instance with the existing persisted entity we found.
-                       // An entity's document handler class will throw this exception only if attempting to create (but not actually creating) duplicate is ok -e.g., Permission records.
-                       //
-                       entity = wrapDoc.getWrappedObject(); // the handler should have reset the wrapped transient object with the existing persisted entity we just found.
-                   }
+            jpaConnectionContext.beginTransaction();
+            try {
+               handler.handle(Action.CREATE, wrapDoc);
+                   JaxbUtils.setValue(entity, "setCreatedAtItem", Date.class, new Date());
+                   jpaConnectionContext.persist(entity);               
+            } catch (EntityExistsException ee) {
+               //
+               // We found an existing matching entity in the store, so we don't need to create one.  Just update the transient 'entity' instance with the existing persisted entity we found.
+               // An entity's document handler class will throw this exception only if attempting to create (but not actually creating) duplicate is ok -e.g., Permission records.
+               //
+               entity = wrapDoc.getWrappedObject(); // the handler should have reset the wrapped transient object with the existing persisted entity we just found.
             }
-            em.getTransaction().commit();
             handler.complete(Action.CREATE, wrapDoc);
-            return (String) JaxbUtils.getValue(entity, "getCsid");
+            jpaConnectionContext.commitTransaction();
+            
+            result = (String)JaxbUtils.getValue(entity, "getCsid");
         } catch (BadRequestException bre) {
-               rollbackTransaction = true;
+               jpaConnectionContext.markForRollback();
             throw bre;
         } catch (DocumentException de) {
-               rollbackTransaction = true;
+               jpaConnectionContext.markForRollback();
             throw de;
+        } catch (RollbackException rbe) {
+               //jpaConnectionContext.markForRollback();
+            throw DocumentException.createDocumentException(rbe);
         } catch (Exception e) {
-               rollbackTransaction = true;
-            if (logger.isDebugEnabled()) {
-                logger.debug("Caught exception ", e);
-            }
+               jpaConnectionContext.markForRollback();
+            logger.debug("Caught exception ", e);
             throw DocumentException.createDocumentException(e);
         } finally {
-            ctx.setProperty(AuthorizationStore.ENTITY_MANAGER_PROP_KEY, null);
-            if (em != null) {
-               if (rollbackTransaction == true) {
-                       if (em.getTransaction().isActive() == true) {
-                               em.getTransaction().rollback();
-                       }
-               }
-               // Don't call this unless "em" is not null -hence the check above.
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+               ctx.closeConnection();
         }
 
+        return result;
     }
 
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings("rawtypes")
+       @Override
     public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
         throw new UnsupportedOperationException();
@@ -184,29 +159,18 @@ public class JpaStorageClientImpl implements StorageClient {
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+       @Override
     public void get(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "get: ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "get: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+
+       JPATransactionContext jpaTransactionContext = (JPATransactionContext)ctx.openConnection();
         try {
             handler.prepare(Action.GET);
             Object o = null;
-            o = JpaStorageUtils.getEntity(getEntityName(ctx), id, 
-                    ctx.getTenantId());
+            o = JpaStorageUtils.getEntity(jpaTransactionContext, getEntityName(ctx), id, ctx.getTenantId());
             if (null == o) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
-                String msg = "could not find entity with id=" + id;
+                String msg = "Could not find entity with id=" + id;
                 throw new DocumentNotFoundException(msg);
             }
             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
@@ -220,16 +184,15 @@ public class JpaStorageClientImpl implements StorageClient {
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#getAll(org.collectionspace.services.common.context.ServiceContext, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings("rawtypes")
+       @Override
     public void getAll(ServiceContext ctx, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
         throw new UnsupportedOperationException("use getFiltered instead");
@@ -238,17 +201,17 @@ public class JpaStorageClientImpl implements StorageClient {
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#getFiltered(org.collectionspace.services.common.context.ServiceContext, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+       @Override
     public void getFiltered(ServiceContext ctx, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
-       QueryContext queryContext = new QueryContext(ctx, handler);
        
         DocumentFilter docFilter = handler.getDocumentFilter();
         if (docFilter == null) {
             docFilter = handler.createDocumentFilter();
         }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
         try {
             handler.prepare(Action.GET_ALL);
             StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
@@ -256,10 +219,8 @@ public class JpaStorageClientImpl implements StorageClient {
             queryStrBldr.append(" a");
             
             List<DocumentFilter.ParamBinding> params = docFilter.buildWhereForSearch(queryStrBldr);
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
             String queryStr = queryStrBldr.toString(); //for debugging
-            Query q = em.createQuery(queryStr);
+            Query q = jpaConnectionContext.createQuery(queryStr);
             //bind parameters
             for (DocumentFilter.ParamBinding p : params) {
                 q.setParameter(p.getName(), p.getValue());
@@ -271,17 +232,14 @@ public class JpaStorageClientImpl implements StorageClient {
                 q.setMaxResults(docFilter.getPageSize());
             }
 
-            //FIXME is transaction required for get?
-            em.getTransaction().begin();
+            jpaConnectionContext.beginTransaction();
             List list = q.getResultList();
-            long totalItems = getTotalItems(em, ctx, handler); // Find out how many items our query would find independent of the paging restrictions
-            em.getTransaction().commit();
-            
+            long totalItems = getTotalItems(jpaConnectionContext, ctx, handler); // Find out how many items our query would find independent of the paging restrictions            
             docFilter.setTotalItemsResult(totalItems); // Save the items total in the doc filter for later reporting
-
             DocumentWrapper<List> wrapDoc = new DocumentWrapperImpl<List>(list);
             handler.handle(Action.GET_ALL, wrapDoc);
             handler.complete(Action.GET_ALL, wrapDoc);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
             throw de;
         } catch (Exception e) {
@@ -290,16 +248,15 @@ public class JpaStorageClientImpl implements StorageClient {
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
     /*
      * Return the COUNT for a query to find the total number of matches independent of the paging restrictions.
      */
-    private long getTotalItems(EntityManager em, ServiceContext ctx, DocumentHandler handler) {
+    @SuppressWarnings("rawtypes")
+       private long getTotalItems(JPATransactionContext jpaTransactionContext, ServiceContext ctx, DocumentHandler handler) {
        long result = -1;
        
         DocumentFilter docFilter = handler.getDocumentFilter();
@@ -309,7 +266,7 @@ public class JpaStorageClientImpl implements StorageClient {
         
         List<DocumentFilter.ParamBinding> params = docFilter.buildWhereForSearch(queryStrBldr);
         String queryStr = queryStrBldr.toString();
-        Query q = em.createQuery(queryStr);
+        Query q = jpaTransactionContext.createQuery(queryStr);
         //bind parameters
         for (DocumentFilter.ParamBinding p : params) {
             q.setParameter(p.getName(), p.getValue());
@@ -323,51 +280,39 @@ public class JpaStorageClientImpl implements StorageClient {
        /* (non-Javadoc)
      * @see org.collectionspace.services.common.storage.StorageClient#update(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
      */
-    @Override
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+       @Override
     public void update(ServiceContext ctx, String id, DocumentHandler handler)
             throws BadRequestException, DocumentNotFoundException,
             DocumentException {
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "update: ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "update: handler is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();        
         try {
+            jpaConnectionContext.beginTransaction();
+            
             handler.prepare(Action.UPDATE);
             Object entityReceived = handler.getCommonPart();
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            em.getTransaction().begin();
-            Object entityFound = getEntity(em, id, entityReceived.getClass());
+            Object entityFound = getEntity(ctx, id, entityReceived.getClass());
             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(entityFound);
             handler.handle(Action.UPDATE, wrapDoc);
             JaxbUtils.setValue(entityFound, "setUpdatedAtItem", Date.class, new Date());
-            em.getTransaction().commit();
             handler.complete(Action.UPDATE, wrapDoc);
+            
+            jpaConnectionContext.commitTransaction();
         } catch (BadRequestException bre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw bre;
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
+            jpaConnectionContext.markForRollback();
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+               ctx.closeConnection();
         }
     }
 
@@ -377,55 +322,33 @@ public class JpaStorageClientImpl implements StorageClient {
      * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String)
      */
     @Override
-    public void delete(ServiceContext ctx, String id)
+    public void delete(@SuppressWarnings("rawtypes") ServiceContext ctx, String id)
             throws DocumentNotFoundException,
             DocumentException {
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("delete(ctx, id): deleting entity with id=" + id);
-        }
-
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "delete(ctx, id): ctx is missing");
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
-
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-
-            em.getTransaction().begin();
-            Object entityFound = getEntity(ctx, em, id);
+               jpaConnectionContext.beginTransaction();
+            Object entityFound = getEntity(ctx, id);
             if (entityFound == null) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
+               jpaConnectionContext.markForRollback();
                 String msg = "delete(ctx, id): could not find entity with id=" + id;
                 logger.error(msg);
                 throw new DocumentNotFoundException(msg);
             }
-            em.remove(entityFound);
-            em.getTransaction().commit();
-
+            jpaConnectionContext.remove(entityFound);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("delete(ctx, id): Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -437,62 +360,42 @@ public class JpaStorageClientImpl implements StorageClient {
      * @throws DocumentNotFoundException
      * @throws DocumentException
      */
-    public void deleteWhere(ServiceContext ctx, String id)
+    public void deleteWhere(@SuppressWarnings("rawtypes") ServiceContext ctx, String id)
             throws DocumentNotFoundException,
             DocumentException {
 
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "deleteWhere(ctx, id) : ctx is missing");
-        }
-
-        if (logger.isDebugEnabled()) {
-            logger.debug("deleteWhere(ctx, id): deleting entity with id=" + id);
-        }
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection();       
         try {
             StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
             deleteStr.append(getEntityName(ctx));
             deleteStr.append(" WHERE csid = :csid and tenantId = :tenantId");
             //TODO: add tenant csidReceived
 
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-            Query q = em.createQuery(deleteStr.toString());
+            Query q = jpaConnectionContext.createQuery(deleteStr.toString());
             q.setParameter("csid", id);
             q.setParameter("tenantId", ctx.getTenantId());
 
             int rcount = 0;
-            em.getTransaction().begin();
+            jpaConnectionContext.beginTransaction();
             rcount = q.executeUpdate();
             if (rcount != 1) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
+               jpaConnectionContext.markForRollback();
                 String msg = "deleteWhere(ctx, id) could not find entity with id=" + id;
                 logger.error(msg);
                 throw new DocumentNotFoundException(msg);
             }
-            em.getTransaction().commit();
-
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("deleteWhere(ctx, id) Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+            ctx.closeConnection();
         }
     }
 
@@ -501,60 +404,39 @@ public class JpaStorageClientImpl implements StorageClient {
      * cost: a get before delete
      * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String)
      */
-    @Override
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+       @Override
     public boolean delete(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
        boolean result = true;
        
-        if (ctx == null) {
-            throw new IllegalArgumentException(
-                    "delete(ctx, ix, handler): ctx is missing");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException(
-                    "delete(ctx, ix, handler): handler is missing");
-        }
-        
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
+       JPATransactionContext jpaConnectionContext = (JPATransactionContext)ctx.openConnection(); 
         try {
+            jpaConnectionContext.beginTransaction();
             handler.prepare(Action.DELETE);
-
-            emf = JpaStorageUtils.getEntityManagerFactory();
-            em = emf.createEntityManager();
-
-            em.getTransaction().begin();
-            Object entityFound = getEntity(ctx, em, id);
+            Object entityFound = getEntity(ctx, id);
             if (entityFound == null) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
+               jpaConnectionContext.markForRollback();
                 String msg = "delete(ctx, ix, handler) could not find entity with id=" + id;
                 logger.error(msg);
                 throw new DocumentNotFoundException(msg);
             }
             DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(entityFound);
             handler.handle(Action.DELETE, wrapDoc);
-            em.remove(entityFound);
-            em.getTransaction().commit();
+            jpaConnectionContext.remove(entityFound);
             handler.complete(Action.DELETE, wrapDoc);
+            jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
-            throw de;
+               jpaConnectionContext.markForRollback();
+               throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("delete(ctx, ix, handler): Caught exception ", e);
             }
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
-            if (emf != null) {
-                JpaStorageUtils.releaseEntityManagerFactory(emf);
-            }
+               ctx.closeConnection();
         }
         
         return result;
@@ -567,7 +449,7 @@ public class JpaStorageClientImpl implements StorageClient {
      * 
      * @return the entityReceived name
      */
-    protected String getEntityName(ServiceContext ctx) {
+    protected String getEntityName(@SuppressWarnings("rawtypes") ServiceContext ctx) {
         Object o = ctx.getProperty(ServiceContextProperties.ENTITY_NAME);
         if (o == null) {
             throw new IllegalArgumentException(ServiceContextProperties.ENTITY_NAME
@@ -581,23 +463,22 @@ public class JpaStorageClientImpl implements StorageClient {
     /**
      * getEntity returns persistent entity for given id. it assumes that
      * service context has property ServiceContextProperties.ENTITY_CLASS set
-     * rolls back the transaction if not found
      * @param ctx service context
-     * @param em entity manager
      * @param csid received
      * @return
-     * @throws DocumentNotFoundException and rollsback the transaction if active
+     * @throws DocumentNotFoundException
+     * @throws TransactionException 
      */
-    protected Object getEntity(ServiceContext ctx, EntityManager em, String id)
-            throws DocumentNotFoundException {
-        Class entityClazz = (Class) ctx.getProperty(ServiceContextProperties.ENTITY_CLASS);
+    protected Object getEntity(@SuppressWarnings("rawtypes") ServiceContext ctx, String id)
+            throws DocumentNotFoundException, TransactionException {
+        Class<?> entityClazz = (Class<?>) ctx.getProperty(ServiceContextProperties.ENTITY_CLASS);
         if (entityClazz == null) {
-            String msg = ServiceContextProperties.ENTITY_CLASS
-                    + " property is missing in the context";
+            String msg = ServiceContextProperties.ENTITY_CLASS + " property is missing in the context";
             logger.error(msg);
             throw new IllegalArgumentException(msg);
         }
-        return getEntity(em, id, entityClazz);
+        
+        return getEntity(ctx, id, entityClazz);
     }
 
     /**
@@ -608,28 +489,36 @@ public class JpaStorageClientImpl implements StorageClient {
      * @param entityClazz
      * @return
      * @throws DocumentNotFoundException and rollsback the transaction if active
+     * @throws TransactionException 
      */
-    protected Object getEntity(EntityManager em, String id, Class entityClazz)
-            throws DocumentNotFoundException {
-        Object entityFound = JpaStorageUtils.getEntity(em, id, entityClazz);
-        if (entityFound == null) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
-            String msg = "could not find entity of type=" + entityClazz.getName()
-                    + " with id=" + id;
-            logger.error(msg);
-            throw new DocumentNotFoundException(msg);
-        }
+    protected Object getEntity(@SuppressWarnings("rawtypes") ServiceContext ctx, String id, Class<?> entityClazz)
+            throws DocumentNotFoundException, TransactionException {
+       Object entityFound = null;
+       
+       JPATransactionContext jpaTransactionConnection = (JPATransactionContext)ctx.openConnection();
+       try {
+               entityFound = JpaStorageUtils.getEntity(jpaTransactionConnection.getEntityManager(), id, entityClazz);
+               if (entityFound == null) {
+                   String msg = "could not find entity of type=" + entityClazz.getName()
+                           + " with id=" + id;
+                   logger.error(msg);
+                   throw new DocumentNotFoundException(msg);
+               }
+       } finally {
+               ctx.closeConnection();
+       }
+       
         return entityFound;
     }
-
-    @Override
+    
+    @SuppressWarnings("rawtypes")
+       @Override
     public void get(ServiceContext ctx, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
         throw new UnsupportedOperationException();
     }
 
+       @SuppressWarnings("rawtypes")
        @Override
        public void doWorkflowTransition(ServiceContext ctx, String id,
                        DocumentHandler handler, TransitionDef transitionDef)
@@ -638,6 +527,7 @@ public class JpaStorageClientImpl implements StorageClient {
                // Do nothing.  JPA services do not support workflow.
        }
 
+       @SuppressWarnings("rawtypes")
        @Override
        public void deleteWithWhereClause(ServiceContext ctx, String whereClause,
                        DocumentHandler handler) throws DocumentNotFoundException,
@@ -645,6 +535,7 @@ public class JpaStorageClientImpl implements StorageClient {
         throw new UnsupportedOperationException();
        }
 
+       @SuppressWarnings("rawtypes")
        @Override
        public boolean synchronize(ServiceContext ctx, Object specifier,
                        DocumentHandler handler) throws DocumentNotFoundException,
@@ -654,6 +545,7 @@ public class JpaStorageClientImpl implements StorageClient {
                return true;
        }
        
+       @SuppressWarnings("rawtypes")
        @Override
        public boolean synchronizeItem(ServiceContext ctx, AuthorityItemSpecifier itemSpecifier,
                        DocumentHandler handler) throws DocumentNotFoundException,
index fa459de0b85a5f6d90c4d5c66ecc42a05368a8af..d3ff99c34a0bea8967e3343e8b74f41845107b95 100644 (file)
@@ -46,9 +46,11 @@ import org.collectionspace.services.authorization.PermissionRoleRel;
 import org.collectionspace.services.authorization.PermissionValue;
 import org.collectionspace.services.authorization.URIResourceImpl;
 import org.collectionspace.services.common.authorization_mgt.AuthorizationRoleRel;
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.document.JaxbUtils;
+import org.collectionspace.services.common.document.TransactionException;
 import org.collectionspace.services.common.security.SecurityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -57,6 +59,7 @@ import org.slf4j.LoggerFactory;
  * Utilities for JpaStorage
  * @author 
  */
+@SuppressWarnings({"rawtypes", "unchecked"})
 public class JpaStorageUtils {
 
     final private static Logger logger = LoggerFactory.getLogger(JpaStorageUtils.class);
@@ -88,8 +91,9 @@ public class JpaStorageUtils {
 
        return result;
     }
-    
-    public static Object getEntity(String id, Class entityClazz) {
+       
+       @Deprecated
+       public static Object getEntity(String id, Class entityClazz) {
         EntityManagerFactory emf = null;
         EntityManager em = null;
         Object entityFound = null;
@@ -135,6 +139,7 @@ public class JpaStorageUtils {
      * @param entityClazz
      * @return
      */
+    @Deprecated
     public static Object getEntity(EntityManager em, String id, Class entityClazz) throws DocumentNotFoundException {
         if (entityClazz == null) {
             String msg = "Not constructed with JpaStorageClientImpl(entityClazz) ctor";
@@ -144,7 +149,18 @@ public class JpaStorageUtils {
         //FIXME: it would be nice to verify tenantid as well
         return em.find(entityClazz, id);
     }
+        
+    public static Object getEntity(JPATransactionContext jpaTransactionContext, String id, Class entityClazz) throws DocumentNotFoundException {
+        if (entityClazz == null) {
+            String msg = "Not constructed with JpaStorageClientImpl(entityClazz) ctor";
+            logger.error(msg);
+            throw new UnsupportedOperationException(msg);
+        }
+        //FIXME: it would be nice to verify tenantid as well
+        return jpaTransactionContext.find(entityClazz, id);
+    }    
     
+    @Deprecated
     private static String getUserId(String csid)
                throws DocumentNotFoundException  {
        String result = null;
@@ -312,58 +328,80 @@ public class JpaStorageUtils {
         return result;
     }
     
-    public static Object getEnityByKey(EntityManager em, String entityName, String key, String value,
-            String tenantId) {
-       Object result = null;
-       
-        if (entityName == null) {
-            throw new IllegalArgumentException("entityName is required");
-        }
-        if (key == null) {
-            throw new IllegalArgumentException("id is required");
-        }
-        if (tenantId == null) {
-            throw new IllegalArgumentException("tenantId is required");
-        }
+    public static Object getEnityByKey(JPATransactionContext jpaTransactionContext, String entityName, String key, String value,
+            String tenantId) throws TransactionException {
+        Object result = null;
         
-        boolean useTenantId = useTenantId(tenantId);
-        StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
-        queryStrBldr.append(entityName);
-        queryStrBldr.append(" a");
-        queryStrBldr.append(" WHERE " + key + " = :" + key);
-        if (useTenantId == true) {
-            queryStrBldr.append(" AND tenantId = :tenantId");
-        }
-        String queryStr = queryStrBldr.toString(); //for debugging
-        Query q = em.createQuery(queryStr);
-        q.setParameter(key, value);
-        if (useTenantId == true) {
-            q.setParameter("tenantId", tenantId);
+        try {
+            boolean useTenantId = useTenantId(tenantId);
+            StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
+            queryStrBldr.append(entityName);
+            queryStrBldr.append(" a");
+            queryStrBldr.append(" WHERE " + key + " = :" + key);
+            if (useTenantId == true) {
+                queryStrBldr.append(" AND tenantId = :tenantId");
+            }
+            String queryStr = queryStrBldr.toString(); //for debugging            
+            Query q = jpaTransactionContext.createQuery(queryStr);
+            q.setParameter(key, value);
+            if (useTenantId == true) {
+                q.setParameter("tenantId", tenantId);
+            }
+            result = q.getSingleResult();
+        } catch (NoResultException nre) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Could not find entity with key ={" + key + "=" + value + "}", nre);
+            }
+            //returns null
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Could not find entity with id=" + key, e);
+            }
+            //returns null
         }
-        result = q.getSingleResult();
-
+        
         return result;
     }
-    
-    public static Object getEntityByDualKeys(EntityManager em, String entityName, 
+
+    /**
+     * 
+     * @param em
+     * @param entityName
+     * @param key1
+     * @param value1
+     * @param key2
+     * @param value2
+     * @return
+     * @throws TransactionException 
+     */
+    public static Object getEntityByDualKeys(
+               JPATransactionContext jpaTransactionContext,
+               String entityName, 
                String key1, String value1,
-               String key2, String value2) {
-       return getEntityByDualKeys(em, entityName, key1, value1, key2, value2, null);
+               String key2, String value2) throws TransactionException {
+       return getEntityByDualKeys(jpaTransactionContext, entityName, key1, value1, key2, value2, null);
     }
     
-    public static Object getEntityByDualKeys(EntityManager em, String entityName, 
+    /**
+     * 
+     * @param em
+     * @param entityName
+     * @param key1
+     * @param value1
+     * @param key2
+     * @param value2
+     * @param tenantId
+     * @return
+     * @throws TransactionException 
+     */
+       public static Object getEntityByDualKeys(
+               JPATransactionContext jpaTransactionContext,
+               String entityName, 
                String key1, String value1,
                String key2, String value2,
-            String tenantId) {
+            String tenantId) throws TransactionException {
        Object result = null;
        
-        if (entityName == null) {
-            throw new IllegalArgumentException("entityName is required");
-        }
-        if (key1 == null || key2 == null) {
-            throw new IllegalArgumentException("key names are required");
-        }
-        
         boolean useTenantId = useTenantId(tenantId);
         StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
         queryStrBldr.append(entityName);
@@ -374,7 +412,7 @@ public class JpaStorageUtils {
             queryStrBldr.append(" AND tenantId = :tenantId");
         }
         String queryStr = queryStrBldr.toString(); //for debugging
-        Query q = em.createQuery(queryStr);
+        Query q = jpaTransactionContext.createQuery(queryStr);
         q.setParameter(key1, value1);
         q.setParameter(key2, value2);
         if (useTenantId == true) {
@@ -385,44 +423,21 @@ public class JpaStorageUtils {
         return result;
     }
     
-    public static Object getEnityByKey(String entityName, String key, String value,
-            String tenantId) {
-        EntityManagerFactory emf = null;
-        EntityManager em = null;
-        Object o = null;
-        
-        try {
-            emf = getEntityManagerFactory();
-            em = emf.createEntityManager();
-            o = getEnityByKey(em, entityName, key, value, tenantId);
-        } catch (NoResultException nre) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
-            if (logger.isDebugEnabled()) {
-                logger.debug("Could not find entity with key ={" + key + "=" + value + "}", nre);
-            }
-            //returns null
-        } catch (Exception e) {
-            if (em != null && em.getTransaction().isActive()) {
-                em.getTransaction().rollback();
-            }
-            if (logger.isDebugEnabled()) {
-                logger.debug("Could not find entity with id=" + key, e);
-            }
-            //returns null
-        } finally {
-            if (em != null) {
-                releaseEntityManagerFactory(emf);
-            }
-        }
-        
-        return o;
-    }
-
-    public static Object getEntity(String entityName, String id,
-            String tenantId) {
-       return getEnityByKey(entityName, CSID_LABEL, id, tenantId);
+    /**
+     * 
+     * @param ctx
+     * @param entityName
+     * @param id
+     * @param tenantId
+     * @return
+     * @throws TransactionException 
+     */
+    public static Object getEntity(
+               JPATransactionContext jpaTransactionContext,
+               String entityName,
+               String id,
+            String tenantId) throws TransactionException {
+       return getEnityByKey(jpaTransactionContext, entityName, CSID_LABEL, id, tenantId);
     }
     
     /**
@@ -490,17 +505,34 @@ public class JpaStorageUtils {
         return o;
     }
 
-    public static Object getEntity(EntityManager em, String entityName,
+    public static Object getEntity(JPATransactionContext jpaTransactionContext, String entityName,
             String whereClause, HashMap<String, Object> paramBindings) {
         Object result = null;
         
-       if (entityName == null) {
-            throw new IllegalArgumentException("entityName is required");
+        StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
+        queryStrBldr.append(entityName);
+        queryStrBldr.append(" a");
+        queryStrBldr.append(" " + whereClause);
+
+        String queryStr = queryStrBldr.toString(); //for debugging
+        Query q = jpaTransactionContext.createQuery(queryStr);
+        for (String paramName : paramBindings.keySet()) {
+            q.setParameter(paramName, paramBindings.get(paramName));
         }
-        if (whereClause == null) {
-            throw new IllegalArgumentException("whereClause is required");
+        
+        result = q.getSingleResult();
+        
+        if (result == null) {
+               logger.debug("Call to getEntity() returned empty set.");
         }
-
+        
+        return result;
+    }
+    
+    public static Object getEntity(EntityManager em, String entityName,
+            String whereClause, HashMap<String, Object> paramBindings) {
+        Object result = null;
+        
         StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
         queryStrBldr.append(entityName);
         queryStrBldr.append(" a");