You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2014/03/05 18:13:15 UTC

svn commit: r1574576 [1/2] - in /chemistry/opencmis/trunk/chemistry-opencmis-server: chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/ chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/open...

Author: fmui
Date: Wed Mar  5 17:13:14 2014
New Revision: 1574576

URL: http://svn.apache.org/r1574576
Log:
CMIS-764: pluggable CMIS service wrappers (unfinished) 

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/ConformanceCmisServiceWrapper.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/SimpleLoggingCmisServiceWrapper.java   (with props)
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisService.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisServiceFactory.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java?rev=1574576&r1=1574575&r2=1574576&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/CmisRepositoryContextListener.java Wed Mar  5 17:13:14 2014
@@ -55,7 +55,13 @@ public class CmisRepositoryContextListen
         }
 
         // create services factory
-        CmisServiceFactory factory = createServiceFactory(configFilename);
+        CmisServiceFactory factory = null;
+        try {
+            factory = createServiceFactory(configFilename);
+        } catch (Exception e) {
+            LOG.error("Service factory couldn't be created: " + e.toString(), e);
+            return;
+        }
 
         // set the services factory into the servlet context
         sce.getServletContext().setAttribute(SERVICES_FACTORY, factory);
@@ -65,7 +71,12 @@ public class CmisRepositoryContextListen
         // destroy services factory
         CmisServiceFactory factory = (CmisServiceFactory) sce.getServletContext().getAttribute(SERVICES_FACTORY);
         if (factory != null) {
-            factory.destroy();
+            try {
+                factory.destroy();
+            } catch (Exception e) {
+                LOG.error("Service factory couldn't be destroyed: " + e.toString(), e);
+                return;
+            }
         }
     }
 

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisService.java?rev=1574576&r1=1574575&r2=1574576&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisService.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisService.java Wed Mar  5 17:13:14 2014
@@ -48,11 +48,12 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.impl.server.AbstractCmisService;
 import org.apache.chemistry.opencmis.commons.server.CallContext;
 import org.apache.chemistry.opencmis.commons.spi.Holder;
+import org.apache.chemistry.opencmis.server.support.wrapper.CallContextAwareCmisService;
 
 /**
  * FileShare Service implementation.
  */
-public class FileShareCmisService extends AbstractCmisService {
+public class FileShareCmisService extends AbstractCmisService implements CallContextAwareCmisService {
 
     private final FileShareRepositoryManager repositoryManager;
     private CallContext context;

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisServiceFactory.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisServiceFactory.java?rev=1574576&r1=1574575&r2=1574576&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisServiceFactory.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-fileshare/src/main/java/org/apache/chemistry/opencmis/fileshare/FileShareCmisServiceFactory.java Wed Mar  5 17:13:14 2014
@@ -27,7 +27,9 @@ import java.util.Map;
 import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory;
 import org.apache.chemistry.opencmis.commons.server.CallContext;
 import org.apache.chemistry.opencmis.commons.server.CmisService;
-import org.apache.chemistry.opencmis.server.support.CmisServiceWrapper;
+import org.apache.chemistry.opencmis.server.support.wrapper.CallContextAwareCmisService;
+import org.apache.chemistry.opencmis.server.support.wrapper.CmisServiceWrapperManager;
+import org.apache.chemistry.opencmis.server.support.wrapper.ConformanceCmisServiceWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,11 +62,12 @@ public class FileShareCmisServiceFactory
     private static final BigInteger DEFAULT_DEPTH_OBJECTS = BigInteger.valueOf(10);
 
     /** Each thread gets its own {@link FileShareCmisService} instance. */
-    private ThreadLocal<CmisServiceWrapper<FileShareCmisService>> threadLocalService = new ThreadLocal<CmisServiceWrapper<FileShareCmisService>>();
+    private ThreadLocal<CallContextAwareCmisService> threadLocalService = new ThreadLocal<CallContextAwareCmisService>();
 
     private FileShareRepositoryManager repositoryManager;
     private FileShareUserManager userManager;
     private FileShareTypeManager typeManager;
+    private CmisServiceWrapperManager wrapperManager;
 
     public FileShareRepositoryManager getRepositoryManager() {
         return repositoryManager;
@@ -84,6 +87,11 @@ public class FileShareCmisServiceFactory
         userManager = new FileShareUserManager();
         typeManager = new FileShareTypeManager();
 
+        wrapperManager = new CmisServiceWrapperManager();
+        wrapperManager.addWrappersFromServiceFactoryParameters(parameters);
+        wrapperManager.addOuterWrapper(ConformanceCmisServiceWrapper.class, DEFAULT_MAX_ITEMS_TYPES,
+                DEFAULT_DEPTH_TYPES, DEFAULT_MAX_ITEMS_OBJECTS, DEFAULT_DEPTH_OBJECTS);
+
         readConfiguration(parameters);
     }
 
@@ -100,19 +108,20 @@ public class FileShareCmisServiceFactory
         userManager.authenticate(context);
 
         // get service object for this thread
-        CmisServiceWrapper<FileShareCmisService> wrapperService = threadLocalService.get();
-        if (wrapperService == null) {
+        CallContextAwareCmisService service = threadLocalService.get();
+        if (service == null) {
             // there is no service object for this thread -> create one
             FileShareCmisService fileShareService = new FileShareCmisService(repositoryManager);
-            wrapperService = new CmisServiceWrapper<FileShareCmisService>(fileShareService, DEFAULT_MAX_ITEMS_TYPES,
-                    DEFAULT_DEPTH_TYPES, DEFAULT_MAX_ITEMS_OBJECTS, DEFAULT_DEPTH_OBJECTS);
-            threadLocalService.set(wrapperService);
+
+            service = (CallContextAwareCmisService) wrapperManager.wrap(fileShareService);
+
+            threadLocalService.set(service);
         }
 
         // hand over the call context to the service object
-        wrapperService.getWrappedService().setCallContext(context);
+        service.setCallContext(context);
 
-        return wrapperService;
+        return service;
     }
 
     // ---- helpers ----

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java?rev=1574576&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java Wed Mar  5 17:13:14 2014
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.chemistry.opencmis.server.support.wrapper;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.data.Acl;
+import org.apache.chemistry.opencmis.commons.data.AllowableActions;
+import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
+import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
+import org.apache.chemistry.opencmis.commons.data.ObjectData;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
+import org.apache.chemistry.opencmis.commons.data.ObjectList;
+import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
+import org.apache.chemistry.opencmis.commons.data.Properties;
+import org.apache.chemistry.opencmis.commons.data.RenditionData;
+import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
+import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
+import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.commons.server.ObjectInfo;
+import org.apache.chemistry.opencmis.commons.spi.Holder;
+
+/**
+ * An abstract CMIS service wrapper.
+ * <p>
+ * All service wrappers managed by {@link CmisServiceWrapperManager} must be
+ * derived from this class and must provide a constructor that takes a
+ * {@link CmisService} object as the sole parameter.
+ */
+public abstract class AbstractCmisServiceWrapper implements CallContextAwareCmisService {
+
+    private CmisService service;
+    private CallContext context;
+
+    public AbstractCmisServiceWrapper(CmisService service) {
+        if (service == null) {
+            throw new IllegalArgumentException("Service must be set!");
+        }
+
+        this.service = service;
+    }
+
+    /**
+     * Initializes the wrapper with a set of parameters.
+     */
+    public void initialize(Object[] params) {
+    }
+
+    /**
+     * Returns the wrapped service or the next service wrapper.
+     * 
+     * @return the wrapped service
+     */
+    public CmisService getWrappedService() {
+        return service;
+    }
+
+    /**
+     * Sets the call context and propagates it down to the next service wrapper
+     * or service if it implements the {@link CallContextAwareCmisService}
+     * interface.
+     */
+    public void setCallContext(CallContext callContext) {
+        this.context = callContext;
+
+        if (service instanceof CallContextAwareCmisService) {
+            ((CallContextAwareCmisService) service).setCallContext(callContext);
+        }
+    }
+
+    /**
+     * Gets the current call context.
+     */
+    public CallContext getCallContext() {
+        return context;
+    }
+
+    // --- service methods ---
+
+    public List<RepositoryInfo> getRepositoryInfos(ExtensionsData extension) {
+        return service.getRepositoryInfos(extension);
+    }
+
+    public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension) {
+        return service.getRepositoryInfo(repositoryId, extension);
+    }
+
+    public TypeDefinitionList getTypeChildren(String repositoryId, String typeId, Boolean includePropertyDefinitions,
+            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service
+                .getTypeChildren(repositoryId, typeId, includePropertyDefinitions, maxItems, skipCount, extension);
+    }
+
+    public List<TypeDefinitionContainer> getTypeDescendants(String repositoryId, String typeId, BigInteger depth,
+            Boolean includePropertyDefinitions, ExtensionsData extension) {
+        return service.getTypeDescendants(repositoryId, typeId, depth, includePropertyDefinitions, extension);
+    }
+
+    public TypeDefinition getTypeDefinition(String repositoryId, String typeId, ExtensionsData extension) {
+        return service.getTypeDefinition(repositoryId, typeId, extension);
+    }
+
+    public TypeDefinition createType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
+        return service.createType(repositoryId, type, extension);
+    }
+
+    public TypeDefinition updateType(String repositoryId, TypeDefinition type, ExtensionsData extension) {
+        return service.updateType(repositoryId, type, extension);
+    }
+
+    public void deleteType(String repositoryId, String typeId, ExtensionsData extension) {
+        service.deleteType(repositoryId, typeId, extension);
+    }
+
+    public ObjectInFolderList getChildren(String repositoryId, String folderId, String filter, String orderBy,
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+            Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service.getChildren(repositoryId, folderId, filter, orderBy, includeAllowableActions,
+                includeRelationships, renditionFilter, includePathSegment, maxItems, skipCount, extension);
+    }
+
+    public List<ObjectInFolderContainer> getDescendants(String repositoryId, String folderId, BigInteger depth,
+            String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+            String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
+        return service.getDescendants(repositoryId, folderId, depth, filter, includeAllowableActions,
+                includeRelationships, renditionFilter, includePathSegment, extension);
+    }
+
+    public List<ObjectInFolderContainer> getFolderTree(String repositoryId, String folderId, BigInteger depth,
+            String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+            String renditionFilter, Boolean includePathSegment, ExtensionsData extension) {
+        return service.getFolderTree(repositoryId, folderId, depth, filter, includeAllowableActions,
+                includeRelationships, renditionFilter, includePathSegment, extension);
+    }
+
+    public List<ObjectParentData> getObjectParents(String repositoryId, String objectId, String filter,
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+            Boolean includeRelativePathSegment, ExtensionsData extension) {
+        return service.getObjectParents(repositoryId, objectId, filter, includeAllowableActions, includeRelationships,
+                renditionFilter, includeRelativePathSegment, extension);
+    }
+
+    public ObjectData getFolderParent(String repositoryId, String folderId, String filter, ExtensionsData extension) {
+        return service.getFolderParent(repositoryId, folderId, filter, extension);
+    }
+
+    public ObjectList getCheckedOutDocs(String repositoryId, String folderId, String filter, String orderBy,
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service.getCheckedOutDocs(repositoryId, folderId, filter, orderBy, includeAllowableActions,
+                includeRelationships, renditionFilter, maxItems, skipCount, extension);
+    }
+
+    public String createDocument(String repositoryId, Properties properties, String folderId,
+            ContentStream contentStream, VersioningState versioningState, List<String> policies, Acl addAces,
+            Acl removeAces, ExtensionsData extension) {
+        return service.createDocument(repositoryId, properties, folderId, contentStream, versioningState, policies,
+                addAces, removeAces, extension);
+    }
+
+    public String createDocumentFromSource(String repositoryId, String sourceId, Properties properties,
+            String folderId, VersioningState versioningState, List<String> policies, Acl addAces, Acl removeAces,
+            ExtensionsData extension) {
+        return service.createDocumentFromSource(repositoryId, sourceId, properties, folderId, versioningState,
+                policies, addAces, removeAces, extension);
+    }
+
+    public String createFolder(String repositoryId, Properties properties, String folderId, List<String> policies,
+            Acl addAces, Acl removeAces, ExtensionsData extension) {
+        return service.createFolder(repositoryId, properties, folderId, policies, addAces, removeAces, extension);
+    }
+
+    public String createRelationship(String repositoryId, Properties properties, List<String> policies, Acl addAces,
+            Acl removeAces, ExtensionsData extension) {
+        return service.createRelationship(repositoryId, properties, policies, addAces, removeAces, extension);
+    }
+
+    public String createPolicy(String repositoryId, Properties properties, String folderId, List<String> policies,
+            Acl addAces, Acl removeAces, ExtensionsData extension) {
+        return service.createPolicy(repositoryId, properties, folderId, policies, addAces, removeAces, extension);
+    }
+
+    public String createItem(String repositoryId, Properties properties, String folderId, List<String> policies,
+            Acl addAces, Acl removeAces, ExtensionsData extension) {
+        return service.createItem(repositoryId, properties, folderId, policies, addAces, removeAces, extension);
+    }
+
+    public AllowableActions getAllowableActions(String repositoryId, String objectId, ExtensionsData extension) {
+        return service.getAllowableActions(repositoryId, objectId, extension);
+    }
+
+    public ObjectData getObject(String repositoryId, String objectId, String filter, Boolean includeAllowableActions,
+            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
+            Boolean includeAcl, ExtensionsData extension) {
+        return service.getObject(repositoryId, objectId, filter, includeAllowableActions, includeRelationships,
+                renditionFilter, includePolicyIds, includeAcl, extension);
+    }
+
+    public Properties getProperties(String repositoryId, String objectId, String filter, ExtensionsData extension) {
+        return service.getProperties(repositoryId, objectId, filter, extension);
+    }
+
+    public List<RenditionData> getRenditions(String repositoryId, String objectId, String renditionFilter,
+            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service.getRenditions(repositoryId, objectId, renditionFilter, maxItems, skipCount, extension);
+    }
+
+    public ObjectData getObjectByPath(String repositoryId, String path, String filter, Boolean includeAllowableActions,
+            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
+            Boolean includeAcl, ExtensionsData extension) {
+        return service.getObjectByPath(repositoryId, path, filter, includeAllowableActions, includeRelationships,
+                renditionFilter, includePolicyIds, includeAcl, extension);
+    }
+
+    public ContentStream getContentStream(String repositoryId, String objectId, String streamId, BigInteger offset,
+            BigInteger length, ExtensionsData extension) {
+        return service.getContentStream(repositoryId, objectId, streamId, offset, length, extension);
+    }
+
+    public void updateProperties(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
+            Properties properties, ExtensionsData extension) {
+        service.updateProperties(repositoryId, objectId, changeToken, properties, extension);
+    }
+
+    public List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(String repositoryId,
+            List<BulkUpdateObjectIdAndChangeToken> objectIdsAndChangeTokens, Properties properties,
+            List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds, ExtensionsData extension) {
+        return service.bulkUpdateProperties(repositoryId, objectIdsAndChangeTokens, properties, addSecondaryTypeIds,
+                removeSecondaryTypeIds, extension);
+    }
+
+    public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId, String sourceFolderId,
+            ExtensionsData extension) {
+        service.moveObject(repositoryId, objectId, targetFolderId, sourceFolderId, extension);
+    }
+
+    public void deleteObject(String repositoryId, String objectId, Boolean allVersions, ExtensionsData extension) {
+        service.deleteObject(repositoryId, objectId, allVersions, extension);
+    }
+
+    public FailedToDeleteData deleteTree(String repositoryId, String folderId, Boolean allVersions,
+            UnfileObject unfileObjects, Boolean continueOnFailure, ExtensionsData extension) {
+        return service.deleteTree(repositoryId, folderId, allVersions, unfileObjects, continueOnFailure, extension);
+    }
+
+    public void setContentStream(String repositoryId, Holder<String> objectId, Boolean overwriteFlag,
+            Holder<String> changeToken, ContentStream contentStream, ExtensionsData extension) {
+        service.setContentStream(repositoryId, objectId, overwriteFlag, changeToken, contentStream, extension);
+    }
+
+    public void deleteContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
+            ExtensionsData extension) {
+        service.deleteContentStream(repositoryId, objectId, changeToken, extension);
+    }
+
+    public void appendContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
+            ContentStream contentStream, boolean isLastChunk, ExtensionsData extension) {
+        service.appendContentStream(repositoryId, objectId, changeToken, contentStream, isLastChunk, extension);
+    }
+
+    public void checkOut(String repositoryId, Holder<String> objectId, ExtensionsData extension,
+            Holder<Boolean> contentCopied) {
+        service.checkOut(repositoryId, objectId, extension, contentCopied);
+    }
+
+    public void cancelCheckOut(String repositoryId, String objectId, ExtensionsData extension) {
+        service.cancelCheckOut(repositoryId, objectId, extension);
+    }
+
+    public void checkIn(String repositoryId, Holder<String> objectId, Boolean major, Properties properties,
+            ContentStream contentStream, String checkinComment, List<String> policies, Acl addAces, Acl removeAces,
+            ExtensionsData extension) {
+        service.checkIn(repositoryId, objectId, major, properties, contentStream, checkinComment, policies, addAces,
+                removeAces, extension);
+    }
+
+    public ObjectData getObjectOfLatestVersion(String repositoryId, String objectId, String versionSeriesId,
+            Boolean major, String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+            String renditionFilter, Boolean includePolicyIds, Boolean includeAcl, ExtensionsData extension) {
+        return service
+                .getObjectOfLatestVersion(repositoryId, objectId, versionSeriesId, major, filter,
+                        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds, includeAcl,
+                        extension);
+    }
+
+    public Properties getPropertiesOfLatestVersion(String repositoryId, String objectId, String versionSeriesId,
+            Boolean major, String filter, ExtensionsData extension) {
+        return service.getPropertiesOfLatestVersion(repositoryId, objectId, versionSeriesId, major, filter, extension);
+    }
+
+    public List<ObjectData> getAllVersions(String repositoryId, String objectId, String versionSeriesId, String filter,
+            Boolean includeAllowableActions, ExtensionsData extension) {
+        return service.getAllVersions(repositoryId, objectId, versionSeriesId, filter, includeAllowableActions,
+                extension);
+    }
+
+    public ObjectList query(String repositoryId, String statement, Boolean searchAllVersions,
+            Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter,
+            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service.query(repositoryId, statement, searchAllVersions, includeAllowableActions, includeRelationships,
+                renditionFilter, maxItems, skipCount, extension);
+    }
+
+    public ObjectList getContentChanges(String repositoryId, Holder<String> changeLogToken, Boolean includeProperties,
+            String filter, Boolean includePolicyIds, Boolean includeAcl, BigInteger maxItems, ExtensionsData extension) {
+        return service.getContentChanges(repositoryId, changeLogToken, includeProperties, filter, includePolicyIds,
+                includeAcl, maxItems, extension);
+    }
+
+    public void addObjectToFolder(String repositoryId, String objectId, String folderId, Boolean allVersions,
+            ExtensionsData extension) {
+        service.addObjectToFolder(repositoryId, objectId, folderId, allVersions, extension);
+    }
+
+    public void removeObjectFromFolder(String repositoryId, String objectId, String folderId, ExtensionsData extension) {
+        service.removeObjectFromFolder(repositoryId, objectId, folderId, extension);
+    }
+
+    public ObjectList getObjectRelationships(String repositoryId, String objectId, Boolean includeSubRelationshipTypes,
+            RelationshipDirection relationshipDirection, String typeId, String filter, Boolean includeAllowableActions,
+            BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
+        return service.getObjectRelationships(repositoryId, objectId, includeSubRelationshipTypes,
+                relationshipDirection, typeId, filter, includeAllowableActions, maxItems, skipCount, extension);
+    }
+
+    public Acl getAcl(String repositoryId, String objectId, Boolean onlyBasicPermissions, ExtensionsData extension) {
+        return service.getAcl(repositoryId, objectId, onlyBasicPermissions, extension);
+    }
+
+    public Acl applyAcl(String repositoryId, String objectId, Acl addAces, Acl removeAces,
+            AclPropagation aclPropagation, ExtensionsData extension) {
+        return service.applyAcl(repositoryId, objectId, addAces, removeAces, aclPropagation, extension);
+    }
+
+    public void applyPolicy(String repositoryId, String policyId, String objectId, ExtensionsData extension) {
+        service.applyPolicy(repositoryId, policyId, objectId, extension);
+    }
+
+    public void removePolicy(String repositoryId, String policyId, String objectId, ExtensionsData extension) {
+        service.removePolicy(repositoryId, policyId, objectId, extension);
+    }
+
+    public List<ObjectData> getAppliedPolicies(String repositoryId, String objectId, String filter,
+            ExtensionsData extension) {
+        return service.getAppliedPolicies(repositoryId, objectId, filter, extension);
+    }
+
+    public String create(String repositoryId, Properties properties, String folderId, ContentStream contentStream,
+            VersioningState versioningState, List<String> policies, ExtensionsData extension) {
+        return service.create(repositoryId, properties, folderId, contentStream, versioningState, policies, extension);
+    }
+
+    public void deleteObjectOrCancelCheckOut(String repositoryId, String objectId, Boolean allVersions,
+            ExtensionsData extension) {
+        service.deleteObjectOrCancelCheckOut(repositoryId, objectId, allVersions, extension);
+    }
+
+    public Acl applyAcl(String repositoryId, String objectId, Acl aces, AclPropagation aclPropagation) {
+        return service.applyAcl(repositoryId, objectId, aces, aclPropagation);
+    }
+
+    public ObjectInfo getObjectInfo(String repositoryId, String objectId) {
+        return service.getObjectInfo(repositoryId, objectId);
+    }
+
+    public void close() {
+        service.close();
+        context = null;
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/AbstractCmisServiceWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java?rev=1574576&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java Wed Mar  5 17:13:14 2014
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.chemistry.opencmis.server.support.wrapper;
+
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+
+/**
+ * Identifies a CMIS service object that can handle call contexts.
+ */
+public interface CallContextAwareCmisService extends CmisService {
+
+    /**
+     * Returns the current call context.
+     * 
+     * @return the call context
+     */
+    CallContext getCallContext();
+
+    /**
+     * Sets a new call context.
+     * 
+     * @param callContext
+     *            the new call context
+     */
+    void setCallContext(CallContext callContext);
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CallContextAwareCmisService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java?rev=1574576&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java Wed Mar  5 17:13:14 2014
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.chemistry.opencmis.server.support.wrapper;
+
+import java.lang.reflect.Constructor;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.ClassLoaderUtil;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages a list of CMIS service wrappers.
+ */
+public class CmisServiceWrapperManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(CmisServiceWrapperManager.class);
+
+    private static final String PARAMS_SERVICE_WRAPPER_PREFIX = "servicewrapper.";
+
+    private final LinkedList<WrapperDefinition> wrapperDefinitions;
+
+    public CmisServiceWrapperManager() {
+        wrapperDefinitions = new LinkedList<WrapperDefinition>();
+    }
+
+    /**
+     * Adds an outer-most (called first) wrapper.
+     * 
+     * @param wrapperClass
+     *            the wrapper class
+     * @param params
+     *            wrapper parameters
+     */
+    public void addOuterWrapper(Class<? extends AbstractCmisServiceWrapper> wrapperClass, Object... params) {
+        wrapperDefinitions.addLast(new WrapperDefinition(wrapperClass, params));
+
+        LOG.debug("Added outer service wrapper: {}", wrapperClass.getName());
+    }
+
+    /**
+     * Adds an inner-most (called last) wrapper.
+     * 
+     * @param wrapperClass
+     *            the wrapper class
+     * @param params
+     *            wrapper parameters
+     */
+    public void addInnerWrapper(Class<? extends AbstractCmisServiceWrapper> wrapperClass, Object... params) {
+        wrapperDefinitions.addFirst(new WrapperDefinition(wrapperClass, params));
+
+        LOG.debug("Added inner service wrapper: {}", wrapperClass.getName());
+    }
+
+    /**
+     * Gets wrapper settings from the service factory parameters and adds them
+     * to the wrappers.
+     * 
+     * @param parameters
+     *            service factory parameters
+     */
+    public void addWrappersFromServiceFactoryParameters(Map<String, String> parameters) {
+        if (parameters == null) {
+            return;
+        }
+
+        TreeMap<Integer, WrapperDefinition> wrappers = new TreeMap<Integer, WrapperDefinition>();
+
+        for (Map.Entry<String, String> entry : parameters.entrySet()) {
+            String key = entry.getKey().trim().toLowerCase(Locale.ENGLISH);
+            if (key.startsWith(PARAMS_SERVICE_WRAPPER_PREFIX) && entry.getKey() != null) {
+                int index = 0;
+                try {
+                    Integer.valueOf(key.substring(PARAMS_SERVICE_WRAPPER_PREFIX.length()));
+                } catch (NumberFormatException e) {
+                    throw new CmisRuntimeException("Invalid service wrapper configuration: " + key, e);
+                }
+
+                String[] value = entry.getValue().trim().split(",");
+                if (value.length > 0) {
+                    Class<?> wrapperClass = null;
+                    try {
+                        wrapperClass = ClassLoaderUtil.loadClass(value[0]);
+                    } catch (ClassNotFoundException e) {
+                        throw new CmisRuntimeException("Service wrapper class not found: " + value[0], e);
+                    }
+
+                    if (!AbstractCmisServiceWrapper.class.isAssignableFrom(wrapperClass)) {
+                        throw new CmisRuntimeException("Class is not a service wrapper: " + value[0]);
+                    }
+
+                    Object[] params = null;
+                    if (value.length > 1) {
+                        params = new Object[value.length - 1];
+                        System.arraycopy(value, 1, params, 0, params.length);
+                    }
+
+                    if (wrappers.containsKey(index)) {
+                        throw new CmisRuntimeException("More than one service wrapper at the same position: " + index);
+                    }
+
+                    LOG.debug("Found wrapper [{}] {} ({})", index, wrapperClass.getName(),
+                            params == null ? "" : params.toString());
+
+                    wrappers.put(index, new WrapperDefinition(
+                            (Class<? extends AbstractCmisServiceWrapper>) wrapperClass, params));
+                }
+            }
+        }
+
+        for (WrapperDefinition def : wrappers.values()) {
+            wrapperDefinitions.add(def);
+            LOG.debug("Added outer service wrapper: {}", def.getWrapperClass().getName());
+        }
+    }
+
+    /**
+     * Removes the outer-most wrapper.
+     */
+    public void removeOuterWrapper() {
+        if (!wrapperDefinitions.isEmpty()) {
+            wrapperDefinitions.removeLast();
+        }
+    }
+
+    /**
+     * Removes the inner-most wrapper.
+     */
+    public void removeInnerWrapper() {
+        if (!wrapperDefinitions.isEmpty()) {
+            wrapperDefinitions.removeFirst();
+        }
+    }
+
+    /**
+     * Wraps a service with all configured wrappers.
+     * 
+     * @param service
+     *            the CMIS service object
+     * @return the wrapped service
+     */
+    public CmisService wrap(CmisService service) {
+        CmisService result = service;
+
+        for (WrapperDefinition def : wrapperDefinitions) {
+            result = def.createWrapperObject(result);
+        }
+
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("[ ");
+
+        int i = 0;
+        for (WrapperDefinition def : wrapperDefinitions) {
+            if (i > 0) {
+                sb.append(",");
+            }
+
+            sb.append(i);
+            sb.append(": ");
+            sb.append(def.getWrapperClass().getName());
+        }
+        sb.append("]");
+
+        return sb.toString();
+    }
+
+    /**
+     * Wrapper Definition.
+     */
+    private static class WrapperDefinition {
+
+        private static final Class<?>[] CONSTRUCTOR_PARAMETERS = new Class<?>[] { CmisService.class };
+
+        private final Class<? extends AbstractCmisServiceWrapper> wrapperClass;
+        private final Constructor<? extends AbstractCmisServiceWrapper> wrapperConstructor;
+        private final Object[] params;
+
+        public WrapperDefinition(Class<? extends AbstractCmisServiceWrapper> wrapperClass, Object... params) {
+            this.wrapperClass = wrapperClass;
+            this.params = params;
+
+            if (wrapperClass == null) {
+                throw new CmisRuntimeException("Wrapper class must be set!");
+            }
+
+            try {
+                wrapperConstructor = wrapperClass.getConstructor(CONSTRUCTOR_PARAMETERS);
+            } catch (Exception e) {
+                throw new CmisRuntimeException("Could not access constructor of service wrapper "
+                        + wrapperClass.getName() + ": " + e.toString(), e);
+            }
+        }
+
+        public Class<? extends AbstractCmisServiceWrapper> getWrapperClass() {
+            return wrapperClass;
+        }
+
+        public AbstractCmisServiceWrapper createWrapperObject(CmisService service) {
+            try {
+                AbstractCmisServiceWrapper wrapper = wrapperConstructor.newInstance(service);
+                wrapper.initialize(params);
+
+                return wrapper;
+            } catch (Exception e) {
+                throw new CmisRuntimeException("Could not instantiate service wrapper " + wrapperClass.getName() + ": "
+                        + e.toString(), e);
+            }
+        }
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-support/src/main/java/org/apache/chemistry/opencmis/server/support/wrapper/CmisServiceWrapperManager.java
------------------------------------------------------------------------------
    svn:eol-style = native