]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-1301 associate role(s) to permi
authorSanjay Dalal <sanjay.dalal@berkeley.edu>
Wed, 14 Apr 2010 20:27:24 +0000 (20:27 +0000)
committerSanjay Dalal <sanjay.dalal@berkeley.edu>
Wed, 14 Apr 2010 20:27:24 +0000 (20:27 +0000)
CSPACE-1302 dis-associate role(s) from perm
CSPACE-1347 role-perm schema
added permission-role relationship. service is available as a subresource of permissions service (/permissions/{csid}/permroles). supports post, get and delete only. this version of delete deletes all associations for a permission.
test: authz-mgt, all services
requires: ant create_db at the service level

M    services/JaxRsServiceProvider/src/main/resources/META-INF/persistence.xml
M    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionResource.java
A    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleDocumentHandler.java
A    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java
A    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleStorageClient.java
A    services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionRoleSubResource.java
_M   services/authorization-mgt/client
M    services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/RoleServiceTest.java
M    services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionServiceTest.java
A    services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionRoleServiceTest.java
A    services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java
A    services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleProxy.java
M    services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationSeedTest.java
M    services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AbstractAuthorizationTestImpl.java
D    services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationGenTest.java
A  + services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationGen.java
M    services/authorization/service/src/test/resources/test-data/test-permissions-roles.xml
M    services/authorization/service/src/main/java/org/collectionspace/services/authorization/AuthZ.java
M    services/authorization/jaxb/src/main/resources/users_roles.xsd
M    services/authorization/jaxb/src/main/resources/permissions.xsd
M    services/authorization/jaxb/src/main/resources/permissions_roles.xsd
M    services/authorization/pstore/src/test/resources/META-INF/persistence.xml
_M   services/jaxb
M    services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java
M    services/common/src/main/config/services/tenant-bindings.xml
M    services/common/pom.xml
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
M    services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
M    services/client/src/main/java/org/collectionspace/services/client/test/BaseServiceTest.java

26 files changed:
services/JaxRsServiceProvider/src/main/resources/META-INF/persistence.xml
services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java [new file with mode: 0644]
services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleProxy.java [new file with mode: 0644]
services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionRoleServiceTest.java [new file with mode: 0644]
services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionServiceTest.java
services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/RoleServiceTest.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionResource.java
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionRoleSubResource.java [new file with mode: 0644]
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleDocumentHandler.java [new file with mode: 0644]
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleStorageClient.java [new file with mode: 0644]
services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java [new file with mode: 0644]
services/authorization/jaxb/src/main/resources/permissions.xsd
services/authorization/jaxb/src/main/resources/permissions_roles.xsd
services/authorization/jaxb/src/main/resources/users_roles.xsd
services/authorization/pstore/src/test/resources/META-INF/persistence.xml
services/authorization/service/src/main/java/org/collectionspace/services/authorization/AuthZ.java
services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AbstractAuthorizationTestImpl.java
services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationGen.java [moved from services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationGenTest.java with 76% similarity]
services/authorization/service/src/test/java/org/collectionspace/services/authorization/test/AuthorizationSeedTest.java
services/authorization/service/src/test/resources/test-data/test-permissions-roles.xml
services/client/src/main/java/org/collectionspace/services/client/test/BaseServiceTest.java
services/common/pom.xml
services/common/src/main/config/services/tenant-bindings.xml
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java

index 120511413f69f8317f7d81d84625c979146ef9a5..ce4dc6a7e0214eee2a1d01fcb542dda1f8234bdd 100644 (file)
         <class>org.collectionspace.services.authentication.User</class>
         <class>org.collectionspace.services.authorization.Permission</class>
         <class>org.collectionspace.services.authorization.PermissionAction</class>
-        <class>org.collectionspace.services.authorization.PermissionsList</class>
+        <class>org.collectionspace.services.authorization.PermissionRoleRel</class>
         <class>org.collectionspace.services.authorization.Role</class>
-        <class>org.collectionspace.services.authorization.RolesList</class>
         <class>org.collectionspace.services.authorization.UserRole</class>
-        <class>org.collectionspace.services.authorization.UsersRolesList</class>
         <properties>
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
             <property name="hibernate.max_fetch_depth" value="3"/>
index 3c5f92d9770cee2efea04f84ff6f3cf0c5cf0711..beb92420a3e6502b5cc2c691edef09cc89ecf38d 100644 (file)
@@ -590,7 +590,7 @@ public class AccountServiceTest extends AbstractServiceTestImpl {
         Assert.assertNotNull(toUpdateAccount);
 
         //change password
-        toUpdateAccount.setPassword(Base64.encodeBase64("imagination".getBytes()));
+        toUpdateAccount.setPassword("imagination".getBytes());
         if (logger.isDebugEnabled()) {
             logger.debug(testName + ": updated object");
             logger.debug(objectAsXmlString(toUpdateAccount,
@@ -640,7 +640,7 @@ public class AccountServiceTest extends AbstractServiceTestImpl {
 
         toUpdateAccount.setUserId(null);
         //change password
-        toUpdateAccount.setPassword(Base64.encodeBase64("imagination".getBytes()));
+        toUpdateAccount.setPassword("imagination".getBytes());
         if (logger.isDebugEnabled()) {
             logger.debug(testName + " : updated object");
             logger.debug(objectAsXmlString(toUpdateAccount,
index be4c7482da8cfa53247506a605a9887d82de4f51..81e0909e092a49b05a4081f7aeb572f76d96cbe7 100644 (file)
@@ -61,10 +61,9 @@ public class AccountStorageClient extends JpaStorageClientImpl {
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
 
-        String docType = ctx.getDocumentType();
-        if (docType == null) {
-            throw new DocumentNotFoundException(
-                    "Unable to find DocumentType for service " + ctx.getServiceName());
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "AccountStorageClient.create : ctx is missing");
         }
         if (handler == null) {
             throw new IllegalArgumentException(
@@ -119,10 +118,9 @@ public class AccountStorageClient extends JpaStorageClientImpl {
     public void update(ServiceContext ctx, String id, DocumentHandler handler)
             throws BadRequestException, DocumentNotFoundException,
             DocumentException {
-        String docType = ctx.getDocumentType();
-        if (docType == null) {
-            throw new DocumentNotFoundException(
-                    "Unable to find DocumentType for service " + ctx.getServiceName());
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "AccountStorageClient.update : ctx is missing");
         }
         if (handler == null) {
             throw new IllegalArgumentException(
@@ -184,10 +182,9 @@ public class AccountStorageClient extends JpaStorageClientImpl {
         if (logger.isDebugEnabled()) {
             logger.debug("deleting entity with id=" + id);
         }
-        String docType = ctx.getDocumentType();
-        if (docType == null) {
-            throw new DocumentNotFoundException(
-                    "Unable to find DocumentType for service " + ctx.getServiceName());
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "AccountStorageClient.delete : ctx is missing");
         }
         EntityManagerFactory emf = null;
         EntityManager em = null;
@@ -265,7 +262,8 @@ public class AccountStorageClient extends JpaStorageClientImpl {
 
     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
-            String msg = "User id " + toAccount.getUserId() + " not found!";
+            String msg = "User id " + toAccount.getUserId() + " does not match " + 
+                    "for given account with csid=" + fromAccount.getCsid();
             logger.error(msg);
             logger.debug(msg + " found userid=" + fromAccount.getUserId());
             throw new BadRequestException(msg);
diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleClient.java
new file mode 100644 (file)
index 0000000..d196054
--- /dev/null
@@ -0,0 +1,111 @@
+/**    
+ * PermissionRoleClient.java
+ *
+ * {Purpose of This Class}
+ *
+ * {Other Notes Relating to This Class (Optional)}
+ *
+ * $LastChangedBy: $
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ *
+ * 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 (C) 2009 {Contributing Institution}
+ *
+ * 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
+ */
+package org.collectionspace.services.client;
+
+import javax.ws.rs.core.Response;
+
+
+import org.collectionspace.services.authorization.PermissionRole;
+import org.jboss.resteasy.client.ProxyFactory;
+import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
+import org.jboss.resteasy.client.ClientResponse;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+
+/**
+ * A PermissionRoleClient.
+
+ * @version $Revision:$
+ */
+public class PermissionRoleClient extends AbstractServiceClientImpl {
+
+    /**
+     *
+     */
+    private PermissionRoleProxy permissionRoleProxy;
+
+    /* (non-Javadoc)
+     * @see 
+     */
+    public String getServicePathComponent() {
+        return "authorization/permissions";
+    }
+
+    /**
+     *
+     * Default constructor for PermissionRoleClient class.
+     *
+     */
+    public PermissionRoleClient() {
+        ResteasyProviderFactory factory = ResteasyProviderFactory.getInstance();
+        RegisterBuiltin.register(factory);
+        setProxy();
+    }
+
+    /**
+     * allow to reset proxy as per security needs
+     */
+    public void setProxy() {
+        if (useAuth()) {
+            permissionRoleProxy = ProxyFactory.create(PermissionRoleProxy.class,
+                    getBaseURL(), getHttpClient());
+        } else {
+            permissionRoleProxy = ProxyFactory.create(PermissionRoleProxy.class,
+                    getBaseURL());
+        }
+    }
+
+
+    /**
+     * @param csid
+     * @param prcsid relationship does not have an id, junk is fine
+     * @return
+     * @see 
+     */
+    public ClientResponse<PermissionRole> read(String csid, String prcsid) {
+        return permissionRoleProxy.read(csid, prcsid);
+    }
+
+    /**
+     * @param permRole
+     * @return
+     * @see 
+     */
+    public ClientResponse<Response> create(String csid, PermissionRole permRole) {
+        return permissionRoleProxy.create(csid, permRole);
+    }
+
+
+    /**
+     * @param csid
+     * @param prcsid relationship does not have an id, junk is fine
+     * @return
+     * @see 
+     */
+    public ClientResponse<Response> delete(String csid, String prcsid) {
+        return permissionRoleProxy.delete(csid, prcsid);
+    }
+}
diff --git a/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleProxy.java b/services/authorization-mgt/client/src/main/java/org/collectionspace/services/client/PermissionRoleProxy.java
new file mode 100644 (file)
index 0000000..9f9ee1d
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * PermissionRoleProxy.java
+ *
+ * {Purpose of This Class}
+ *
+ * {Other Notes Relating to This Class (Optional)}
+ *
+ * $LastChangedBy: $
+ * $LastChangedRevision: $
+ * $LastChangedDate: $
+ *
+ * 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 (C) 2009 {Contributing Institution}
+ *
+ * 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
+ */
+package org.collectionspace.services.client;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+
+import org.collectionspace.services.authorization.PermissionRole;
+import org.jboss.resteasy.client.ClientResponse;
+
+/**
+ * @version $Revision:$
+ */
+@Path("/authorization/permissions")
+@Produces({"application/xml"})
+@Consumes({"application/xml"})
+public interface PermissionRoleProxy {
+
+    //(C)reate
+    @POST
+    @Path("/{csid}/permroles")
+    ClientResponse<Response> create(@PathParam("csid") String csid, PermissionRole permRole);
+
+    //(R)ead
+    @GET
+    @Path("/{csid}/permroles/{prcsid}")
+    ClientResponse<PermissionRole> read(@PathParam("csid") String csid,
+            @PathParam("prcsid") String prcsid);
+
+    //(D)elete
+    @DELETE
+    @Path("/{csid}/permroles/{prcsid}")
+    ClientResponse<Response> delete(@PathParam("csid") String csid,
+            @PathParam("prcsid") String prcsid);
+}
diff --git a/services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionRoleServiceTest.java b/services/authorization-mgt/client/src/test/java/org/collectionspace/services/authorization/client/test/PermissionRoleServiceTest.java
new file mode 100644 (file)
index 0000000..5db336d
--- /dev/null
@@ -0,0 +1,463 @@
+/**
+ * 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 Â© 2009 Regents of the University of California
+ *
+ * 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 permRoles and
+ * limitations under the License.
+ */
+package org.collectionspace.services.authorization.client.test;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import javax.ws.rs.core.Response;
+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.Role;
+import org.collectionspace.services.client.PermissionClient;
+import org.collectionspace.services.client.PermissionRoleClient;
+import org.collectionspace.services.client.RoleClient;
+import org.collectionspace.services.client.test.AbstractServiceTestImpl;
+import org.collectionspace.services.client.test.ServiceRequestType;
+import org.jboss.resteasy.client.ClientResponse;
+
+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;
+
+/**
+ * PermissionServiceTest, carries out tests against a
+ * deployed and running Permission, Role and PermissionRole Services.
+ * 
+ * $LastChangedRevision: 917 $
+ * $LastChangedDate: 2009-11-06 12:20:28 -0800 (Fri, 06 Nov 2009) $
+ */
+public class PermissionRoleServiceTest extends AbstractServiceTestImpl {
+
+    private final Logger logger =
+            LoggerFactory.getLogger(PermissionRoleServiceTest.class);
+    // Instance variables specific to this test.
+    private PermissionRoleClient client = new PermissionRoleClient();
+    private String knownResourceId = null;
+    private List<String> allResourceIdsCreated = new ArrayList();
+    private Hashtable<String, String> permIds = new Hashtable<String, String>();
+    private Hashtable<String, String> roleIds = new Hashtable<String, String>();
+    /*
+     * This method is called only by the parent class, AbstractServiceTestImpl
+     */
+
+    @Override
+    protected String getServicePathComponent() {
+        return client.getServicePathComponent();
+    }
+
+    @BeforeClass(alwaysRun = true)
+    public void seedData() {
+        String accPermId = createPermission("accounts", EffectType.PERMIT);
+        permIds.put("accounts", accPermId);
+
+        String coPermId = createPermission("collectionobjects", EffectType.DENY);
+        permIds.put("collectionobjects", coPermId);
+
+        String iPermId = createPermission("intakes", EffectType.DENY);
+        permIds.put("intakes", iPermId);
+
+        String r1RoleId = createRole("ROLE_CO1");
+        roleIds.put("ROLE_1", r1RoleId);
+
+        String r2RoleId = createRole("ROLE_CO2");
+        roleIds.put("ROLE_2", r2RoleId);
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : CREATE tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void create(String testName) throws Exception {
+
+        // Perform setup, such as initializing the type of service request
+        // (e.g. CREATE, DELETE), its valid and expected status codes, and
+        // its associated HTTP method name (e.g. POST, DELETE).
+        setupCreate(testName);
+
+        // Submit the request to the service and store the response.
+        PermissionRole permRole = createPermissionRoleInstance(permIds.get("accounts"),
+                roleIds.values().toArray(new String[0]), true, true);
+        ClientResponse<Response> res = client.create(permIds.get("accounts"), permRole);
+        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, EXPECTED_STATUS_CODE);
+
+        // Store the ID returned from this create operation
+        // for additional tests below.
+        //this is is not important in case of this relationship
+        knownResourceId = extractId(res);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": knownResourceId=" + knownResourceId);
+        }
+    }
+
+    //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 {
+
+        setupCreate(testName);
+        // Submit the request to the service and store the response.
+        PermissionRole permRole = createPermissionRoleInstance(permIds.get("collectionobjects"),
+                roleIds.values().toArray(new String[0]), true, true);
+        ClientResponse<Response> res = client.create(permIds.get("collectionobjects"), permRole);
+        int statusCode = res.getStatus();
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        //id of relationship is not important
+        allResourceIdsCreated.add(permIds.get("collectionobjects"));
+
+        PermissionRole permRole2 = createPermissionRoleInstance(permIds.get("intakes"),
+                roleIds.values().toArray(new String[0]), true, true);
+        res = client.create(permIds.get("intakes"), permRole2);
+        statusCode = res.getStatus();
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        //id of relationship is not important
+        allResourceIdsCreated.add(permIds.get("intakes"));
+
+    }
+
+    // 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 {
+
+        // Perform setup.
+        setupRead(testName);
+
+        // Submit the request to the service and store the response.
+        ClientResponse<PermissionRole> res = client.read(permIds.get("accounts"), "123");
+        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);
+
+        PermissionRole output = (PermissionRole) res.getEntity();
+        Assert.assertNotNull(output);
+    }
+
+    // Failure outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void readNonExistent(String testName) throws Exception {
+
+        // Perform setup.
+        setupReadNonExistent(testName);
+
+        // Submit the request to the service and store the response.
+        ClientResponse<PermissionRole> res = client.read(NON_EXISTENT_ID, "123");
+        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);
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : READ_LIST tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"createList", "read"})
+    public void readList(String testName) throws Exception {
+    }
+
+    // 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 {
+    }
+
+    // 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 = {"readNonExistent", "testSubmitRequest"})
+    public void updateNonExistent(String testName) throws Exception {
+    }
+
+    // ---------------------------------------------------------------
+    // CRUD tests : DELETE tests
+    // ---------------------------------------------------------------
+    // Success outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+    dependsOnMethods = {"read"})
+    public void delete(String testName) throws Exception {
+
+        // Perform setup.
+        setupDelete(testName);
+
+        // Submit the request to the service and store the response.
+        ClientResponse<Response> res = client.delete(permIds.get("accounts"), "123");
+        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);
+
+    }
+
+    // Failure outcomes
+    @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
+    public void deleteNonExistent(String testName) throws Exception {
+
+        // Perform setup.
+        setupDeleteNonExistent(testName);
+
+        // Submit the request to the service and store the response.
+        ClientResponse<Response> res = client.delete(NON_EXISTENT_ID, "123");
+        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);
+    }
+
+    // ---------------------------------------------------------------
+    // 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 {
+
+        // Expected status code: 200 OK
+        final int EXPECTED_STATUS = Response.Status.OK.getStatusCode();
+
+        // Submit the request to the service and store the response.
+        String method = ServiceRequestType.READ.httpMethodName();
+        String url = getResourceURL(permIds.get("accounts"));
+        int statusCode = submitRequest(method, url);
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug("testSubmitRequest: url=" + url
+                    + " status=" + statusCode);
+        }
+        Assert.assertEquals(statusCode, EXPECTED_STATUS);
+
+    }
+
+    // ---------------------------------------------------------------
+    // Utility methods used by tests above
+    // ---------------------------------------------------------------
+    /**
+     * create permRolerole instance
+     * @param permId
+     * @param roleIds array of role ids
+     * @param userPermId
+     * @param useRoleId
+     * @return
+     */
+    private PermissionRole createPermissionRoleInstance(String permId,
+            String[] roleIds,
+            boolean usePermId,
+            boolean useRoleId) {
+
+        PermissionRole permRole = new PermissionRole();
+        //service consume is not required to provide subject as it is determined
+        //from URI used
+//        permRole.setSubject(SubjectType.ROLE);
+        if (usePermId) {
+            ArrayList<String> pl = new ArrayList<String>();
+            pl.add(permId);
+            permRole.setPermissionIds(pl);
+        }
+        if (useRoleId) {
+            ArrayList<String> rl = new ArrayList<String>();
+            for (String roleId : roleIds) {
+                rl.add(roleId);
+            }
+            permRole.setRoleIds(rl);
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("to be created, permRole common");
+            logger.debug(objectAsXmlString(permRole, PermissionRole.class));
+        }
+        return permRole;
+    }
+
+    @AfterClass(alwaysRun = true)
+    public void cleanUp() {
+        setupDelete("delete");
+        if (logger.isDebugEnabled()) {
+            logger.debug("Cleaning up temporary resources created for testing ...");
+        }
+        for (String resourceId : allResourceIdsCreated) {
+            // Note: Any non-success responses are ignored and not reported.
+            ClientResponse<Response> res = client.delete(resourceId, "123");
+            int statusCode = res.getStatus();
+            Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                    invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+            Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        }
+
+        for (String permId : permIds.values()) {
+            deletePermission(permId);
+        }
+
+        for (String roleId : roleIds.values()) {
+            deleteRole(roleId);
+        }
+    }
+
+    private String createPermission(String resName, EffectType effect) {
+        setupCreate();
+        PermissionClient permClient = new PermissionClient();
+        List<PermissionAction> actions = PermissionServiceTest.getDefaultActions();
+        Permission permission = PermissionServiceTest.createPermissionInstance(resName,
+                "default permissions for " + resName,
+                actions, EffectType.PERMIT, true, true, true);
+        ClientResponse<Response> res = permClient.create(permission);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("createPermission" + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        return extractId(res);
+    }
+
+    private void deletePermission(String permId) {
+        setupDelete();
+        PermissionClient permClient = new PermissionClient();
+        ClientResponse<Response> res = permClient.delete(permId);
+        int statusCode = res.getStatus();
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
+
+    private String createRole(String roleName) {
+        setupCreate();
+        RoleClient roleClient = new RoleClient();
+
+        Role role = RoleServiceTest.createRoleInstance(roleName,
+                "role for " + roleName, true);
+        ClientResponse<Response> res = roleClient.create(role);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug("createRole" + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        return extractId(res);
+    }
+
+    private void deleteRole(String roleId) {
+        setupDelete();
+        RoleClient roleClient = new RoleClient();
+        ClientResponse<Response> res = roleClient.delete(roleId);
+        int statusCode = res.getStatus();
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+    }
+}
index 3a15e30f4aebfb632dc4d8a4b21fc3e451e76df0..486e4f381b6f2df02ecfc977ac83549d7a4d7e97 100644 (file)
@@ -52,7 +52,7 @@ import org.testng.annotations.AfterClass;
  */
 public class PermissionServiceTest extends AbstractServiceTestImpl {
 
-    private final Logger logger =
+    static private final Logger logger =
             LoggerFactory.getLogger(PermissionServiceTest.class);
     // Instance variables specific to this test.
     private PermissionClient client = new PermissionClient();
@@ -163,8 +163,8 @@ public class PermissionServiceTest extends AbstractServiceTestImpl {
         Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
         allResourceIdsCreated.add(extractId(res));
 
-        Permission permission2 = createPermissionInstance("intakes",
-                "default permissions for intakes",
+        Permission permission2 = createPermissionInstance("acquisitions",
+                "default permissions for acquisitions",
                 actions,
                 EffectType.PERMIT,
                 true,
@@ -300,7 +300,7 @@ public class PermissionServiceTest extends AbstractServiceTestImpl {
         setupReadList(testName);
 
         // Submit the request to the service and store the response.
-        ClientResponse<PermissionsList> res = client.readSearchList("intake");
+        ClientResponse<PermissionsList> res = client.readSearchList("acquisition");
         PermissionsList list = res.getEntity();
         int statusCode = res.getStatus();
         // Check the status code of the response: does it match
@@ -409,8 +409,8 @@ public class PermissionServiceTest extends AbstractServiceTestImpl {
         // Note: The ID used in this 'create' call may be arbitrary.
         // The only relevant ID may be the one used in updatePermission(), below.
         List<PermissionAction> actions = getDefaultActions();
-        Permission permission = createPermissionInstance("intakes",
-                "default permissions for intakes",
+        Permission permission = createPermissionInstance("acquisitions",
+                "default permissions for acquisitions",
                 actions,
                 EffectType.PERMIT,
                 true,
@@ -521,7 +521,7 @@ public class PermissionServiceTest extends AbstractServiceTestImpl {
      * @param useEffect
      * @return
      */
-    private Permission createPermissionInstance(String resourceName,
+    static Permission createPermissionInstance(String resourceName,
             String description,
             List<PermissionAction> actionList,
             EffectType effect,
@@ -548,7 +548,7 @@ public class PermissionServiceTest extends AbstractServiceTestImpl {
         return permission;
     }
 
-    private List<PermissionAction> getDefaultActions() {
+    static List<PermissionAction> getDefaultActions() {
         List<PermissionAction> actions = new ArrayList<PermissionAction>();
         PermissionAction create = new PermissionAction();
         create.setName(ActionType.CREATE);
index 59e085de749a1a4796097ca70d2be74c64a72d24..6616b18b61e766ab1ffc0faa89e80b6563ebcfd4 100644 (file)
@@ -49,7 +49,7 @@ import org.testng.annotations.AfterClass;
  */
 public class RoleServiceTest extends AbstractServiceTestImpl {
 
-    private final Logger logger =
+    static private final Logger logger =
             LoggerFactory.getLogger(RoleServiceTest.class);
     // Instance variables specific to this test.
     private RoleClient client = new RoleClient();
@@ -509,7 +509,7 @@ public class RoleServiceTest extends AbstractServiceTestImpl {
      * @param useRoleName
      * @return
      */
-    private Role createRoleInstance(String roleName,
+    static Role createRoleInstance(String roleName,
             String description,
             boolean useRoleName) {
 
index 37a0f0a33896afd828fdd10f0d803b5ff7b56b78..88ccc3970cae30a25767e55dc954ebf520638c16 100644 (file)
@@ -299,4 +299,140 @@ public class PermissionResource
         }
 
     }
+
+    @POST
+    @Path("{csid}/permroles")
+    public Response createPermissionRole(@PathParam("csid") String permCsid,
+            PermissionRole input) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("createPermissionRole with permCsid=" + permCsid);
+        }
+        if (permCsid == null || "".equals(permCsid)) {
+            logger.error("createPermissionRole: missing permCsid!");
+            Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                    "create failed on PermissionRole permCsid=" + permCsid).type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        try {
+            PermissionRoleSubResource subResource = new PermissionRoleSubResource();
+            String permrolecsid = subResource.createPermissionRole(input, SubjectType.ROLE);
+            UriBuilder path = UriBuilder.fromResource(PermissionResource.class);
+            path.path(permCsid + "/permroles/" + permrolecsid);
+            Response response = Response.created(path.build()).build();
+            return response;
+        } catch (BadRequestException bre) {
+            Response response = Response.status(
+                    Response.Status.BAD_REQUEST).entity("Create failed reason "
+                    + bre.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (UnauthorizedException ue) {
+            Response response = Response.status(
+                    Response.Status.UNAUTHORIZED).entity("Create failed reason "
+                    + ue.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception in createPermissionRole", e);
+            }
+            Response response = Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).entity(
+                    "Create failed").type("text/plain").build();
+            throw new WebApplicationException(response);
+        }
+    }
+
+    @GET
+    @Path("{csid}/permroles/{permrolecsid}")
+    public PermissionRole getPermissionRole(
+            @PathParam("csid") String permCsid,
+            @PathParam("permrolecsid") String permrolecsid) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("getPermissionRole with permCsid=" + permCsid);
+        }
+        if (permCsid == null || "".equals(permCsid)) {
+            logger.error("getPermissionRole: missing permCsid!");
+            Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                    "get failed on PermissionRole permCsid=" + permCsid).type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        PermissionRole result = null;
+        try {
+            PermissionRoleSubResource subResource = new PermissionRoleSubResource();
+            //get relationships for a permission
+            result = subResource.getPermissionRole(permCsid, SubjectType.ROLE);
+        } catch (UnauthorizedException ue) {
+            Response response = Response.status(
+                    Response.Status.UNAUTHORIZED).entity("Get failed reason "
+                    + ue.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (DocumentNotFoundException dnfe) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("getPermissionRole", dnfe);
+            }
+            Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                    "Get failed on PermissionRole permrolecsid=" + permrolecsid).type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("getPermissionRole", e);
+            }
+            Response response = Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).entity(
+                    "Get failed").type("text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        if (result == null) {
+            Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                    "Get failed, the requested PermissionRole permrolecsid:" + permrolecsid
+                    + ": was not found.").type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        return result;
+    }
+
+    @DELETE
+    @Path("{csid}/permroles/{permrolecsid}")
+    public Response deletePermissionRole(
+            @PathParam("csid") String permCsid,
+            @PathParam("permrolecsid") String permrolecsid) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("deletePermissionRole with permCsid=" + permCsid);
+        }
+        if (permCsid == null || "".equals(permCsid)) {
+            logger.error("deletePermissionRole: missing permCsid!");
+            Response response = Response.status(Response.Status.BAD_REQUEST).entity(
+                    "delete failed on PermissionRole permCsid=" + permCsid).type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        }
+        try {
+            PermissionRoleSubResource subResource = new PermissionRoleSubResource();
+            //delete all relationships for a permission
+            subResource.deletePermissionRole(permCsid, SubjectType.ROLE);
+            return Response.status(HttpResponseCodes.SC_OK).build();
+        } catch (UnauthorizedException ue) {
+            Response response = Response.status(
+                    Response.Status.UNAUTHORIZED).entity("Delete failed reason "
+                    + ue.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (DocumentNotFoundException dnfe) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("caught exception in deletePermissionRole", dnfe);
+            }
+            Response response = Response.status(Response.Status.NOT_FOUND).entity(
+                    "Delete failed on PermissionRole permrolecsid=" + permrolecsid).type(
+                    "text/plain").build();
+            throw new WebApplicationException(response);
+        } catch (Exception e) {
+            Response response = Response.status(
+                    Response.Status.INTERNAL_SERVER_ERROR).entity(
+                    "Delete failed").type("text/plain").build();
+            throw new WebApplicationException(response);
+        }
+
+    }
 }
diff --git a/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionRoleSubResource.java b/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/PermissionRoleSubResource.java
new file mode 100644 (file)
index 0000000..2b59ec2
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ *  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 2009 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.
+ */
+package org.collectionspace.services.authorization;
+
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+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;
+import org.collectionspace.services.authorization.storage.PermissionRoleStorageClient;
+
+import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
+import org.collectionspace.services.common.context.RemoteServiceContextImpl;
+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.StorageClient;
+import org.jboss.resteasy.util.HttpResponseCodes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * PermissionRoleSubResource is used to manage permission-role relationship
+ * @author
+ */
+public class PermissionRoleSubResource
+        extends AbstractCollectionSpaceResourceImpl {
+
+    //this service is never exposed as standalone RESTful service...just use unique
+    //service name to identify binding
+    final private String serviceName = "authorization/permroles";
+    final Logger logger = LoggerFactory.getLogger(PermissionRoleSubResource.class);
+    final StorageClient storageClient = new PermissionRoleStorageClient();
+
+    @Override
+    protected String getVersionString() {
+        /** The last change revision. */
+        final String lastChangeRevision = "$LastChangedRevision: 1165 $";
+        return lastChangeRevision;
+    }
+
+    @Override
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    private <T> ServiceContext createServiceContext(T obj, SubjectType subject) throws Exception {
+        ServiceContext ctx = new RemoteServiceContextImpl<T, T>(getServiceName());
+        ctx.setInput(obj);
+        ctx.setDocumentType(PermissionRole.class.getPackage().getName()); //persistence unit
+        ctx.setProperty("entity-name", PermissionRoleRel.class.getName());
+        //subject name is necessary to indicate if role or permission is a subject
+        ctx.setProperty("subject", subject);
+        return ctx;
+    }
+
+    @Override
+    public StorageClient getStorageClient(ServiceContext ctx) {
+        //FIXME use ctx to identify storage client
+        return storageClient;
+    }
+
+    @Override
+    public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
+        DocumentHandler docHandler = ctx.getDocumentHandler();
+        docHandler.setCommonPart(ctx.getInput());
+        return docHandler;
+    }
+
+    /**
+     * createPermissionRole creates one or more permission-role relationships
+     * between object (permission/role) and subject (role/permission)
+     * @param input
+     * @param subject
+     * @return
+     * @throws Exception
+     */
+    public String createPermissionRole(PermissionRole input, SubjectType subject)
+            throws Exception {
+
+        ServiceContext ctx = createServiceContext(input, subject);
+        DocumentHandler handler = createDocumentHandler(ctx);
+        return getStorageClient(ctx).create(ctx, handler);
+    }
+
+    /**
+     * getPermissionRole retrieves permission-role relationships using given
+     * csid of object (permission/role) and subject (role/permission)
+     * @param csid
+     * @param subject
+     * @return
+     * @throws Exception
+     */
+    public PermissionRole getPermissionRole(
+            String csid, SubjectType subject) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("getPermissionRole with csid=" + csid);
+        }
+        PermissionRole result = null;
+        ServiceContext ctx = createServiceContext((PermissionRole) null, subject);
+        DocumentHandler handler = createDocumentHandler(ctx);
+        getStorageClient(ctx).get(ctx, csid, handler);
+        result = (PermissionRole) ctx.getOutput();
+
+        return result;
+    }
+
+    /**
+     * deletePermissionRole deletes permission-role relationships using given
+     * csid of object (permission/role) and subject (role/permission)
+     * @param csid
+     * @param subject
+     * @return
+     * @throws Exception
+     */
+    public void deletePermissionRole(String csid,
+            SubjectType subject) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("deletePermissionRole with csid=" + csid);
+        }
+        ServiceContext ctx = createServiceContext((PermissionRole) null, subject);
+        getStorageClient(ctx).delete(ctx, csid);
+    }
+}
diff --git a/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleDocumentHandler.java b/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleDocumentHandler.java
new file mode 100644 (file)
index 0000000..8bd86ea
--- /dev/null
@@ -0,0 +1,180 @@
+/**
+ *  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 2009 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 permissionRoles and
+ *  limitations under the License.
+ */
+package org.collectionspace.services.authorization.storage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.collectionspace.services.authorization.PermissionRole;
+import org.collectionspace.services.authorization.PermissionRoleRel;
+import org.collectionspace.services.authorization.PermissionsRolesList;
+import org.collectionspace.services.authorization.SubjectType;
+import org.collectionspace.services.common.context.ServiceContext;
+
+import org.collectionspace.services.common.document.AbstractDocumentHandlerImpl;
+import org.collectionspace.services.common.document.DocumentFilter;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Document handler for PermissionRole association
+ * @author 
+ */
+public class PermissionRoleDocumentHandler
+        extends AbstractDocumentHandlerImpl<PermissionRole, PermissionsRolesList, List<PermissionRoleRel>, List<PermissionRoleRel>> {
+
+    private final Logger logger = LoggerFactory.getLogger(PermissionRoleDocumentHandler.class);
+    private PermissionRole permissionRole;
+    private PermissionsRolesList permissionRolesList;
+
+    @Override
+    public void handleCreate(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+        fillCommonPart(getCommonPart(), wrapDoc);
+    }
+
+    @Override
+    public void handleUpdate(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+        throw new UnsupportedOperationException("operation not relevant for PermissionRoleDocumentHandler");
+    }
+
+    @Override
+    public void completeUpdate(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+        throw new UnsupportedOperationException("operation not relevant for PermissionRoleDocumentHandler");
+    }
+
+    @Override
+    public void handleGet(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+        setCommonPart(extractCommonPart(wrapDoc));
+        getServiceContext().setOutput(permissionRole);
+    }
+
+    @Override
+    public void handleGetAll(DocumentWrapper<List<PermissionRoleRel>> wrapDoc) throws Exception {
+        throw new UnsupportedOperationException("operation not relevant for PermissionRoleDocumentHandler");
+    }
+
+    @Override
+    public PermissionRole extractCommonPart(
+            DocumentWrapper<List<PermissionRoleRel>> wrapDoc)
+            throws Exception {
+        List<PermissionRoleRel> prrl = wrapDoc.getWrappedObject();
+        PermissionRole pr = new PermissionRole();
+        SubjectType subject = PermissionRoleUtil.getSubject(getServiceContext());
+        pr.setSubject(subject);
+        if (SubjectType.ROLE.equals(subject)) {
+            List<String> permIds = new ArrayList<String>();
+            permIds.add(prrl.get(0).getPermissionId());
+            pr.setPermissionIds(permIds);
+            List<String> roleIds = new ArrayList<String>();
+            for (PermissionRoleRel prr : prrl) {
+                roleIds.add(prr.getRoleId());
+                pr.setCreatedAt(prr.getCreatedAt());
+                pr.setUpdatedAt(prr.getUpdatedAt());
+            }
+            pr.setRoleIds(roleIds);
+        } else {
+            List<String> roleIds = new ArrayList<String>();
+            roleIds.add(prrl.get(0).getRoleId());
+            pr.setRoleIds(roleIds);
+            List<String> permIds = new ArrayList<String>();
+            for (PermissionRoleRel prr : prrl) {
+                permIds.add(prr.getPermissionId());
+                pr.setCreatedAt(prr.getCreatedAt());
+                pr.setUpdatedAt(prr.getUpdatedAt());
+            }
+            pr.setPermissionIds(permIds);
+        }
+        return pr;
+    }
+
+    @Override
+    public void fillCommonPart(PermissionRole pr, DocumentWrapper<List<PermissionRoleRel>> wrapDoc)
+            throws Exception {
+        List<PermissionRoleRel> prrl = wrapDoc.getWrappedObject();
+        SubjectType subject = pr.getSubject();
+        if (subject == null) {
+            //it is not required to give subject as URI determines the subject
+            subject = PermissionRoleUtil.getSubject(getServiceContext());
+        } else {
+            //subject mismatch should have been checked during validation
+        }
+        if (subject.equals(SubjectType.ROLE)) {
+            String permId = pr.getPermissionIds().get(0);
+            for (String roleId : pr.getRoleIds()) {
+                PermissionRoleRel prr = new PermissionRoleRel();
+                prr.setPermissionId(permId);
+                prr.setRoleId(roleId);
+                prrl.add(prr);
+            }
+        } else {
+            String roleId = pr.getRoleIds().get(0);
+            for (String permId : pr.getPermissionIds()) {
+                PermissionRoleRel prr = new PermissionRoleRel();
+                prr.setPermissionId(permId);
+                prr.setRoleId(roleId);
+                prrl.add(prr);
+            }
+        }
+    }
+
+    @Override
+    public PermissionsRolesList extractCommonPartList(
+            DocumentWrapper<List<PermissionRoleRel>> wrapDoc)
+            throws Exception {
+
+        throw new UnsupportedOperationException("operation not relevant for PermissionRoleDocumentHandler");
+    }
+
+    @Override
+    public PermissionRole getCommonPart() {
+        return permissionRole;
+    }
+
+    @Override
+    public void setCommonPart(PermissionRole permissionRole) {
+        this.permissionRole = permissionRole;
+    }
+
+    @Override
+    public PermissionsRolesList getCommonPartList() {
+        return permissionRolesList;
+    }
+
+    @Override
+    public void setCommonPartList(PermissionsRolesList permissionRolesList) {
+        this.permissionRolesList = permissionRolesList;
+    }
+
+    @Override
+    public String getQProperty(
+            String prop) {
+        return null;
+    }
+
+    @Override
+    public DocumentFilter createDocumentFilter(ServiceContext ctx) {
+        return new DocumentFilter();
+    }
+}
diff --git a/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleStorageClient.java b/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleStorageClient.java
new file mode 100644 (file)
index 0000000..20c1b82
--- /dev/null
@@ -0,0 +1,277 @@
+/**
+ *  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 2009 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.
+ */
+package org.collectionspace.services.authorization.storage;
+
+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.Query;
+import org.collectionspace.services.authorization.PermissionRoleRel;
+import org.collectionspace.services.authorization.SubjectType;
+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.DocumentHandler;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+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.storage.jpa.JpaStorageClientImpl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * PermissionRoleStorageClient deals with PermissionRole relationship
+ * in persistent storage. This storage client deals with bulk operations, i.e.
+ * create/post inserts multiple tuples between the given object and subjects
+ * get retrieves all subjects for the given object in relationship
+ * delete deletes all subjects for the given object in relationship
+ * @author 
+ */
+public class PermissionRoleStorageClient extends JpaStorageClientImpl {
+
+    private final Logger logger = LoggerFactory.getLogger(PermissionRoleStorageClient.class);
+
+    public PermissionRoleStorageClient() {
+    }
+
+    /**
+     * create of PermissionRole relationship creates one or more relationships between
+     * permission and role
+     * the object and subjects of the relationship is chosen (by doc handler) from
+     * the payload
+     * @param ctx
+     * @param handler
+     * @return
+     * @throws BadRequestException
+     * @throws DocumentException
+     */
+    @Override
+    public String create(ServiceContext ctx,
+            DocumentHandler handler) throws BadRequestException,
+            DocumentException {
+
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "PermissionRoleStorageClient.create : ctx is missing");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException(
+                    "PermissionRoleStorageClient.create: handler is missing");
+        }
+        EntityManagerFactory emf = null;
+        EntityManager em = null;
+        try {
+            handler.prepare(Action.CREATE);
+            List<PermissionRoleRel> prrl = new ArrayList<PermissionRoleRel>();
+            DocumentWrapper<List<PermissionRoleRel>> wrapDoc =
+                    new DocumentWrapperImpl<List<PermissionRoleRel>>(prrl);
+            handler.handle(Action.CREATE, wrapDoc);
+            emf = getEntityManagerFactory();
+            em = emf.createEntityManager();
+            em.getTransaction().begin();
+            for (PermissionRoleRel prr : prrl) {
+                prr.setCreatedAtItem(new Date());
+                em.persist(prr);
+            }
+            em.getTransaction().commit();
+            handler.complete(Action.CREATE, wrapDoc);
+            return UUID.randomUUID().toString(); //filler, not useful
+        } catch (BadRequestException bre) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            throw bre;
+        } catch (Exception e) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception ", e);
+            }
+            throw new DocumentException(e);
+        } finally {
+            if (em != null) {
+                releaseEntityManagerFactory(emf);
+            }
+        }
+    }
+
+    /**
+     * get retrieves all relationships for the object in the relationship
+     * identified by the id. the object could be a permission or a role
+     * @param ctx
+     * @param id of the object in the relationship
+     * @param handler
+     * @throws DocumentNotFoundException
+     * @throws DocumentException
+     */
+    public void get(ServiceContext ctx, String id, DocumentHandler handler)
+            throws DocumentNotFoundException, DocumentException {
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.get: ctx is missing");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.get: handler is missing");
+        }
+        DocumentFilter docFilter = handler.getDocumentFilter();
+        if (docFilter == null) {
+            docFilter = handler.createDocumentFilter(ctx);
+        }
+        EntityManagerFactory emf = null;
+        EntityManager em = null;
+        try {
+            handler.prepare(Action.GET);
+            StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
+            queryStrBldr.append(getEntityName(ctx));
+            queryStrBldr.append(" a");
+            SubjectType subject = PermissionRoleUtil.getSubject(ctx);
+            String objectId = "permission_id";
+            if (SubjectType.PERMISSION.equals(subject)) {
+                objectId = "role_id";
+            }
+            queryStrBldr.append(" WHERE " + objectId + " = :objectId");
+            String where = docFilter.getWhereClause();
+            if ((null != where) && (where.length() > 0)) {
+                queryStrBldr.append(" AND " + where);
+            }
+            emf = getEntityManagerFactory();
+            em = emf.createEntityManager();
+            String queryStr = queryStrBldr.toString(); //for debugging
+            Query q = em.createQuery(queryStr);
+            q.setParameter("objectId", id);
+
+            List<PermissionRoleRel> prrl = new ArrayList<PermissionRoleRel>();
+            try {
+                //require transaction for get?
+                em.getTransaction().begin();
+                prrl = q.getResultList();
+                em.getTransaction().commit();
+            } catch (NoResultException nre) {
+                if (em != null && em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+                String msg = "could not find entity with id=" + id;
+                logger.error(msg, nre);
+                throw new DocumentNotFoundException(msg, nre);
+            }
+            if (prrl.size() == 0) {
+                String msg = "could not find entity with id=" + id;
+                logger.error(msg);
+                throw new DocumentNotFoundException(msg);
+            }
+            DocumentWrapper<List<PermissionRoleRel>> wrapDoc =
+                    new DocumentWrapperImpl<List<PermissionRoleRel>>(prrl);
+            handler.handle(Action.GET, wrapDoc);
+            handler.complete(Action.GET, wrapDoc);
+        } catch (DocumentException de) {
+            throw de;
+        } catch (Exception e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Caught exception ", e);
+            }
+            throw new DocumentException(e);
+        } finally {
+            if (emf != null) {
+                releaseEntityManagerFactory(emf);
+            }
+        }
+    }
+
+    /**
+     * delete removes all the relationships for the object in the relationship
+     * identified by the id. the object could be a permission or a role
+     * @param ctx
+     * @param id of the object in the relationship
+     * @throws DocumentNotFoundException
+     * @throws DocumentException
+     */
+    @Override
+    public void delete(ServiceContext ctx, String id)
+            throws DocumentNotFoundException,
+            DocumentException {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("deleting entity with id=" + id);
+        }
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "PermissionRoleStorageClient.delete : ctx is missing");
+        }
+        EntityManagerFactory emf = null;
+        EntityManager em = null;
+        try {
+            StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
+            deleteStr.append(getEntityName(ctx));
+            SubjectType subject = PermissionRoleUtil.getSubject(ctx);
+            String objectId = "permission_id";
+            if (SubjectType.PERMISSION.equals(subject)) {
+                objectId = "role_id";
+            }
+            deleteStr.append(" WHERE " + objectId + " = :objectId");
+            emf = getEntityManagerFactory();
+            em = emf.createEntityManager();
+            Query q = em.createQuery(deleteStr.toString());
+            q.setParameter("objectId", id);
+            int rcount = 0;
+            em.getTransaction().begin();
+            rcount = q.executeUpdate();
+            if (rcount == 0) {
+                if (em != null && em.getTransaction().isActive()) {
+                    em.getTransaction().rollback();
+                }
+                String msg = "could not find entity with id=" + id;
+                logger.error(msg);
+                throw new DocumentNotFoundException(msg);
+            }
+            em.getTransaction().commit();
+
+        } catch (DocumentException de) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            throw de;
+        } catch (Exception e) {
+            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) {
+                releaseEntityManagerFactory(emf);
+            }
+        }
+    }
+}
diff --git a/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java b/services/authorization-mgt/service/src/main/java/org/collectionspace/services/authorization/storage/PermissionRoleUtil.java
new file mode 100644 (file)
index 0000000..6121b51
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ *  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 2009 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.
+ */
+package org.collectionspace.services.authorization.storage;
+
+import org.collectionspace.services.authorization.SubjectType;
+import org.collectionspace.services.common.context.ServiceContext;
+
+/**
+ *
+ * @author 
+ */
+public class PermissionRoleUtil {
+
+    static SubjectType getSubject(ServiceContext ctx) {
+        Object o = ctx.getProperty("subject");
+        if (o == null) {
+            throw new IllegalArgumentException("property subject missing in context "
+                    + ctx.toString());
+        }
+        return (SubjectType) o;
+    }
+}
index 94c696b4eb1d9711e1fef79e369eca7a43725115..d0ed3f16157ba5ec7f8f00bd2f3bd726edab64cd 100644 (file)
@@ -11,7 +11,7 @@
 -->
 
 <xs:schema 
-xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
     xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
     xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
@@ -92,7 +92,7 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema"
                 </xs:annotation>
             </xs:element>
             <xs:element name="action" type="permission_action" minOccurs="1" maxOccurs="unbounded"/>
-            <xs:element name="effect" type="EffectType" minOccurs="1" maxOccurs="1">
+            <xs:element name="effect" type="effect_type" minOccurs="1" maxOccurs="1">
                 <xs:annotation>
                     <xs:appinfo>
                         <hj:basic>
@@ -150,7 +150,7 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema"
             </xs:appinfo>
         </xs:annotation>
         <xs:sequence>
-            <xs:element name="name" type="ActionType" minOccurs="1">
+            <xs:element name="name" type="action_type" minOccurs="1">
                 <xs:annotation>
                     <xs:appinfo>
                         <hj:basic>
@@ -162,7 +162,7 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema"
         </xs:sequence>
     </xs:complexType>
 
-    <xs:simpleType name = "ActionType">
+    <xs:simpleType name = "action_type">
         <xs:restriction base = "xs:string">
             <xs:enumeration value = "CREATE"/>
             <xs:enumeration value = "READ"/>
@@ -176,7 +176,7 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema"
         </xs:restriction>
     </xs:simpleType>
 
-    <xs:simpleType name = "EffectType">
+    <xs:simpleType name = "effect_type">
         <xs:restriction base = "xs:string">
             <xs:enumeration value = "PERMIT"/>
             <xs:enumeration value = "DENY"/>
index 492d64d6df237e3402ef54ee241cdb3233f4f7a1..5d00ac2a01c93b7a125a1920dd8b1fabae2b0b2b 100644 (file)
@@ -3,23 +3,25 @@
 <!--
     CollectionSpace default (security) authorization provider schema (XSD)
 
-    Entity(s)  : permissions_roles
+    Entity(s)  : permissions_roles association
     Used for:
 
     $LastChangedRevision: 916 $
     $LastChangedDate: 2009-11-05 16:59:20 -0800 (Thu, 05 Nov 2009) $
 -->
 
-<xs:schema 
+<xs:schema
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+    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="http://collectionspace.org/services/authorization"
     targetNamespace="http://collectionspace.org/services/authorization"
     version="0.1"
-    jaxb:extensionBindingPrefixes="hj orm"
+    jaxb:version="1.0"
+    jaxb:extensionBindingPrefixes="hj orm xjc"
     >
 
     <!--
     hbm2ddl makes column length >= 256 as long text, such as column cannot be used
     in defining a key (pk, fk or constraint)
     -->
+    <!--xs:annotation>
+    Note that roles.xsd already defines global bindings for the authorization namespace
+    so, it is not necessary to give the bindingings here because all the xsds are compiled
+    at once for this namespace
+        <xs:appinfo>
+            <jaxb:globalBindings>
+                <xjc:simple />
+            </jaxb:globalBindings>
+        </xs:appinfo>
+    </xs:annotation-->
+
     <xs:element name="permissions_roles_list">
         <xs:complexType>
             <xs:annotation>
+                <xs:documentation>
+                    A list of permission_role association for a permission or a role
+                </xs:documentation>
                 <xs:appinfo>
                     <hj:ignored/>
                 </xs:appinfo>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
-    
+
+
+    <xs:element name="permission_role" type="permission_role"/>
     <xs:complexType name="permission_role">
         <xs:annotation>
-            <xs:documentation>PermissionRole defines association between permission and role in CollectionSpace</xs:documentation>
+            <xs:documentation>
+                PermissionRole defines 1-n association between
+                either permission and role or role and permission
+            </xs:documentation>
+            <xs:appinfo>
+                <hj:ignored/>
+            </xs:appinfo>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="subject" type="subject_type" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="permissionId" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
+            <xs:element name="roleId" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
+            <xs:element name="createdAt" type="xs:dateTime"/>
+            <xs:element name="updatedAt" type="xs:dateTime"/>
+        </xs:sequence>
+    </xs:complexType>
+
+
+    <xs:simpleType name="subject_type">
+        <xs:restriction base = "xs:string">
+            <xs:enumeration value = "PERMISSION"/>
+            <xs:enumeration value = "ROLE"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="permission_role_rel">
+        <xs:annotation>
+            <xs:documentation>
+                PermissionRoleRel defines 1-1 association between
+                permission and role in CollectionSpace. Note that this relation 
+                is defined exclusively for service-side use only.
+            </xs:documentation>
             <xs:appinfo>
                 <hj:entity>
                     <orm:table name="permissions_roles">
index 745d139b364fe261d3dc3abc37d463117063643b..b9337bddaf70332b2c95f294943c9282d7c38f72 100644 (file)
     $LastChangedDate: 2009-11-05 16:59:20 -0800 (Thu, 05 Nov 2009) $
 -->
 
-<xs:schema 
+<xs:schema
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+    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="http://collectionspace.org/services/authorization"
     targetNamespace="http://collectionspace.org/services/authorization"
     version="0.1"
-    jaxb:extensionBindingPrefixes="hj orm"
+    jaxb:version="1.0"
+    jaxb:extensionBindingPrefixes="hj orm xjc"
     >
 
     <!--
     hbm2ddl makes column length >= 256 as long text, such as column cannot be used
     in defining a key (pk, fk or constraint)
     -->
-    <xs:element name="users_roles_list" >
-        <xs:complexType>
-            <xs:annotation>
-                <xs:appinfo>
-                    <hj:ignored/>
-                </xs:appinfo>
-            </xs:annotation>
-            <xs:sequence>
-                <xs:annotation>
-                    <xs:documentation>user role list</xs:documentation>
-                </xs:annotation>
-                <xs:element name="userRole" type="user_role" minOccurs="1" maxOccurs="unbounded"/>
-            </xs:sequence>
-        </xs:complexType>
-    </xs:element>
+    <!--xs:annotation>
+    Note that roles.xsd already defines global bindings for the authorization namespace
+    so, it is not necessary to give the bindingings here because all the xsds are compiled
+    at once for this namespace
+        <xs:appinfo>
+            <jaxb:globalBindings>
+                <xjc:simple />
+            </jaxb:globalBindings>
+        </xs:appinfo>
+    </xs:annotation-->
 
+    <xs:element name="user_role" type="user_role"/>
     <xs:complexType name="user_role">
         <xs:annotation>
             <xs:documentation>UserRole defines association between user and role in CollectionSpace</xs:documentation>
         </xs:sequence>
     </xs:complexType>
 
+    <xs:element name="users_roles_list" >
+        <xs:complexType>
+            <xs:annotation>
+                <xs:documentation>users roles list</xs:documentation>
+                <xs:appinfo>
+                    <hj:ignored/>
+                </xs:appinfo>
+            </xs:annotation>
+            <xs:sequence>
+                <xs:annotation>
+                    <xs:documentation>account role list</xs:documentation>
+                </xs:annotation>
+                <xs:element name="userRole" type="user_role" minOccurs="1" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
 
 
 </xs:schema>
index ed8a21fafe4777efa838cc95c136b85b74129ec5..18d7e06bf3682c6e4d370a09bd7fed4e2a203f84 100644 (file)
@@ -4,13 +4,9 @@
     <persistence-unit name="org.collectionspace.services.authorization">
         <class>org.collectionspace.services.authorization.Permission</class>
         <class>org.collectionspace.services.authorization.PermissionAction</class>
-        <class>org.collectionspace.services.authorization.PermissionsList</class>
-        <class>org.collectionspace.services.authorization.PermissionRole</class>
-        <class>org.collectionspace.services.authorization.PermissionsRolesList</class>
+        <class>org.collectionspace.services.authorization.PermissionRoleRel</class>
         <class>org.collectionspace.services.authorization.Role</class>
-        <class>org.collectionspace.services.authorization.RolesList</class>
         <class>org.collectionspace.services.authorization.UserRole</class>
-        <class>org.collectionspace.services.authorization.UsersRolesList</class>
         <properties>
             <property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml"/>
 
index 13547bb7659f9f91558c14795de2e63416124140..5a116808139263d5ca258664e6e9580be56ad493 100644 (file)
@@ -108,14 +108,15 @@ public class AuthZ {
             List<PermissionRole> permRoles) {
         List<String> principals = new ArrayList<String>();
         for (PermissionRole permRole : permRoles) {
-            if (!perm.getCsid().equals(permRole.getPermissionId())) {
+            if (!perm.getCsid().equals(permRole.getPermissionIds().get(0))) {
                 throw new IllegalArgumentException("permission ids do not"
-                        + " match role=" + permRole.getRoleId()
-                        + " permission=" + perm.getCsid());
+                        + " match for role=" + permRole.getRoleIds().get(0)
+                        + " with permissionId=" + permRole.getPermissionIds().get(0)
+                        + " for permission with csid=" + perm.getCsid());
             }
             //assuming permrole belongs to the same perm
             //FIXME should use role name
-            principals.add(permRole.getRoleId());
+            principals.add(permRole.getRoleIds().get(0));
         }
         List<PermissionAction> permActions = perm.getActions();
         for (PermissionAction permAction : permActions) {
index f8364c9fc88d0b27517fda769af6de7d894a9427..259ae39c7891a6521ed564d1be9f306cccc644ee 100644 (file)
 package org.collectionspace.services.authorization.test;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.InputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.HashSet;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
-import org.collectionspace.services.authorization.ActionType;
 import org.collectionspace.services.authorization.AuthZ;
-import org.collectionspace.services.authorization.Permission;
-import org.collectionspace.services.authorization.EffectType;
-import org.collectionspace.services.authorization.PermissionAction;
-import org.collectionspace.services.authorization.PermissionsList;
-import org.collectionspace.services.authorization.PermissionRole;
-import org.collectionspace.services.authorization.PermissionsList;
-import org.collectionspace.services.authorization.PermissionsRolesList;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
@@ -77,7 +69,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.DefaultTransactionDefinition;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -89,6 +80,7 @@ public abstract class AbstractAuthorizationTestImpl {
 
     final Logger logger = LoggerFactory.getLogger(AbstractAuthorizationTestImpl.class);
     private org.springframework.jdbc.datasource.DataSourceTransactionManager txManager;
+    final static String testDataDir = "src/test/resources/test-data/";
 
     /**
      * Returns the name of the currently running test.
@@ -107,7 +99,6 @@ public abstract class AbstractAuthorizationTestImpl {
                 };
     }
 
-
     protected void setup() {
         ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
                 new String[]{"applicationContext-authorization-test.xml"});
@@ -144,8 +135,7 @@ public abstract class AbstractAuthorizationTestImpl {
         txManager.commit(status);
     }
 
-
-    protected void toFile(Object o, Class jaxbClass, String fileName) {
+    static void toFile(Object o, Class jaxbClass, String fileName) {
         File f = new File(fileName);
         try {
             JAXBContext jc = JAXBContext.newInstance(jaxbClass);
@@ -158,14 +148,22 @@ public abstract class AbstractAuthorizationTestImpl {
         }
     }
 
-    protected Object fromFile(Class jaxbClass, String fileName) throws Exception {
-        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
-        InputStream is = tccl.getResourceAsStream(fileName);
-        JAXBContext context = JAXBContext.newInstance(jaxbClass);
-        Unmarshaller unmarshaller = context.createUnmarshaller();
-        //note: setting schema to null will turn validator off
-        unmarshaller.setSchema(null);
-        return jaxbClass.cast(unmarshaller.unmarshal(is));
+    static Object fromFile(Class jaxbClass, String fileName) throws Exception {
+        InputStream is = new FileInputStream(fileName);
+        try {
+            JAXBContext context = JAXBContext.newInstance(jaxbClass);
+            Unmarshaller unmarshaller = context.createUnmarshaller();
+            //note: setting schema to null will turn validator off
+            unmarshaller.setSchema(null);
+            return jaxbClass.cast(unmarshaller.unmarshal(is));
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (Exception e) {
+                }
+            }
+        }
     }
 
     @Test(dataProvider = "testName", dataProviderClass = AbstractAuthorizationTestImpl.class)
@@ -48,6 +48,7 @@ package org.collectionspace.services.authorization.test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.ArrayList;
+import java.util.List;
 import org.collectionspace.services.authorization.ActionType;
 import org.collectionspace.services.authorization.Permission;
 import org.collectionspace.services.authorization.EffectType;
@@ -55,17 +56,16 @@ import org.collectionspace.services.authorization.PermissionAction;
 import org.collectionspace.services.authorization.PermissionRole;
 import org.collectionspace.services.authorization.PermissionsList;
 import org.collectionspace.services.authorization.PermissionsRolesList;
-import org.testng.annotations.Test;
+import org.collectionspace.services.authorization.SubjectType;
 
 /**
  *
  * @author 
  */
-public class AuthorizationGenTest extends AbstractAuthorizationTestImpl {
+public class AuthorizationGen {
 
-    final Logger logger = LoggerFactory.getLogger(AuthorizationGenTest.class);
+    final Logger logger = LoggerFactory.getLogger(AuthorizationGen.class);
 
-    @Test
     public void genPermissions() {
         PermissionsList pcList = new PermissionsList();
         ArrayList<Permission> apcList = new ArrayList<Permission>();
@@ -75,7 +75,10 @@ public class AuthorizationGenTest extends AbstractAuthorizationTestImpl {
         apcList.add(accPerm);
         Permission coPerm = buildCommonPermission("2", "collectionobjects");
         apcList.add(coPerm);
-        toFile(pcList, PermissionsList.class, "./target/test-permissions.xml");
+        AbstractAuthorizationTestImpl.toFile(pcList, PermissionsList.class,
+                AbstractAuthorizationTestImpl.testDataDir + "test-permissions.xml");
+        logger.info("generated permissions to "
+                + AbstractAuthorizationTestImpl.testDataDir + "test-permissions.xml");
 
     }
 
@@ -103,27 +106,31 @@ public class AuthorizationGenTest extends AbstractAuthorizationTestImpl {
         return perm;
     }
 
-    @Test
     public void genPermissionsRoles() {
         PermissionsRolesList psrsl = new PermissionsRolesList();
-        ArrayList<PermissionRole> prl = buildCommonPermissionRoles("1");
-        prl.addAll(buildCommonPermissionRoles("2"));
+        ArrayList<PermissionRole> prl = new ArrayList<PermissionRole>();
+        prl.add(buildCommonPermissionRoles("1"));
+        prl.add(buildCommonPermissionRoles("2"));
         psrsl.setPermissionRoles(prl);
-        toFile(psrsl, PermissionsRolesList.class, "./target/test-permissions-roles.xml");
+        AbstractAuthorizationTestImpl.toFile(psrsl, PermissionsRolesList.class,
+                AbstractAuthorizationTestImpl.testDataDir + "test-permissions-roles.xml");
+        logger.info("generated permissions-roles to "
+                + AbstractAuthorizationTestImpl.testDataDir + "test-permissions-roles.xml");
     }
 
-    private ArrayList<PermissionRole> buildCommonPermissionRoles(String id) {
-        ArrayList<PermissionRole> prl = new ArrayList<PermissionRole>();
+    private PermissionRole buildCommonPermissionRoles(String id) {
+
         PermissionRole pr = new PermissionRole();
-        pr.setPermissionId(id);
+        pr.setSubject(SubjectType.ROLE);
+        List<String> permIds = new ArrayList<String>();
+        permIds.add(id);
+        pr.setPermissionIds(permIds);
         //FIXME should using role id
-        pr.setRoleId("ROLE_USERS");
-        prl.add(pr);
-        PermissionRole pr1 = new PermissionRole();
-        pr1.setPermissionId(id);
-        //FIXME shoudl use role id
-        pr1.setRoleId("ROLE_ADMINISTRATOR");
-        prl.add(pr1);
-        return prl;
+        List<String> roleIds = new ArrayList<String>();
+        roleIds.add("ROLE_USERS");
+        roleIds.add("ROLE_ADMINISTRATOR");
+        pr.setRoleIds(roleIds);
+        return pr;
+
     }
 }
index 63781455c1c3b0bb3db1f89f1858ebbf1aa11374..4abddef0508685a17841a849c0f60aac9302191b 100644 (file)
@@ -43,7 +43,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.collectionspace.services.authorization.test;
 
 import java.util.ArrayList;
@@ -71,6 +70,9 @@ public class AuthorizationSeedTest extends AbstractAuthorizationTestImpl {
         setup();
         TransactionStatus status = beginTransaction("seedData");
         try {
+            AuthorizationGen authzGen = new AuthorizationGen();
+            authzGen.genPermissions();
+            authzGen.genPermissionsRoles();
             seedRoles();
             seedPermissions();
         } catch (Exception ex) {
@@ -88,12 +90,14 @@ public class AuthorizationSeedTest extends AbstractAuthorizationTestImpl {
 
         PermissionsList pcList =
                 (PermissionsList) fromFile(PermissionsList.class,
-                "./test-data/test-permissions.xml");
-
+                 AbstractAuthorizationTestImpl.testDataDir + "test-permissions.xml");
+        logger.info("read permissions from "
+                + AbstractAuthorizationTestImpl.testDataDir + "test-permissions.xml");
         PermissionsRolesList pcrList =
                 (PermissionsRolesList) fromFile(PermissionsRolesList.class,
-                "./test-data/test-permissions-roles.xml");
-
+                AbstractAuthorizationTestImpl.testDataDir + "test-permissions-roles.xml");
+        logger.info("read permissions-roles from "
+                + AbstractAuthorizationTestImpl.testDataDir + "test-permissions.xml");
         AuthZ authZ = AuthZ.get();
         for (Permission p : pcList.getPermissions()) {
             if (logger.isDebugEnabled()) {
@@ -107,9 +111,9 @@ public class AuthorizationSeedTest extends AbstractAuthorizationTestImpl {
     private List<PermissionRole> getPermissionRoles(PermissionsRolesList pcrList, String permId) {
         List<PermissionRole> prList = new ArrayList<PermissionRole>();
         for (PermissionRole pr : pcrList.getPermissionRoles()) {
-            if (pr.getPermissionId().equals(permId)) {
-                prList.add(pr);
-            }
+            if (pr.getPermissionIds().get(0).equals(permId)) {
+            prList.add(pr);
+        }
         }
         return prList;
     }
index f58460500f29cdc58a2ad3ad04bbfb0a6777b6f5..67b54370bb158d63950804bd1db843330cece147 100644 (file)
@@ -1,19 +1,15 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <ns2:permissions_roles_list xmlns:ns2="http://collectionspace.org/services/authorization">
     <permissionRole>
+        <subject>ROLE</subject>
         <permissionId>1</permissionId>
         <roleId>ROLE_USERS</roleId>
-    </permissionRole>
-    <permissionRole>
-        <permissionId>1</permissionId>
         <roleId>ROLE_ADMINISTRATOR</roleId>
     </permissionRole>
     <permissionRole>
+        <subject>ROLE</subject>
         <permissionId>2</permissionId>
         <roleId>ROLE_USERS</roleId>
-    </permissionRole>
-    <permissionRole>
-        <permissionId>2</permissionId>
         <roleId>ROLE_ADMINISTRATOR</roleId>
     </permissionRole>
 </ns2:permissions_roles_list>
index 7234718b75c20533cb8d733646789b156579ec7c..a85550c4045b90596ad5eb8170eaf451f47b8486 100644 (file)
@@ -33,299 +33,298 @@ import org.w3c.dom.Document;
 \r
 public abstract class BaseServiceTest {\r
 \r
-       protected final Logger logger = LoggerFactory.getLogger(BaseServiceTest.class);\r
-       protected static final TestServiceClient serviceClient = new TestServiceClient();\r
-       protected final String NON_EXISTENT_ID = createNonExistentIdentifier();\r
-       protected int EXPECTED_STATUS_CODE = 0;\r
-       protected ServiceRequestType REQUEST_TYPE = ServiceRequestType.NON_EXISTENT;\r
-       protected static final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";\r
-       protected static final String MALFORMED_XML_DATA = XML_DECLARATION +\r
-                   "<malformed_xml>wrong schema contents</malformed_xml";\r
-       protected final String WRONG_XML_SCHEMA_DATA = XML_DECLARATION +\r
-                   "<wrong_schema>wrong schema contents</wrong_schema>";\r
-       final String NULL_CHARSET = null;\r
+    static protected final Logger logger = LoggerFactory.getLogger(BaseServiceTest.class);\r
+    protected static final TestServiceClient serviceClient = new TestServiceClient();\r
+    protected final String NON_EXISTENT_ID = createNonExistentIdentifier();\r
+    protected int EXPECTED_STATUS_CODE = 0;\r
+    protected ServiceRequestType REQUEST_TYPE = ServiceRequestType.NON_EXISTENT;\r
+    protected static final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";\r
+    protected static final String MALFORMED_XML_DATA = XML_DECLARATION\r
+            + "<malformed_xml>wrong schema contents</malformed_xml";\r
+    protected final String WRONG_XML_SCHEMA_DATA = XML_DECLARATION\r
+            + "<wrong_schema>wrong schema contents</wrong_schema>";\r
+    final String NULL_CHARSET = null;\r
 \r
-       /**\r
-           * Returns the name of the currently running test.\r
-           *\r
-           * Note: although the return type is listed as Object[][],\r
-           * this method instead returns a String.\r
-           *\r
-           * @param   m  The currently running test method.\r
-           *\r
-           * @return  The name of the currently running test method.\r
-           */\r
-       @DataProvider(name = "testName")\r
-       public static Object[][] testName(Method m) {\r
-           return new Object[][]{\r
-               new Object[] { m.getName() }\r
-           };\r
-       }\r
+    /**\r
+     * Returns the name of the currently running test.\r
+     *\r
+     * Note: although the return type is listed as Object[][],\r
+     * this method instead returns a String.\r
+     *\r
+     * @param   m  The currently running test method.\r
+     *\r
+     * @return  The name of the currently running test method.\r
+     */\r
+    @DataProvider(name = "testName")\r
+    public static Object[][] testName(Method m) {\r
+        return new Object[][]{\r
+                    new Object[]{m.getName()}\r
+                };\r
+    }\r
 \r
-       /**\r
-        * Returns the URL path component of the service.\r
-        *\r
-        * This component will follow directly after the\r
-        * base path, if any.\r
-        *\r
-        * @return The URL path component of the service.\r
-        */\r
-       protected abstract String getServicePathComponent();\r
+    /**\r
+     * Returns the URL path component of the service.\r
+     *\r
+     * This component will follow directly after the\r
+     * base path, if any.\r
+     *\r
+     * @return The URL path component of the service.\r
+     */\r
+    protected abstract String getServicePathComponent();\r
 \r
-       /**\r
-        * Reinitializes setup values, to help expose any unintended reuse\r
-        * of those values between tests.\r
-        */\r
-       protected void clearSetup() {\r
-           EXPECTED_STATUS_CODE = 0;\r
-           REQUEST_TYPE = ServiceRequestType.NON_EXISTENT;\r
-       }\r
-       \r
-       /**\r
-        * Initializes setup valuesfor a given test.\r
-        */\r
-       protected void testSetup( \r
-                       int                                     expectedStatusCode, \r
-                       ServiceRequestType      reqType, \r
-                       String                          bannerLabel ) {\r
-           clearSetup();\r
-           EXPECTED_STATUS_CODE = expectedStatusCode;\r
-           REQUEST_TYPE = reqType;\r
-           // Print a banner identifying the test that will be run.\r
-           if (logger.isDebugEnabled()) {\r
-               banner(bannerLabel);\r
-           }\r
-       }\r
+    /**\r
+     * Reinitializes setup values, to help expose any unintended reuse\r
+     * of those values between tests.\r
+     */\r
+    protected void clearSetup() {\r
+        EXPECTED_STATUS_CODE = 0;\r
+        REQUEST_TYPE = ServiceRequestType.NON_EXISTENT;\r
+    }\r
 \r
+    /**\r
+     * Initializes setup valuesfor a given test.\r
+     */\r
+    protected void testSetup(\r
+            int expectedStatusCode,\r
+            ServiceRequestType reqType,\r
+            String bannerLabel) {\r
+        clearSetup();\r
+        EXPECTED_STATUS_CODE = expectedStatusCode;\r
+        REQUEST_TYPE = reqType;\r
+        // Print a banner identifying the test that will be run.\r
+        if (logger.isDebugEnabled()) {\r
+            banner(bannerLabel);\r
+        }\r
+    }\r
 \r
-       public BaseServiceTest() {\r
-               super();\r
-       }\r
+    public BaseServiceTest() {\r
+        super();\r
+    }\r
 \r
-       /**\r
-        * Returns an error message indicating that the status code returned by a\r
-        * specific call to a service does not fall within a set of valid status\r
-        * codes for that service.\r
-        *\r
-        * @param serviceRequestType  A type of service request (e.g. CREATE, DELETE).\r
-        *\r
-        * @param statusCode  The invalid status code that was returned in the response,\r
-        *                    from submitting that type of request to the service.\r
-        *\r
-        * @return An error message.\r
-        */\r
-       protected String invalidStatusCodeMessage(ServiceRequestType requestType, int statusCode) {\r
-           return "Status code '" + statusCode +\r
-               "' in response is NOT within the expected set: " +\r
-               requestType.validStatusCodesAsString();\r
-       }\r
+    /**\r
+     * Returns an error message indicating that the status code returned by a\r
+     * specific call to a service does not fall within a set of valid status\r
+     * codes for that service.\r
+     *\r
+     * @param serviceRequestType  A type of service request (e.g. CREATE, DELETE).\r
+     *\r
+     * @param statusCode  The invalid status code that was returned in the response,\r
+     *                    from submitting that type of request to the service.\r
+     *\r
+     * @return An error message.\r
+     */\r
+    protected String invalidStatusCodeMessage(ServiceRequestType requestType, int statusCode) {\r
+        return "Status code '" + statusCode\r
+                + "' in response is NOT within the expected set: "\r
+                + requestType.validStatusCodesAsString();\r
+    }\r
 \r
-       /**\r
-        * Returns the root URL for a service.\r
-        *\r
-        * This URL consists of a base URL for all services, followed by\r
-        * a path component (or components) for a service.\r
-        *\r
-        * @return The root URL for a service.\r
-        */\r
-       protected String getServiceRootURL() {\r
-           return serviceClient.getBaseURL() + getServicePathComponent();\r
-       }\r
+    /**\r
+     * Returns the root URL for a service.\r
+     *\r
+     * This URL consists of a base URL for all services, followed by\r
+     * a path component (or components) for a service.\r
+     *\r
+     * @return The root URL for a service.\r
+     */\r
+    protected String getServiceRootURL() {\r
+        return serviceClient.getBaseURL() + getServicePathComponent();\r
+    }\r
 \r
-       /**\r
-        * Returns the URL of a specific resource managed by a service, and\r
-        * designated by an identifier (such as a universally unique ID, or UUID).\r
-        *\r
-        * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.\r
-        *\r
-        * @return The URL of a specific resource managed by a service.\r
-        */\r
-       protected String getResourceURL(String resourceIdentifier) {\r
-           return getServiceRootURL() + "/" + resourceIdentifier;\r
-       }\r
+    /**\r
+     * Returns the URL of a specific resource managed by a service, and\r
+     * designated by an identifier (such as a universally unique ID, or UUID).\r
+     *\r
+     * @param  resourceIdentifier  An identifier (such as a UUID) for a resource.\r
+     *\r
+     * @return The URL of a specific resource managed by a service.\r
+     */\r
+    protected String getResourceURL(String resourceIdentifier) {\r
+        return getServiceRootURL() + "/" + resourceIdentifier;\r
+    }\r
 \r
-       /**\r
-        * Submits an HTTP request to a specified URL, and returns the\r
-        * status code of the response.  Currently accepts GET and DELETE\r
-        * requests.\r
-        *\r
-        * @param  method  An HTTP method.\r
-        *\r
-        * @param  url     A String representation of a URL.\r
-        *\r
-        * @return The status code received in the HTTP response.\r
-        */\r
-       protected int submitRequest(String method, String url) {\r
-           int statusCode = 0;\r
-           try{\r
-               TestServiceClient client = new TestServiceClient();\r
-               if(method.equals(javax.ws.rs.HttpMethod.DELETE)){\r
-                   DeleteMethod deleteMethod = new DeleteMethod(url);\r
-                   statusCode = client.getHttpClient().executeMethod(deleteMethod);\r
-               }else if(method.equals(javax.ws.rs.HttpMethod.GET)){\r
-                   GetMethod getMethod = new GetMethod(url);\r
-                   statusCode = client.getHttpClient().executeMethod(getMethod);\r
-               }else{\r
-                   // Do nothing - leave status code at default value.\r
-               }\r
-           }catch(Exception e){\r
-               logger.error(\r
-                   "Exception during HTTP " + method + " request to " +\r
-                   url + ":", e);\r
-           }\r
-           return statusCode;\r
-       }\r
+    /**\r
+     * Submits an HTTP request to a specified URL, and returns the\r
+     * status code of the response.  Currently accepts GET and DELETE\r
+     * requests.\r
+     *\r
+     * @param  method  An HTTP method.\r
+     *\r
+     * @param  url     A String representation of a URL.\r
+     *\r
+     * @return The status code received in the HTTP response.\r
+     */\r
+    protected int submitRequest(String method, String url) {\r
+        int statusCode = 0;\r
+        try {\r
+            TestServiceClient client = new TestServiceClient();\r
+            if (method.equals(javax.ws.rs.HttpMethod.DELETE)) {\r
+                DeleteMethod deleteMethod = new DeleteMethod(url);\r
+                statusCode = client.getHttpClient().executeMethod(deleteMethod);\r
+            } else if (method.equals(javax.ws.rs.HttpMethod.GET)) {\r
+                GetMethod getMethod = new GetMethod(url);\r
+                statusCode = client.getHttpClient().executeMethod(getMethod);\r
+            } else {\r
+                // Do nothing - leave status code at default value.\r
+            }\r
+        } catch (Exception e) {\r
+            logger.error(\r
+                    "Exception during HTTP " + method + " request to "\r
+                    + url + ":", e);\r
+        }\r
+        return statusCode;\r
+    }\r
 \r
-       /**\r
-        * Submits an HTTP request to a specified URL, with the submitted\r
-        * entity body, and returns the status code of the response.\r
-        * Currently accepts POST and PUT requests.\r
-        *\r
-        * @param  method  An HTTP method.\r
-        *\r
-        * @param  url     A String representation of a URL.\r
-        *\r
-        * @param  mediaType  The media type of the entity body to be submitted.\r
-        *\r
-        * @param  entity     The contents of the entity body to be submitted.\r
-        *\r
-        * @return The status code received in the HTTP response.\r
-        */\r
-       protected int submitRequest(String method, String url, String mediaType,\r
-                       String entityStr) {\r
-                           int statusCode = 0;\r
-                           try{\r
-                               TestServiceClient client = new TestServiceClient();\r
-                               if(method.equals(javax.ws.rs.HttpMethod.POST)){\r
-                                   StringRequestEntity entityBody =\r
-                                       new StringRequestEntity(mediaType, entityStr, NULL_CHARSET);\r
-                                   PostMethod postMethod = new PostMethod(url);\r
-                                   postMethod.setRequestEntity(entityBody);\r
-                                   statusCode = client.getHttpClient().executeMethod(postMethod);\r
-                               }else if(method.equals(javax.ws.rs.HttpMethod.PUT)){\r
-                                   StringRequestEntity entityBody =\r
-                                       new StringRequestEntity(mediaType, entityStr, NULL_CHARSET);\r
-                                   PutMethod putMethod = new PutMethod(url);\r
-                                   putMethod.setRequestEntity(entityBody);\r
-                                   statusCode = client.getHttpClient().executeMethod(putMethod);\r
-                               }else{\r
-                                   // Do nothing - leave status code at default value.\r
-                               }\r
-                           }catch(Exception e){\r
-                               logger.error(\r
-                                   "Exception during HTTP " + method + " request to " +\r
-                                   url + ":", e);\r
-                           }\r
-                           return statusCode;\r
-                       }\r
+    /**\r
+     * Submits an HTTP request to a specified URL, with the submitted\r
+     * entity body, and returns the status code of the response.\r
+     * Currently accepts POST and PUT requests.\r
+     *\r
+     * @param  method  An HTTP method.\r
+     *\r
+     * @param  url     A String representation of a URL.\r
+     *\r
+     * @param  mediaType  The media type of the entity body to be submitted.\r
+     *\r
+     * @param  entity     The contents of the entity body to be submitted.\r
+     *\r
+     * @return The status code received in the HTTP response.\r
+     */\r
+    protected int submitRequest(String method, String url, String mediaType,\r
+            String entityStr) {\r
+        int statusCode = 0;\r
+        try {\r
+            TestServiceClient client = new TestServiceClient();\r
+            if (method.equals(javax.ws.rs.HttpMethod.POST)) {\r
+                StringRequestEntity entityBody =\r
+                        new StringRequestEntity(mediaType, entityStr, NULL_CHARSET);\r
+                PostMethod postMethod = new PostMethod(url);\r
+                postMethod.setRequestEntity(entityBody);\r
+                statusCode = client.getHttpClient().executeMethod(postMethod);\r
+            } else if (method.equals(javax.ws.rs.HttpMethod.PUT)) {\r
+                StringRequestEntity entityBody =\r
+                        new StringRequestEntity(mediaType, entityStr, NULL_CHARSET);\r
+                PutMethod putMethod = new PutMethod(url);\r
+                putMethod.setRequestEntity(entityBody);\r
+                statusCode = client.getHttpClient().executeMethod(putMethod);\r
+            } else {\r
+                // Do nothing - leave status code at default value.\r
+            }\r
+        } catch (Exception e) {\r
+            logger.error(\r
+                    "Exception during HTTP " + method + " request to "\r
+                    + url + ":", e);\r
+        }\r
+        return statusCode;\r
+    }\r
 \r
-       protected String extractId(ClientResponse<Response> res) {\r
-           MultivaluedMap mvm = res.getMetadata();\r
-           String uri = (String) ((ArrayList) mvm.get("Location")).get(0);\r
-           if(logger.isDebugEnabled()){\r
-               logger.debug("extractId:uri=" + uri);\r
-           }\r
-           String[] segments = uri.split("/");\r
-           String id = segments[segments.length - 1];\r
-           if(logger.isDebugEnabled()){\r
-               logger.debug("id=" + id);\r
-           }\r
-           return id;\r
-       }\r
+    static protected String extractId(ClientResponse<Response> res) {\r
+        MultivaluedMap mvm = res.getMetadata();\r
+        String uri = (String) ((ArrayList) mvm.get("Location")).get(0);\r
+        if (logger.isDebugEnabled()) {\r
+            logger.debug("extractId:uri=" + uri);\r
+        }\r
+        String[] segments = uri.split("/");\r
+        String id = segments[segments.length - 1];\r
+        if (logger.isDebugEnabled()) {\r
+            logger.debug("id=" + id);\r
+        }\r
+        return id;\r
+    }\r
 \r
-       protected String createIdentifier() {\r
-           long identifier = System.currentTimeMillis();\r
-           return Long.toString(identifier);\r
-       }\r
+    static protected String createIdentifier() {\r
+        long identifier = System.currentTimeMillis();\r
+        return Long.toString(identifier);\r
+    }\r
 \r
-       protected String createNonExistentIdentifier() {\r
-           return Long.toString(Long.MAX_VALUE);\r
-       }\r
+    protected String createNonExistentIdentifier() {\r
+        return Long.toString(Long.MAX_VALUE);\r
+    }\r
 \r
-       protected Object extractPart(MultipartInput input, String label, Class clazz)\r
-                       throws Exception {\r
-                           Object obj = null;\r
-                           String partLabel = "";\r
-                           List<InputPart> parts = input.getParts();\r
-                           if (parts.size() == 0) {\r
-                               logger.warn("No parts found in multipart body.");\r
-                           }\r
-                           if(logger.isDebugEnabled()){\r
-                               logger.debug("Parts:");\r
-                               for(InputPart part : parts){\r
-                                  partLabel = part.getHeaders().getFirst("label");\r
-                                  logger.debug("part = " + partLabel);\r
-                               }\r
-                           }\r
-                           boolean partLabelMatched = false;\r
-                           for(InputPart part : parts){\r
-                               partLabel = part.getHeaders().getFirst("label");\r
-                               if(label.equalsIgnoreCase(partLabel)){\r
-                                   partLabelMatched = true;\r
-                                   if(logger.isDebugEnabled()){\r
-                                       logger.debug("found part" + partLabel);\r
-                                   }\r
-                                   String partStr = part.getBodyAsString();\r
-                                   if (partStr == null || partStr.trim().isEmpty()) {\r
-                                       logger.warn("Part '" + label + "' in multipart body is empty.");\r
-                                   } else {\r
-                                       if (logger.isDebugEnabled()){\r
-                                           logger.debug("extracted part as str=\n" + partStr);\r
-                                       }\r
-                                       obj = part.getBody(clazz, null);\r
-                                       if(logger.isDebugEnabled()){\r
-                                           logger.debug("extracted part as obj=\n",\r
-                                               objectAsXmlString(obj, clazz));\r
-                                       }\r
-                                   }\r
-                                   break;\r
-                               }\r
-                           }\r
-                           if (! partLabelMatched) {\r
-                               logger.warn("Could not find part '" + label + "' in multipart body.");\r
-                           // In the event that getBodyAsString() or getBody(), above, do *not*\r
-                           // throw an IOException, but getBody() nonetheless retrieves a null object.\r
-                           // This *may* be unreachable.\r
-                           } else if (obj == null) {\r
-                               logger.warn("Could not extract part '" + label +\r
-                                   "' in multipart body as an object.");\r
-                           }\r
-                           return obj;\r
-                       }\r
+    static protected Object extractPart(MultipartInput input, String label, Class clazz)\r
+            throws Exception {\r
+        Object obj = null;\r
+        String partLabel = "";\r
+        List<InputPart> parts = input.getParts();\r
+        if (parts.size() == 0) {\r
+            logger.warn("No parts found in multipart body.");\r
+        }\r
+        if (logger.isDebugEnabled()) {\r
+            logger.debug("Parts:");\r
+            for (InputPart part : parts) {\r
+                partLabel = part.getHeaders().getFirst("label");\r
+                logger.debug("part = " + partLabel);\r
+            }\r
+        }\r
+        boolean partLabelMatched = false;\r
+        for (InputPart part : parts) {\r
+            partLabel = part.getHeaders().getFirst("label");\r
+            if (label.equalsIgnoreCase(partLabel)) {\r
+                partLabelMatched = true;\r
+                if (logger.isDebugEnabled()) {\r
+                    logger.debug("found part" + partLabel);\r
+                }\r
+                String partStr = part.getBodyAsString();\r
+                if (partStr == null || partStr.trim().isEmpty()) {\r
+                    logger.warn("Part '" + label + "' in multipart body is empty.");\r
+                } else {\r
+                    if (logger.isDebugEnabled()) {\r
+                        logger.debug("extracted part as str=\n" + partStr);\r
+                    }\r
+                    obj = part.getBody(clazz, null);\r
+                    if (logger.isDebugEnabled()) {\r
+                        logger.debug("extracted part as obj=\n",\r
+                                objectAsXmlString(obj, clazz));\r
+                    }\r
+                }\r
+                break;\r
+            }\r
+        }\r
+        if (!partLabelMatched) {\r
+            logger.warn("Could not find part '" + label + "' in multipart body.");\r
+            // In the event that getBodyAsString() or getBody(), above, do *not*\r
+            // throw an IOException, but getBody() nonetheless retrieves a null object.\r
+            // This *may* be unreachable.\r
+        } else if (obj == null) {\r
+            logger.warn("Could not extract part '" + label\r
+                    + "' in multipart body as an object.");\r
+        }\r
+        return obj;\r
+    }\r
 \r
-       protected Object getPartObject(String partStr, Class clazz)\r
-                       throws JAXBException {\r
-                           JAXBContext jc = JAXBContext.newInstance(clazz);\r
-                           ByteArrayInputStream bais = null;\r
-                           Object obj = null;\r
-                           try{\r
-                               bais = new ByteArrayInputStream(partStr.getBytes());\r
-                               Unmarshaller um = jc.createUnmarshaller();\r
-                               obj = um.unmarshal(bais);\r
-                           }finally{\r
-                               if(bais != null){\r
-                                   try{\r
-                                       bais.close();\r
-                                   }catch(Exception e){\r
-                                   }\r
-                               }\r
-                           }\r
-                           return obj;\r
-                       }\r
+    static protected Object getPartObject(String partStr, Class clazz)\r
+            throws JAXBException {\r
+        JAXBContext jc = JAXBContext.newInstance(clazz);\r
+        ByteArrayInputStream bais = null;\r
+        Object obj = null;\r
+        try {\r
+            bais = new ByteArrayInputStream(partStr.getBytes());\r
+            Unmarshaller um = jc.createUnmarshaller();\r
+            obj = um.unmarshal(bais);\r
+        } finally {\r
+            if (bais != null) {\r
+                try {\r
+                    bais.close();\r
+                } catch (Exception e) {\r
+                }\r
+            }\r
+        }\r
+        return obj;\r
+    }\r
 \r
-       protected String objectAsXmlString(Object o, Class clazz) {\r
-           StringWriter sw = new StringWriter();\r
-           try{\r
-               JAXBContext jc = JAXBContext.newInstance(clazz);\r
-               Marshaller m = jc.createMarshaller();\r
-               m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,\r
-                       Boolean.TRUE);\r
-               m.marshal(o, sw);\r
-           }catch(Exception e){\r
-               e.printStackTrace();\r
-           }\r
-           return sw.toString();\r
-       }\r
+    static protected String objectAsXmlString(Object o, Class clazz) {\r
+        StringWriter sw = new StringWriter();\r
+        try {\r
+            JAXBContext jc = JAXBContext.newInstance(clazz);\r
+            Marshaller m = jc.createMarshaller();\r
+            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,\r
+                    Boolean.TRUE);\r
+            m.marshal(o, sw);\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+        }\r
+        return sw.toString();\r
+    }\r
 \r
     /**\r
      * getObjectFromFile get object of given class from given file (in classpath)\r
@@ -334,7 +333,7 @@ public abstract class BaseServiceTest {
      * @return\r
      * @throws Exception\r
      */\r
-    protected Object getObjectFromFile(Class jaxbClass, String fileName)\r
+    static protected Object getObjectFromFile(Class jaxbClass, String fileName)\r
             throws Exception {\r
 \r
         JAXBContext context = JAXBContext.newInstance(jaxbClass);\r
@@ -346,7 +345,7 @@ public abstract class BaseServiceTest {
         return getObjectFromStream(jaxbClass, is);\r
     }\r
 \r
-    protected Document getXmlDocument(String fileName) throws Exception {\r
+    static protected Document getXmlDocument(String fileName) throws Exception {\r
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\r
         File f = new File(fileName);\r
         if (!f.exists()) {\r
@@ -356,12 +355,11 @@ public abstract class BaseServiceTest {
         return factory.newDocumentBuilder().parse(f);\r
     }\r
 \r
-    protected String getXmlDocumentAsString(String fileName) throws Exception {\r
+    static protected String getXmlDocumentAsString(String fileName) throws Exception {\r
         byte[] b = FileUtils.readFileToByteArray(new File(fileName));\r
         return new String(b);\r
     }\r
 \r
-\r
     /**\r
      * getObjectFromStream get object of given class from given inputstream\r
      * @param jaxbClass\r
@@ -369,29 +367,29 @@ public abstract class BaseServiceTest {
      * @return\r
      * @throws Exception\r
      */\r
-    protected Object getObjectFromStream(Class jaxbClass, InputStream is) throws Exception {\r
+    static protected Object getObjectFromStream(Class jaxbClass, InputStream is) throws Exception {\r
         JAXBContext context = JAXBContext.newInstance(jaxbClass);\r
         Unmarshaller unmarshaller = context.createUnmarshaller();\r
         //note: setting schema to null will turn validator off\r
         unmarshaller.setSchema(null);\r
         return jaxbClass.cast(unmarshaller.unmarshal(is));\r
     }\r
-       protected String mapAsString(MultivaluedMap map) {\r
-           StringBuffer sb = new StringBuffer();\r
-           for(Object entry : map.entrySet()){\r
-               MultivaluedMap.Entry mentry = (MultivaluedMap.Entry) entry;\r
-               sb.append("    name=" + mentry.getKey());\r
-               sb.append(" value=" + mentry.getValue() + "\n");\r
-           }\r
-           return sb.toString();\r
-       }\r
 \r
-       protected void banner(String label) {\r
-           if(logger.isDebugEnabled()){\r
-               logger.debug("===================================================");\r
-               logger.debug(" Test = " + label);\r
-               logger.debug("===================================================");\r
-           }\r
-       }\r
+    protected String mapAsString(MultivaluedMap map) {\r
+        StringBuffer sb = new StringBuffer();\r
+        for (Object entry : map.entrySet()) {\r
+            MultivaluedMap.Entry mentry = (MultivaluedMap.Entry) entry;\r
+            sb.append("    name=" + mentry.getKey());\r
+            sb.append(" value=" + mentry.getValue() + "\n");\r
+        }\r
+        return sb.toString();\r
+    }\r
 \r
-}
\ No newline at end of file
+    protected void banner(String label) {\r
+        if (logger.isDebugEnabled()) {\r
+            logger.debug("===================================================");\r
+            logger.debug(" Test = " + label);\r
+            logger.debug("===================================================");\r
+        }\r
+    }\r
+}\r
index b560216499a7d0e1e7b5cd5aa0d9cff63f6f9100..17befac66853e4d577876f8f381d53fbcd08261c 100644 (file)
             <artifactId>org.collectionspace.services.authentication.service</artifactId>\r
             <version>${project.version}</version>\r
             <scope>provided</scope>\r
-        </dependency>        \r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.collectionspace.services</groupId>\r
+            <artifactId>org.collectionspace.services.authorization.jaxb</artifactId>\r
+            <version>${project.version}</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
         <dependency>\r
             <groupId>org.collectionspace.services</groupId>\r
             <artifactId>org.collectionspace.services.authorization.service</artifactId>\r
             <groupId>javax.persistence</groupId>\r
             <artifactId>persistence-api</artifactId>\r
         </dependency>\r
-        \r
+\r
         <dependency>\r
             <groupId>com.sun.xml.bind</groupId>\r
             <artifactId>jaxb-impl</artifactId>\r
index cdb85fb611187df5a9efbf23ddaca865c0850fa4..a2e82ac476235f8ba54fa8d4d309df21d2ae2624 100644 (file)
             </service:object>
         </tenant:serviceBindings>
         <!-- end role service meta-data -->
-                <!-- begin permission service meta-data -->
+        <!-- begin permission service meta-data -->
         <tenant:serviceBindings name="authorization/permissions" version="0.1">
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.authorization.storage.PermissionDocumentHandler
             </service:object>
         </tenant:serviceBindings>
         <!-- end permission service meta-data -->
+        <!-- begin permission-role service meta-data -->
+        <tenant:serviceBindings name="authorization/permroles" version="0.1">
+            <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
+                org.collectionspace.services.authorization.storage.PermissionRoleDocumentHandler
+            </service:documentHandler>
+            <!--service:validatorHandler xmlns:service='http://collectionspace.org/services/common/service'>
+                org.collectionspace.services.authorization.storage.PermissionRoleValidatorHandler
+            </service:validatorHandler-->
+            <service:object name="PermissionRole" version="0.1"
+                            xmlns:service='http://collectionspace.org/services/common/service'>
+                <service:part id="0" control_group="Managed"
+                              versionable="true" auditable="false"
+                              label="permroles_system" updated="" order="0">
+                    <service:content contentType="application/xml">
+                        <service:xmlContent
+                            namespaceURI="http://collectionspace.org/services/common/system"
+                            schemaLocation="http://collectionspace.org/services/common/system http://collectionspace.org/services/common/system/system-response.xsd">
+                        </service:xmlContent>
+                    </service:content>
+                </service:part>
+                <service:part id="1" control_group="Managed"
+                              versionable="true" auditable="false"
+                              label="permroles" updated="" order="1">
+                    <service:content contentType="application/xml">
+                        <service:xmlContent
+                            namespaceURI="http://collectionspace.org/services/authorization"
+                            schemaLocation="http://collectionspace.org/services/authorization http://services.collectionspace.org/authorization/permissions_roles.xsd">
+                        </service:xmlContent>
+                    </service:content>
+                </service:part>
+            </service:object>
+        </tenant:serviceBindings>
+        <!-- end permission-role service meta-data -->
     </tenant:tenantBinding>
     <!-- end movingimages.us tenant meta-data -->
 </tenant:TenantBindingConfig>
index f865119a786e5b143eb214bbdba76b189c97d473..0203b73e1c6a1fef901a6085dc6c7a518c743c9d 100644 (file)
@@ -103,6 +103,10 @@ public class JpaStorageClientImpl implements StorageClient {
             DocumentHandler handler) throws BadRequestException,
             DocumentException {
 
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.create: ctx is missing");
+        }
         if (handler == null) {
             throw new IllegalArgumentException(
                     "JpaStorageClient.create: handler is missing");
@@ -159,6 +163,10 @@ public class JpaStorageClientImpl implements StorageClient {
     @Override
     public void get(ServiceContext ctx, String id, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.get: ctx is missing");
+        }
         if (handler == null) {
             throw new IllegalArgumentException(
                     "JpaStorageClient.get: handler is missing");
@@ -238,6 +246,10 @@ public class JpaStorageClientImpl implements StorageClient {
     @Override
     public void getFiltered(ServiceContext ctx, DocumentHandler handler)
             throws DocumentNotFoundException, DocumentException {
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.getFiltered: ctx is missing");
+        }
         if (handler == null) {
             throw new IllegalArgumentException(
                     "JpaStorageClient.getFiltered: handler is missing");
@@ -299,6 +311,10 @@ public class JpaStorageClientImpl implements StorageClient {
     public void update(ServiceContext ctx, String id, DocumentHandler handler)
             throws BadRequestException, DocumentNotFoundException,
             DocumentException {
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.update: ctx is missing");
+        }
         if (handler == null) {
             throw new IllegalArgumentException(
                     "JpaStorageClient.update: handler is missing");
@@ -357,6 +373,11 @@ public class JpaStorageClientImpl implements StorageClient {
             throws DocumentNotFoundException,
             DocumentException {
 
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.delete: ctx is missing");
+        }
+
         if (logger.isDebugEnabled()) {
             logger.debug("deleting entity with id=" + id);
         }
@@ -411,6 +432,10 @@ public class JpaStorageClientImpl implements StorageClient {
             throws DocumentNotFoundException,
             DocumentException {
 
+        if (ctx == null) {
+            throw new IllegalArgumentException(
+                    "JpaStorageClient.deleteWhere: ctx is missing");
+        }
 
         if (logger.isDebugEnabled()) {
             logger.debug("deleting entity with id=" + id);
@@ -427,7 +452,7 @@ public class JpaStorageClientImpl implements StorageClient {
             em = emf.createEntityManager();
             Query q = em.createQuery(deleteStr.toString());
             q.setParameter("csid", id);
-            //TODO: add tenant id
+
             int rcount = 0;
             em.getTransaction().begin();
             rcount = q.executeUpdate();