jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r191722 - in /incubator/jackrabbit/trunk/contrib/jcr-rmi: ./ src/java/org/apache/jackrabbit/rmi/client/ src/java/org/apache/jackrabbit/rmi/iterator/ src/java/org/apache/jackrabbit/rmi/observation/ src/java/org/apache/jackrabbit/rmi/remote/ ...
Date Tue, 21 Jun 2005 20:44:23 GMT
Author: jukka
Date: Tue Jun 21 13:44:22 2005
New Revision: 191722

URL: http://svn.apache.org/viewcvs?rev=191722&view=rev
Log:
JCR-RMI: Added ObservationManager implementation contributed by Felix Meschberger.

Added:
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java   (with props)
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java   (with props)
Modified:
    incubator/jackrabbit/trunk/contrib/jcr-rmi/project.xml
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientAdapterFactory.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientSession.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientWorkspace.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/LocalAdapterFactory.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteWorkspace.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/RemoteAdapterFactory.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerAdapterFactory.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerSession.java
    incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerWorkspace.java

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/project.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/project.xml?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/project.xml (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/project.xml Tue Jun 21 13:44:22 2005
@@ -76,6 +76,10 @@
       <id>junit</id>
       <version>3.8.1</version>
     </dependency>
+    <dependency>
+      <id>commons-logging</id>
+      <version>1.0</version>
+    </dependency>
   </dependencies>
 
   <build>

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientAdapterFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientAdapterFactory.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientAdapterFactory.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientAdapterFactory.java Tue Jun 21 13:44:22 2005
@@ -29,6 +29,7 @@
 import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
@@ -44,6 +45,7 @@
 import org.apache.jackrabbit.rmi.remote.RemoteNodeDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeType;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeTypeManager;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
 import org.apache.jackrabbit.rmi.remote.RemoteProperty;
 import org.apache.jackrabbit.rmi.remote.RemotePropertyDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteQuery;
@@ -97,6 +99,17 @@
         return new ClientWorkspace(session, remote, this);
     }
 
+    /**
+     * Creates and returns a
+     * {@link ClientObservationManager ClientObservationManager} instance.
+     *
+     * {@inheritDoc}
+     */
+    public ObservationManager getObservationManager(
+            RemoteObservationManager remote) {
+        return new ClientObservationManager(remote);
+    }
+    
     /**
      * Creates and returns a
      * {@link ClientNamespaceRegistry ClientClientNamespaceRegistry} instance.

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.client;
+
+import java.rmi.RemoteException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.jackrabbit.rmi.iterator.ArrayEventListenerIterator;
+import org.apache.jackrabbit.rmi.observation.ClientEventPoll;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
+
+/**
+ * The <code>ClientObservationManager</code> class
+ * <p>
+ * This class uses an instance of the
+ * {@link org.apache.jackrabbit.rmi.observation.ClientEventPoll} class for the
+ * actual registration and event dispatching.
+ * <p>
+ * This class does not require the
+ * {@link org.apache.jackrabbit.rmi.client.LocalAdapterFactory} and consequently
+ * calls the base class constructor with a <code>null</code> factory. 
+ * <p>
+ * See the <a href="../observation/package.html><code>observation</code></a>
+ * package comment for a description on how event listener registration and
+ * notification is implemented. 
+ * 
+ * @author Felix Meschberger
+ * 
+ * @see org.apache.jackrabbit.rmi.observation.ClientEventPoll
+ */
+public class ClientObservationManager extends ClientObject implements
+        ObservationManager {
+
+    /** The remote observation manager */
+    private final RemoteObservationManager remote;
+    
+    /** The ClientEventPoll class internally used for event dispatching */
+    private ClientEventPoll poller;
+    
+    /**
+     * Creates an instance of this class talking to the given remote observation
+     * manager.
+     * 
+     * @param remote The {@link RemoteObservationManager} backing this 
+     *      client-side observation manager.
+     */
+    public ClientObservationManager(RemoteObservationManager remote) {
+        super(null);
+        this.remote = remote;
+    }
+
+    /** {@inheritDoc} */
+    public void addEventListener(EventListener listener, int eventTypes, 
+            String absPath, boolean isDeep, String[] uuid, 
+            String[] nodeTypeName, boolean noLocal) 
+            throws RepositoryException {
+        try {
+            long listenerId = getClientEventPoll().addListener(listener);
+            remote.addEventListener(listenerId, eventTypes, absPath, 
+                isDeep, uuid, nodeTypeName, noLocal);
+        } catch (RemoteException ex) {
+            throw new RemoteRepositoryException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void removeEventListener(EventListener listener)
+            throws RepositoryException {
+        try {
+            long id = getClientEventPoll().removeListener(listener);
+            remote.removeEventListener(id);
+        } catch (RemoteException ex) {
+            throw new RemoteRepositoryException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public EventListenerIterator getRegisteredEventListeners() {
+        return new ArrayEventListenerIterator(poller.getListeners());
+    }
+
+    //---------- internal ------------------------------------------------------
+    
+    /**
+     * Returns the {@link ClientEventPoll} instance used by this (client-side)
+     * observation manager. This method creates the instance on the first call
+     * and starts the poller thread to wait for remote events.
+     */
+    private synchronized ClientEventPoll getClientEventPoll() {
+        if (poller == null) {
+            poller = new ClientEventPoll(remote);
+            poller.start();
+        }
+        return poller;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientObservationManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientSession.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientSession.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientSession.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientSession.java Tue Jun 21 13:44:22 2005
@@ -64,6 +64,15 @@
 
     /** The adapted remote session. */
     private RemoteSession remote;
+    
+    /**
+     * The adapted workspace of this session. This field is set on the first
+     * call to the {@link #getWorkspace()} method assuming, that a workspace
+     * instance is not changing during the lifetime of a session, that is,
+     * each call to the server-side <code>Session.getWorkspace()</code> allways
+     * returns the same object.
+     */
+    private Workspace workspace;
 
     /**
      * Creates a client adapter for the given remote session.
@@ -117,11 +126,16 @@
 
     /** {@inheritDoc} */
     public Workspace getWorkspace() {
-        try {
-            return getFactory().getWorkspace(this, remote.getWorkspace());
-        } catch (RemoteException ex) {
-            throw new RemoteRuntimeException(ex);
+        if (workspace == null) {
+            try {
+                workspace = 
+                    getFactory().getWorkspace(this, remote.getWorkspace());
+            } catch (RemoteException ex) {
+                throw new RemoteRuntimeException(ex);
+            }
         }
+        
+        return workspace;
     }
 
     /** {@inheritDoc} */

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientWorkspace.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientWorkspace.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientWorkspace.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/ClientWorkspace.java Tue Jun 21 13:44:22 2005
@@ -57,6 +57,16 @@
     private RemoteWorkspace remote;
 
     /**
+     * The adapted observation manager of this workspace. This field is set on
+     * the first call to the {@link #getObservationManager()()} method assuming,
+     * that the observation manager instance is not changing during the lifetime
+     * of a workspace instance, that is, each call to the server-side
+     * <code>Workspace.getObservationManager()</code> allways returns the same
+     * object.
+     */
+    private ObservationManager observationManager;
+
+    /**
      * Creates a client adapter for the given remote workspace.
      *
      * @param session current session
@@ -150,9 +160,17 @@
     /** {@inheritDoc} */
     public ObservationManager getObservationManager()
             throws RepositoryException {
-        // TODO Auto-generated method stub
-        // return null;
-        throw new UnsupportedRepositoryOperationException();
+        if (observationManager == null) {
+            try {
+                observationManager = 
+                    getFactory().
+                        getObservationManager(remote.getObservationManager());
+            } catch (RemoteException ex) {
+                throw new RemoteRepositoryException(ex);
+            }
+        }
+        
+        return observationManager;
     }
 
     /** {@inheritDoc} */

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/LocalAdapterFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/LocalAdapterFactory.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/LocalAdapterFactory.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/client/LocalAdapterFactory.java Tue Jun 21 13:44:22 2005
@@ -24,11 +24,12 @@
 import javax.jcr.Session;
 import javax.jcr.Workspace;
 import javax.jcr.lock.Lock;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
@@ -44,6 +45,7 @@
 import org.apache.jackrabbit.rmi.remote.RemoteNodeDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeType;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeTypeManager;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
 import org.apache.jackrabbit.rmi.remote.RemoteProperty;
 import org.apache.jackrabbit.rmi.remote.RemotePropertyDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteQuery;
@@ -102,6 +104,15 @@
      * @return local workspace adapter
      */
     Workspace getWorkspace(Session session, RemoteWorkspace remote);
+
+    /**
+     * Factory method for creating a local adapter for a remote observation
+     * manager.
+     *
+     * @param remote remote observation manager
+     * @return local observation manager adapter
+     */
+    ObservationManager getObservationManager(RemoteObservationManager remote);
 
     /**
      * Factory method for creating a local adapter for a remote namespace

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.iterator;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+
+/**
+ * Array implementation of the JCR
+ * {@link javax.jcr.EventIterator EventIterator} interface.
+ * This class is used by the JCR-RMI client adapters to convert
+ * node arrays to iterators.
+ *
+ * @author Felix Meschberger
+ */
+public class ArrayEventIterator extends ArrayIterator implements EventIterator {
+
+    /**
+     * Creates an iterator for the given array of events.
+     *
+     * @param nodes the nodes to iterate
+     */
+    public ArrayEventIterator(Event[] nodes) {
+        super(nodes);
+    }
+
+    /** {@inheritDoc} */
+    public Event nextEvent() {
+        return (Event) next();
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.iterator;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
+
+/**
+ * Array implementation of the JCR
+ * {@link javax.jcr.EventListenerIterator EventListenerIterator} interface.
+ * This class is used by the JCR-RMI client adapters to convert
+ * listener arrays to iterators.
+ *
+ * @author Felix Meschberger
+ */
+public class ArrayEventListenerIterator extends ArrayIterator 
+        implements EventListenerIterator {
+
+    /**
+     * Creates an iterator for the given array of listeners.
+     *
+     * @param listeners the listeners to iterate
+     */
+    public ArrayEventListenerIterator(EventListener[] listeners) {
+        super(listeners);
+    }
+
+    /** {@inheritDoc} */
+    public EventListener nextEventListener() {
+        return (EventListener) next();
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/iterator/ArrayEventListenerIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.observation;
+
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.rmi.iterator.ArrayEventIterator;
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
+
+/**
+ * The <code>ClientEventPoll</code> class is the registry for client-side
+ * event listeners on behalf of the
+ * {@link org.apache.jackrabbit.rmi.client.ClientObservationManager} class. In
+ * addition this class extends the <code>java.lang.Thread</code> class able
+ * to be run in a separate thread to constantly poll the server-side observation
+ * manager for new events.
+ * <p>
+ * Notes:
+ * <ol>
+ * <li>Only one instance of this class should be instantiated for each instance
+ * of a {@link org.apache.jackrabbit.rmi.remote.RemoteObservationManager} class.
+ * <li><code>EventListener</code>s registered with this class must properly
+ * implement the <code>Object.hashCode()</code> and <code>Object.equals()</code>
+ * contracts for them to be handled correctly by this class.
+ * </ol>
+ * 
+ * @author Felix Meschberger
+ * @see #run()
+ */
+public class ClientEventPoll extends Thread {
+
+    /** logger */
+    private static final Log log = LogFactory.getLog(ClientEventPoll.class);
+    
+    /**
+     * The time in milliseconds the {@link #run()} method should be waiting
+     * for remote events.
+     * @see #run()  
+     */
+    private static final long POLL_TIMEOUT = 5000;
+    
+    /** The thread name */
+    private static final String THREAD_NAME = "Client Event Poller";
+    
+    /** The primitive unique identifier generator. */
+    private static long counter = 0;
+    
+    /** The {@link RemoteObservationManager} called for the new events. */
+    private final RemoteObservationManager remote;
+    
+    /** The map of locally registered listeners indexed by the unique identifier */
+    private Map listenerMap = new HashMap();
+    
+    /** The map of unique identifieres indexed by the registered listeners */
+    private Map idMap = new HashMap();
+    
+    /**
+     * Flag indicating whether the {@link #run()} method should terminate.
+     * @see #run()
+     */
+    private boolean running = true;
+    
+    /**
+     * Creates an instance of this class talking to the given
+     * {@link RemoteObservationManager}.
+     * 
+     * @param remote The remote observation manager which is asked for new
+     *      events. This must not be <code>null</code>.
+     * 
+     * @throws NullPointerException if <code>remote</code> is <code>null</code>.
+     */
+    public ClientEventPoll(RemoteObservationManager remote) {
+        super(THREAD_NAME);
+        
+        // check remote and assign
+        if (remote == null) {
+            throw new NullPointerException("remote");
+        }
+        this.remote = remote;
+    }
+
+    /**
+     * Registers the given local listener with this instance and returns the
+     * unique identifier assigned to it.
+     *  
+     * @param listener The <code>EventListener</code> to register.
+     * 
+     * @return The unique identifier assigned to the newly registered event
+     *      listener.
+     */
+    public synchronized long addListener(EventListener listener) {
+        Long id = new Long(counter++);
+        listenerMap.put(id, listener);
+        idMap.put(listener, id);
+        return id.longValue();
+    }
+    
+    /**
+     * Unregisters the given local listener from this instance and returns the
+     * unique identifier assigned to it.
+     *  
+     * @param listener The <code>EventListener</code> to unregister.
+     * 
+     * @return The unique identifier assigned to the unregistered event listener
+     *      or <code>-1</code> if the listener was not registered.
+     */
+    public synchronized long removeListener(EventListener listener) {
+        Long key = (Long) idMap.remove(listener);
+        if (key != null) {
+            listenerMap.remove(key);
+            return key.longValue();
+        }
+        
+        return -1;
+    }
+    
+    /**
+     * Returns an array of the registered event listeners.
+     */
+    public synchronized EventListener[] getListeners() {
+        return (EventListener[]) listenerMap.values().toArray(
+            new EventListener[(listenerMap.size())]);
+    }
+    
+    /**
+     * Indicates to the {@link #run()} method, that asking for events should
+     * be terminated.
+     * 
+     * @see #run()
+     */
+    public void terminate() {
+        this.running = false;
+    }
+    
+    //---------- Thread overwrite ---------------------------------------------
+    
+    /**
+     * Checks for remote events and dispatches them to the locally registered
+     * event listeners. This is how this method works:
+     * <ol>
+     * <li>Continue with next step if {@link #terminate()} has not been called
+     * yet.
+     * <li>Call the {@link RemoteObservationManager#getNextEvent(long)} method
+     * waiting for a specified time (5 seconds).
+     * <li>If no event was received in the specified time go back to step #1.
+     * <li>Extract the unique listener identifier from the remote event and
+     * find it in the list of locally registered event listeners. Go back to 
+     * step #1 if no such listener exists.
+     * <li>Convert the remote event list to an <code>EventIterator</code> and
+     * call the <code>EventListener.onEvent()</code> method.
+     * <li>Go back to step #1.
+     * </ol> 
+     */
+    public void run() {
+        while (running) {
+            try {
+                // ask for an event waiting at most POLL_TIMEOUT milliseconds
+                RemoteEventCollection remoteEvent = remote.getNextEvent(POLL_TIMEOUT);
+                
+                // poll time out, check running and ask again
+                if (remoteEvent == null) {
+                    continue;
+                }
+                
+                // extract the listener id from the remote event and find
+                // the locally registered event listener
+                Long id = new Long(remoteEvent.getListenerId());
+                EventListener listener = (EventListener) listenerMap.get(id);
+                
+                // if the listener is not registered (anymore), the event is
+                // silently ignored, running is checked and the server asked again
+                if (listener == null) {
+                    continue;
+                }
+                
+                // otherwise convert the remote events into an EventIterator
+                // and the listener is called
+                RemoteEventCollection.RemoteEvent[] remoteEvents = remoteEvent.getEvents(); 
+                EventIterator events = toEvents(remoteEvents);
+                try {
+                    listener.onEvent(events);
+                } catch (Exception e) {
+                    log.error("Unexpected failure of Listener " + listener, e);
+                }
+                
+            } catch (RemoteException re) {
+                log.error("Problem handling event. Looking for next one.", re);
+            }
+        }
+    }
+    
+    //---------- internal -----------------------------------------------------
+    
+    /**
+     * Converts an array of {@link RemoteEventCollection.RemoteEvent} instances to an
+     * instance of <code>EventIterator</code> suitable to be sent to the
+     * event listener.
+     */
+    private EventIterator toEvents(RemoteEventCollection.RemoteEvent[] remoteEvents) 
+            throws RemoteException {
+        Event[] events = new Event[remoteEvents.length];
+        for (int i=0; i < events.length; i++) {
+            events[i] = new JCREvent(remoteEvents[i]);
+        }
+        return new ArrayEventIterator(events);
+    }
+    
+    /**
+     * The <code>JCREvent</code> class is a simple implementation of the JCR
+     * <code>Event</code> interface to be sent to the locally registered
+     * event listeners.
+     * 
+     * @author Felix Meschberger
+     */
+    private static class JCREvent implements Event {
+        
+        /** The event type */
+        private final int type;
+        
+        /** The path of the repository item underlying the event */
+        private final String path;
+        
+        /** The user id of the session originating the event */
+        private final String userID;
+
+        /**
+         * Creates an instance of this class from the contents of the given
+         * <code>remoteEvent</code>.
+         * 
+         * @param remoteEvent The {@link RemoteEventCollection.RemoteEvent} instance
+         *      providing the data for this event.
+         * 
+         * @throws RemoteException if an RMI error occurrs.
+         */
+        private JCREvent(RemoteEventCollection.RemoteEvent remoteEvent) throws RemoteException {
+            type = remoteEvent.getType();
+            path = remoteEvent.getPath();
+            userID = remoteEvent.getUserID();
+        }
+        
+        /** @inheritDoc */
+        public int getType() {
+            return type;
+        }
+        
+        /** @inheritDoc */
+        public String getPath() {
+            return path;
+        }
+        
+        /** @inheritDoc */
+        public String getUserID() {
+            return userID;
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ClientEventPoll.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.observation;
+
+import java.util.LinkedList;
+
+/**
+ * The <code>Queue</code> class is a very simple queue assuming that there is
+ * at least one consumer and potentially multiple producers. This class poses
+ * no restrictions on the size of the queue. 
+ * 
+ * @author Felix Meschberger
+ */
+public class Queue {
+
+    /** The linked list implementing the queue of data */
+    private final LinkedList queue;
+    
+    /**
+     * Creates an instance of this queue.
+     */
+    public Queue() {
+        queue = new LinkedList();
+    }
+
+    /**
+     * Appends the given <code>object</code> to the end of the queue.
+     * <p>
+     * After appending the element, the queue is notified such that threads
+     * waiting to retrieve an element from the queue are woken up.
+     */
+    public void put(Object object) {
+        synchronized (queue) {
+            queue.addLast(object);
+            queue.notifyAll();
+        }
+    }
+
+    /**
+     * Returns the first element from the queue. If the queue is currently empty
+     * the method waits at most the given number of milliseconds.
+     * 
+     * @param timeout The maximum number of milliseconds to wait for an entry in
+     *      the queue if the queue is empty. If zero, the method waits forever
+     *      for an element.
+     * 
+     * @return The first element of the queue or <code>null</code> if the method
+     *      timed out waiting for an entry.
+     * 
+     * @throws InterruptedException Is thrown if the current thread is
+     *      interrupted while waiting for the queue to get at least one entry.
+     */
+    public Object get(long timeout) throws InterruptedException {
+        synchronized (queue) {
+            // wait for data if the queue is empty
+            if (queue.isEmpty()) {
+                queue.wait(timeout);
+            }
+            
+            // return null if queue is (still) empty
+            if (queue.isEmpty()) {
+                return null;
+            }
+            
+            // return first if queue has content now
+            return queue.removeFirst();
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/Queue.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.observation;
+
+import java.rmi.RemoteException;
+
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
+import org.apache.jackrabbit.rmi.server.RemoteAdapterFactory;
+
+/**
+ * The <code>ServerEventListenerProxy</code> class is the server-side event
+ * listener proxy registered on behalf of a client-side event listener identified
+ * with the unique identifier.
+ * <p>
+ * The term <i>Server</i> in this class indicates, that this is a server-side
+ * class. In contrast to the classes in the
+ * {@link org.apache.jackrabbit.rmi.server} package, this class neither extends
+ * the {@link org.apache.jackrabbit.rmi.server.ServerObject} class nor does it
+ * implement any of the remote interfaces in the
+ * {@link org.apache.jackrabbit.rmi.remote} package because it only is
+ * instantiated to be used on the server side.
+ * <p>
+ * See the package overview for an explanation of the mechanisms implemented for
+ * event dispatching.
+ * 
+ * @author Felix Meschberger
+ */
+public class ServerEventListenerProxy implements EventListener {
+
+    /** logger */
+    private static final Log log = 
+        LogFactory.getLog(ServerEventListenerProxy.class);
+    
+    /** The factory used to convert event iterators to remote events */
+    private final RemoteAdapterFactory factory;
+    
+    /**
+     * The unique indentifier of the client-side event listener on whose
+     * behalf this listener proxy is registered.
+     */
+    private final long listenerId;
+    
+    /**
+     * The queue to which remote events are queue for them to be picked up
+     * by calls to the
+     * {@link org.apache.jackrabbit.rmi.remote.RemoteObservationManager#getNextEvent(long)}
+     * method.
+     */
+    private final Queue queue;
+    
+    /**
+     * Creates a new instance of this listener proxy.
+     * 
+     * @param factory The {@link RemoteAdapterFactory} used to convert the
+     *      {@link EventIterator} instances to {@link RemoteEventCollection} objects.
+     * @param listenerId The unique identifier of the client-side event listener
+     *      on whose behalf this proxy works.
+     * @param queue The sink to which events to be dispatched to the client are
+     *      queued to be picked up.
+     */
+    public ServerEventListenerProxy(RemoteAdapterFactory factory, 
+            long listenerId, Queue queue) {
+        this.factory = factory;
+        this.listenerId = listenerId;
+        this.queue = queue;
+    }
+    
+    /**
+     * Converts the {@link javax.jcr.observation.Event} instances in the given
+     * iterator to an instance of {@link RemoteEventCollection} for them to be dispatched
+     * to the client-side event listener.
+     * 
+     * @param events The {@link javax.jcr.observation.Event Events} to be
+     *      dispatched.
+     */
+    public void onEvent(EventIterator events) {
+        try {
+            RemoteEventCollection remoteEvent = factory.getRemoteEvent(listenerId, events);
+            queue.put(remoteEvent);
+        } catch (RemoteException re) {
+            Throwable t = (re.getCause() == null) ? re : re.getCause(); 
+            log.error("Problem creating remote event for " + listenerId, t);
+        }
+    }
+    
+    //---------- Object overwrite ----------------------------------------------
+    
+    /**
+     * Returns the client-side listener identifier as its hash code.
+     */
+    public int hashCode() {
+        return (int) listenerId;
+    }
+    
+    /**
+     * Returns <code>true</code> if <code>obj</code> is either the same as this
+     * or a proxy for the same client-side listener, which is identicated by the
+     * same listener identifier.
+     * 
+     * @param obj The object to compare to.
+     * 
+     * @return <code>true</code> if <code>obj</code> is the same or a proxy for
+     *      the same client-side listener.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        } else if (obj instanceof ServerEventListenerProxy) {
+            return listenerId == ((ServerEventListenerProxy) obj).listenerId;
+        } else {
+            return false;
+        }
+    }
+    
+    /**
+     * Returns the a string representation of this instance, which is an
+     * indication of this class's name and the unique identifier of the real
+     * event listener.
+     */
+    public String toString() {
+        return "EventListenerProxy: listenerId=" + listenerId;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/ServerEventListenerProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html Tue Jun 21 13:44:22 2005
@@ -0,0 +1,67 @@
+<body>
+
+<p>
+Helper class used by the observation manager classes.
+</p>
+
+<p>
+The JCR observation framework defines a notification mechanism where an
+<code>EventListener</code> is registered with the observation manager
+to receive certain events during the lifetime of the registration. For
+the remote case, where the repository and the application run in different
+Java VMs on possibly different hosts, there are issues related to the
+observation framework.
+
+<p>
+The listener mechanism is a call-back mechanism where the server calls
+code in the client application. The client application code most probably
+hooks into other parts of that application. Therefore it is not practically
+feasible to just require the client listener to be serializable to be sent
+to the server for several reasons:
+
+<ul>
+<li>The RMI server cannot call any method on the RMI client. To support such
+call-back situations, the client side application would have to register
+another server, which the server side would have to call.
+<li>When trying to "transfer" the listener to the server side, the listener
+class would have to be available to the server side - either locally in the
+class path or through RMI class loading mechanisms.
+<ul>
+
+<p>
+To circumvent these issues and still be able to register event listeners,
+support for observation events is implemented in a manner similar to the Java
+Management Extensions Remote API 1.0 (JSR 160) as laid out in Chapter 2.4,
+Adding Remote Listeners:
+
+<p>
+The ObservationManager interface is not implemented in the RMI layer like
+other interfaces, which just forward calls to the API to the corresponding
+remote object by means of the RMI framework. Instead the client-side
+ObservationManager manages its own list of registered event listeners. Each
+listener registered with an ObservationManager is assigned a unique
+identifier.
+
+<p>
+The unique identifier along with the filter configuration (event type, 
+path, depth flag, uuid list, node type list, local flag) is sent to the
+server-side remote observation manager. This latter instantiates a proxy
+event listener representing the client side event listener contains the
+unique identifier as a ilnk to the client side event listener. The proxy
+event listener is the registered to the repository's ObservationManager
+with the configuration received from the client side.
+
+<p>
+When an event arrives at the event listener proxy, the proxy creates a
+new RemoteEvent instance, which contains the client-side event listener
+identifier along with the Event objects from the EventIterator. This
+RemoteEvent instance is added to a server-side queue, which may be
+retrieved from the client-side.
+
+<p>
+The client-side ObservationManager has a helper class ClientEventPoll,
+which works in the background asking the server for the RemoteEvents from
+the event queue. Each such event is then dispatched to the client-side
+event listener by calling the EventListener.onEvent() method.
+
+</body
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/observation/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import javax.jcr.observation.Event;
+
+/**
+ * The <code>RemoteEventCollection</code> class serves as a container for
+ * notifications sent to registered event listeners. Instances of this class are
+ * created by the server-side event listener proxies and sent to the client-side
+ * event poller. On the client-side the enclosed list of events is then sent to
+ * the listener identified by the contained listener identifier.
+ * 
+ * @author Felix Meschberger
+ */
+public interface RemoteEventCollection extends Remote {
+
+    /**
+     * Returns unique identifier of the client-side listener to which the
+     * enclosed events should be sent. 
+     * @throws RemoteException on RMI errors
+     */
+    long getListenerId() throws RemoteException;
+    
+    /**
+     * Returns the list of events to be sent to the client-side listener
+     * identified by {@link #getListenerId()}.
+     * @throws RemoteException on RMI errors
+     */
+    RemoteEvent[] getEvents() throws RemoteException;
+ 
+    /**
+     * The <code>RemoteEvent</code> class provides an encapsulation of single
+     * events in an event list sent to a registered listener.
+     */
+    public static interface RemoteEvent extends Remote {
+        /**
+         * Returns the event type.
+         * @throws RemoteException on RMI errors
+         */ 
+        int getType() throws RemoteException;
+
+        /**
+         * Returns the absolute path of the underlying item.
+         * @throws RemoteException on RMI errors
+         */ 
+        String getPath() throws RemoteException;
+
+        /**
+         * Returns the userID of the session causing this event.
+         * @throws RemoteException on RMI errors
+         */ 
+        String getUserID() throws RemoteException;
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteEventCollection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
+
+import org.apache.jackrabbit.rmi.client.RemoteRepositoryException;
+
+/**
+ * Remote version of the JCR {@link javax.jcr.observation.ObservationManager ObservationManager}
+ * interface. Used by the
+ * {@link org.apache.jackrabbit.rmi.server.ServerObservationManager ServerObservationManager}
+ * and
+ * {@link org.apache.jackrabbit.rmi.client.ClientObservationManager ClientObservationManager}
+ * adapter base classes to provide transparent RMI access to remote observation
+ * managers.
+ * <p>
+ * See the <a href="../observation/package.html><code>observation</code></a>
+ * package comment for a description on how event listener registration and
+ * notification is implemented. 
+ *
+ * @author Felix Meschberger
+ * 
+ * @see javax.jcr.observation.ObservationManager
+ * @see org.apache.jackrabbit.rmi.client.ClientObservationManager
+ * @see org.apache.jackrabbit.rmi.server.ServerObservationManager
+ */
+public interface RemoteObservationManager extends Remote {
+    
+    /**
+     * Remote version of the
+     * {@link javax.jcr.observation.ObservationManager#addEventListener(javax.jcr.observation.EventListener, int, java.lang.String, boolean, java.lang.String[], java.lang.String[], boolean) ObservationManager.addEventListener()}
+     * method. See class comment for an explanation on how the
+     * <code>listenerId</code> is used.
+     *
+     * @param listenerId The identification of the listener on the client
+     *      side to which events will be directed.
+     * @param eventTypes The mask of event types to be sent to this listener.
+     * @param absPath The root item defining a subtree for which events are to
+     *      be delivered.
+     * @param isDeep <code>true</code> if the events from the complete subtree
+     *      rooted at <code>absPath</code> are to be sent or only for the item
+     *      at the given path.
+     * @param uuid An optional list of node UUIDs for which events are to be
+     *      sent. If <code>null</code> this parameter is ignored.
+     * @param nodeTypeName An optional list of node type names for which events
+     *      are to be sent. If <code>null</code> this parameter is ignored.
+     * @param noLocal <code>true</code> if only events are to be sent which do
+     *      not originate from the session to which this instance belongs.
+     * 
+     * @throws RepositoryException on repository errors
+     * @throws RemoteException on RMI errors
+     */
+    public void addEventListener(long listenerId, int eventTypes, 
+        String absPath, boolean isDeep, String[] uuid, 
+        String[] nodeTypeName, boolean noLocal) 
+        throws RepositoryException, RemoteException;
+
+    /**
+     * Remote version of the
+     * {@link javax.jcr.observation.ObservationManager#removeEventListener(javax.jcr.observation.EventListener) ObservationManager.removeEventListener()}
+     * method. See class comment for an explanation on how the
+     * <code>listenerId</code> is used.
+     *
+     * @param listenerId The identification of the listener on the client
+     *      side to which events will be directed.
+     * 
+     * @throws RepositoryException on repository errors
+     * @throws RemoteException on RMI errors
+     */
+    public void removeEventListener(long listenerId)
+        throws RepositoryException, RemoteException;
+
+    /**
+     * Returns the next event to be dispatched to registered event listeners. If
+     * no event is available, this method blocks until one is available or until
+     * the given timeout expires.
+     * 
+     * @param timeout The time in milliseconds to wait for the next event
+     *      available to be dispatched. If negative or zero, this method waits
+     *      for ever.
+     * 
+     * @return The {@link RemoteEventCollection} to be dispatched. <code>null</code> is
+     *      returned if the method timed out waiting for an event to be
+     *      dispatched.
+     * 
+     * @throws RemoteException on RMI errors
+     */
+    public RemoteEventCollection getNextEvent(long timeout) 
+        throws RemoteException;
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteObservationManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteWorkspace.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteWorkspace.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteWorkspace.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/remote/RemoteWorkspace.java Tue Jun 21 13:44:22 2005
@@ -147,6 +147,18 @@
 
     /**
      * Remote version of the
+     * {@link javax.jcr.Workspace#getObservationManager() Workspace.getObservationManager()}
+     * method.
+     *
+     * @return observation manager
+     * @throws RepositoryException on repository errors
+     * @throws RemoteException on RMI errors
+     */
+    RemoteObservationManager getObservationManager()
+            throws RepositoryException, RemoteException;
+
+    /**
+     * Remote version of the
      * {@link javax.jcr.Workspace#getAccessibleWorkspaceNames() Workspace.getAccessibleWorkspaceNames()}
      * method.
      *

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/RemoteAdapterFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/RemoteAdapterFactory.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/RemoteAdapterFactory.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/RemoteAdapterFactory.java Tue Jun 21 13:44:22 2005
@@ -31,6 +31,8 @@
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.PropertyDefinition;
 import javax.jcr.nodetype.ItemDefinition;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
@@ -38,6 +40,7 @@
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionHistory;
 
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
 import org.apache.jackrabbit.rmi.remote.RemoteItem;
 import org.apache.jackrabbit.rmi.remote.RemoteItemDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteLock;
@@ -46,6 +49,7 @@
 import org.apache.jackrabbit.rmi.remote.RemoteNodeDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeType;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeTypeManager;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
 import org.apache.jackrabbit.rmi.remote.RemoteProperty;
 import org.apache.jackrabbit.rmi.remote.RemotePropertyDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteQuery;
@@ -108,6 +112,17 @@
             throws RemoteException;
 
     /**
+     * Returns a remote adapter for the given local observation manager.
+     *
+     * @param observationManager local observation manager
+     * @return remote observation manager adapter
+     * @throws RemoteException on RMI errors
+     */
+    RemoteObservationManager getRemoteObservationManager(
+            ObservationManager observationManager)
+            throws RemoteException;
+
+    /**
      * Returns a remote adapter for the given local namespace registry.
      *
      * @param registry local namespace registry
@@ -268,4 +283,15 @@
      */
     RemoteRow getRemoteRow(Row row) throws RemoteException;
 
+    /**
+     * Returns a remote adapter for the given local events.
+     *
+     * @param listenerId The listener identifier to which the events are to be
+     *      dispatched.
+     * @param event the local events
+     * @return remote event iterator adapter
+     * @throws RemoteException on RMI errors
+     */
+    RemoteEventCollection getRemoteEvent(long listenerId, EventIterator events)
+        throws RemoteException;
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerAdapterFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerAdapterFactory.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerAdapterFactory.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerAdapterFactory.java Tue Jun 21 13:44:22 2005
@@ -17,20 +17,26 @@
 package org.apache.jackrabbit.rmi.server;
 
 import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.jcr.Item;
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Workspace;
 import javax.jcr.lock.Lock;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
@@ -38,6 +44,7 @@
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionHistory;
 
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
 import org.apache.jackrabbit.rmi.remote.RemoteItem;
 import org.apache.jackrabbit.rmi.remote.RemoteItemDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteLock;
@@ -46,6 +53,7 @@
 import org.apache.jackrabbit.rmi.remote.RemoteNodeDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeType;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeTypeManager;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
 import org.apache.jackrabbit.rmi.remote.RemoteProperty;
 import org.apache.jackrabbit.rmi.remote.RemotePropertyDefinition;
 import org.apache.jackrabbit.rmi.remote.RemoteQuery;
@@ -98,6 +106,16 @@
     }
 
     /**
+     * Creates a {@link ServerObservationManager ServerObservationManager}
+     * instance.
+     * {@inheritDoc}
+     */
+    public RemoteObservationManager getRemoteObservationManager(
+        ObservationManager observationManager) throws RemoteException {
+        return new ServerObservationManager(observationManager, this);
+    }
+    
+    /**
      * Creates a {@link ServerNamespaceRegistry ServerNamespaceRegistry}
      * instance.
      * {@inheritDoc}
@@ -238,4 +256,31 @@
         return new ServerRow(row, this);
     }
 
+    /**
+     * Creates a {@link ServerEventCollection ServerEventCollection} instances.
+     * {@inheritDoc}
+     */
+    public RemoteEventCollection getRemoteEvent(long listenerId, EventIterator events)
+            throws RemoteException {
+        RemoteEventCollection.RemoteEvent[] remoteEvents;
+        if (events != null) {
+            List eventList = new ArrayList();
+            for (int i=0; events.hasNext(); i++) {
+                Event event = events.nextEvent();
+                try {
+                    eventList.add(new ServerEventCollection.ServerEvent(event.getType(),
+                        event.getPath(), event.getUserID()));
+                } catch (RepositoryException re) {
+                    throw new RemoteException(re.getMessage(), re);
+                }
+            }
+            remoteEvents = new RemoteEventCollection.RemoteEvent[eventList.size()];
+            eventList.toArray(remoteEvents);
+            
+        } else {
+            remoteEvents = new RemoteEventCollection.RemoteEvent[0]; // for safety
+        }
+        
+        return new ServerEventCollection(listenerId, remoteEvents);
+    }
 }

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.server;
+
+import java.rmi.RemoteException;
+
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection.RemoteEvent;
+
+/**
+ * The <code>ServerEventCollection</code> class implemnts the
+ * {@link org.apache.jackrabbit.rmi.remote.RemoteEventCollection}event to
+ * actually sent the server-side event to the client.
+ * <p>
+ * This class does not directly relate to any JCR class because beside the list
+ * of events the unique identifier of the client-side listener has to be
+ * provided such that the receiving listener may be identified on the
+ * client-side.
+ * <p>
+ * This class does not require the
+ * {@link org.apache.jackrabbit.rmi.server.RemoteAdapterFactory}and
+ * consequently calls the base class constructor with a <code>null</code>
+ * factory.
+ * 
+ * @author Felix Meschberger
+ */
+public class ServerEventCollection extends ServerObject implements
+        RemoteEventCollection {
+
+    /** The unique identifier of the receiving listener */
+    private final long listenerId;
+    
+    /**
+     * The list of
+     * {@link org.apache.jackrabbit.rmi.remote.RemoteEventCollection.RemoteEvent}.
+     */
+    private final RemoteEvent[] events;
+    
+    /**
+     * Creates an instance of this class.
+     * 
+     * @param listenerId The unique identifier of the client-side listener to
+     *            which the events should be sent.
+     * @param events The list of {@link RemoteEvent remote events}.
+     * 
+     * @throws RemoteException on RMI errors
+     */
+    ServerEventCollection(long listenerId, RemoteEvent[] events)
+            throws RemoteException {
+        super(null);
+        
+        this.listenerId = listenerId;
+        this.events = events;
+    }
+
+    /** {@inheritDoc} */
+    public long getListenerId() {
+        return listenerId;
+    }
+
+    /** {@inheritDoc} */
+    public RemoteEvent[] getEvents() {
+        return events;
+    }
+
+    /**
+     * Server side implementation of the {@link RemoteEvent} interface.
+     * 
+     * {@inheritDoc}
+     */
+    public static class ServerEvent extends ServerObject implements RemoteEvent {
+        
+        private final int type;
+        private final String path;
+        private final String userID;
+        
+        /**
+         * Creates an instance of this class.
+         * @param type The event type.
+         * @param path The absolute path to the underlying item.
+         * @param userId The userID of the originating session.
+         * 
+         * @throws RemoteException declared because of the declaration in the
+         *      base class constructor called. In fact this exception is never
+         *      thrown. 
+         */
+        ServerEvent(int type, String path, String userId) throws RemoteException {
+            super(null);
+            this.type = type;
+            this.path = path;
+            this.userID = userId;
+        }
+        
+        /** {@inheritDoc} */
+        public String getPath() {
+            return path;
+        }
+
+        /** {@inheritDoc} */
+        public int getType() {
+            return type;
+        }
+
+        /** {@inheritDoc} */
+        public String getUserID() {
+            return userID;
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerEventCollection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java?rev=191722&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java Tue Jun 21 13:44:22 2005
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed 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.jackrabbit.rmi.server;
+
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.jackrabbit.rmi.observation.Queue;
+import org.apache.jackrabbit.rmi.observation.ServerEventListenerProxy;
+import org.apache.jackrabbit.rmi.remote.RemoteEventCollection;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
+
+/**
+ * The <code>ServerObservationManager</code> class 
+ * 
+ * @author Felix Meschberger
+ */
+/**
+ * Remote adapter for the JCR
+ * {@link javax.jcr.observation.ObservationManager ObservationManager} interface.
+ * This class makes a local item available as an RMI service using
+ * the {@link org.apache.jackrabbit.rmi.remote.RemoteObservationManager RemoteObservationManager}
+ * interface.
+ * <p>
+ * This class works in conjunction with the
+ * {@link org.apache.jackrabbit.rmi.client.ClientObservationManager} class to
+ * implement the distributed the event listener registration described in
+ * <a href="../observation/package.html><code>observation</code></a> package
+ * comment.
+ *
+ * @author Felix Meschberger
+ * @see javax.jcr.observation.ObservationManager
+ * @see org.apache.jackrabbit.rmi.remote.RemoteObservationManager
+ */
+public class ServerObservationManager extends ServerObject implements
+        RemoteObservationManager {
+
+    /** The adapted local observation manager. */
+    private ObservationManager observationManager;
+    
+    /**
+     * The map of event listener proxies indexed by the unique identifier.
+     */
+    private Map proxyMap;
+    
+    /** 
+     * The queue to which event listener proxies post events to be reported
+     * by the {@link #getNextEvent(long)} method.
+     */
+    private Queue queue;
+
+    /**
+     * Creates a remote adapter for the given local workspace.
+     *
+     * @param observationManager local observation manager
+     * @param factory remote adapter factory
+     * @throws RemoteException on RMI errors
+     */
+    public ServerObservationManager(ObservationManager observationManager,
+            RemoteAdapterFactory factory)
+            throws RemoteException {
+        super(factory);
+        this.observationManager = observationManager;
+    }
+
+    /** {@inheritDoc} */
+    public void addEventListener(long listenerId, int eventTypes,
+        String absPath, boolean isDeep, String[] uuid, String[] nodeTypeName,
+        boolean noLocal) throws RepositoryException, RemoteException {
+        
+        // find the proxy or create one
+        ServerEventListenerProxy proxy;
+        synchronized (this) {
+            if (proxyMap == null) {
+                proxyMap = new HashMap();
+            }
+            
+            Long id = new Long(listenerId);
+            proxy = (ServerEventListenerProxy) proxyMap.get(id);
+            if (proxy == null) {
+                proxy = new ServerEventListenerProxy(getFactory(), listenerId, 
+                    getQueue());
+                proxyMap.put(id, proxy);
+            }
+        }
+        
+        // register the proxy with the observation manager
+        observationManager.addEventListener(proxy, eventTypes, absPath,
+            isDeep, uuid, nodeTypeName, noLocal);
+    }
+
+    /** {@inheritDoc} */
+    public void removeEventListener(long listenerId)
+        throws RepositoryException, RemoteException {
+        
+        // try to find the proxy in the map
+        ServerEventListenerProxy proxy;
+        synchronized (this) {
+            if (proxyMap == null) {
+                return;
+            }
+            
+            Long id = new Long(listenerId);
+            proxy = (ServerEventListenerProxy) proxyMap.remove(id);
+            if (proxy == null) {
+                return;
+            }
+        }
+        
+        // register the proxy with the observation manager
+        observationManager.removeEventListener(proxy);
+    }
+    
+    /** {@inheritDoc} */
+    public RemoteEventCollection getNextEvent(long timeout) throws RemoteException {
+        // need the queue
+        checkQueue();
+        
+        try {
+            if (timeout < 0) timeout = 0;
+            return (RemoteEventCollection) queue.get(timeout);
+        } catch (InterruptedException ie) {
+            // don't retry, but log
+        }
+        
+        // did not get anything, fall back to nothing
+        return null;
+    }
+    
+    //---------- internal ------------------------------------------------------
+    
+    /**
+     * Makes sure, the {@link #queue} field is assigned a value.
+     */
+    private synchronized void checkQueue() {
+        if (queue == null) {
+            queue = new Queue();
+        }
+    }
+    
+    /**
+     * Returns the <code>Channel</code> allocating it if required.
+     */
+    private Queue getQueue() {
+        checkQueue();
+        return queue;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerObservationManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerSession.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerSession.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerSession.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerSession.java Tue Jun 21 13:44:22 2005
@@ -45,6 +45,15 @@
 
     /** The adapted local session. */
     private Session session;
+    
+    /**
+     * The server workspace for this session. This field is assigned on demand
+     * by the first call to {@link #getWorkspace()}. The assumption is that
+     * there is only one workspace instance per session and that each call to
+     * the <code>Session.getWorkspace()</code> method of a single session will
+     * allways return the same object.
+     */
+    private RemoteWorkspace remoteWorkspace;
 
     /**
      * Creates a remote adapter for the given local session.
@@ -87,7 +96,12 @@
 
     /** {@inheritDoc} */
     public RemoteWorkspace getWorkspace() throws RemoteException {
-        return getFactory().getRemoteWorkspace(session.getWorkspace());
+        if (remoteWorkspace == null) {
+            remoteWorkspace = 
+                getFactory().getRemoteWorkspace(session.getWorkspace());
+        }
+        
+        return remoteWorkspace;
     }
 
     /** {@inheritDoc} */

Modified: incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerWorkspace.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerWorkspace.java?rev=191722&r1=191721&r2=191722&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerWorkspace.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-rmi/src/java/org/apache/jackrabbit/rmi/server/ServerWorkspace.java Tue Jun 21 13:44:22 2005
@@ -24,10 +24,12 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Workspace;
 import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.QueryManager;
 
 import org.apache.jackrabbit.rmi.remote.RemoteNamespaceRegistry;
 import org.apache.jackrabbit.rmi.remote.RemoteNodeTypeManager;
+import org.apache.jackrabbit.rmi.remote.RemoteObservationManager;
 import org.apache.jackrabbit.rmi.remote.RemoteQueryManager;
 import org.apache.jackrabbit.rmi.remote.RemoteWorkspace;
 
@@ -45,6 +47,16 @@
     private Workspace workspace;
 
     /**
+     * The remote observation manager for this workspace. This field is assigned
+     * on demand by the first call to {@link #getObservationManager()}. The
+     * assumption is that there is only one observation manager instance per
+     * workspace and that each call to the
+     * <code>Workspace.getObservationManager()</code> method of a single
+     * workspace will allways return the same object.
+     */
+    private RemoteObservationManager remoteObservationManager;
+
+    /**
      * Creates a remote adapter for the given local workspace.
      *
      * @param workspace local workspace
@@ -136,6 +148,22 @@
         }
     }
 
+    /** {@inheritDoc} */
+    public RemoteObservationManager getObservationManager()
+            throws RepositoryException, RemoteException {
+        try {
+            if (remoteObservationManager == null) {
+                ObservationManager observationManager = 
+                    workspace.getObservationManager();
+                remoteObservationManager =
+                    getFactory().getRemoteObservationManager(observationManager);
+            }
+            return remoteObservationManager;
+        } catch (RepositoryException ex) {
+            throw getRepositoryException(ex);
+        }
+    }
+    
     /** {@inheritDoc} */
     public String[] getAccessibleWorkspaceNames()
             throws RepositoryException, RemoteException {



Mime
View raw message