]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-1087, CSPACE-1141: Relation validation handler now prevents creating relations...
authorRichard Millet <richard.millet@berkeley.edu>
Fri, 7 Jan 2011 17:29:57 +0000 (17:29 +0000)
committerRichard Millet <richard.millet@berkeley.edu>
Fri, 7 Jan 2011 17:29:57 +0000 (17:29 +0000)
services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java
services/common/.classpath
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/document/InvalidDocumentException.java
services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandler.java
services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandlerImpl.java [new file with mode: 0644]
services/common/src/main/resources/service.xsd
services/relation/client/src/test/java/org/collectionspace/services/client/test/RelationServiceTest.java
services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java
services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationValidatorHandler.java

index 318841c959e5dc9d1149b5bdea1def46d53a3d35..007a19005849f28daa679ff77f783a46910b8a58 100644 (file)
@@ -123,6 +123,16 @@ public abstract class AbstractServiceTestImpl extends BaseServiceTest implements
         REQUEST_TYPE = ServiceRequestType.CREATE;
         testSetup(EXPECTED_STATUS_CODE, REQUEST_TYPE);
     }
+    
+    /**
+     * Sets up create tests with empty entity body.
+     */
+    protected void setupCreateWithInvalidBody() {
+        EXPECTED_STATUS_CODE = STATUS_BAD_REQUEST;
+        REQUEST_TYPE = ServiceRequestType.CREATE;
+        testSetup(EXPECTED_STATUS_CODE, REQUEST_TYPE);
+    }
+    
 
     /* (non-Javadoc)
      * @see org.collectionspace.services.client.test.ServiceTest#createWithMalformedXml(java.lang.String)
index 557f8a4e07f9616882b7ea73418b64a2bb068cb6..c9fc5a5af4124d7db01212698b29678a48e983c0 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <classpath>\r
        <classpathentry kind="src" output="target/classes" path="src/main/java"/>\r
-       <classpathentry kind="src" output="target/classes" path="target/generated-sources/xjc"/>\r
+       <classpathentry including="**/*.java" kind="src" output="target/classes" path="target/generated-sources/xjc"/>\r
        <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>\r
        <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>\r
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
index 658c14b2e40d2c4d4b3ab630d762deb6630d3ed1..e12b4daaff54a174c23e3d6222b26f802344dba6 100644 (file)
@@ -84,7 +84,7 @@ public abstract class AbstractServiceContextImpl<IT, OT>
     /** The override document type. */
     private String overrideDocumentType = null;
     /** The val handlers. */
-    private List<ValidatorHandler> valHandlers = null;
+    private List<ValidatorHandler<IT, OT>> valHandlers = null;
     /** The doc handler. */
     private DocumentHandler docHandler = null;
     /** security context */
@@ -507,21 +507,36 @@ public abstract class AbstractServiceContextImpl<IT, OT>
         }
         return serviceBinding.getDocumentHandler().trim();
     }
-
+    
+    /*
+     * If this element is set in the service binding then use it otherwise
+     * assume that asserts are NOT disabled.
+     */
+    private boolean disableValidationAsserts() {
+       boolean result;
+       Boolean disableAsserts = getServiceBinding().isDisableAsserts();
+       result = (disableAsserts != null) ? disableAsserts : false;
+       return result;
+    }
+    
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
      */
     @Override
-    public List<ValidatorHandler> getValidatorHandlers() throws Exception {
+    public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception {
         if (valHandlers != null) {
             return valHandlers;
         }
         List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
-        List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
+        List<ValidatorHandler<IT, OT>> handlers = new ArrayList<ValidatorHandler<IT, OT>>(handlerClazzes.size());
         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
         for (String clazz : handlerClazzes) {
             clazz = clazz.trim();
             Class<?> c = tccl.loadClass(clazz);
+            if (disableValidationAsserts() == false) {
+               // enable validation assertions
+               tccl.setClassAssertionStatus(clazz, true);
+            }
             if (ValidatorHandler.class.isAssignableFrom(c)) {
                 handlers.add((ValidatorHandler) c.newInstance());
             }
index fd53db1f14585cadae7a84450dd836c38d58a5ca..369e2a664c4c6b2b2af2179e54e85be61939b1b9 100644 (file)
@@ -237,7 +237,7 @@ public interface ServiceContext<IT, OT> {
      * for the service. it creates the handlers if necessary.
      * @return validation handlers
      */
-    public List<ValidatorHandler> getValidatorHandlers() throws Exception;
+    public List<ValidatorHandler<IT, OT>> getValidatorHandlers() throws Exception;
 
     /**
      * Gets the query params.
index c1000e963a1067a2c2394e6f5be0dca1da464b71..4051dbd57042deb020a8ff9a0aaee4888ea4dd40 100644 (file)
@@ -43,7 +43,7 @@ public class InvalidDocumentException extends BadRequestException {
      * Creates a new instance of <code>InvalidDocumentException</code> without detail message.
      */
     public InvalidDocumentException() {
-       //empty constructor
+       super();
     }
 
     /**
index 2fc6559a757cd666d59176a821ce2a23c6f8409f..ec33de30e42d8902be14cc178983889142d1ce3f 100644 (file)
@@ -30,7 +30,7 @@ import org.collectionspace.services.common.document.DocumentHandler.Action;
  * ValidatorHandler provides plugin for application level validation
  * for content received by services serving objects with extensible schema
  */
-public interface ValidatorHandler {
+public interface ValidatorHandler<IT, OT> {
 
     /**
      * validate is called by the document handler for CREATE and UPDATE actions.
@@ -41,6 +41,6 @@ public interface ValidatorHandler {
      * @param ctx
      * @throws InvalidDocumentException
      */
-    public void validate(Action action, ServiceContext ctx)
+    public void validate(Action action, ServiceContext<IT, OT> ctx)
             throws InvalidDocumentException;
 }
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandlerImpl.java
new file mode 100644 (file)
index 0000000..562566b
--- /dev/null
@@ -0,0 +1,118 @@
+package org.collectionspace.services.common.document;\r
+\r
+import java.lang.reflect.Field;\r
+import java.lang.reflect.ParameterizedType;\r
+import java.lang.reflect.Type;\r
+import java.lang.reflect.TypeVariable;\r
+import java.util.ArrayList;\r
+\r
+import org.collectionspace.services.common.context.MultipartServiceContext;\r
+import org.collectionspace.services.common.context.ServiceContext;\r
+import org.collectionspace.services.common.document.DocumentHandler.Action;\r
+import org.collectionspace.services.relation.RelationsCommon;\r
+import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;\r
+import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+// TODO: Auto-generated Javadoc\r
+/**\r
+ * The Class ValidatorHandlerImpl.\r
+ */\r
+public abstract class ValidatorHandlerImpl<IT, OT> implements ValidatorHandler<IT, OT> {\r
+       \r
+    /** The logger. */\r
+    private final Logger logger = LoggerFactory.getLogger(ValidatorHandlerImpl.class);\r
+    \r
+    private ServiceContext<IT, OT> ctx;\r
+    \r
+    protected ServiceContext<IT, OT> getServiceContext() {\r
+       return ctx;\r
+    }\r
+    \r
+    protected void setServiceContext(ServiceContext<IT, OT> ctx) {\r
+       this.ctx = ctx;\r
+    }\r
+       \r
+       /* (non-Javadoc)\r
+        * @see org.collectionspace.services.common.document.ValidatorHandler#validate(org.collectionspace.services.common.document.DocumentHandler.Action, org.collectionspace.services.common.context.ServiceContext)\r
+        */\r
+       @Override\r
+    public void validate(Action action, ServiceContext<IT, OT> ctx)\r
+               throws InvalidDocumentException {\r
+               setServiceContext(ctx);\r
+               switch (action) {\r
+                       case CREATE:\r
+                               handleCreate();\r
+                               break;\r
+                       case GET:\r
+                               handleGet();\r
+                               break;\r
+                       case GET_ALL:\r
+                               handleGetAll();\r
+                               break;\r
+                       case UPDATE:\r
+                               handleUpdate();\r
+                               break;\r
+                       case DELETE:\r
+                               handleDelete();\r
+                               break;\r
+                       default:\r
+                               throw new UnsupportedOperationException("ValidatorHandlerImpl: Unknow action = " +\r
+                                               action);\r
+               }       \r
+    }\r
+       \r
+    protected Object getCommonPart() {\r
+       Object result = null;           \r
+\r
+       try {\r
+               MultipartServiceContext multiPartCtx = (MultipartServiceContext) getServiceContext();\r
+               result = multiPartCtx.getInputPart(ctx.getCommonPartLabel(),\r
+                               getCommonPartClass());\r
+       } catch (Exception e) {\r
+               if (logger.isDebugEnabled() == true) {\r
+                       logger.debug("Could not extract common part from multipart input.", e);\r
+               }\r
+       }\r
+       \r
+       return result;          \r
+    }  \r
+       \r
+    abstract protected Class<?> getCommonPartClass();\r
+    \r
+       /**\r
+        * Handle create.\r
+        *\r
+        * @param ctx the ctx\r
+        */\r
+       abstract protected void handleCreate() throws InvalidDocumentException;\r
+       \r
+       /**\r
+        * Handle get.\r
+        *\r
+        * @param ctx the ctx\r
+        */\r
+       abstract protected void handleGet() throws InvalidDocumentException;\r
+       \r
+       /**\r
+        * Handle get all.\r
+        *\r
+        * @param ctx the ctx\r
+        */\r
+       abstract protected void handleGetAll() throws InvalidDocumentException;\r
+       \r
+       /**\r
+        * Handle update.\r
+        *\r
+        * @param ctx the ctx\r
+        */\r
+       abstract protected void handleUpdate() throws InvalidDocumentException;\r
+\r
+       /**\r
+        * Handle delete.\r
+        *\r
+        * @param ctx the ctx\r
+        */\r
+       abstract protected void handleDelete() throws InvalidDocumentException; \r
+}
\ No newline at end of file
index af351db823c7c5f81318a0ff1a255f9f211fb972..45b49438ba7029c635bb27182ee07831b0cba7b9 100644 (file)
@@ -44,6 +44,7 @@
             <!-- validator handler(s) to be used to validate the content (need to be in classpath) -->
             <!-- validator handler is called for create (POST) and update (PUT) requests only -->
             <xs:element name="validatorHandler" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="disableAsserts" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
             <!-- initHandler is a post-init task after the Nuxeo repository is available. -->
             <!-- worked: <xs:element name="initHandler" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>-->
             <xs:element name="initHandler" type="initHandler" minOccurs="0" maxOccurs="unbounded"/>
index c9ac4b32ca6a391797088090b379ef60d0b00552..a12c5f291e6a592e9c57f1afb755b57686eca95d 100644 (file)
@@ -143,6 +143,39 @@ public class RelationServiceTest extends AbstractServiceTestImpl {
             create(testName);
         }
     }
+    
+    @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class,
+            dependsOnMethods = {"create"})
+    public void createWithSelfRelation(String testName) throws Exception {
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testBanner(testName, CLASS_NAME));
+        }
+
+        setupCreateWithInvalidBody();
+
+        // Submit the request to the service and store the response.
+        RelationClient client = new RelationClient();
+        String identifier = createIdentifier();
+        RelationsCommon relationsCommon = createRelationsCommon(identifier);
+        // Make the subject ID equal to the object ID
+        relationsCommon.setDocumentId1(relationsCommon.getDocumentId2());
+        MultipartOutput multipart = createRelationInstance(relationsCommon);
+        ClientResponse<Response> res = client.create(multipart);
+        int statusCode = res.getStatus();
+
+        // Check the status code of the response: does it match
+        // the expected response(s)?
+        //
+        // Does it fall within the set of valid status codes?
+        // Does it exactly match the expected status code?
+        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
     // Placeholders until the three tests below can be uncommented.
@@ -777,6 +810,24 @@ public class RelationServiceTest extends AbstractServiceTestImpl {
         return SERVICE_PATH_COMPONENT;
     }
 
+    private RelationsCommon createRelationsCommon(String identifier) {
+        RelationsCommon result = new RelationsCommon();
+        fillRelation(result, identifier);
+        return result;
+    }
+    
+    private MultipartOutput createRelationInstance(RelationsCommon relation) {
+        MultipartOutput result = new MultipartOutput();
+        OutputPart commonPart =
+               result.addPart(relation, MediaType.APPLICATION_XML_TYPE);
+        commonPart.getHeaders().add("label", new RelationClient().getCommonPartName());
+        if(logger.isDebugEnabled()){
+          logger.debug("to be created, relation common");
+          logger.debug(objectAsXmlString(relation, RelationsCommon.class));
+        }
+        return result;
+    }
+    
     /**
      * Creates the relation instance.
      *
@@ -784,18 +835,9 @@ public class RelationServiceTest extends AbstractServiceTestImpl {
      * @return the multipart output
      */
     private MultipartOutput createRelationInstance(String identifier) {
-        RelationsCommon relation = new RelationsCommon();
-        fillRelation(relation, identifier);
-
-        MultipartOutput multipart = new MultipartOutput();
-        OutputPart commonPart =
-                multipart.addPart(relation, MediaType.APPLICATION_XML_TYPE);
-        commonPart.getHeaders().add("label", new RelationClient().getCommonPartName());
-        if(logger.isDebugEnabled()){
-          logger.debug("to be created, relation common");
-          logger.debug(objectAsXmlString(relation, RelationsCommon.class));
-        }
-        return multipart;
+        RelationsCommon relation = createRelationsCommon(identifier);
+        MultipartOutput result = createRelationInstance(relation);
+        return result;
     }
 
     /**
index 9888829541c178f77908d86841f6c9c33588a5ba..f822ad6941331323b9ca0182465d83380bc13a63 100644 (file)
@@ -47,6 +47,7 @@ import org.collectionspace.services.common.relation.IRelationsManager;
 import org.collectionspace.services.common.relation.nuxeo.RelationsUtils;
 import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl;
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.security.UnauthorizedException;
@@ -122,6 +123,11 @@ public class NewRelationResource extends
                                        .entity("Create failed reason " + ue.getErrorReason())
                                        .type("text/plain").build();
                        throw new WebApplicationException(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 (Exception e) {
                        if (logger.isDebugEnabled()) {
                                logger.debug("Caught exception in createRelation", e);
index 3a2adac86e841ed7e481ea071d38175872670a4a..1299076a2d92e7ef59b013de6d3b884b81b7fb0a 100644 (file)
@@ -1,17 +1,90 @@
 package org.collectionspace.services.relation.nuxeo;\r
 \r
+//import junit.framework.Assert;\r
+\r
+import org.collectionspace.services.common.context.MultipartServiceContext;\r
 import org.collectionspace.services.common.context.ServiceContext;\r
+\r
 import org.collectionspace.services.common.document.InvalidDocumentException;\r
 import org.collectionspace.services.common.document.ValidatorHandler;\r
+import org.collectionspace.services.common.document.ValidatorHandlerImpl;\r
 import org.collectionspace.services.common.document.DocumentHandler.Action;\r
 \r
-public class RelationValidatorHandler implements ValidatorHandler {\r
+import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;\r
+import org.collectionspace.services.relation.RelationsCommon;\r
+\r
+import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;\r
+import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+//import org.testng.Assert;\r
+\r
+public class RelationValidatorHandler extends ValidatorHandlerImpl<MultipartInput, MultipartOutput>     {\r
+\r
+    /** The logger. */\r
+    private final Logger logger = LoggerFactory.getLogger(RelationValidatorHandler.class);\r
+    \r
+    /* Error messages \r
+     */\r
+    private static final String VALIDATION_ERROR = "The relation record is invalid. See log file for more details.";\r
+    private static final String SUBJECT_EQUALS_PREDICATE_ERROR = "The subject ID and object ID cannot be the same.";\r
+    \r
+    @Override\r
+    protected Class<?> getCommonPartClass() {\r
+       return RelationsCommon.class;\r
+    }\r
+    \r
+    @Override\r
+    protected void handleCreate()\r
+               throws InvalidDocumentException{\r
+       ServiceContext<MultipartInput, MultipartOutput> ctx = getServiceContext();\r
+       try {\r
+               RelationsCommon relationsCommon = (RelationsCommon)getCommonPart();\r
+               assert(relationsCommon != null);\r
+               \r
+               assert(relationsCommon.getDocumentId1() != null);\r
+               assert(relationsCommon.getDocumentId1().length() != 0);\r
+               \r
+               assert(relationsCommon.getDocumentId2() != null);\r
+               assert(relationsCommon.getDocumentId2().length() != 0);\r
+               \r
+               assert(relationsCommon.getRelationshipType() != null);\r
+               //\r
+               // Assert that the Subject ID and Predicate ID are not the same\r
+               //\r
+               assert(relationsCommon.getDocumentId1().equalsIgnoreCase(relationsCommon.getDocumentId2()) == false) :\r
+                       SUBJECT_EQUALS_PREDICATE_ERROR;\r
+       } catch (AssertionError e) {\r
+               if (logger.isErrorEnabled() == true) {\r
+                       logger.error(e.getMessage(), e);\r
+               }\r
+               throw new InvalidDocumentException(VALIDATION_ERROR, e);\r
+       }\r
+    }\r
+\r
+       @Override\r
+       protected void handleGet() {\r
+               // TODO Auto-generated method stub\r
+               \r
+       }\r
+\r
+       @Override\r
+       protected void handleGetAll() {\r
+               // TODO Auto-generated method stub\r
+               \r
+       }\r
+\r
+       @Override\r
+       protected void handleUpdate() {\r
+               // TODO Auto-generated method stub\r
+               \r
+       }\r
 \r
        @Override\r
-       public void validate(Action action, ServiceContext ctx)\r
-                       throws InvalidDocumentException {\r
+       protected void handleDelete() {\r
                // TODO Auto-generated method stub\r
-               System.out.println("RelationValidatorHandler executed.");\r
+               \r
        }\r
 \r
 }\r