You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2011/09/02 18:35:57 UTC

svn commit: r1164616 - in /jackrabbit/sandbox/jackrabbit-mk: jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/...

Author: mduerig
Date: Fri Sep  2 16:35:56 2011
New Revision: 1164616

URL: http://svn.apache.org/viewvc?rev=1164616&view=rev
Log:
Microkernel based Jackrabbit prototype (WIP)
observation: use ExecutorService for change polling instead of per session thread

Modified:
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
    jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Subscription.java

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java Fri Sep  2 16:35:56 2011
@@ -79,6 +79,7 @@ import javax.jcr.version.Version;
 import javax.jcr.version.VersionException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.concurrent.ExecutorService;
 
 /**
  * <code>WorkspaceImpl</code>...

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Fri Sep  2 16:35:56 2011
@@ -16,32 +16,6 @@
  */
 package org.apache.jackrabbit.jcr2spi;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.MergeException;
-import javax.jcr.NamespaceException;
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.ReferentialIntegrityException;
-import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.query.InvalidQueryException;
-import javax.jcr.version.VersionException;
-
 import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEventListener;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
@@ -116,6 +90,22 @@ import org.apache.jackrabbit.spi.commons
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.lock.LockException;
+import javax.jcr.query.InvalidQueryException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+
 /**
  * <code>WorkspaceManager</code>...
  */
@@ -131,7 +121,7 @@ public class WorkspaceManager implements
     private final HierarchyManager hierarchyManager;
 
     private final CacheBehaviour cacheBehaviour;
-    private final boolean observationSupported;
+    private final ExecutorService changePollingExecutor;
     private final int pollTimeout;
 
     private final IdFactory idFactory;
@@ -152,12 +142,7 @@ public class WorkspaceManager implements
      * It is also <code>null</code> if {@link CacheBehaviour#INVALIDATE} is
      * configured and no event listeners have been registered.
      */
-    private Thread changeFeed;
-
-    /**
-     * Flag that indicates that the changeFeed thread should be disposed.
-     */
-    private volatile boolean disposeChangeFeed;
+    private Future<Object> changeFeed;  // No bottom type in Java. Use object and discard return value
 
     /**
      * List of event listener that are set on this WorkspaceManager to get
@@ -176,13 +161,16 @@ public class WorkspaceManager implements
     private ItemInfoCache cache;
 
     public WorkspaceManager(RepositoryService service, SessionInfo sessionInfo, CacheBehaviour cacheBehaviour,
-            int pollTimeout, boolean observationSupported) throws RepositoryException {
+            int pollTimeout, boolean observationSupported)
+            throws RepositoryException {
 
         this.service = service;
         this.sessionInfo = sessionInfo;
         this.cacheBehaviour = cacheBehaviour;
-        this.observationSupported = observationSupported;
         this.pollTimeout = pollTimeout;
+        changePollingExecutor = observationSupported
+            ?  service.getChangePollingExecutor()
+            : null;
 
         nameFactory = service.getNameFactory();
         pathFactory = service.getPathFactory();
@@ -353,8 +341,8 @@ public class WorkspaceManager implements
      * @throws RepositoryException if the listener cannot be registered.
      */
     public void addEventListener(InternalEventListener listener) throws RepositoryException {
-        if (changeFeed == null) {
-            changeFeed = createChangeFeed(pollTimeout, observationSupported);
+        if (changeFeed == null && changePollingExecutor != null) {
+            changeFeed = changePollingExecutor.submit(new ChangePolling(pollTimeout));
         }
 
         synchronized (listeners) {
@@ -525,26 +513,6 @@ public class WorkspaceManager implements
         return new ItemDefinitionProviderImpl(entProvider, service, sessionInfo);
     }
 
-    /**
-     * Creates a background thread which polls for external changes on the
-     * RepositoryService.
-     *
-     * @param pollTimeout the polling timeout in milliseconds.
-     * @param enableObservation if observation should be enabled.
-     * @return the background polling thread or <code>null</code> if the underlying
-     *         <code>RepositoryService</code> does not support observation.
-     */
-    private Thread createChangeFeed(int pollTimeout, boolean enableObservation) {
-        Thread t = null;
-        if (enableObservation) {
-            t = new Thread(new ChangePolling(pollTimeout));
-            t.setName("Change Polling");
-            t.setDaemon(true);
-            t.start();
-        }
-        return t;
-    }
-
     //-----------------------------------------------------< wsp management >---
 
     /**
@@ -631,9 +599,7 @@ public class WorkspaceManager implements
         }
         try {
             if (changeFeed != null) {
-                disposeChangeFeed = true;
-                changeFeed.interrupt();
-                changeFeed.join();
+                changeFeed.cancel(true);
             }
             hierarchyManager.dispose();
             if (subscription != null) {
@@ -1089,7 +1055,7 @@ public class WorkspaceManager implements
     /**
      * Implements the polling for changes on the repository service.
      */
-    private final class ChangePolling implements Runnable {
+    private final class ChangePolling implements Callable<Object> {
 
         /**
          * The polling timeout in milliseconds.
@@ -1106,44 +1072,35 @@ public class WorkspaceManager implements
         }
 
         @Override
-        public void run() {
+        public Object call() throws Exception {
             String wspName = sessionInfo.getWorkspaceName();            
-            while (!Thread.interrupted() && !disposeChangeFeed) {
-                try {
-                    InternalEventListener[] iel;
-                    Subscription subscription;
-                    synchronized (listeners) {
-                        while (WorkspaceManager.this.subscription == null) {
-                            listeners.wait();
-                        }
-                        iel = listeners.toArray(new InternalEventListener[listeners.size()]);
-                        subscription = WorkspaceManager.this.subscription;
+            try {
+                InternalEventListener[] iel;
+                Subscription subscription;
+                synchronized (listeners) {
+                    while (WorkspaceManager.this.subscription == null) {
+                        listeners.wait();
                     }
+                    iel = listeners.toArray(new InternalEventListener[listeners.size()]);
+                    subscription = WorkspaceManager.this.subscription;
+                }
 
-                    log.debug("calling getEvents() (Workspace={})", wspName);
-                    EventBundle[] bundles = service.getEvents(subscription, pollTimeout);
-                    log.debug("returned from getEvents() (Workspace={})", wspName);
-                    // check if thread had been interrupted while
-                    // getting events
-                    if (Thread.interrupted() || disposeChangeFeed) {
-                        log.debug("Thread interrupted, terminating...");
-                        break;
-                    }
-                    if (bundles.length > 0) {
-                        onEventReceived(bundles, iel);
-                    }
-                } catch (UnsupportedRepositoryOperationException e) {
-                    log.error("SPI implementation does not support observation: " + e);
-                    // terminate
-                    break;
-                } catch (RepositoryException e) {
-                    log.info("Workspace=" + wspName + ": Exception while retrieving event bundles: " + e);
-                    log.debug("Dump:", e);
-                } catch (InterruptedException e) {
-                    // terminate
-                    break;
+                log.debug("calling getEvents() (Workspace={})", wspName);
+                EventBundle[] bundles = service.getEvents(subscription, pollTimeout);
+                log.debug("returned from getEvents() (Workspace={})", wspName);
+
+                if (!Thread.interrupted() && bundles.length > 0) {
+                    onEventReceived(bundles, iel);
                 }
+                changePollingExecutor.submit(this);
+            } catch (UnsupportedRepositoryOperationException e) {
+                log.error("SPI implementation does not support observation: " + e);
+            } catch (RepositoryException e) {
+                log.info("Workspace=" + wspName + ": Exception while retrieving event bundles: " + e);
+                log.debug("Dump:", e);
             }
+            return null;
         }
+
     }
 }

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java Fri Sep  2 16:35:56 2011
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutorService;
 
 import javax.jcr.Credentials;
 import javax.jcr.ItemNotFoundException;
@@ -523,9 +524,13 @@ public abstract class AbstractJCR2SPITes
                 values);
     }
 
-
     //--------------------------------------------------------< Observation >---
 
+    @Override
+    public ExecutorService getChangePollingExecutor() throws RepositoryException {
+        return repositoryService.getChangePollingExecutor();
+    }
+
     public EventFilter createEventFilter(SessionInfo sessionInfo, int eventTypes, Path absPath,
             boolean isDeep, String[] uuid, Name[] nodeTypeName, boolean noLocal) throws RepositoryException {
 

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractReadableRepositoryService.java Fri Sep  2 16:35:56 2011
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ExecutorService;
 
 import javax.jcr.Credentials;
 import javax.jcr.ItemNotFoundException;

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java Fri Sep  2 16:35:56 2011
@@ -16,39 +16,6 @@
  */
 package org.apache.jackrabbit.spi.commons;
 
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Credentials;
-import javax.jcr.GuestCredentials;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.ItemExistsException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.LoginException;
-import javax.jcr.MergeException;
-import javax.jcr.NamespaceException;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.ReferentialIntegrityException;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.ValueFormatException;
-import javax.jcr.lock.LockException;
-import javax.jcr.nodetype.ConstraintViolationException;
-import javax.jcr.nodetype.InvalidNodeTypeDefinitionException;
-import javax.jcr.nodetype.NoSuchNodeTypeException;
-import javax.jcr.nodetype.NodeTypeExistsException;
-import javax.jcr.query.InvalidQueryException;
-import javax.jcr.version.VersionException;
-
 import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
 import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.spi.Batch;
@@ -81,6 +48,40 @@ import org.apache.jackrabbit.spi.commons
 import org.apache.jackrabbit.spi.commons.nodetype.QDefinitionBuilderFactory;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 
+import javax.jcr.AccessDeniedException;
+import javax.jcr.Credentials;
+import javax.jcr.GuestCredentials;
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.LoginException;
+import javax.jcr.MergeException;
+import javax.jcr.NamespaceException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.InvalidNodeTypeDefinitionException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeTypeExistsException;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.version.VersionException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 /**
  * <code>AbstractRepositoryService</code> provides an abstract base class for
  * repository service implementations. This class provides default
@@ -114,6 +115,9 @@ public abstract class AbstractRepository
      */
     protected QNodeDefinition rootNodeDefinition;
 
+    /** Executor service for change polling */
+    private ExecutorService changePollingExecutor;
+
     /**
      * @return {@link IdFactoryImpl#getInstance()}.
      * @throws RepositoryException if an error occurs.
@@ -387,7 +391,9 @@ public abstract class AbstractRepository
      * This default implementation does nothing.
      */
     public void dispose(SessionInfo sessionInfo) throws RepositoryException {
-        // do nothing
+        if (changePollingExecutor != null) {
+            changePollingExecutor.shutdown();
+        }
     }
 
     //-----------------------------< node types >-------------------------------
@@ -881,4 +887,17 @@ public abstract class AbstractRepository
         throw new UnsupportedRepositoryOperationException();
     }
 
+    //------------------------------------------< observation >---
+
+    /**
+     * @return  an instance of a single thread executor
+     */
+    @Override
+    public ExecutorService getChangePollingExecutor() {
+        if (changePollingExecutor == null) {
+            changePollingExecutor = Executors.newSingleThreadExecutor();
+        }
+        return changePollingExecutor;
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java Fri Sep  2 16:35:56 2011
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.spi.common
 import java.io.InputStream;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.concurrent.ExecutorService;
 
 import javax.jcr.Credentials;
 import javax.jcr.RepositoryException;
@@ -586,6 +587,15 @@ public class RepositoryServiceLogger ext
                 qnodeTypeName, noLocal});
     }
 
+    @Override
+    public ExecutorService getChangePollingExecutor() throws RepositoryException {
+        return (ExecutorService) execute(new Callable() {
+            public Object call() throws RepositoryException {
+                return service.getChangePollingExecutor();
+            }
+        }, "getChangePollingExecutor()", new Object[]{});
+    }
+
     public Subscription createSubscription(final SessionInfo sessionInfo, final EventFilter[] filters)
             throws RepositoryException {
 

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java Fri Sep  2 16:35:56 2011
@@ -42,6 +42,8 @@ import javax.jcr.version.VersionExceptio
 import java.io.InputStream;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 /**
  * The <code>RepositoryService</code> interface defines methods used to
@@ -920,6 +922,14 @@ public interface RepositoryService {
             throws RepositoryException;
 
     //--------------------------------------------------------< Observation >---
+
+    /**
+     * Return an executor service to use for change polling. If <code>null</code>
+     * observation is disabled.
+     * @return
+     */
+    public ExecutorService getChangePollingExecutor() throws RepositoryException;
+
     /**
      * Creates an event filter. If the repository supports observation, the
      * filter created is based on the parameters available in {@link

Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Subscription.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Subscription.java?rev=1164616&r1=1164615&r2=1164616&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Subscription.java (original)
+++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Subscription.java Fri Sep  2 16:35:56 2011
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.spi;
 
+import java.util.concurrent.ExecutorService;
+
 /**
  * <code>Subscription</code> defines a marker interface for an event
  * subscription. An implementation will likely keep information in this object