jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1352593 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/
Date Thu, 21 Jun 2012 16:14:02 GMT
Author: mduerig
Date: Thu Jun 21 16:14:02 2012
New Revision: 1352593

URL: http://svn.apache.org/viewvc?rev=1352593&view=rev
Log:
OAK-144: Implement observation
alternative approach: initial implementation

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeExtractor.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ObservationManagerImpl.java
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeSet.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeExtractor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeExtractor.java?rev=1352593&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeExtractor.java
(added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ChangeExtractor.java
Thu Jun 21 16:14:02 2012
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.api;
+
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+/**
+ * An instance of {@code ChangeExtractor} can be used to follow changes
+ * done to a {@link Root} instance.
+ */
+public interface ChangeExtractor {
+
+    /**
+     * Get the most recent changes.
+     * @param diff  {@code NodeStateDiff} to receive the changes
+     */
+    void getChanges(NodeStateDiff diff);
+
+    /**
+     * Compares the given two node states. Any found differences are
+     * reported by calling the relevant added, changed or deleted methods
+     * of the given handler.
+     *
+     * @param before node state before changes
+     * @param after node state after changes
+     * @param diff handler of node state differences
+     */
+    void getChanges(NodeState before, NodeState after, NodeStateDiff diff);
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ContentSession.java
Thu Jun 21 16:14:02 2012
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.api;
 
 import java.io.Closeable;
 
-import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
 /**
@@ -93,21 +92,5 @@ public interface ContentSession extends 
     @Nonnull
     CoreValueFactory getCoreValueFactory();
 
-    /**
-     * Retrieves {@link ChangeSet changes} in the underlying repository which
-     * occurred at {@code path}. If {@code previous} is {@code null} this method
-     * blocks until a changes occurs but no longer than for {@code timeout}
-     * milliseconds. If {@code previous} is not {@code null} this method returns a
-     * {@code ChangeSet} instance which follows the one given in {@code previous}.
-     *
-     * @param path  path to the subtree
-     * @param previous  previous {@code ChangeSet} or {@code null}.
-     * @param timeout the maximum time to wait in milliseconds
-     * @return  a next {@code ChangeSet} or {@code null} if a timeout occurred.
-     */
-    @CheckForNull
-    ChangeSet getChanges(String path, ChangeSet previous, long timeout);
-
     // TODO : add versioning operations
-
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java Thu
Jun 21 16:14:02 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.oak.api;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 
 /**
  * The root of a {@link Tree}.
@@ -93,4 +94,11 @@ public interface Root {
      * @return  {@code true} iff this tree was modified
      */
     boolean hasPendingChanges();
+
+    /**
+     * Return a {@link ChangeExtractor} for this {@code Root}.
+     * @return a {@code ChangeExtractor}.
+     */
+    @Nonnull
+    ChangeExtractor getChangeExtractor();
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
Thu Jun 21 16:14:02 2012
@@ -24,7 +24,6 @@ import javax.security.auth.login.LoginCo
 import javax.security.auth.login.LoginException;
 
 import org.apache.jackrabbit.oak.api.AuthInfo;
-import org.apache.jackrabbit.oak.api.ChangeSet;
 import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.api.QueryEngine;
@@ -98,9 +97,4 @@ class ContentSessionImpl implements Cont
     public CoreValueFactory getCoreValueFactory() {
         return store.getValueFactory();
     }
-
-    @Override
-    public ChangeSet getChanges(String path, ChangeSet previous, long timeout) {
-        return null; // todo implement getChanges. See OAK-144
-    }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
Thu Jun 21 16:14:02 2012
@@ -20,9 +20,11 @@ package org.apache.jackrabbit.oak.core;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Nonnull;
 
+import org.apache.jackrabbit.oak.api.ChangeExtractor;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.ConflictHandler;
 import org.apache.jackrabbit.oak.api.ConflictHandler.Resolution;
@@ -94,6 +96,12 @@ public class RootImpl implements Root {
     }
 
     /**
+     * Reference to a {@code NodeState} of the revision up to which
+     * observation events are generated.
+     */
+    private final AtomicReference<NodeState> observationLimit;
+
+    /**
      * New instance bases on a given {@link NodeStore} and a workspace
      * @param store  node store
      * @param workspaceName  name of the workspace
@@ -102,6 +110,7 @@ public class RootImpl implements Root {
     @SuppressWarnings("UnusedParameters")
     public RootImpl(NodeStore store, String workspaceName) {
         this.store = store;
+        this.observationLimit = new AtomicReference<NodeState>(store.getRoot());
         branch = store.branch();
         root = TreeImpl.createRoot(this);
     }
@@ -152,6 +161,10 @@ public class RootImpl implements Root {
     @Override
     public void refresh() {
         currentRootState = null;
+        // There is a small race here an we risk to get an "earlier" revision for the
+        // observation limit than for the branch. This is not a problem though since
+        // observation will catch up later on.
+        observationLimit.set(store.getRoot());
         branch = store.branch();
         root = TreeImpl.createRoot(this);
     }
@@ -169,6 +182,26 @@ public class RootImpl implements Root {
         return !getBaseState().equals(getCurrentRootState());
     }
 
+    @Override
+    @Nonnull
+    public ChangeExtractor getChangeExtractor() {
+        return new ChangeExtractor() {
+            private NodeState baseLine = observationLimit.get();
+
+            @Override
+            public void getChanges(NodeStateDiff diff) {
+                NodeState head = observationLimit.get();
+                store.compare(baseLine, head, diff);
+                baseLine = head;
+            }
+
+            @Override
+            public void getChanges(NodeState before, NodeState after, NodeStateDiff diff)
{
+                store.compare(before, after, diff);
+            }
+        };
+    }
+
     /**
      * Add a {@code PurgeListener} to this instance. Listeners are automatically
      * unregistered after having been called. If further notifications are required,

Added: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ObservationManagerImpl.java?rev=1352593&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ObservationManagerImpl.java
(added)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ObservationManagerImpl.java
Thu Jun 21 16:14:02 2012
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.jcr;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventJournal;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.EventListenerIterator;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.jackrabbit.commons.iterator.EventListenerIteratorAdapter;
+import org.apache.jackrabbit.oak.api.ChangeExtractor;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+
+public class ObservationManagerImpl implements ObservationManager {
+    private final SessionDelegate sessionDelegate;
+    private final Map<EventListener, ChangeProcessor> processors =
+            new HashMap<EventListener, ChangeProcessor>();
+
+    private final Timer timer = new Timer("ObservationManager", true);
+
+    public ObservationManagerImpl(SessionDelegate sessionDelegate) {
+        this.sessionDelegate = sessionDelegate;
+    }
+
+    public void dispose() {
+        for (ChangeProcessor processor : processors.values()) {
+            processor.stop();
+        }
+        timer.cancel();
+    }
+
+    @Override
+    public void addEventListener(EventListener listener, int eventTypes, String absPath,
+            boolean isDeep, String[] uuid, String[] nodeTypeName, boolean noLocal)
+            throws RepositoryException {
+
+        ChangeProcessor processor = processors.get(listener);
+        if (processor == null) {
+            ChangeExtractor extractor = sessionDelegate.getChangeExtractor();
+            ChangeFilter filter = new ChangeFilter(eventTypes, absPath, isDeep, uuid, nodeTypeName,
noLocal);
+            ChangeProcessor changeProcessor = new ChangeProcessor(extractor, listener, filter);
+            processors.put(listener, changeProcessor);
+            timer.schedule(changeProcessor, 0, 1000);
+        }
+        else {
+            ChangeFilter filter = new ChangeFilter(eventTypes, absPath, isDeep, uuid, nodeTypeName,
noLocal);
+            processor.setFilter(filter);
+        }
+    }
+
+    @Override
+    public void removeEventListener(EventListener listener) throws RepositoryException {
+        ChangeProcessor processor = processors.remove(listener);
+        if (processor != null) {
+            processor.stop();
+        }
+    }
+
+    @Override
+    public EventListenerIterator getRegisteredEventListeners() throws RepositoryException
{
+        return new EventListenerIteratorAdapter(processors.keySet());
+    }
+
+    @Override
+    public void setUserData(String userData) throws RepositoryException {
+        // todo implement setUserData
+    }
+
+    @Override
+    public EventJournal getEventJournal() throws RepositoryException {
+        return null; // todo implement getEventJournal
+    }
+
+    @Override
+    public EventJournal getEventJournal(int eventTypes, String absPath, boolean isDeep, String[]
uuid, String[]
+            nodeTypeName) throws RepositoryException {
+        return null; // todo implement getEventJournal
+    }
+
+    //------------------------------------------------------------< private >---
+
+    private static class ChangeProcessor extends TimerTask {
+        private final ChangeExtractor changeExtractor;
+        private final EventListener listener;
+        private final AtomicReference<ChangeFilter> filterRef;
+
+        private volatile boolean stopped;
+
+        public ChangeProcessor(ChangeExtractor changeExtractor, EventListener listener, ChangeFilter
filter) {
+            this.changeExtractor = changeExtractor;
+            this.listener = listener;
+            filterRef = new AtomicReference<ChangeFilter>(filter);
+        }
+
+        public void setFilter(ChangeFilter filter) {
+            filterRef.set(filter);
+        }
+
+        public void stop() {
+            cancel();
+            stopped = true;
+        }
+
+        @Override
+        public void run() {
+            changeExtractor.getChanges(new EventGeneratingNodeStateDiff());
+        }
+
+        private class EventGeneratingNodeStateDiff implements NodeStateDiff {
+            private final String path;
+
+            private EventGeneratingNodeStateDiff(String path) {
+                this.path = path;
+            }
+
+            public EventGeneratingNodeStateDiff() {
+                this("");
+            }
+
+            @Override
+            public void propertyAdded(PropertyState after) {
+                if (!stopped && filterRef.get().include(Event.PROPERTY_ADDED, path,
after)) {
+                    // todo implement propertyAdded
+//                    listener.onEvent(null);
+                }
+            }
+
+            @Override
+            public void propertyChanged(PropertyState before, PropertyState after) {
+                if (!stopped && filterRef.get().include(Event.PROPERTY_CHANGED, path,
before)) {
+                    // todo implement propertyChanged
+//                    listener.onEvent(null);
+                }
+            }
+
+            @Override
+            public void propertyDeleted(PropertyState before) {
+                if (!stopped && filterRef.get().include(Event.PROPERTY_REMOVED, path,
before)) {
+                    // todo implement propertyDeleted
+//                    listener.onEvent(null);
+                }
+            }
+
+            @Override
+            public void childNodeAdded(String name, NodeState after) {
+                if (!stopped && filterRef.get().include(Event.NODE_ADDED, path, after))
{
+                    // todo implement childNodeAdded
+//                    listener.onEvent(null);
+                }
+            }
+
+            @Override
+            public void childNodeDeleted(String name, NodeState before) {
+                if (!stopped && filterRef.get().include(Event.NODE_REMOVED, path,
before)) {
+                    // todo implement childNodeDeleted
+//                    listener.onEvent(null);
+                }
+            }
+
+            @Override
+            public void childNodeChanged(String name, NodeState before, NodeState after)
{
+                if (!stopped && filterRef.get().includeChildren(path)) {
+                    changeExtractor.getChanges(before, after,
+                            new EventGeneratingNodeStateDiff(PathUtils.concat(path, name)));
+                }
+            }
+        }
+    }
+
+    private static class ChangeFilter {
+        public ChangeFilter(int eventTypes, String absPath, boolean deep, String[] uuid,
String[] nodeTypeName,
+                boolean noLocal) {
+            // todo implement ChangeFilter
+        }
+
+        public boolean include(int eventType, String path, PropertyState propertyState) {
+            return true; // todo implement include
+        }
+
+        public boolean include(int eventType, String path, NodeState nodeState) {
+            return true; // todo implement include
+        }
+
+        public boolean includeChildren(String path) {
+            return true; // todo implement includeChildren
+        }
+    }
+}

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
Thu Jun 21 16:14:02 2012
@@ -32,11 +32,13 @@ import javax.jcr.Session;
 import javax.jcr.Workspace;
 import javax.jcr.lock.LockManager;
 import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.observation.ObservationManager;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.version.VersionManager;
 
 import org.apache.jackrabbit.oak.api.AuthInfo;
+import org.apache.jackrabbit.oak.api.ChangeExtractor;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.ConflictHandler;
 import org.apache.jackrabbit.oak.api.ContentSession;
@@ -70,6 +72,7 @@ public class SessionDelegate {
     private final Root root;
     private final ConflictHandler conflictHandler;
 
+    private ObservationManagerImpl observationManager;
     private boolean isAlive = true;
 
     SessionDelegate(Repository repository, ContentSession contentSession) throws RepositoryException
{
@@ -111,6 +114,9 @@ public class SessionDelegate {
         }
 
         isAlive = false;
+        if (observationManager != null) {
+            observationManager.dispose();
+        }
         // TODO
 
         try {
@@ -253,6 +259,11 @@ public class SessionDelegate {
         }
     }
 
+    @Nonnull
+    public ChangeExtractor getChangeExtractor() {
+        return root.getChangeExtractor();
+    }
+
     //----------------------------------------------------------< Workspace >---
 
     @Nonnull
@@ -361,6 +372,14 @@ public class SessionDelegate {
     }
 
     @Nonnull
+    public ObservationManager getObservationManager() {
+        if (observationManager == null) {
+            observationManager = new ObservationManagerImpl(this);
+        }
+        return observationManager;
+    }
+
+    @Nonnull
     public ContentSession getContentSession() {
         return contentSession;
     }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java?rev=1352593&r1=1352592&r2=1352593&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/WorkspaceImpl.java
Thu Jun 21 16:14:02 2012
@@ -16,17 +16,8 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
-import org.apache.jackrabbit.api.JackrabbitWorkspace;
-import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
-import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.jcr.nodetype.NodeTypeManagerImpl;
-import org.apache.jackrabbit.oak.jcr.query.QueryManagerImpl;
-import org.apache.jackrabbit.oak.jcr.security.privilege.PrivilegeManagerImpl;
-import org.apache.jackrabbit.oak.plugins.name.NamespaceRegistryImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
+import java.io.IOException;
+import java.io.InputStream;
 
 import javax.jcr.NamespaceRegistry;
 import javax.jcr.Repository;
@@ -39,8 +30,18 @@ import javax.jcr.observation.Observation
 import javax.jcr.query.QueryManager;
 import javax.jcr.version.Version;
 import javax.jcr.version.VersionManager;
-import java.io.IOException;
-import java.io.InputStream;
+
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.jcr.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.oak.jcr.query.QueryManagerImpl;
+import org.apache.jackrabbit.oak.jcr.security.privilege.PrivilegeManagerImpl;
+import org.apache.jackrabbit.oak.plugins.name.NamespaceRegistryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
 
 /**
  * {@code WorkspaceImpl}...
@@ -164,8 +165,7 @@ public class WorkspaceImpl implements Ja
         ensureIsAlive();
         ensureSupportedOption(Repository.OPTION_OBSERVATION_SUPPORTED);
 
-        // TODO
-        throw new UnsupportedRepositoryOperationException("TODO: Workspace.getObservationManager");
+        return sessionDelegate.getObservationManager();
     }
 
     @Override
@@ -343,4 +343,5 @@ public class WorkspaceImpl implements Ja
             throw new UnsupportedRepositoryOperationException(option + " is not supported
by this repository.");
         }
     }
+
 }



Mime
View raw message