]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6347: Now supporting 'impTimout' query param for most requests.
authorremillet <remillet@yahoo.com>
Thu, 30 Apr 2015 21:21:58 +0000 (14:21 -0700)
committerremillet <remillet@yahoo.com>
Thu, 30 Apr 2015 21:21:58 +0000 (14:21 -0700)
services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/document/TransactionException.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoClientEmbedded.java
services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java
services/imports/service/src/main/java/org/collectionspace/services/imports/ImportsResource.java
services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/ImportCommand.java
services/imports/service/src/main/java/org/collectionspace/services/imports/nuxeo/LoggedXMLDirectoryReader.java

index 48e1665633adaebcf33c4c6201d0c62f7de19c85..5ec16b6f9a23ffde300bbd7e6f8b109c88e173a6 100644 (file)
@@ -46,10 +46,8 @@ import org.collectionspace.services.common.repository.RepositoryClientFactory;
 import org.collectionspace.services.common.security.UnauthorizedException;
 import org.collectionspace.services.common.storage.StorageClient;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
-
 import org.jboss.resteasy.core.ResourceMethod;
 import org.jboss.resteasy.spi.HttpRequest;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -74,7 +72,7 @@ public abstract class AbstractCollectionSpaceResourceImpl<IT, OT>
     
     /** The storage client. */
     private StorageClient storageClient;
-
+    
     /**
      * Extract id.
      *
@@ -87,8 +85,8 @@ public abstract class AbstractCollectionSpaceResourceImpl<IT, OT>
         String[] segments = uri.split("/");
         String id = segments[segments.length - 1];
         return id;
-    }    
-    
+    }
+            
     /**
      * Instantiates a new abstract collection space resource.
      */
index 076cd90791ff50bea2dadfc15bdb47365c3b4a3a..f6b080220f49c21a27bab5b485d13ac7a1c71841 100644 (file)
@@ -27,10 +27,12 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.UriInfo;
 
 import org.collectionspace.authentication.spi.AuthNContext;
+import org.collectionspace.services.client.IClientQueryParams;
 import org.collectionspace.services.client.IQueryManager;
 import org.collectionspace.services.client.workflow.WorkflowClient;
 import org.collectionspace.services.common.ServiceMain;
@@ -77,6 +79,7 @@ public abstract class AbstractServiceContextImpl<IT, OT>
 
     /** The logger. */
     final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
+    
     /** The properties. */
     Map<String, Object> properties = new HashMap<String, Object>();
     /** The object part map. */
@@ -101,7 +104,7 @@ public abstract class AbstractServiceContextImpl<IT, OT>
     private Object currentRepositorySession;
     /** A reference count for the current repository session */
     private int currentRepoSesssionRefCount = 0;
-
+        
     /**
      * Instantiates a new abstract service context impl.
      */
@@ -165,6 +168,30 @@ public abstract class AbstractServiceContextImpl<IT, OT>
                }
         }
     }
+    
+    public int getTimeoutParam(UriInfo ui) {
+               int result = DEFAULT_TX_TIMEOUT;
+
+               MultivaluedMap<String, String> queryParams = (ui == null) ? null : ui.getQueryParameters();
+               if (queryParams != null) {
+                       String timeoutString = queryParams.getFirst(IClientQueryParams.IMPORT_TIMEOUT_PARAM);
+                       if (timeoutString != null)
+                               try {
+                                       result = Integer.parseInt(timeoutString);
+                               } catch (NumberFormatException e) {
+                                       logger.warn("Transaction timeout period parameter could not be parsed.  The characters in the parameter string must all be decimal digits.  The Import service will use the default timeout period instead.",
+                                                       e);
+                               }
+               }
+
+               return result;
+       }
+    
+    @Override
+    public int getTimeoutSecs() {
+       UriInfo uriInfo = this.getUriInfo();
+       return this.getTimeoutParam(uriInfo);
+    }
 
     /* (non-Javadoc)
      * @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
index 1dd07be55275f980eecddd43957134ef7ca96f1b..552732f566d803977272bcdd8c407e83e3fd22dc 100644 (file)
@@ -61,6 +61,20 @@ public interface ServiceContext<IT, OT> {
     /** Used to qualify document types **/
        public static final String TENANT_SUFFIX = "Tenant";    
 
+    /** 
+     * Tells the TransactionManager to use the default value.  The default value can
+     * be set in this file:
+     *                 services/JaxRsServiceProvider/src/main/webapp/META-INF/context.xml
+     * at this section:
+     *                 <Resource name="TransactionManager" auth="Container" type="javax.transaction.TransactionManager"
+     *                 factory="org.nuxeo.runtime.jtajca.NuxeoTransactionManagerFactory"
+     *                 transactionTimeoutSeconds="300"/>
+     * See the following documentation page for more details:
+     *                 http://docs.oracle.com/javaee/7/api/javax/transaction/TransactionManager.html#setTransactionTimeout(int)
+     * 
+     */
+       public static final int DEFAULT_TX_TIMEOUT = 0;
+       
        /* 
         * Sets the current/open repository session
         */
@@ -81,6 +95,11 @@ public interface ServiceContext<IT, OT> {
      */
     public SecurityContext getSecurityContext();
 
+    /**
+     * getTimeoutSecs();
+     */
+    public int getTimeoutSecs();
+    
     /**
      * getUserId get authenticated user's userId
      */
index 92316e0d4139b7b52235c35a2224fa955a28ac6a..7f979b16409c57cd8d0489e0f5c141010d680190 100644 (file)
@@ -85,7 +85,7 @@ public class TransactionException extends DocumentException {
      *         unknown.)
      * @since  1.4
      */
-    public TransactionException(Throwable cause) {
+    public TransactionException(Throwable cause) {     
         super(TRANSACTION_FAILED_MSG, cause);
         setErrorCode(HTTP_CODE);
     }
index 0547e446b75549fc4de0706c39272755e7ec13d0..b6db6f339864070cdfbfb971785a54ca244acfa0 100644 (file)
@@ -25,9 +25,9 @@ import java.util.Iterator;
 import java.util.Map.Entry;
 import java.security.Principal;
 
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.repository.RepositoryInstanceWrapperAdvice;
 import org.collectionspace.services.config.tenant.RepositoryDomainType;
-
 import org.nuxeo.ecm.core.api.repository.Repository;
 import org.nuxeo.ecm.core.api.CoreInstance;
 import org.nuxeo.ecm.core.api.CoreSession;
@@ -35,9 +35,11 @@ import org.nuxeo.ecm.core.api.NuxeoPrincipal;
 import org.nuxeo.ecm.core.api.SystemPrincipal;
 import org.nuxeo.ecm.core.api.repository.RepositoryManager;
 import org.nuxeo.runtime.api.Framework;
+import org.nuxeo.runtime.jtajca.NuxeoContainer;
 import org.nuxeo.runtime.transaction.TransactionHelper;
 
 import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -118,14 +120,14 @@ public final class NuxeoClientEmbedded {
      * Open a Nuxeo repo session using the passed in repoDomain and use the default tx timeout period
      */
     public CoreSessionInterface openRepository(RepositoryDomainType repoDomain) throws Exception {
-        return openRepository(repoDomain.getRepositoryName(), -1);
+        return openRepository(repoDomain.getRepositoryName(), ServiceContext.DEFAULT_TX_TIMEOUT);
     }
     
     /*
      * Open a Nuxeo repo session using the passed in repoDomain and use the default tx timeout period
      */
     public CoreSessionInterface openRepository(String repoName) throws Exception {
-        return openRepository(repoName, -1);
+        return openRepository(repoName, ServiceContext.DEFAULT_TX_TIMEOUT);
     }    
 
     public CoreSessionInterface openRepository(String repoName, int timeoutSeconds) throws Exception {
@@ -136,7 +138,14 @@ public final class NuxeoClientEmbedded {
        //
        if (timeoutSeconds > 0) {
                TransactionManager transactionMgr = TransactionHelper.lookupTransactionManager();
-               transactionMgr.setTransactionTimeout(timeoutSeconds);
+            TransactionManager tm = NuxeoContainer.getTransactionManager();
+            if (logger.isDebugEnabled()) {
+               if (tm != transactionMgr) {
+                       logger.debug("TransactionHelper's manager is different than NuxeoContainer's.");
+               }
+            }
+               
+               transactionMgr.setTransactionTimeout(timeoutSeconds); // For the current thread only
                if (logger.isInfoEnabled()) {
                        logger.info(String.format("Changing current request's transaction timeout period to %d seconds",
                                        timeoutSeconds));
@@ -268,9 +277,14 @@ public final class NuxeoClientEmbedded {
                        logger.trace("Could not remove a repository instance from our repo list.  Current count is now: "
                                        + repositoryInstances.size());
                }
-            }
+            }            
+            //
+            // Last but not least, try to commit the current Nuxeo-related transaction.
+            //
             if (TransactionHelper.isTransactionActiveOrMarkedRollback() == true) {
                TransactionHelper.commitOrRollbackTransaction();
+               UserTransaction ut = TransactionHelper.lookupUserTransaction();
+               TransactionManager tm = TransactionHelper.lookupTransactionManager();                   
                logger.trace(String.format("Transaction closed on thread '%d'", Thread.currentThread().getId()));
             }
         }
index 6d4f231b6475a36be0e240cde53ba3498e76c215..ad8a81569e8187686b164781c7599dd753a82141 100644 (file)
@@ -34,14 +34,12 @@ import javax.ws.rs.core.MultivaluedMap;
 
 import org.collectionspace.services.lifecycle.TransitionDef;
 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
-
 import org.collectionspace.services.client.CollectionSpaceClient;
 import org.collectionspace.services.client.IQueryManager;
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
 import org.collectionspace.services.client.Profiler;
 import org.collectionspace.services.client.workflow.WorkflowClient;
-
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.query.QueryContext;
 import org.collectionspace.services.common.repository.RepositoryClient;
@@ -63,7 +61,6 @@ import org.collectionspace.services.common.config.ConfigUtils;
 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
 import org.collectionspace.services.common.config.TenantBindingUtils;
 import org.collectionspace.services.common.storage.PreparedStatementBuilder;
-
 import org.collectionspace.services.config.tenant.TenantBindingType;
 import org.collectionspace.services.config.tenant.RepositoryDomainType;
 
@@ -74,7 +71,6 @@ import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
 import org.apache.chemistry.opencmis.commons.server.CallContext;
 import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
 import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory;
-
 import org.nuxeo.common.utils.IdUtils;
 import org.nuxeo.ecm.core.api.ClientException;
 import org.nuxeo.ecm.core.api.DocumentModel;
@@ -88,7 +84,6 @@ import org.nuxeo.ecm.core.api.PathRef;
 import org.nuxeo.runtime.transaction.TransactionRuntimeException;
 import org.nuxeo.ecm.core.opencmis.bindings.NuxeoCmisServiceFactory;
 import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -1719,11 +1714,11 @@ public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn,
     }
 
     public CoreSessionInterface getRepositorySession(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
-        return getRepositorySession(ctx, ctx.getRepositoryName());
+        return getRepositorySession(ctx, ctx.getRepositoryName(), ctx.getTimeoutSecs());
     }
 
     public CoreSessionInterface getRepositorySession(String repoName) throws Exception {
-        return getRepositorySession(null, repoName);
+        return getRepositorySession(null, repoName, ServiceContext.DEFAULT_TX_TIMEOUT);
     }
 
     /**
@@ -1733,7 +1728,9 @@ public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn,
      * @return the repository session
      * @throws Exception the exception
      */
-    public CoreSessionInterface getRepositorySession(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String repoName) throws Exception {
+    public CoreSessionInterface getRepositorySession(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
+               String repoName,
+               int timeoutSeconds) throws Exception {
        CoreSessionInterface repoSession = null;
 
         Profiler profiler = new Profiler("getRepositorySession():", 2);
@@ -1755,7 +1752,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn,
         //
         if (repoSession == null) {
             NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
-            repoSession = client.openRepository(repoName);
+            repoSession = client.openRepository(repoName, timeoutSeconds);
         } else {
             if (logger.isDebugEnabled() == true) {
                 logger.warn("Reusing the current context's repository session.");
@@ -1797,11 +1794,23 @@ public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn,
                 client.releaseRepository(repoSession); //repo session was acquired without a service context
             }
         } catch (TransactionRuntimeException tre) {
-            TransactionException te = new TransactionException(tre);
+               String causeMsg = null;
+               Throwable cause = tre.getCause();
+               if (cause != null) {
+                       causeMsg = cause.getMessage();
+               }
+               
+            TransactionException te; // a CollectionSpace specific tx exception
+            if (causeMsg != null) {
+               te = new TransactionException(causeMsg, tre);
+            } else {
+               te = new TransactionException(tre);
+            }
+            
             logger.error(te.getMessage(), tre); // Log the standard transaction exception message, plus an exception-specific stack trace
             throw te;
         } catch (Exception e) {
-            logger.error("Could not close the repository session", e);
+            logger.error("Could not close the repository session.", e);
             // no need to throw this service specific exception
         }
     }
index c167de8d552a65ffe2a35f92972a4ca1e53c7393..94010f7cf30804089551d78e7d074f46738f07c4 100644 (file)
@@ -24,7 +24,6 @@
 package org.collectionspace.services.imports;
 
 import org.collectionspace.authentication.AuthN;
-import org.collectionspace.services.client.IClientQueryParams;
 import org.collectionspace.services.client.PoxPayloadIn;
 import org.collectionspace.services.client.PoxPayloadOut;
 import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
@@ -37,6 +36,7 @@ import org.collectionspace.services.common.api.Tools;
 import org.collectionspace.services.common.api.ZipTools;
 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
 import org.collectionspace.services.common.context.MultipartServiceContextFactory;
+import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.context.ServiceContextFactory;
 import org.collectionspace.services.config.tenant.RepositoryDomainType;
 import org.collectionspace.services.config.tenant.TenantBindingType;
@@ -46,7 +46,6 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils;
 
 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.xml.sax.InputSource;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
@@ -57,7 +56,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.UriInfo;
 
 import java.io.ByteArrayInputStream;
@@ -67,8 +67,10 @@ import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
 
 // The modified Nuxeo ImportCommand from nuxeo's shell:
 
@@ -80,13 +82,11 @@ import org.slf4j.LoggerFactory;
 @Consumes({ "application/xml" })
 public class ImportsResource extends AbstractCollectionSpaceResourceImpl<PoxPayloadIn, PoxPayloadOut> {
     
-        private final static Logger logger = LoggerFactory.getLogger(TemplateExpander.class);
+       private final static Logger logger = LoggerFactory.getLogger(TemplateExpander.class);
 
        public static final String SERVICE_NAME = "imports";
        public static final String SERVICE_PATH = "/" + SERVICE_NAME;
-        private static String NUXEO_SPACES_PATH_DELIMITER = "/";
-
-       private static final int DEFAULT_TX_TIMEOUT = 600; // timeout period in seconds
+    private static String NUXEO_SPACES_PATH_DELIMITER = "/";
 
        /*
         * ASSUMPTION: All Nuxeo services of a given tenancy store their stuff in
@@ -189,26 +189,6 @@ public class ImportsResource extends AbstractCollectionSpaceResourceImpl<PoxPayl
        // }
        // }
 
-       private int getTimeoutParam(UriInfo ui) {
-               int result = DEFAULT_TX_TIMEOUT;
-
-               MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
-               if (queryParams != null) {
-                       String timeoutString = queryParams
-                                       .getFirst(IClientQueryParams.IMPORT_TIMEOUT_PARAM);
-                       if (timeoutString != null)
-                               try {
-                                       result = Integer.parseInt(timeoutString);
-                               } catch (NumberFormatException e) {
-                                       logger.warn(
-                                                       "Timeout period parameter could not be parsed.  The characters in the parameter string must all be decimal digits.  The Import service will use the default timeout period instead.",
-                                                       e);
-                               }
-               }
-
-               return result;
-       }
-
        /**
         * you can test this with something like: curl -X POST
         * http://localhost:8180/cspace-services/imports -i -u
@@ -220,21 +200,22 @@ public class ImportsResource extends AbstractCollectionSpaceResourceImpl<PoxPayl
        @POST
        @Consumes("application/xml")
        @Produces("application/xml")
-       public javax.ws.rs.core.Response create(@Context UriInfo ui,
+       public Response create(@Context UriInfo ui,
                        String xmlPayload) {
                String result = null;
-               javax.ws.rs.core.Response.ResponseBuilder rb;
+               ResponseBuilder rb;
                try {
-                       int timeout = getTimeoutParam(ui);
+            ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
+                       int timeout = ctx.getTimeoutSecs(); // gets it from query param 'impTimout' or uses default if no query param specified
                        // InputSource inputSource = payloadToInputSource(xmlPayload);
                        // result = createFromInputSource(inputSource);
                        String inputFilename = payloadToFilename(xmlPayload);
                        result = createFromFilename(inputFilename, timeout);
-                       rb = javax.ws.rs.core.Response.ok();
+                       rb = Response.ok();
                } catch (Exception e) {
                        result = Tools.errorToString(e, true);
-                       rb = javax.ws.rs.core.Response
-                                       .status(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR);
+                       rb = Response
+                                       .status(Response.Status.INTERNAL_SERVER_ERROR);
                }
                rb.entity(result);
                return rb.build();
@@ -423,25 +404,24 @@ public class ImportsResource extends AbstractCollectionSpaceResourceImpl<PoxPayl
        @POST
        @Consumes("multipart/form-data")
        @Produces("application/xml")
-       public javax.ws.rs.core.Response acceptUpload(@Context UriInfo ui,
+       public Response acceptUpload(@Context UriInfo ui,
                        @Context HttpServletRequest req, MultipartFormDataInput partFormData) {
-               javax.ws.rs.core.Response response = null;
+               Response response = null;
                StringBuffer resultBuf = new StringBuffer();
+               
                try {
+            ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
+                       int timeout = ctx.getTimeoutSecs(); // gets it from query param 'impTimout' or uses default if no query param specified
+                       
                        InputStream fileStream = null;
                        String preamble = partFormData.getPreamble();
-                        if (logger.isTraceEnabled()) {
-                            logger.trace("Preamble type is:" + preamble);
-                        }
-                       Map<String, List<InputPart>> partsMap = partFormData
-                                       .getFormDataMap();
+                       logger.trace("Preamble type is:" + preamble);
+                        
+                       Map<String, List<InputPart>> partsMap = partFormData.getFormDataMap();
                        List<InputPart> fileParts = partsMap.get("file");
-                       int timeout = this.getTimeoutParam(ui);
                        for (InputPart part : fileParts) {
                                String mediaType = part.getMediaType().toString();
-                                if (logger.isTraceEnabled()) {
-                                    logger.trace("Media type is:" + mediaType);
-                                }
+                               logger.trace("Media type is:" + mediaType);
                                if (mediaType.equalsIgnoreCase(MediaType.APPLICATION_XML)
                                                || mediaType.equalsIgnoreCase(MediaType.TEXT_XML)) {
                                        // FIXME For an alternate approach, potentially preferable,
@@ -459,45 +439,41 @@ public class ImportsResource extends AbstractCollectionSpaceResourceImpl<PoxPayl
                                }
 
                                //
-                               // This code was never finished to support the import of a zipped directory
+                               // TODO: This code was never finished to support the import of a zipped directory
                                //
                                if (mediaType.equalsIgnoreCase("application/zip")) {
-                                       logger.error("The Import service does not yet support .zip files."); //We should also send back a meaningful error message and status code here.
+                                       logger.error("The Import service does not yet support .zip files."); // We should also send back a meaningful error message and status code here.
 
                                        fileStream = part.getBody(InputStream.class, null);
 
                                        File zipfile = FileUtils.createTmpFile(fileStream,
                                                        getServiceName() + "_");
                                        String zipfileName = zipfile.getCanonicalPath();
-                                        if (logger.isTraceEnabled()) {
-                                            logger.trace("Imports zip file saved to:"
-                                                            + zipfileName);
-                                        }
+                                       logger.trace("Imports zip file saved to:" + zipfileName);
 
                                        String baseOutputDir = FileTools.createTmpDir("imports-")
                                                        .getCanonicalPath();
                                        File indir = new File(baseOutputDir + "/in");
                                        indir.mkdir();
                                        ZipTools.unzip(zipfileName, indir.getCanonicalPath());
-                                        String result = "\r\n<zipResult>Zipfile " + zipfileName
-                                                + "extracted to: " + indir.getCanonicalPath()
-                                                + "</zipResult>";
-                                        if (logger.isTraceEnabled()) {
-                                            logger.trace(result);
-                                        }
-                                       long start = System.currentTimeMillis();
+                    String result = "\r\n<zipResult>Zipfile " + zipfileName
+                            + "extracted to: " + indir.getCanonicalPath()
+                            + "</zipResult>";
+                    logger.trace(result);
+
                                        // TODO: now call import service...
                                        resultBuf.append(result);
                                        continue;
                                }
                        }
-                       javax.ws.rs.core.Response.ResponseBuilder rb = javax.ws.rs.core.Response
-                                       .ok();
+                       
+                       Response.ResponseBuilder rb = Response.ok();
                        rb.entity(resultBuf.toString());
                        response = rb.build();
                } catch (Exception e) {
                        throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
                }
+               
                return response;
        }
 
index 6754b5e2206d5ffd262ce34d1266bedce8362802..7e66710419cf488c2bab279605b206eaef09cdb5 100644 (file)
@@ -9,6 +9,7 @@ import java.util.TreeSet;
 import org.collectionspace.services.nuxeo.client.java.NuxeoClientEmbedded;
 import org.collectionspace.services.nuxeo.client.java.NuxeoConnectorEmbedded;
 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
+
 import org.nuxeo.ecm.core.api.DocumentModel;
 import org.nuxeo.ecm.core.api.DocumentRef;
 import org.nuxeo.ecm.core.io.DocumentPipe;
@@ -26,18 +27,18 @@ public class ImportCommand {
 
     private final Logger logger = LoggerFactory.getLogger(ImportCommand.class);
 
-    public String run(String src, String repoName, String workspacesPath, int timeOut) throws Exception {
+    public String run(String src, String repoName, String workspacesPath, int timeout) throws Exception {
         File file = new File(src);
         ///cspace way of configuring client and auth:
         NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
         CoreSessionInterface repoSession = null;
         try {
-            repoSession = client.openRepository(repoName, timeOut);
+            repoSession = client.openRepository(repoName, timeout);
             if (logger.isDebugEnabled()) {
                 String msg = String.format("Start of import is Local time: %tT", Calendar.getInstance());
                 logger.debug(msg);
             }
-            return importTree(repoSession, file, workspacesPath);
+            return importTree(repoSession, file, workspacesPath, timeout);
         } catch (Exception e) {
             throw e;
         } finally {
@@ -49,7 +50,10 @@ public class ImportCommand {
         }
     }
 
-    String importTree(CoreSessionInterface repoSession, File file, String toPath) throws Exception {
+    /*
+     * If the import exceeds the number of seconds in 'timeout', we'll thrown an exception and rollback all import work
+     */
+    String importTree(CoreSessionInterface repoSession, File file, String toPath, int timeout) throws Exception {
         Exception failed = null;
         DocumentReader reader = null;
         DocumentWriter writer = null;
@@ -62,9 +66,10 @@ public class ImportCommand {
         int totalRecordsImported = 0;
         try {
             if (logger.isInfoEnabled()) {
-                logger.info("importTree reading file: " + file + (file != null ? " exists? " + file.exists() : " file param is null"));
+                logger.info("ImportCommand.importTree() method reading file: " + file + (file != null ? " exists? " + file.exists() : " file param is null"));
+                logger.info(String.format("ImportCommand.importTree() will timeout if import does not complete in %d seconds.", timeout));
             }
-            reader = new LoggedXMLDirectoryReader(file);  //our overload of XMLDirectoryReader.
+            reader = new LoggedXMLDirectoryReader(file, timeout);  //our overload of XMLDirectoryReader.
             writer = new DocumentModelWriter(repoSession.getCoreSession(), toPath, 10);
             DocumentPipe pipe = new DocumentPipeImpl(10);
             // pipe.addTransformer(transformer);
index fc5be016c094f5535a5281eff203678bd0a11156..d87c3d9cafacd34312f81a9755fcd0c76a28a43a 100644 (file)
@@ -7,9 +7,11 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+
 import org.dom4j.Document;
 import org.dom4j.DocumentException;
 import org.dom4j.io.SAXReader;
+
 import org.nuxeo.common.utils.FileTreeIterator;
 import org.nuxeo.common.utils.FileUtils;
 import org.nuxeo.common.utils.Path;
@@ -19,13 +21,17 @@ import org.nuxeo.ecm.core.io.ExportedDocument;
 import org.nuxeo.ecm.core.io.impl.AbstractDocumentReader;
 import org.nuxeo.ecm.core.io.impl.ExportedDocumentImpl;
 import org.nuxeo.runtime.services.streaming.FileSource;
+import org.nuxeo.runtime.transaction.TransactionHelper;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
     
-    private final Logger logger = LoggerFactory.getLogger(LoggedXMLDirectoryReader.class);
-
+    private static final int TIMEOUT_NEVER = 0;
+       private final Logger logger = LoggerFactory.getLogger(LoggedXMLDirectoryReader.class);
+    protected long timeoutMillis = TIMEOUT_NEVER;
+    protected int totalTimeLimitSecs = 0; // the number of seconds before we timeout
 
     protected Document loadXML(File file) throws IOException {
         String filename = file.getCanonicalPath();
@@ -60,10 +66,14 @@ public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
     private FileTreeIterator iterator;
 
     public LoggedXMLDirectoryReader(String sourcePath) {
-        this(new File(sourcePath));
+        this(new File(sourcePath), TIMEOUT_NEVER);
     }
 
-    public LoggedXMLDirectoryReader(File source) {
+    public LoggedXMLDirectoryReader(File source, int timeout) {
+       if (timeout > 0) {
+               this.totalTimeLimitSecs = timeout;
+               this.timeoutMillis = System.currentTimeMillis() + (timeout * 1000); // set the timeout milliseconds time
+       }
         this.source = source;
         iterator = new FileTreeIterator(source);
         iterator.setFilter(new FileFilter() {
@@ -94,6 +104,19 @@ public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
         }
         return result.toString();
     }
+    
+    /*
+     * Returns 'true' if we've timed out.
+     */
+    protected boolean hasTimedOut() {
+       boolean result = false;
+       
+       if (totalTimeLimitSecs > 0 && System.currentTimeMillis() > timeoutMillis) {
+               result = true;
+       }
+       
+       return result;
+    }
 
 
     @Override
@@ -107,6 +130,11 @@ public class LoggedXMLDirectoryReader extends AbstractDocumentReader {
             ExportedDocument xdoc = new ExportedDocumentImpl();
             for (File file : dir.listFiles()) {
                 if (file.isFile()) {
+                       if (hasTimedOut() == true) { // Check to see if the current transaction has already timed out.
+                               TransactionHelper.setTransactionRollbackOnly();
+                               String errMsg = String.format("Import transaction timed out by exceeding %d seconds.", this.totalTimeLimitSecs);
+                               throw new IOException(errMsg);
+                       }
                     String name = file.getName();
                     if (ExportConstants.DOCUMENT_FILE.equals(name)) {
                         Document doc = loadXML(file);