]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-396, CSPACE-787, CSPACE-400
authorSanjay Dalal <sanjay.dalal@berkeley.edu>
Fri, 29 Jan 2010 22:55:28 +0000 (22:55 +0000)
committerSanjay Dalal <sanjay.dalal@berkeley.edu>
Fri, 29 Jan 2010 22:55:28 +0000 (22:55 +0000)
Added validation handler. One or more handlers could configured in service binding. If a handler is configured for the service, the service layer callsback on the handler before create and update operations. Example validatorHandlers could be found in Account and CollectionObject services. Sends 400 (bad request) if  validation fails.
Deleted DocumentHandlerFactory.java and moved that code to AbstractServiceContext.java. Service context (that is aware of ther service binding) also acts as a factory for various handlers (validator, document) configured in the binding.
tests: account validation (userid, tenant info), collectionobject (othernumber), all service tests

M    services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java
A    services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/nuxeo/CollectionObjectValidatorHandler.java
M    services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java
M    services/dimension/service/src/main/java/org/collectionspace/services/dimension/DimensionResource.java
M    services/common/src/main/java/org/collectionspace/services/common/ServiceException.java
M    services/common/src/main/java/org/collectionspace/services/common/context/RemoteServiceContextImpl.java
M    services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
M    services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java
M    services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContext.java
M    services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContextImpl.java
M    services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandler.java
A    services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandler.java
D    services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandlerFactory.java
A    services/common/src/main/java/org/collectionspace/services/common/document/InvalidDocumentException.java
M    services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClient.java
M    services/common/src/main/config/tenant-bindings.xml
M    services/common/src/main/resources/service.xsd
M    services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java
M    services/contact/service/src/main/java/org/collectionspace/services/contact/ContactResource.java
A    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountJpaFilter.java
M    services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
M    services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
M    services/organization/service/src/main/java/org/collectionspace/services/organization/OrgAuthorityResource.java
_M   services/organization/import
M    services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java
M    services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java
M    services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java
M    services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java

29 files changed:
services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountJpaFilter.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java [new file with mode: 0644]
services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java
services/collectionobject/client/src/test/java/org/collectionspace/services/client/test/CollectionObjectServiceTest.java
services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java
services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/nuxeo/CollectionObjectValidatorHandler.java [new file with mode: 0644]
services/common/src/main/config/tenant-bindings.xml
services/common/src/main/java/org/collectionspace/services/common/ServiceException.java
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/context/MultipartServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/RemoteServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandler.java
services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandlerFactory.java [deleted file]
services/common/src/main/java/org/collectionspace/services/common/document/InvalidDocumentException.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandler.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClient.java
services/common/src/main/resources/service.xsd
services/contact/service/src/main/java/org/collectionspace/services/contact/ContactResource.java
services/dimension/service/src/main/java/org/collectionspace/services/dimension/DimensionResource.java
services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java
services/organization/service/src/main/java/org/collectionspace/services/organization/OrgAuthorityResource.java
services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java
services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java
services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java

index 09bb984ada704a94f390ec9a070d11235b252de8..aefc914ecd2350c516680f7e511b50aead510d34 100644 (file)
@@ -176,7 +176,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         resource2Id = extractId(res);
 
         AccountsCommon account3 =
-                createAccountInstance("dj", "hithere10", "dj@dinoland.com", true, true, true);
+                createAccountInstance("mj", "hithere10", "mj@dinoland.com", true, true, true);
         res = client.create(account3);
         statusCode = res.getStatus();
         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
index 4cbf0f54a35d489f08de5b95284587120643575e..2ff00573e4082bc1b26317c0d22d6c2231934d2e 100644 (file)
@@ -46,7 +46,6 @@ import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.storage.StorageClient;
 import org.jboss.resteasy.util.HttpResponseCodes;
@@ -91,9 +90,7 @@ public class AccountResource
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         docHandler.setCommonPart(ctx.getInput());
         return docHandler;
     }
index ec11b7dd971abf868d4a0c4e4242d90fbd00bf1b..f35de77316a17a88aa7518e738ede6e3c0ecbc56 100644 (file)
@@ -51,29 +51,12 @@ public class AccountDocumentHandler
     public void handleCreate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
         String id = UUID.randomUUID().toString();
         AccountsCommon account = wrapDoc.getWrappedObject();
-        if (account.getUserId() == null || "".equals(account.getUserId())) {
-            String msg = "userId is missing";
-            logger.error(msg);
-            throw new BadRequestException(msg);
-        }
-        List<AccountsCommon.Tenant> tl = account.getTenant();
-        if (tl == null || tl.size() == 0) {
-            String msg = "missing tenant information!";
-            logger.error(msg);
-            throw new BadRequestException(msg);
-        }
         account.setCsid(id);
         account.setStatus(Status.ACTIVE);
     }
 
     @Override
     public void handleUpdate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
-        if (account.getPassword() != null
-                && (account.getUserId() == null || "".equals(account.getUserId()))) {
-            String msg = "userId is missing";
-            logger.error(msg);
-            throw new BadRequestException(msg);
-        }
     }
 
     @Override
index 17635853c10631aa0229b1f78b1e4724a01d5011..ad6c95353c702684e6598d34c93f234444c25642 100644 (file)
@@ -104,7 +104,7 @@ public class AccountJpaFilter extends JpaDocumentFilter {
             hasWhere = true;
         }
 
-                String email = null;
+        String email = null;
         List<String> emailvals = getQueryParam(AccountStorageConstants.Q_EMAIL);
         if (emailvals != null) {
             email = emailvals.get(0);
diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java b/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java
new file mode 100644 (file)
index 0000000..487175f
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ *  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.
+ *//**
+ *  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.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.collectionspace.services.account.storage;
+
+import java.util.List;
+import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.document.InvalidDocumentException;
+import org.collectionspace.services.common.document.ValidatorHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author 
+ */
+public class AccountValidatorHandler implements ValidatorHandler {
+
+    final Logger logger = LoggerFactory.getLogger(AccountValidatorHandler.class);
+
+    @Override
+    public void validate(Action action, ServiceContext ctx)
+            throws InvalidDocumentException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("validate() action=" + action.name());
+        }
+        try {
+            AccountsCommon account = (AccountsCommon) ctx.getInput();
+            String msg = "validate() ";
+            boolean invalid = false;
+
+            List<AccountsCommon.Tenant> tl = account.getTenant();
+            if (tl == null || tl.size() == 0) {
+                msg += " missing tenant information!";
+                invalid = true;
+            }
+            if (action.equals(Action.CREATE)) {
+                //create specific validation here
+                if (account.getUserId() == null || "".equals(account.getUserId())) {
+                    invalid = true;
+                    msg += " userId is missing";
+                }
+            } else if (action.equals(Action.UPDATE)) {
+                //update specific validation here
+                if (account.getPassword() != null
+                        && (account.getUserId() == null || "".equals(account.getUserId()))) {
+                    invalid = true;
+                    msg += " userId is needed with password";
+                }
+            }
+            if (invalid) {
+                logger.error(msg);
+                throw new InvalidDocumentException(msg);
+            }
+        } catch (InvalidDocumentException ide) {
+            throw ide;
+        } catch (Exception e) {
+            throw new InvalidDocumentException(e);
+        }
+    }
+}
index eaab128527eb1ff3b9d779443836c10960b83526..951146ea0c54068356dbed92d36aedb529ea9f43 100644 (file)
@@ -45,7 +45,6 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.query.IQueryManager;
 import org.collectionspace.services.common.query.QueryManager;
 import org.collectionspace.services.common.security.UnauthorizedException;
@@ -78,9 +77,7 @@ public class AcquisitionResource
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), AcquisitionsCommon.class);
             if (obj != null) {
index bef77e5b3391f58bf8fd31824a7294019ac3cc47..45362fa0d36bb94ac9d1301fcd7fd8bbd89a1e94 100644 (file)
@@ -104,7 +104,7 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
 
         // Store the ID returned from the first resource created
         // for additional tests below.
-        if (knownResourceId == null){
+        if (knownResourceId == null) {
             knownResourceId = extractId(res);
             if (logger.isDebugEnabled()) {
                 logger.debug(testName + ": knownResourceId=" + knownResourceId);
@@ -132,14 +132,34 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
     // Placeholders until the three tests below can be uncommented.
     // See Issue CSPACE-401.
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class)
     public void createWithEmptyEntityBody(String testName) throws Exception {
     }
 
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class)
     public void createWithMalformedXml(String testName) throws Exception {
+        setupCreate(testName);
+
+        CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
+        collectionObject.setTitle("atitle");
+        //don't set objectNumber to check validation
+        collectionObject.setObjectName("some name");
+        MultipartOutput multipart =
+                createCollectionObjectInstance(client.getCommonPartName(), collectionObject, null);
+        ClientResponse<Response> res = client.create(multipart);
+        int statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
     }
 
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class)
     public void createWithWrongXmlSchema(String testName) throws Exception {
     }
 
@@ -350,12 +370,7 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
         // Perform setup.
         setupUpdate(testName);
 
-        ClientResponse<MultipartInput> res =
-                client.read(knownResourceId);
-        if (logger.isDebugEnabled()) {
-            logger.debug(testName + ": read status = " + res.getStatus());
-        }
-        Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
+        ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
 
         if (logger.isDebugEnabled()) {
             logger.debug("got object to update with ID: " + knownResourceId);
@@ -375,12 +390,8 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
                     CollectionobjectsCommon.class));
         }
 
-        // Submit the request to the service and store the response.
-        MultipartOutput output = new MultipartOutput();
-        OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
-        commonPart.getHeaders().add("label", client.getCommonPartName());
+        res = updateSend(testName, knownResourceId, collectionObject);
 
-        res = client.update(knownResourceId, output);
         int statusCode = res.getStatus();
         // Check the status code of the response: does it match the expected response(s)?
         if (logger.isDebugEnabled()) {
@@ -403,18 +414,82 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
 
     }
 
+    private ClientResponse<MultipartInput> updateRetrieve(String testName, String id) {
+        ClientResponse<MultipartInput> res =
+                client.read(id);
+        if (logger.isDebugEnabled()) {
+            logger.debug("read in updateRetrieve for " + testName + " status = " + res.getStatus());
+        }
+        Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("got object to updateRetrieve for " + testName + " with ID: " + id);
+        }
+        return res;
+    }
+
+    private ClientResponse<MultipartInput> updateSend(String testName, String id,
+            CollectionobjectsCommon collectionObject) {
+        MultipartOutput output = new MultipartOutput();
+        OutputPart commonPart = output.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
+        commonPart.getHeaders().add("label", client.getCommonPartName());
+
+        ClientResponse<MultipartInput> res = client.update(knownResourceId, output);
+        // Check the status code of the response: does it match the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug("updateSend for " + testName + ": status = " + res.getStatus());
+        }
+        return res;
+    }
+
     // Failure outcomes
     // Placeholders until the three tests below can be uncommented.
     // See Issue CSPACE-401.
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"read"})
     public void updateWithEmptyEntityBody(String testName) throws Exception {
     }
 
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"read"})
     public void updateWithMalformedXml(String testName) throws Exception {
+        // Perform setup.
+        setupUpdate(testName);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + " got object to update with ID: " + knownResourceId);
+        }
+
+        ClientResponse<MultipartInput> res = updateRetrieve(testName, knownResourceId);
+
+        MultipartInput input = (MultipartInput) res.getEntity();
+        CollectionobjectsCommon collectionObject =
+                (CollectionobjectsCommon) extractPart(input,
+                client.getCommonPartName(), CollectionobjectsCommon.class);
+        Assert.assertNotNull(collectionObject);
+
+        //update with invalid content
+        collectionObject.setObjectNumber("");
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + " updated object");
+            logger.debug(objectAsXmlString(collectionObject,
+                    CollectionobjectsCommon.class));
+        }
+
+        // Submit the request to the service and store the response.
+        res = updateSend(testName, knownResourceId, collectionObject);
+        int statusCode = res.getStatus();
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
+
     }
 
     @Override
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"read"})
     public void updateWithWrongXmlSchema(String testName) throws Exception {
     }
 
@@ -654,6 +729,20 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
         collectionObject.setBriefDescription("Papier mache bird cow mask with horns, "
                 + "painted red with black and yellow spots. "
                 + "Puerto Rico. ca. 8&quot; high, 6&quot; wide, projects 10&quot; (with horns).");
+
+        CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
+        conh.setNhString("test-string");
+        conh.setNhInt(999);
+        conh.setNhLong(9999);
+
+
+        MultipartOutput multipart = createCollectionObjectInstance(commonPartName, collectionObject, conh);
+        return multipart;
+    }
+
+    private MultipartOutput createCollectionObjectInstance(String commonPartName,
+            CollectionobjectsCommon collectionObject, CollectionobjectsNaturalhistory conh) {
+
         MultipartOutput multipart = new MultipartOutput();
         OutputPart commonPart = multipart.addPart(collectionObject,
                 MediaType.APPLICATION_XML_TYPE);
@@ -665,17 +754,15 @@ public class CollectionObjectServiceTest extends AbstractServiceTest {
                     CollectionobjectsCommon.class));
         }
 
-        CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
-        conh.setNhString("test-string");
-        conh.setNhInt(999);
-        conh.setNhLong(9999);
-        OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
-        nhPart.getHeaders().add("label", getNHPartName());
+        if (conh != null) {
+            OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
+            nhPart.getHeaders().add("label", getNHPartName());
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("to be created, collectionobject nhistory");
-            logger.debug(objectAsXmlString(conh,
-                    CollectionobjectsNaturalhistory.class));
+            if (logger.isDebugEnabled()) {
+                logger.debug("to be created, collectionobject nhistory");
+                logger.debug(objectAsXmlString(conh,
+                        CollectionobjectsNaturalhistory.class));
+            }
         }
         return multipart;
 
index caf3e1c69d62534625daf599b9cb982d99b3376d..44e9ae78afcf4abc93abbd0c7b09f2f3d3d85031 100644 (file)
@@ -46,10 +46,10 @@ import org.collectionspace.services.common.AbstractCollectionSpaceResource;
 import org.collectionspace.services.common.context.MultipartServiceContext;
 import org.collectionspace.services.common.context.MultipartServiceContextFactory;
 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.document.DocumentFilter;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
@@ -68,11 +68,11 @@ public class CollectionObjectResource
 
     @Override
     protected String getVersionString() {
-       /** The last change revision. */
-       final String lastChangeRevision = "$LastChangedRevision$";
-       return lastChangeRevision;
+        /** The last change revision. */
+        final String lastChangeRevision = "$LastChangedRevision$";
+        return lastChangeRevision;
     }
-    
+
     @Override
     public String getServiceName() {
         return serviceName;
@@ -80,11 +80,10 @@ public class CollectionObjectResource
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
-            Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), CollectionobjectsCommon.class);
+            Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(),
+                    CollectionobjectsCommon.class);
             if (obj != null) {
                 docHandler.setCommonPart((CollectionobjectsCommon) obj);
             }
@@ -102,6 +101,10 @@ public class CollectionObjectResource
             path.path("" + csid);
             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();
@@ -211,6 +214,10 @@ public class CollectionObjectResource
             DocumentHandler handler = createDocumentHandler(ctx);
             getRepositoryClient(ctx).update(ctx, csid, handler);
             result = (MultipartOutput) ctx.getOutput();
+        } catch (BadRequestException bre) {
+            Response response = Response.status(
+                    Response.Status.BAD_REQUEST).entity("Update failed reason " + bre.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
         } catch (UnauthorizedException ue) {
             Response response = Response.status(
                     Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
@@ -268,12 +275,12 @@ public class CollectionObjectResource
         }
 
     }
-    
+
     @GET
-    @Path("/search")    
+    @Path("/search")
     @Produces("application/xml")
     public CollectionobjectsCommonList keywordsSearchCollectionObjects(@Context UriInfo ui,
-               @QueryParam (IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords) {
+            @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords) {
         CollectionobjectsCommonList collectionObjectList = new CollectionobjectsCommonList();
         try {
             ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
@@ -281,18 +288,18 @@ public class CollectionObjectResource
 
             // perform a keyword search
             if (keywords != null && !keywords.isEmpty()) {
-               String whereClause = QueryManager.createWhereClauseFromKeywords(keywords);
-                   DocumentFilter documentFilter = handler.getDocumentFilter();
-                   documentFilter.setWhereClause(whereClause);
-                   if (logger.isDebugEnabled()) {
-                       logger.debug("The WHERE clause is: " + documentFilter.getWhereClause());
-                   }
-                   getRepositoryClient(ctx).getFiltered(ctx, handler);
+                String whereClause = QueryManager.createWhereClauseFromKeywords(keywords);
+                DocumentFilter documentFilter = handler.getDocumentFilter();
+                documentFilter.setWhereClause(whereClause);
+                if (logger.isDebugEnabled()) {
+                    logger.debug("The WHERE clause is: " + documentFilter.getWhereClause());
+                }
+                getRepositoryClient(ctx).getFiltered(ctx, handler);
             } else {
-               getRepositoryClient(ctx).getAll(ctx, handler);
-            }            
+                getRepositoryClient(ctx).getAll(ctx, handler);
+            }
             collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
-            
+
         } catch (UnauthorizedException ue) {
             Response response = Response.status(
                     Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
@@ -306,5 +313,5 @@ public class CollectionObjectResource
             throw new WebApplicationException(response);
         }
         return collectionObjectList;
-    }    
+    }
 }
diff --git a/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/nuxeo/CollectionObjectValidatorHandler.java b/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/nuxeo/CollectionObjectValidatorHandler.java
new file mode 100644 (file)
index 0000000..a8a8730
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ *  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.
+ *//**
+ *  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.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.collectionspace.services.collectionobject.nuxeo;
+
+import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
+import org.collectionspace.services.common.context.MultipartServiceContext;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.document.InvalidDocumentException;
+import org.collectionspace.services.common.document.ValidatorHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author 
+ */
+public class CollectionObjectValidatorHandler implements ValidatorHandler {
+
+    final Logger logger = LoggerFactory.getLogger(CollectionObjectValidatorHandler.class);
+
+    @Override
+    public void validate(Action action, ServiceContext ctx)
+            throws InvalidDocumentException {
+        if(logger.isDebugEnabled()) {
+            logger.debug("validate() action=" + action.name());
+        }
+        try {
+            MultipartServiceContext mctx = (MultipartServiceContext) ctx;
+            CollectionobjectsCommon co = (CollectionobjectsCommon) mctx.getInputPart(mctx.getCommonPartLabel(),
+                    CollectionobjectsCommon.class);
+            String msg = "";
+            boolean invalid = false;
+            if (co.getObjectNumber() == null || co.getObjectNumber().isEmpty()) {
+                invalid = true;
+                msg += "objectNumber is missing!";
+            }
+            if(action.equals(Action.CREATE)) {
+                //create specific validation here
+            } else if(action.equals(Action.UPDATE)) {
+                //update specific validation here
+            }
+
+            if (invalid) {
+                logger.error(msg);
+                throw new InvalidDocumentException(msg);
+            }
+        } catch (InvalidDocumentException ide) {
+            throw ide;
+        } catch (Exception e) {
+            throw new InvalidDocumentException(e);
+        }
+    }
+}
index 4c3b3ae69464e87a1111afcf5b422d066e9d8308..072bfdb3985c4448ce447f870a05db0a4a691930 100644 (file)
@@ -19,6 +19,9 @@
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.collectionobject.nuxeo.CollectionObjectDocumentModelHandler
             </service:documentHandler>
+            <service:validatorHandler xmlns:service='http://collectionspace.org/services/common/service'>
+                org.collectionspace.services.collectionobject.nuxeo.CollectionObjectValidatorHandler
+            </service:validatorHandler>
             <service:object name="CollectionObject" version="0.1"
                             xmlns:service='http://collectionspace.org/services/common/service'>
                 <service:part id="0" control_group="Managed"
             <service:documentHandler xmlns:service='http://collectionspace.org/services/common/service'>
                 org.collectionspace.services.account.storage.AccountDocumentHandler
             </service:documentHandler>
+            <service:validatorHandler xmlns:service='http://collectionspace.org/services/common/service'>
+                org.collectionspace.services.account.storage.AccountValidatorHandler
+            </service:validatorHandler>
             <service:object name="Acccount" version="0.1"
                             xmlns:service='http://collectionspace.org/services/common/service'>
                 <service:part id="0" control_group="Managed"
index dca50ac1c1e4f5a0242317ddad8f3ae2227bc203..f396bbb7ab21f92f11f8866b252966f8adf1c9aa 100644 (file)
@@ -36,7 +36,6 @@ package org.collectionspace.services.common;
 public class ServiceException extends Exception {
 
     private int errorCode;
-    private String errorReason;
 
     /**
      * Creates a new instance of <code>ServiceException</code> without detail message, error code
@@ -68,8 +67,8 @@ public class ServiceException extends Exception {
      * @param errorReason reason for error
      */
     public ServiceException(int errorCode, String errorReason) {
+        super(errorReason);
         this.errorCode = errorCode;
-        this.errorReason = errorReason;
     }
 
     /**
@@ -124,13 +123,6 @@ public class ServiceException extends Exception {
      * @return the errorReason
      */
     public String getErrorReason() {
-        return errorReason;
-    }
-
-    /**
-     * @param errorReason the ErrorReason to set
-     */
-    public void setErrorReason(String errorReason) {
-        this.errorReason = errorReason;
+        return getMessage();
     }
 }
index 7c43515813a3d4e3745059e3b1c8eb11f5b1fa88..0bdca628f76a6afb7c88bc7adbfda848d5ad74a5 100644 (file)
@@ -24,6 +24,7 @@
 package org.collectionspace.services.common.context;
 
 import java.security.acl.Group;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
@@ -37,6 +38,8 @@ import org.collectionspace.authentication.CSpaceTenant;
 import org.collectionspace.services.common.ClientType;
 import org.collectionspace.services.common.ServiceMain;
 import org.collectionspace.services.common.config.TenantBindingConfigReader;
+import org.collectionspace.services.common.document.DocumentHandler;
+import org.collectionspace.services.common.document.ValidatorHandler;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.service.ObjectPartType;
 import org.collectionspace.services.common.service.ServiceBindingType;
@@ -60,6 +63,8 @@ public abstract class AbstractServiceContext<IT, OT>
     private ServiceBindingType serviceBinding;
     private TenantBindingType tenantBinding;
     private String overrideDocumentType = null;
+    private List<ValidatorHandler> valHandlers = null;
+    private DocumentHandler docHandler = null;
 
     public AbstractServiceContext(String serviceName) throws UnauthorizedException {
         TenantBindingConfigReader tReader =
@@ -130,7 +135,7 @@ public abstract class AbstractServiceContext<IT, OT>
 
     @Override
     public String getRepositoryClientName() {
-        if(serviceBinding.getRepositoryClient() == null) {
+        if (serviceBinding.getRepositoryClient() == null) {
             return null;
         }
         return serviceBinding.getRepositoryClient().trim();
@@ -164,19 +169,6 @@ public abstract class AbstractServiceContext<IT, OT>
         return serviceBinding;
     }
 
-    @Override
-    public String getDocumentHandlerClass() {
-        if (serviceBinding.getDocumentHandler() == null
-                || serviceBinding.getDocumentHandler().isEmpty()) {
-            String msg = "Missing documentHandler in service binding for "
-                    + getServiceName() + " for tenant id=" + getTenantId()
-                    + " name=" + getTenantName();
-            logger.error(msg);
-            throw new IllegalStateException(msg);
-        }
-        return serviceBinding.getDocumentHandler().trim();
-    }
-
     @Override
     public String getServiceName() {
         return serviceBinding.getName();
@@ -282,6 +274,54 @@ public abstract class AbstractServiceContext<IT, OT>
         return tenantId;
     }
 
+    @Override
+    public DocumentHandler getDocumentHandler() throws Exception {
+        if (docHandler != null) {
+            return docHandler;
+        }
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        Class c = tccl.loadClass(getDocumentHandlerClass());
+        if (DocumentHandler.class.isAssignableFrom(c)) {
+            docHandler = (DocumentHandler) c.newInstance();
+        } else {
+            throw new IllegalArgumentException("Not of type " +
+                    DocumentHandler.class.getCanonicalName());
+        }
+        docHandler.setServiceContext(this);
+        return docHandler;
+    }
+
+    private String getDocumentHandlerClass() {
+        if (serviceBinding.getDocumentHandler() == null
+                || serviceBinding.getDocumentHandler().isEmpty()) {
+            String msg = "Missing documentHandler in service binding for "
+                    + getServiceName() + " for tenant id=" + getTenantId()
+                    + " name=" + getTenantName();
+            logger.error(msg);
+            throw new IllegalStateException(msg);
+        }
+        return serviceBinding.getDocumentHandler().trim();
+    }
+
+    @Override
+    public List<ValidatorHandler> getValidatorHandlers() throws Exception {
+        if (valHandlers != null) {
+            return valHandlers;
+        }
+        List<String> handlerClazzes = getServiceBinding().getValidatorHandler();
+        List<ValidatorHandler> handlers = new ArrayList<ValidatorHandler>(handlerClazzes.size());
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        for (String clazz : handlerClazzes) {
+            clazz = clazz.trim();
+            Class c = tccl.loadClass(clazz);
+            if (ValidatorHandler.class.isAssignableFrom(c)) {
+                handlers.add((ValidatorHandler) c.newInstance());
+            }
+        }
+        valHandlers = handlers;
+        return valHandlers;
+    }
+
     @Override
     public String toString() {
         StringBuilder msg = new StringBuilder();
index e17a5abdcc9e1ce197ef491981071d2d0151a48e..7063485a1a52a87fb282a74686bc2b25c181c78a 100644 (file)
@@ -24,6 +24,7 @@
 package org.collectionspace.services.common.context;
 
 import java.io.IOException;
+import java.io.InputStream;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 import org.w3c.dom.Document;
@@ -65,13 +66,28 @@ public interface MultipartServiceContext
     public void setOutput(MultipartOutput output);
 
     /**
-     * getInputPart returns part for given label from input
+     * getInputPart returns the input part object for given label and clazz
      * @param label
      * @param clazz class of the object
      * @return part
      */
     public Object getInputPart(String label, Class clazz) throws IOException;
 
+    /**
+     * getInputPartAsString returns the input part with given label in the string form
+     * @param label
+     * @return
+     * @throws IOException
+     */
+    public String getInputPartAsString(String label) throws IOException;
+
+    /**
+     * getInputPartAsStream returns input part as stream for given label
+     * @param label
+     * @return
+     * @throws IOException
+     */
+    public InputStream getInputPartAsStream(String label) throws IOException;
     /**
      * addOutputPart adds given XML part with given label and content type to output
      * @param label
index 5e99ab85033123d2010351a021149a35239264d6..a997a4102333de07984d2304b1f03452e49b0ceb 100644 (file)
  */
 package org.collectionspace.services.common.context;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.lang.reflect.Constructor;
 import javax.ws.rs.core.MediaType;
 import org.collectionspace.services.common.document.DocumentUtils;
@@ -55,41 +57,68 @@ public class MultipartServiceContextImpl
     }
 
 
-    @Override
-    public Object getInputPart(String label, Class clazz) throws IOException {
-        Object obj = null;
-        if(getInput() != null){
+    private InputPart getInputPart(String label) throws IOException {
+        if (getInput() != null) {
             MultipartInput fdip = getInput();
 
-            for(InputPart part : fdip.getParts()){
+            for (InputPart part : fdip.getParts()) {
                 String partLabel = part.getHeaders().getFirst("label");
-                if(label.equalsIgnoreCase(partLabel)){
-                    if(logger.isDebugEnabled()){
-                        logger.debug("received part label=" + partLabel +
-                                "\npayload=" + part.getBodyAsString());
+                if (label.equalsIgnoreCase(partLabel)) {
+                    if (logger.isTraceEnabled()) {
+                        logger.trace("getInputPart found part with label=" + partLabel
+                                "\npayload=" + part.getBodyAsString());
                     }
-                    obj = part.getBody(clazz, null);
-                    break;
+                    return part;
                 }
             }
         }
+        return null;
+    }
+
+    @Override
+    public Object getInputPart(String label, Class clazz) throws IOException {
+        Object obj = null;
+        InputPart part = getInputPart(label);
+        if (part != null) {
+            obj = part.getBody(clazz, null);
+        }
         return obj;
     }
 
+    @Override
+    public String getInputPartAsString(String label) throws IOException {
+        InputPart part = getInputPart(label);
+        if (part != null) {
+            return part.getBodyAsString();
+        }
+        return null;
+    }
+
+    @Override
+    public InputStream getInputPartAsStream(String label) throws IOException {
+        InputPart part = getInputPart(label);
+        if (part != null) {
+            return new ByteArrayInputStream(part.getBodyAsString().getBytes());
+        }
+        return null;
+    }
+
+
     @Override
     public void addOutputPart(String label, Document doc, String contentType) throws Exception {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try{
+        try {
             DocumentUtils.writeDocument(doc, baos);
             baos.close();
             OutputPart part = getOutput().addPart(new String(baos.toByteArray()),
                     MediaType.valueOf(contentType));
             part.getHeaders().add("label", label);
-        }finally{
-            if(baos != null){
-                try{
+        } finally {
+            if (baos != null) {
+                try {
                     baos.close();
-                }catch(Exception e){
+                } catch (Exception e) {
                 }
             }
         }
@@ -99,13 +128,13 @@ public class MultipartServiceContextImpl
     public ServiceContext getLocalContext(String localContextClassName) throws Exception {
         ClassLoader cloader = Thread.currentThread().getContextClassLoader();
         Class ctxClass = cloader.loadClass(localContextClassName);
-        if(!ServiceContext.class.isAssignableFrom(ctxClass)) {
-            throw new IllegalArgumentException("getLocalContext requires " +
-                    " implementation of " + ServiceContext.class.getName());
+        if (!ServiceContext.class.isAssignableFrom(ctxClass)) {
+            throw new IllegalArgumentException("getLocalContext requires "
+                    " implementation of " + ServiceContext.class.getName());
         }
-        
+
         Constructor ctor = ctxClass.getConstructor(java.lang.String.class);
-        ServiceContext ctx = (ServiceContext)ctor.newInstance(getServiceName());
+        ServiceContext ctx = (ServiceContext) ctor.newInstance(getServiceName());
         return ctx;
     }
 }
index d5321864445168e377103da9770779b36da76b73..ca4da809922e417609f62cd28bc9bc9454ff9362 100644 (file)
@@ -53,7 +53,13 @@ public class RemoteServiceContextImpl<IT, OT>
     }
 
     @Override
-    public void setInput(IT input){
+    public void setInput(IT input) {
+        //for security reasons, do not allow to set input again (from handlers)
+        if (this.input != null) {
+            String msg = "Non-null input cannot be set!";
+            logger.error(msg);
+            throw new IllegalStateException(msg);
+        }
         this.input = input;
     }
 
@@ -63,22 +69,21 @@ public class RemoteServiceContextImpl<IT, OT>
     }
 
     @Override
-    public void setOutput(OT output){
+    public void setOutput(OT output) {
         this.output = output;
     }
 
-
     @Override
     public ServiceContext getLocalContext(String localContextClassName) throws Exception {
         ClassLoader cloader = Thread.currentThread().getContextClassLoader();
         Class ctxClass = cloader.loadClass(localContextClassName);
-        if(!ServiceContext.class.isAssignableFrom(ctxClass)) {
-            throw new IllegalArgumentException("getLocalContext requires " +
-                    " implementation of " + ServiceContext.class.getName());
+        if (!ServiceContext.class.isAssignableFrom(ctxClass)) {
+            throw new IllegalArgumentException("getLocalContext requires "
+                    " implementation of " + ServiceContext.class.getName());
         }
-        
+
         Constructor ctor = ctxClass.getConstructor(java.lang.String.class);
-        ServiceContext ctx = (ServiceContext)ctor.newInstance(getServiceName());
+        ServiceContext ctx = (ServiceContext) ctor.newInstance(getServiceName());
         return ctx;
     }
 }
index 6ce74c0be91b6cda560fd77beeff754399fb9e80..ac06bd2f4b85b92f8ea6570551e457f7dd564830 100644 (file)
  */
 package org.collectionspace.services.common.context;
 
-import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 import org.collectionspace.services.common.ClientType;
+import org.collectionspace.services.common.document.DocumentHandler;
+import org.collectionspace.services.common.document.ValidatorHandler;
 import org.collectionspace.services.common.service.ObjectPartType;
 import org.collectionspace.services.common.service.ServiceBindingType;
 
@@ -126,11 +127,6 @@ public interface ServiceContext<IT, OT> {
      */
     public String getRepositoryWorkspaceId();
 
-    /**
-     * getDocumentHandlerClass returns the class name for document handler
-     * @return class name of document handler
-     */
-    public String getDocumentHandlerClass();
 
     /**
      * Get input parts as received over the wire from service consumer
@@ -200,6 +196,21 @@ public interface ServiceContext<IT, OT> {
      */
     public void setProperty(String name, Object o);
 
+
+    /**
+     * getDocumentHanlder returns document handler configured in the the binding
+     * it creates the handler if necessary.
+     * @return document handler
+     */
+    public DocumentHandler getDocumentHandler() throws Exception;
+
+    /**
+     * getValidatorHandlers returns registered (from binding) validtor handlers
+     * for the service. it creates the handlers if necessary.
+     * @return validation handlers
+     */
+    public List<ValidatorHandler> getValidatorHandlers() throws Exception;
+
 }
 
 
index 12821e8126a782596ec4a65c60ff6fbff7f193fd..a6d388f00c0d963e825bae47dbc0bd27da9fb400 100644 (file)
@@ -24,6 +24,7 @@
 package org.collectionspace.services.common.document;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import java.util.StringTokenizer;
@@ -98,10 +99,12 @@ public abstract class AbstractDocumentHandler<T, TL, WT, WTL>
     final public void prepare(Action action) throws Exception {
         switch (action) {
             case CREATE:
+                validate(action);
                 prepareCreate();
                 break;
 
             case UPDATE:
+                validate(action);
                 prepareUpdate();
                 break;
 
@@ -258,4 +261,11 @@ public abstract class AbstractDocumentHandler<T, TL, WT, WTL>
     public String getServiceContextPath() {
         return "/" + getServiceContext().getServiceName().toLowerCase() + "/";
     }
+
+    private void validate(Action action) throws Exception {
+        List<ValidatorHandler> valHandlers = serviceContext.getValidatorHandlers();
+        for (ValidatorHandler handler : valHandlers) {
+            handler.validate(action, serviceContext);
+        }
+    }
 }
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandlerFactory.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandlerFactory.java
deleted file mode 100644 (file)
index 3bd6d75..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- *  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.common.document;
-
-/**
- *
- * DocumentHandlerFactory creates document handler
- *
- */
-public class DocumentHandlerFactory {
-
-    private static final DocumentHandlerFactory self = new DocumentHandlerFactory();
-
-    private DocumentHandlerFactory() {
-    }
-
-    public static DocumentHandlerFactory getInstance() {
-        return self;
-    }
-
-    /**
-     * getHandler returns a document handler. The factory may create a new
-     * stateful handler or return an existing stateless handler.
-     * @param clazz name of the class to instantiate. The class should implement
-     * DocumentHandler
-     */
-    public DocumentHandler getHandler(String clazz)
-            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
-        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
-        Class c = tccl.loadClass(clazz);
-        if (DocumentHandler.class.isAssignableFrom(c)) {
-            return (DocumentHandler) c.newInstance();
-        } else {
-            throw new IllegalArgumentException("Not of type " + DocumentHandler.class.getCanonicalName());
-        }
-    }
-}
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/InvalidDocumentException.java b/services/common/src/main/java/org/collectionspace/services/common/document/InvalidDocumentException.java
new file mode 100644 (file)
index 0000000..0abded3
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ *  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.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.collectionspace.services.common.document;
+
+/**
+ * InvalidDocumentException is used to indicate one or more parts of service
+ * document has failed to validate
+ * @author 
+ */
+public class InvalidDocumentException extends BadRequestException {
+
+    /**
+     * Creates a new instance of <code>InvalidDocumentException</code> without detail message.
+     */
+    public InvalidDocumentException() {
+    }
+
+    /**
+     * Constructs an instance of <code>InvalidDocumentException</code> with the specified detail message.
+     * @param msg the detail message.
+     */
+    public InvalidDocumentException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * <code>cause</code> is <i>not</i> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param  message the detail message (which is saved for later retrieval
+     *         by the {@link #getMessage()} method).
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     * @since  1.4
+     */
+    public InvalidDocumentException(String message, Throwable cause) {
+        super(message, cause);
+        setErrorCode(HTTP_CODE);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail
+     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+     * typically contains the class and detail message of <tt>cause</tt>).
+     * This constructor is useful for exceptions that are little more than
+     * wrappers for other throwables (for example, {@link
+     * java.security.PrivilegedActionException}).
+     *
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     * @since  1.4
+     */
+    public InvalidDocumentException(Throwable cause) {
+        super(cause);
+        setErrorCode(HTTP_CODE);
+    }
+}
diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandler.java b/services/common/src/main/java/org/collectionspace/services/common/document/ValidatorHandler.java
new file mode 100644 (file)
index 0000000..2fc6559
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ *  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.common.document;
+
+import org.collectionspace.services.common.context.ServiceContext;
+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 {
+
+    /**
+     * validate is called by the document handler for CREATE and UPDATE actions.
+     * validation is performed as soon as requests are unmarshalled but before any
+     * storage work is performed.
+     * the handler is caleld only if it is registered using the service binding
+     * @param action
+     * @param ctx
+     * @throws InvalidDocumentException
+     */
+    public void validate(Action action, ServiceContext ctx)
+            throws InvalidDocumentException;
+}
index 15f9b03620165b2df7d3a70d7bf473629b8f05b9..27f475394dacab08a01ae331f0dd46630bc90579 100644 (file)
@@ -84,8 +84,8 @@ public class RepositoryJavaClient implements RepositoryClient {
         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
         if (nuxeoWspaceId == null) {
             throw new DocumentNotFoundException(
-                    "Unable to find workspace for service " + ctx.getServiceName() +
-                    " check if the workspace exists in the Nuxeo repository");
+                    "Unable to find workspace for service " + ctx.getServiceName()
+                    " check if the workspace exists in the Nuxeo repository");
         }
         RepositoryInstance repoSession = null;
         try {
@@ -107,6 +107,8 @@ public class RepositoryJavaClient implements RepositoryClient {
             repoSession.save();
             handler.complete(Action.CREATE, wrapDoc);
             return id;
+        } catch (BadRequestException bre) {
+            throw bre;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
@@ -193,9 +195,9 @@ public class RepositoryJavaClient implements RepositoryClient {
         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
         if (nuxeoWspaceId == null) {
             throw new DocumentNotFoundException(
-                    "Unable to find workspace for service " +
-                    ctx.getServiceName() +
-                    " check if the workspace exists in the Nuxeo repository");
+                    "Unable to find workspace for service "
+                    + ctx.getServiceName()
+                    " check if the workspace exists in the Nuxeo repository");
         }
         RepositoryInstance repoSession = null;
 
@@ -264,7 +266,7 @@ public class RepositoryJavaClient implements RepositoryClient {
             query.append(" WHERE ecm:path STARTSWITH '/" + domain + "'");
             if ((null != where) && (where.length() > 0)) {
 //              query.append(" AND " + where);
-                query.append(" AND " + where + "AND ecm:isProxy = 0");                
+                query.append(" AND " + where + "AND ecm:isProxy = 0");
             }
             DocumentModelList docList = null;
             if ((docFilter.getOffset() > 0) || (docFilter.getPageSize() > 0)) {
@@ -331,6 +333,8 @@ public class RepositoryJavaClient implements RepositoryClient {
             repoSession.saveDocument(doc);
             repoSession.save();
             handler.complete(Action.UPDATE, wrapDoc);
+        } catch (BadRequestException bre) {
+            throw bre;
         } catch (DocumentException de) {
             throw de;
         } catch (Exception e) {
@@ -392,20 +396,20 @@ public class RepositoryJavaClient implements RepositoryClient {
         try {
             repoSession = getRepositorySession();
             DocumentRef docRef = new PathRef(
-                    "/" + tenantDomain +
-                    "/" + "workspaces");
+                    "/" + tenantDomain
+                    "/" + "workspaces");
             DocumentModel parent = repoSession.getDocument(docRef);
             DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
                     workspaceName, "Workspace");
             doc.setPropertyValue("dc:title", workspaceName);
-            doc.setPropertyValue("dc:description", "A CollectionSpace workspace for " +
-                    workspaceName);
+            doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
+                    workspaceName);
             doc = repoSession.createDocument(doc);
             workspaceId = doc.getId();
             repoSession.save();
             if (logger.isDebugEnabled()) {
-                logger.debug("created workspace name=" + workspaceName +
-                        " id=" + workspaceId);
+                logger.debug("created workspace name=" + workspaceName
+                        " id=" + workspaceId);
             }
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
@@ -427,9 +431,9 @@ public class RepositoryJavaClient implements RepositoryClient {
         try {
             repoSession = getRepositorySession();
             DocumentRef docRef = new PathRef(
-                    "/" + tenantDomain +
-                    "/" + "workspaces" +
-                    "/" + workspaceName);
+                    "/" + tenantDomain
+                    + "/" + "workspaces"
+                    "/" + workspaceName);
             DocumentModel workspace = repoSession.getDocument(docRef);
             workspaceId = workspace.getId();
         } catch (DocumentException de) {
@@ -465,7 +469,7 @@ public class RepositoryJavaClient implements RepositoryClient {
             client.releaseRepository(repoSession);
         } catch (Exception e) {
             logger.error("Could not close the repository session", e);
-        // no need to throw this service specific exception
+            // no need to throw this service specific exception
         }
     }
 }
index a944daa641c864c6949c52a3d401cf4ce6434efb..78e85f2fed52ec5e258d6fedc09e0f1eb52ca4a8 100644 (file)
@@ -39,9 +39,6 @@
             <!-- 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"/>
-            <!-- event handler is called during prepare and complete document handler events -->
-            <!-- event handler is called for create, get, update, delete, index and search requests -->
-            <xs:element name="eventHandler" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
             <!-- name of the repository client (from service-config.xml) -->
             <xs:element name="repositoryClient" type="xs:string" minOccurs="0" maxOccurs="1"/>
             <!-- repositoryWorkspaceId could be workspace id -->
index 6879e24d8823f2ecfcb6f7bc115f1c6027080c28..22fc2dad043ec0596a138006d218f7cbdc16073b 100644 (file)
@@ -46,7 +46,6 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
 
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
@@ -82,9 +81,7 @@ public class ContactResource extends AbstractCollectionSpaceResource {
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(), ContactsCommon.class);
             if (obj != null) {
index 73ed3f3a967e02a639f07b10e525092cbf51889a..c7d27878ef60be92a5d037b9d1dae488ab7dd6c6 100644 (file)
@@ -47,7 +47,6 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
 import org.jboss.resteasy.util.HttpResponseCodes;
@@ -82,9 +81,7 @@ public class DimensionResource extends AbstractCollectionSpaceResource {
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(), DimensionsCommon.class);
             if (obj != null) {
index d84f4138c53736369019efcda44a7f6dc75ed9c0..d437fb00237e467c46d0e333bf6f817898daab73 100644 (file)
@@ -48,7 +48,6 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.query.IQueryManager;
 import org.collectionspace.services.common.query.QueryManager;
 import org.collectionspace.services.common.security.UnauthorizedException;
@@ -86,9 +85,7 @@ public class IntakeResource extends AbstractCollectionSpaceResource {
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), IntakesCommon.class);
             if (obj != null) {
index 3826866d6007f074570e74815091817c63803a37..6f592b92c9ad222c840c11398164fe6754151fd8 100644 (file)
@@ -48,7 +48,6 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor
 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.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.query.IQueryManager;
@@ -99,9 +98,7 @@ public class OrgAuthorityResource extends AbstractCollectionSpaceResource {
      */
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler =ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), OrgauthoritiesCommon.class);
             if (obj != null) {
@@ -114,9 +111,7 @@ public class OrgAuthorityResource extends AbstractCollectionSpaceResource {
     private DocumentHandler createItemDocumentHandler(
             ServiceContext ctx,
             String inAuthority) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         ((OrganizationDocumentModelHandler) docHandler).setInAuthority(inAuthority);
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()),
index de99b0d5f0f6f23b4b35f15bd9dddb3061a16279..45f9f9c23e2271cb9d53b208cf89015446368d7e 100644 (file)
@@ -48,7 +48,6 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor
 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.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.query.IQueryManager;
@@ -99,9 +98,7 @@ public class PersonAuthorityResource extends AbstractCollectionSpaceResource {
      */
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), PersonauthoritiesCommon.class);
             if (obj != null) {
@@ -114,9 +111,7 @@ public class PersonAuthorityResource extends AbstractCollectionSpaceResource {
     private DocumentHandler createItemDocumentHandler(
             ServiceContext ctx,
             String inAuthority) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         ((PersonDocumentModelHandler) docHandler).setInAuthority(inAuthority);
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()),
index c7c2d3909bdc907523a3c91e392da76579747b0a..6763ff0bb25f3f5fc4f8652d30b5d648810b7e94 100644 (file)
@@ -50,7 +50,6 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.relation.IRelationsManager;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
@@ -80,9 +79,7 @@ public class NewRelationResource extends AbstractCollectionSpaceResource {
 
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), RelationsCommon.class);
             if (obj != null) {
index 6360a229fd50b7c6a04b21d3e85dc678e87afc77..d933061bddadecf41297ce393c1f96b561549607 100644 (file)
@@ -48,7 +48,6 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor
 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.document.DocumentHandlerFactory;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.query.IQueryManager;
@@ -99,9 +98,7 @@ public class VocabularyResource extends AbstractCollectionSpaceResource {
      */
     @Override
     public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), VocabulariesCommon.class);
             if (obj != null) {
@@ -114,9 +111,7 @@ public class VocabularyResource extends AbstractCollectionSpaceResource {
     private DocumentHandler createItemDocumentHandler(
             ServiceContext ctx,
             String inVocabulary) throws Exception {
-        DocumentHandler docHandler = DocumentHandlerFactory.getInstance().getHandler(
-                ctx.getDocumentHandlerClass());
-        docHandler.setServiceContext(ctx);
+        DocumentHandler docHandler = ctx.getDocumentHandler();
         ((VocabularyItemDocumentModelHandler) docHandler).setInVocabulary(inVocabulary);
         if (ctx.getInput() != null) {
             Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()),