]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-595 added a test for multi-tenancy. it uses two pre-configured users in ROLE_T...
authorSanjay Dalal <sanjay.dalal@berkeley.edu>
Fri, 11 Jun 2010 19:09:27 +0000 (19:09 +0000)
committerSanjay Dalal <sanjay.dalal@berkeley.edu>
Fri, 11 Jun 2010 19:09:27 +0000 (19:09 +0000)
test: MultiTenancyTest, all service tests

M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/RoleJpaFilter.java
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionDocumentHandler.java
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionJpaFilter.java
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/AuthorizationDelegate.java
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/RoleDocumentHandler.java
M    services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java
M    services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountJpaFilter.java
A    services/security/client/src/test/java/org/collectionspace/services/security/client/test/MultiTenancyTest.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/AccountJpaFilter.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/AuthorizationDelegate.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionDocumentHandler.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionJpaFilter.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/RoleDocumentHandler.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/RoleJpaFilter.java
services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java
services/security/client/src/test/java/org/collectionspace/services/security/client/test/MultiTenancyTest.java [new file with mode: 0644]

index 7fcc775afc70ea3831f4ac174de3f901842f936c..454f19c497d60f408f9d178558386acce5c12ca8 100644 (file)
@@ -37,6 +37,7 @@ import org.collectionspace.services.common.document.AbstractDocumentHandlerImpl;
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -212,7 +213,9 @@ public class AccountDocumentHandler
      */
     private void sanitize(AccountsCommon account) {
         account.setPassword(null);
-        account.setTenants(new ArrayList<AccountTenant>(0));
+        if (!SecurityUtils.isCSpaceAdmin()) {
+            account.setTenants(new ArrayList<AccountTenant>(0));
+        }
     }
 
     /* (non-Javadoc)
index eaa84856f7ac30e5c482128bfa50f0e35d567a8b..8cae963834ea8abb900f1caae25bb95b2303741a 100644 (file)
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentFilter;
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.security.SecurityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,9 +53,16 @@ public class AccountJpaFilter extends JpaDocumentFilter {
         if (null != snvals && snvals.size() > 0) {
             screenName = snvals.get(0);
         }
-        queryStrBldr.append(addTenant(false, paramList));
+        boolean csAdmin = SecurityUtils.isCSpaceAdmin();
+        if (!csAdmin) {
+            queryStrBldr.append(addTenant(false, paramList));
+        }
         if (null != screenName && !screenName.isEmpty()) {
-            queryStrBldr.append(" AND");
+            if (!csAdmin) {
+                queryStrBldr.append(" AND");
+            } else {
+                queryStrBldr.append(" WHERE");
+            }
             queryStrBldr.append(" UPPER(a." + AccountStorageConstants.SCREEN_NAME + ")");
             queryStrBldr.append(" LIKE");
             queryStrBldr.append(" :" + AccountStorageConstants.Q_SCREEN_NAME);
@@ -68,7 +76,11 @@ public class AccountJpaFilter extends JpaDocumentFilter {
             uid = uidvals.get(0);
         }
         if (null != uid && !uid.isEmpty()) {
-            queryStrBldr.append(" AND");
+            if (!csAdmin) {
+                queryStrBldr.append(" AND");
+            } else {
+                queryStrBldr.append(" WHERE");
+            }
             queryStrBldr.append(" UPPER(a." + AccountStorageConstants.USER_ID + ")");
             queryStrBldr.append(" LIKE");
             queryStrBldr.append(" :" + AccountStorageConstants.Q_USER_ID);
@@ -83,14 +95,18 @@ public class AccountJpaFilter extends JpaDocumentFilter {
         }
         if (null != email && !email.isEmpty()) {
 
-            queryStrBldr.append(" AND");
+            if (!csAdmin) {
+                queryStrBldr.append(" AND");
+            } else {
+                queryStrBldr.append(" WHERE");
+            }
             queryStrBldr.append(" UPPER(a." + AccountStorageConstants.EMAIL + ")");
             queryStrBldr.append(" LIKE");
             queryStrBldr.append(" :" + AccountStorageConstants.Q_EMAIL);
             paramList.add(new ParamBinding(AccountStorageConstants.Q_EMAIL, "%"
                     + email.toUpperCase() + "%"));
         }
-        
+
         if (logger.isDebugEnabled()) {
             String query = queryStrBldr.toString();
             logger.debug("query=" + query);
@@ -106,8 +122,9 @@ public class AccountJpaFilter extends JpaDocumentFilter {
 
     @Override
     protected String addTenant(boolean append, List<ParamBinding> paramList) {
+        String tenantId = getTenantId();
         String whereClause = " JOIN a.tenants as at WHERE at.tenantId = :tenantId";
-        paramList.add(new ParamBinding("tenantId", getTenantId()));
+        paramList.add(new ParamBinding("tenantId", tenantId));
         return whereClause;
     }
 }
index b103b552a45dfc95a1aff80c4a99d4a37143ff97..0b02e44dbedac9a67d5925f7386540d95c85a440 100644 (file)
@@ -35,6 +35,7 @@ import org.collectionspace.services.authorization.PermissionAction;
 import org.collectionspace.services.authorization.PermissionException;
 import org.collectionspace.services.authorization.PermissionRole;
 import org.collectionspace.services.authorization.PermissionValue;
+import org.collectionspace.services.authorization.Role;
 import org.collectionspace.services.authorization.RoleValue;
 import org.collectionspace.services.authorization.SubjectType;
 import org.collectionspace.services.authorization.URIResourceImpl;
@@ -80,12 +81,19 @@ public class AuthorizationDelegate {
             }
         } else if (SubjectType.PERMISSION.equals(subject)) {
             RoleValue rv = pr.getRoles().get(0);
+            Role r = getRole(rv.getRoleId());
+            if (r == null) {
+                String msg = "addPermissions: No role found for id=" + rv.getRoleId();
+                logger.error(msg);
+                throw new DocumentNotFoundException(msg);
+            }
             String[] roles = {rv.getRoleName()};
             for (PermissionValue pv : pr.getPermissions()) {
                 Permission p = getPermission(pv.getPermissionId());
                 if (p == null) {
                     String msg = "addPermissions: No permission found for id=" + pv.getPermissionId();
                     logger.error(msg);
+                    //TODO: would be nice contiue to still send 400 back
                     continue;
                 }
                 CSpaceResource[] resources = getResources(p);
@@ -155,10 +163,14 @@ public class AuthorizationDelegate {
     private static String[] getRoles(List<RoleValue> rvl) {
         List<String> rvls = new ArrayList<String>();
         for (RoleValue rv : rvl) {
-            //assumption: rolename is relationship metadata is mandatory
-            if (rv.getRoleName() != null) {
-                rvls.add(rv.getRoleName());
+            Role r = getRole(rv.getRoleId());
+            if (r == null) {
+                String msg = "getRoles: No role found for id=" + rv.getRoleId();
+                logger.error(msg);
+                //TODO: would be nice contiue to still send 400 back
+                continue;
             }
+            rvls.add(r.getRoleName());
         }
         return rvls.toArray(new String[0]);
     }
@@ -174,9 +186,14 @@ public class AuthorizationDelegate {
         List<CSpaceResource> rl = new ArrayList<CSpaceResource>();
 
         for (PermissionAction pa : p.getActions()) {
-
-            CSpaceResource res = new URIResourceImpl(p.getResourceName(),
-                    getAction(pa.getName()));
+            CSpaceResource res = null;
+            if (p.getTenantId() == null) {
+                res = new URIResourceImpl(p.getResourceName(),
+                        getAction(pa.getName()));
+            } else {
+                res = new URIResourceImpl(p.getTenantId(), p.getResourceName(),
+                        getAction(pa.getName()));
+            }
             rl.add(res);
         }
         return rl.toArray(new CSpaceResource[0]);
@@ -188,6 +205,12 @@ public class AuthorizationDelegate {
         return p;
     }
 
+    private static Role getRole(String roleCsid) {
+        Role r = (Role) JpaStorageUtils.getEntity(roleCsid,
+                Role.class);
+        return r;
+    }
+
     /**
      * getAction is a convenience method to get corresponding action for
      * given ActionType
index d2b16e465ca162a45c684bfc78f48762f4e74e5d..0252948731e27e22c993ef8414d99f40360ecabc 100644 (file)
@@ -36,6 +36,7 @@ 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -197,7 +198,9 @@ public class PermissionDocumentHandler
      * @param permission
      */
     private void sanitize(Permission permission) {
-        permission.setTenantId(null);
+        if (!SecurityUtils.isCSpaceAdmin()) {
+            permission.setTenantId(null);
+        }
     }
 
     private void setTenant(Permission permission) {
index cfe69cf12f2e7d30e14f6337e6660dbc3bdcd62f..8a57775b1774f4e9443874b792e853d539039952 100644 (file)
@@ -27,6 +27,7 @@ package org.collectionspace.services.authorization.storage;
 import java.util.ArrayList;
 import java.util.List;
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.security.SecurityUtils;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,9 +59,16 @@ public class PermissionJpaFilter extends JpaDocumentFilter {
         if (null != rn && rn.size() > 0) {
             resName = rn.get(0);
         }
-        queryStrBldr.append(addTenant(false, paramList));
+        boolean csAdmin = SecurityUtils.isCSpaceAdmin();
+        if (!csAdmin) {
+            queryStrBldr.append(addTenant(false, paramList));
+        }
         if (null != resName && !resName.isEmpty()) {
-            queryStrBldr.append(" AND");
+            if (!csAdmin) {
+                queryStrBldr.append(" AND");
+            } else {
+                queryStrBldr.append(" WHERE");
+            }
             queryStrBldr.append(" UPPER(a." + PermissionStorageConstants.RESOURCE_NAME + ")");
             queryStrBldr.append(" LIKE");
             queryStrBldr.append(" :" + PermissionStorageConstants.Q_RESOURCE_NAME);
index 6af23e53ccedc8793b2ab393686fe0c5157689a4..4a3da1578bf726552bc0545db48a333f37052b68 100644 (file)
@@ -23,6 +23,7 @@
  */
 package org.collectionspace.services.authorization.storage;
 
+import java.util.HashMap;
 import java.util.List;
 import org.collectionspace.services.authorization.PermissionRole;
 import org.collectionspace.services.authorization.PermissionRoleRel;
@@ -31,6 +32,7 @@ import org.collectionspace.services.authorization.RoleValue;
 import org.collectionspace.services.authorization.SubjectType;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextProperties;
+import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
 
 /**
  *
@@ -82,7 +84,7 @@ public class PermissionRoleUtil {
             }
         }
     }
-    
+
     static private PermissionRoleRel buildPermissonRoleRel(PermissionValue pv, RoleValue rv) {
         PermissionRoleRel prr = new PermissionRoleRel();
         prr.setPermissionId(pv.getPermissionId());
@@ -91,4 +93,25 @@ public class PermissionRoleUtil {
         prr.setRoleName(rv.getRoleName());
         return prr;
     }
+
+    static boolean isInvalidTenant(String tenantId, StringBuilder msgBldr) {
+        boolean invalid = false;
+
+        if (tenantId == null || tenantId.isEmpty()) {
+            invalid = true;
+            msgBldr.append("\n tenant : tenantId is missing");
+        }
+        String whereClause = "where id = :id";
+        HashMap<String, Object> params = new HashMap<String, Object>();
+        params.put("id", tenantId);
+
+        Object tenantFound = JpaStorageUtils.getEntity(
+                "org.collectionspace.services.account.Tenant", whereClause, params);
+        if (tenantFound == null) {
+            invalid = true;
+            msgBldr.append("\n tenant : tenantId=" + tenantId
+                    + " not found");
+        }
+        return invalid;
+    }
 }
index 0171d0325752db8ca455f372a4e378638bc1eecd..7be60a26cfa897dfab38332ed60c35f9c3f61b54 100644 (file)
@@ -24,7 +24,6 @@
 package org.collectionspace.services.authorization.storage;
 
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
@@ -36,6 +35,7 @@ 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -180,7 +180,9 @@ public class RoleDocumentHandler
      * @param roleFound
      */
     private void sanitize(Role role) {
-        role.setTenantId(null);
+        if (!SecurityUtils.isCSpaceAdmin()) {
+            role.setTenantId(null);
+        }
     }
 
     private String fixRoleName(String role) {
index 35751bb44ea02a605c481af648b6ccba43e35895..483baa9a3e633412bd2fd53f277ad1818899da3d 100644 (file)
@@ -27,6 +27,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.collectionspace.services.common.storage.jpa.JpaDocumentFilter;
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.security.SecurityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,9 +52,16 @@ public class RoleJpaFilter extends JpaDocumentFilter {
         if (null != rn && rn.size() > 0) {
             roleName = rn.get(0);
         }
-        queryStrBldr.append(addTenant(false, paramList));
+        boolean csAdmin = SecurityUtils.isCSpaceAdmin();
+        if (!csAdmin) {
+            queryStrBldr.append(addTenant(false, paramList));
+        }
         if (null != roleName && !roleName.isEmpty()) {
-            queryStrBldr.append(" AND");
+            if (!csAdmin) {
+                queryStrBldr.append(" AND");
+            } else {
+                queryStrBldr.append(" WHERE");
+            }
             queryStrBldr.append(" UPPER(a." + RoleStorageConstants.ROLE_NAME + ")");
             queryStrBldr.append(" LIKE");
             queryStrBldr.append(" :" + RoleStorageConstants.Q_ROLE_NAME);
index c7e8d46db52e5cd7b348a8385973bc5d86ba3e21..de57be1ad758f6bc476c600288765529c12a25da 100644 (file)
@@ -22,6 +22,7 @@
  */
 package org.collectionspace.services.common.security;
 
+import org.collectionspace.authentication.AuthN;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -66,4 +67,22 @@ public class SecurityUtils {
             throw new IllegalArgumentException(msg);
         }
     }
+
+    /**
+     * isCSpaceAdmin check if authenticated user is a CSpace administrator
+     * @param tenantId
+     * @return
+     */
+    public static boolean isCSpaceAdmin() {
+        String tenantId = AuthN.get().getCurrentTenantId();
+        if (tenantId != null) {
+            if (!"0".equals(tenantId)) {
+                return false;
+            } else {
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
 }
index e387baa85fbaedf41bc8a9eb0c5b68a39d380325..dac25d85293dcc13cffadc821d27b898a122f26b 100644 (file)
 package org.collectionspace.services.common.storage.jpa;
 
 import java.util.HashMap;
-import java.util.List;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.NoResultException;
 import javax.persistence.Persistence;
 import javax.persistence.Query;
-import org.collectionspace.services.common.document.DocumentFilter;
+import org.collectionspace.services.common.security.SecurityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -110,13 +109,19 @@ public class JpaStorageUtils {
             StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
             queryStrBldr.append(entityName);
             queryStrBldr.append(" a");
-            queryStrBldr.append(" WHERE csid = :csid AND tenantId = :tenantId");
+            queryStrBldr.append(" WHERE csid = :csid");
+            boolean csAdmin = SecurityUtils.isCSpaceAdmin();
+            if (!csAdmin) {
+                queryStrBldr.append(" AND tenantId = :tenantId");
+            }
             emf = getEntityManagerFactory();
             em = emf.createEntityManager();
             String queryStr = queryStrBldr.toString(); //for debugging
             Query q = em.createQuery(queryStr);
             q.setParameter("csid", id);
-            q.setParameter("tenantId", tenantId);
+            if (!csAdmin) {
+                q.setParameter("tenantId", tenantId);
+            }
             o = q.getSingleResult();
         } catch (NoResultException nre) {
             if (em != null && em.getTransaction().isActive()) {
diff --git a/services/security/client/src/test/java/org/collectionspace/services/security/client/test/MultiTenancyTest.java b/services/security/client/src/test/java/org/collectionspace/services/security/client/test/MultiTenancyTest.java
new file mode 100644 (file)
index 0000000..75075ec
--- /dev/null
@@ -0,0 +1,891 @@
+/**
+ *  This document is a part of the source code and related artifacts
+ *  for CollectionSpace, an open source collections management system
+ *  for museums and related institutions:
+
+ *  http://www.collectionspace.org
+ *  http://wiki.collectionspace.org
+
+ *  Copyright 2010 University of California at Berkeley
+
+ *  Licensed under the Educational Community License (ECL), Version 2.0.
+ *  You may not use this file except in compliance with this License.
+
+ *  You may obtain a copy of the ECL 2.0 License at
+
+ *  https://source.collectionspace.org/collection-space/LICENSE.txt
+
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.collectionspace.services.security.client.test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.List;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.authorization.AccountRole;
+import org.collectionspace.services.authorization.AccountValue;
+import org.collectionspace.services.authorization.ActionType;
+import org.collectionspace.services.authorization.EffectType;
+
+import org.collectionspace.services.authorization.Permission;
+import org.collectionspace.services.authorization.PermissionAction;
+import org.collectionspace.services.authorization.PermissionRole;
+import org.collectionspace.services.authorization.PermissionValue;
+import org.collectionspace.services.authorization.Role;
+import org.collectionspace.services.authorization.RoleValue;
+import org.collectionspace.services.client.AccountClient;
+import org.collectionspace.services.client.AccountFactory;
+import org.collectionspace.services.client.AccountRoleClient;
+import org.collectionspace.services.client.AccountRoleFactory;
+import org.collectionspace.services.client.CollectionSpaceClient;
+import org.collectionspace.services.client.DimensionClient;
+import org.collectionspace.services.client.DimensionFactory;
+import org.collectionspace.services.client.PermissionClient;
+import org.collectionspace.services.client.PermissionFactory;
+import org.collectionspace.services.client.PermissionRoleClient;
+import org.collectionspace.services.client.PermissionRoleFactory;
+import org.collectionspace.services.client.RoleClient;
+import org.collectionspace.services.client.RoleFactory;
+import org.collectionspace.services.client.test.AbstractServiceTestImpl;
+import org.collectionspace.services.dimension.DimensionsCommon;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.jboss.resteasy.client.ClientResponse;
+import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
+import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
+import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+/**
+ * AuthorizationServiceTest, carries out tests against a
+ * deployed and running Permission, Role, AccountRole, PermissionRole and
+ * CollectionObject Services.
+ *
+ * Pre-requisite : authorization-mgt/client tests seed some permissions used
+ * by this test
+ *
+ * $LastChangedRevision: 917 $
+ * $LastChangedDate: 2009-11-06 12:20:28 -0800 (Fri, 06 Nov 2009) $
+ */
+public class MultiTenancyTest extends AbstractServiceTestImpl {
+
+    private final String CLASS_NAME = MultiTenancyTest.class.getName();
+    private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
+    private final static String TENANT_1_ADMIN_USER = "test";
+    private final static String TENANT_2_ADMIN_USER = "test-pahma";
+    private final static String TENANT_1_USER = "user1@museum1.org";
+    private final static String TENANT_2_USER = "user2@museum2.org";
+    private final static String TENANT_1 = "1";
+    private final static String TENANT_2 = "2";
+    private final static String TEST_ROLE_NAME = "ROLE_TEST_REGISTRAR";
+    private final static String TEST_SERVICE_A = "dimensions";
+
+    private static class UserInfo {
+
+        String userName;
+        String password;
+
+        UserInfo(String u, String p) {
+            userName = u;
+            password = p;
+        }
+    }
+    // Instance variables specific to this test.
+    private String TENANT_RESOURCE_1 = null;
+    private String TENANT_RESOURCE_2 = null;
+    private List<String> allResourceIdsCreated = new ArrayList();
+    //key for userAccounts is userId
+    private Hashtable<String, AccountValue> userAccounts = new Hashtable<String, AccountValue>();
+    //key for permValues is id as there could be several perms for the same resource
+    private Hashtable<String, PermissionValue> permValues = new Hashtable<String, PermissionValue>();
+    //key for all tenantXXX tables is tenant id, expecting only one entity per tenant for this test
+    private Hashtable<String, UserInfo> tenantAdminUsers = new Hashtable<String, UserInfo>();
+    private Hashtable<String, AccountValue> tenantAccounts = new Hashtable<String, AccountValue>();
+    private Hashtable<String, RoleValue> tenantRoles = new Hashtable<String, RoleValue>();
+    private Hashtable<String, Role> tenantAdminRoles = new Hashtable<String, Role>();
+    private Hashtable<String, PermissionValue> tenantPermissions = new Hashtable<String, PermissionValue>();
+
+//    private String permId1;
+//    private String permId2;
+
+    /*
+     * This method is called only by the parent class, AbstractServiceTestImpl
+     */
+    @Override
+    protected String getServicePathComponent() {
+        return null;
+    }
+
+    @BeforeClass(alwaysRun = true)
+    public void seedData() {
+        if (logger.isDebugEnabled()) {
+            testBanner("seedData", CLASS_NAME);
+        }
+
+        //tenant admin users are used to create accounts, roles and permissions and relationships
+        //assumption : two tenant admin users exist before running this test
+        tenantAdminUsers.put(TENANT_1, new UserInfo(TENANT_1_ADMIN_USER, "test"));
+        tenantAdminUsers.put(TENANT_2, new UserInfo(TENANT_2_ADMIN_USER, "test"));
+
+        seedAccounts();
+        seedPermissions();
+        seedRoles();
+        seedAccountRoles();
+        seedPermissionRoles();
+    }
+
+    private void seedAccounts() {
+        seedAccount(TENANT_1, TENANT_1_USER);
+        seedAccount(TENANT_2, TENANT_2_USER);
+    }
+
+    private void seedAccount(String tenantId, String userId) {
+        //create account using default user in admin role but assign tenant id
+        //create username, email and password same for simplicity
+        String accId = createAccount(tenantId, userId, userId);
+        AccountValue ava = new AccountValue();
+        ava.setScreenName(userId);
+        ava.setUserId(userId);
+        ava.setAccountId(accId);
+        userAccounts.put(ava.getUserId(), ava);
+        tenantAccounts.put(tenantId, ava);
+        if (logger.isDebugEnabled()) {
+            logger.debug("seedAccount tenantId=" + tenantId + " userId=" + userId);
+        }
+    }
+
+    private void seedPermissions() {
+        String resource = TEST_SERVICE_A;
+
+        PermissionAction pac = new PermissionAction();
+        pac.setName(ActionType.CREATE);
+        PermissionAction par = new PermissionAction();
+        par.setName(ActionType.READ);
+        PermissionAction pau = new PermissionAction();
+        pau.setName(ActionType.UPDATE);
+        PermissionAction pad = new PermissionAction();
+        pad.setName(ActionType.DELETE);
+
+        //both users can create, read and update and delete
+        List<PermissionAction> testActions = new ArrayList<PermissionAction>();
+        testActions.add(pac);
+        testActions.add(par);
+        testActions.add(pau);
+        testActions.add(pad);
+
+        seedPermission(TENANT_1, resource, testActions, EffectType.PERMIT);
+        seedPermission(TENANT_2, resource, testActions, EffectType.PERMIT);
+    }
+
+    private void seedPermission(String tenantId,
+            String resource, List<PermissionAction> testActions, EffectType effect) {
+        //create permission using default user in admin role but assign tenant id
+        String id = createPermission(tenantId, resource, testActions, effect);
+        PermissionValue pv = new PermissionValue();
+        pv.setResourceName(resource);
+        pv.setPermissionId(id);
+        permValues.put(pv.getPermissionId(), pv);
+        tenantPermissions.put(tenantId, pv);
+        if (logger.isDebugEnabled()) {
+            logger.debug("seedPermission tenantId=" + tenantId
+                    + " permId=" + id + " resource=" + resource);
+        }
+    }
+
+    private void seedRoles() {
+        //create role using default user in admin role but assign tenant id
+        //use the same role name to check constraints
+        seedRole(TENANT_1, TEST_ROLE_NAME);
+        seedRole(TENANT_2, TEST_ROLE_NAME);
+    }
+
+    private void seedRole(String tenantId, String roleName) {
+        String rid = createRole(tenantId, roleName);
+        RoleValue rv = new RoleValue();
+        rv.setRoleId(rid);
+        rv.setRoleName(roleName);
+        tenantRoles.put(tenantId, rv);
+        if (logger.isDebugEnabled()) {
+            logger.debug("seedRole tenantId=" + tenantId + " roleName=" + roleName);
+        }
+    }
+
+    private void seedAccountRoles() {
+
+        for (String tenantId : tenantAccounts.keySet()) {
+            AccountValue av = (AccountValue) tenantAccounts.get(tenantId);
+            seedAccountRole(tenantId, av.getUserId());
+        }
+    }
+
+    private void seedAccountRole(String tenantId, String userId) {
+        List<RoleValue> tenantRoleValues = new ArrayList<RoleValue>();
+        tenantRoleValues.add(tenantRoles.get(tenantId));
+        createAccountRole(tenantId, userAccounts.get(userId), tenantRoleValues);
+        if (logger.isDebugEnabled()) {
+            logger.debug("seedAccountRole tenantId=" + tenantId + " userId=" + userId);
+        }
+    }
+
+    private void seedPermissionRoles() {
+
+        for (String tenantId : tenantPermissions.keySet()) {
+            PermissionValue pv = tenantPermissions.get(tenantId);
+            seedPermissionRole(tenantId, pv.getPermissionId());
+        }
+    }
+
+    private void seedPermissionRole(String tenantId, String permId) {
+        List<RoleValue> tenantRoleValues = new ArrayList<RoleValue>();
+        tenantRoleValues.add(tenantRoles.get(tenantId));
+        PermissionValue pv = permValues.get(permId);
+        createPermissionRole(tenantId, permValues.get(permId), tenantRoleValues);
+        if (logger.isDebugEnabled()) {
+            logger.debug("seedPermissionRole tenantId=" + tenantId
+                    + " permId=" + permId + " resource=" + pv.getResourceName());
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
+     */
+    @Override
+    protected CollectionSpaceClient getClientInstance() {
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
+     */
+    @Override
+    protected AbstractCommonList getAbstractCommonList(
+            ClientResponse<AbstractCommonList> response) {
+        //FIXME: http://issues.collectionspace.org/browse/CSPACE-1697
+        throw new UnsupportedOperationException();
+    }
+
+    @Test(dataProvider = "testName")
+    @Override
+    public void readPaginatedList(String testName) throws Exception {
+        //FIXME: http://issues.collectionspace.org/browse/CSPACE-1697
+    }
+    // ---------------------------------------------------------------
+    // CRUD tests : CREATE tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void create(String testName) throws Exception {
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+
+        ClientResponse<Response> res = create(testName, TENANT_1_USER, TENANT_1);
+
+        TENANT_RESOURCE_1 = extractId(res);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": tenantId= " + TENANT_1
+                    + " userId=" + TENANT_1_USER
+                    + " TENANT_RESOURCE_1 id=" + TENANT_RESOURCE_1);
+        }
+    }
+
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void create2(String testName) throws Exception {
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+
+        ClientResponse<Response> res = create(testName, TENANT_2_USER, TENANT_2);
+
+        TENANT_RESOURCE_2 = extractId(res);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": tenantId= " + TENANT_2
+                    + " userId=" + TENANT_2_USER
+                    + " TENANT_RESOURCE_2 id=" + TENANT_RESOURCE_2);
+        }
+    }
+
+    private ClientResponse<Response> create(String testName, String userName, String tenatnId) {
+        setupCreate();
+        // Submit the request to the service and store the response.
+        DimensionClient client = new DimensionClient();
+        client.setAuth(true, userName, true, userName, true);
+        String identifier = createIdentifier();
+        DimensionsCommon dimension = new DimensionsCommon();
+        dimension.setDimension("dimensionType");
+        dimension.setValue("value-" + identifier);
+        dimension.setValueDate(new Date().toString());
+        MultipartOutput multipart = DimensionFactory.createDimensionInstance(client.getCommonPartName(),
+                dimension);
+        ClientResponse<Response> res = client.create(multipart);
+        int statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.CREATED.getStatusCode());
+        return res;
+
+    }
+
+    //to not cause uniqueness violation for permRole, createList is removed
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"create"})
+    public void createList(String testName) throws Exception {
+    }
+
+    // Failure outcomes
+    // Placeholders until the three tests below can be uncommented.
+    // See Issue CSPACE-401.
+    @Override
+    public void createWithEmptyEntityBody(String testName) throws Exception {
+    }
+
+    @Override
+    public void createWithMalformedXml(String testName) throws Exception {
+    }
+
+    @Override
+    public void createWithWrongXmlSchema(String testName) throws Exception {
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : READ tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"create"})
+    public void read(String testName) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+        DimensionsCommon dimension = read(testName, TENANT_RESOURCE_1, TENANT_1_USER);
+        Assert.assertNotNull(dimension);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": tenantId= " + TENANT_1
+                    + " userId=" + TENANT_1_USER
+                    + " TENANT_RESOURCE_1 retrieved id=" + dimension.getCsid());
+        }
+    }
+
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"create2"})
+    public void read2(String testName) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+        DimensionsCommon dimension = read(testName, TENANT_RESOURCE_2, TENANT_2_USER);
+        Assert.assertNotNull(dimension);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": tenantId= " + TENANT_2
+                    + " userId=" + TENANT_2_USER
+                    + " TENANT_RESOURCE_1 retrieved id=" + dimension.getCsid());
+        }
+    }
+
+    private DimensionsCommon read(String testName, String id, String userName) throws Exception {
+        setupRead();
+        // Submit the request to the service and store the response.
+        DimensionClient client = new DimensionClient();
+        client.setAuth(true, userName, true, userName, true);
+        ClientResponse<MultipartInput> res = client.read(id);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+        MultipartInput input = (MultipartInput) res.getEntity();
+        return (DimensionsCommon) extractPart(input,
+                client.getCommonPartName(), DimensionsCommon.class);
+    }
+    // Failure outcomes
+
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void readNonExistent(String testName) throws Exception {
+
+        // Perform setup.
+        setupReadNonExistent();
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : READ_LIST tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"createList", "read"})
+    public void readList(String testName) throws Exception {
+        setupReadList();
+    }
+
+    // Failure outcomes
+    // None at present.
+    // ---------------------------------------------------------------
+    // CRUD tests : UPDATE tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"read", "readList", "readNonExistent"})
+    public void update(String testName) throws Exception {
+        setupUpdate();
+
+    }
+
+    // Failure outcomes
+    // Placeholders until the three tests below can be uncommented.
+    // See Issue CSPACE-401.
+    @Override
+    public void updateWithEmptyEntityBody(String testName) throws Exception {
+    }
+
+    @Override
+    public void updateWithMalformedXml(String testName) throws Exception {
+    }
+
+    @Override
+    public void updateWithWrongXmlSchema(String testName) throws Exception {
+    }
+
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"read2", "readNonExistent", "testSubmitRequest"})
+    public void updateNonExistent(String testName) throws Exception {
+
+        DimensionClient client = new DimensionClient();
+        //TENANT_1_USER is not allowed to update the resource of TENANT_2
+        client.setAuth(true, TENANT_1_USER, true, TENANT_1_USER, true);
+
+        DimensionsCommon dimension = new DimensionsCommon();
+        dimension.setDimension("dimensionType");
+        // Update the content of this resource.
+        dimension.setValue("updated-" + dimension.getValue());
+        dimension.setValueDate("updated-" + dimension.getValueDate());
+        // Submit the request to the service and store the response.
+        MultipartOutput output = new MultipartOutput();
+        OutputPart commonPart = output.addPart(dimension, MediaType.APPLICATION_XML_TYPE);
+        commonPart.getHeaders().add("label", client.getCommonPartName());
+
+        ClientResponse<MultipartInput> res = client.update(TENANT_RESOURCE_2, output);
+        int statusCode = res.getStatus();
+        // Check the status code of the response: does it match the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + " resource = " + TENANT_RESOURCE_2
+                    + " status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        //going to incorrect Nuxeo domain would give DocumentNotFoundException
+        //instead of giving FORBIDDEN
+        Assert.assertEquals(statusCode, Response.Status.NOT_FOUND.getStatusCode());
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : DELETE tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"deleteNonExistent"})
+    public void delete(String testName) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+
+        int statusCode = delete(testName, TENANT_RESOURCE_1, TENANT_1_USER);
+    }
+
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"updateNonExistent"})
+    public void delete2(String testName) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+        int statusCode = delete(testName, TENANT_RESOURCE_2, TENANT_2_USER);
+
+    }
+
+    private int delete(String testName, String id, String userName) throws Exception {
+        // Perform setup.
+        setupDelete();
+        // Submit the request to the service and store the response.
+        DimensionClient client = new DimensionClient();
+        client.setAuth(true, userName, true, userName, true);
+        ClientResponse<Response> res = client.delete(id);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        return statusCode;
+    }
+
+    // Failure outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"read"})
+    public void deleteNonExistent(String testName) throws Exception {
+        //ignoring this test as the service side returns 200 now even if it does
+        //not find a record in the db
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+        // Perform setup.
+        setupDelete();
+
+        // Submit the request to the service and store the response.
+        DimensionClient client = new DimensionClient();
+        //TENANT_2_USER of TENANT_2 is not allowed to delete the resource of TENANT_1
+        client.setAuth(true, TENANT_2_USER, true, TENANT_2_USER, true);
+        ClientResponse<Response> res = client.delete(TENANT_RESOURCE_1);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        //going to incorrect Nuxeo domain would give DocumentNotFoundException
+        //instead of giving FORBIDDEN
+        Assert.assertEquals(statusCode, Response.Status.NOT_FOUND.getStatusCode());
+    }
+
+    // ---------------------------------------------------------------
+    // Utility tests : tests of code used in tests above
+    // ---------------------------------------------------------------
+    /**
+     * Tests the code for manually submitting data that is used by several
+     * of the methods above.
+     */
+    @Test(dependsOnMethods = {"create"})
+    public void testSubmitRequest() throws Exception {
+    }
+
+    // ---------------------------------------------------------------
+    // Utility methods used by tests above
+    // ---------------------------------------------------------------
+    @AfterClass(alwaysRun = true)
+    public void cleanUp() {
+        if (logger.isDebugEnabled()) {
+            testBanner("cleanUp", CLASS_NAME);
+        }
+        setupDelete();
+        String noTest = System.getProperty("noTestCleanup");
+        if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Skipping Cleanup phase ...");
+            }
+            return;
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("Cleaning up temporary resources created for testing ...");
+        }
+
+        //tenant admin users are used to create accounts, roles and permissions and relationships
+        //assumption : two tenant admin users exist before running this test
+
+        //FIXME delete on permission role deletes all roles associated with the permission
+        //this would delete association with ROLE_ADMINISTRATION too
+        //deletePermissionRoles();
+        deleteAccountRoles();
+        //FIXME delete on permission role deletes all roles associated with the permission
+        //this would delete association with ROLE_ADMINISTRATION too
+        //deletePermissions();
+        deleteRoles();
+        deleteAccounts();
+    }
+
+    private void deletePermissionRoles() {
+
+        //first delete relationships between the entities
+        for (String tenantId : tenantPermissions.keySet()) {
+            PermissionValue pv = tenantPermissions.get(tenantId);
+            deletePermissionRole(tenantId, pv.getPermissionId());
+        }
+    }
+
+    private void deleteAccountRoles() {
+        for (String tenantId : tenantAccounts.keySet()) {
+            AccountValue av = tenantAccounts.get(tenantId);
+            deleteAccountRole(tenantId, av.getAccountId());
+        }
+    }
+
+    private void deletePermissions() {
+        for (String tenantId : tenantPermissions.keySet()) {
+            PermissionValue pv = tenantPermissions.get(tenantId);
+            deletePermission(tenantId, pv.getPermissionId());
+        }
+    }
+
+    private void deleteRoles() {
+        for (String tenantId : tenantRoles.keySet()) {
+            RoleValue rv = tenantRoles.get(tenantId);
+            deleteRole(tenantId, rv.getRoleId());
+        }
+    }
+
+    private void deleteAccounts() {
+
+        for (String tenantId : tenantAccounts.keySet()) {
+            AccountValue av = tenantAccounts.get(tenantId);
+            deleteAccount(tenantId, av.getAccountId());
+        }
+    }
+
+    private String createPermission(String tenantId, String resName,
+            List<PermissionAction> actions, EffectType effect) {
+        setupCreate();
+        PermissionClient permClient = new PermissionClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        permClient.setAuth(true, ui.userName, true, ui.password, true);
+        Permission permission = PermissionFactory.createPermissionInstance(resName,
+                "default permissions for " + resName,
+                actions, effect, true, true, true);
+        permission.setTenantId(tenantId);
+        ClientResponse<Response> res = permClient.create(permission);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("createPermission: resName=" + resName
+                    + " status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+        return extractId(res);
+    }
+
+    private void deletePermission(String tenantId, String permId) {
+        setupDelete();
+        PermissionClient permClient = new PermissionClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        permClient.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = permClient.delete(permId);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("deletePermission: delete permission id="
+                    + permId + " status=" + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+    }
+
+    private String createRole(String tenantId, String roleName) {
+        setupCreate();
+        RoleClient roleClient = new RoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        roleClient.setAuth(true, ui.userName, true, ui.password, true);
+        Role role = RoleFactory.createRoleInstance(roleName,
+                "role for " + roleName, true);
+        role.setTenantId(tenantId);
+        ClientResponse<Response> res = roleClient.create(role);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("createRole: name=" + roleName
+                    + " status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+        return extractId(res);
+    }
+
+    private void deleteRole(String tenantId, String roleId) {
+        setupDelete();
+        RoleClient roleClient = new RoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        roleClient.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = roleClient.delete(roleId);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("deleteRole: delete role id=" + roleId
+                    + " status=" + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+    }
+
+    private String createAccount(String tenantId, String userName, String email) {
+        setupCreate();
+        AccountClient accountClient = new AccountClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        accountClient.setAuth(true, ui.userName, true, ui.password, true);
+        AccountsCommon account = AccountFactory.createAccountInstance(
+                userName, userName, userName, email, tenantId,
+                true, false, true, true);
+        ClientResponse<Response> res = accountClient.create(account);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("createAccount: tenantId=" + tenantId + " userName=" + userName
+                    + " status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+        return extractId(res);
+    }
+
+    private void deleteAccount(String tenantId, String accId) {
+        setupDelete();
+        AccountClient accClient = new AccountClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        accClient.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = accClient.delete(accId);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("deleteAccount: delete account id="
+                    + accId + " status=" + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+    }
+
+    private String createAccountRole(String tenantId, AccountValue av,
+            Collection<RoleValue> rvs) {
+        setupCreate();
+
+        // Submit the request to the service and store the response.
+        AccountRole accRole = AccountRoleFactory.createAccountRoleInstance(
+                av, rvs, true, true);
+        AccountRoleClient client = new AccountRoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        client.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = client.create(av.getAccountId(), accRole);
+        int statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("createAccountRole: status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+        return extractId(res);
+    }
+
+    private void deleteAccountRole(String tenantId, String accountId) {
+        // Perform setup.
+        setupDelete();
+
+        // Submit the request to the service and store the response.
+        AccountRoleClient client = new AccountRoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        client.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = client.delete(
+                accountId, "123");
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug("deleteAccountRole: status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+    }
+
+    private String createPermissionRole(String tenantId, PermissionValue pv,
+            Collection<RoleValue> rvs) {
+        setupCreate();
+        List<RoleValue> rvls = new ArrayList<RoleValue>();
+        rvls.addAll(rvs);
+        PermissionRole permRole = PermissionRoleFactory.createPermissionRoleInstance(
+                pv, rvls, true, true);
+        PermissionRoleClient client = new PermissionRoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        client.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = client.create(pv.getPermissionId(), permRole);
+        int statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("createPermissionRole: status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+        return extractId(res);
+    }
+
+    private void deletePermissionRole(String tenantId, String permId) {
+
+        // Perform setup.
+        setupDelete();
+
+        // Submit the request to the service and store the response.
+        PermissionRoleClient client = new PermissionRoleClient();
+        UserInfo ui = tenantAdminUsers.get(tenantId);
+        client.setAuth(true, ui.userName, true, ui.password, true);
+        ClientResponse<Response> res = client.delete(permId, "123");
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug("deletePermissionRole : status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        res.releaseConnection();
+    }
+}