Author: mduerig
Date: Tue Dec 3 21:28:15 2013
New Revision: 1547592
URL: http://svn.apache.org/r1547592
Log:
OAK-1120: Enhance observation mechanism to support Apache Sling
Integrate Observer and Observable with Whiteboard
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ObserverTracker.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreService.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java?rev=1547592&r1=1547591&r2=1547592&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/Oak.java
Tue Dec 3 21:28:15 2013
@@ -16,6 +16,11 @@
*/
package org.apache.jackrabbit.oak;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.io.Closeable;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -25,6 +30,7 @@ import java.util.concurrent.ScheduledThr
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+
import javax.annotation.Nonnull;
import javax.jcr.NoSuchWorkspaceException;
import javax.management.JMException;
@@ -53,6 +59,8 @@ import org.apache.jackrabbit.oak.spi.com
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
+import org.apache.jackrabbit.oak.spi.commit.Observable;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.lifecycle.CompositeInitializer;
import org.apache.jackrabbit.oak.spi.lifecycle.OakInitializer;
import org.apache.jackrabbit.oak.spi.lifecycle.RepositoryInitializer;
@@ -67,9 +75,8 @@ import org.apache.jackrabbit.oak.spi.sta
import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Lists.newArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Builder class for constructing {@link ContentRepository} instances with
@@ -80,6 +87,7 @@ import static com.google.common.collect.
* @since Oak 0.6
*/
public class Oak {
+ private static final Logger LOG = LoggerFactory.getLogger(Oak.class);
/**
* Constant for the default workspace name
@@ -152,6 +160,7 @@ public class Oak {
@Override
public <T> Registration register(
Class<T> type, T service, Map<?, ?> properties) {
+ Closeable subscription = null;
Future<?> future = null;
if (executor != null && type == Runnable.class) {
Runnable runnable = (Runnable) service;
@@ -169,6 +178,8 @@ public class Oak {
runnable, period, period, TimeUnit.SECONDS);
}
}
+ } else if (type == Observer.class && store instanceof Observable) {
+ subscription = ((Observable) store).addObserver((Observer)
service);
}
ObjectName objectName = null;
@@ -188,6 +199,7 @@ public class Oak {
final Future<?> f = future;
final ObjectName on = objectName;
+ final Closeable sub = subscription;
return new Registration() {
@Override
public void unregister() {
@@ -201,6 +213,13 @@ public class Oak {
// ignore
}
}
+ if (sub != null) {
+ try {
+ sub.close();
+ } catch (IOException e) {
+ LOG.warn("Unexpected IOException while
unsubscribing observer", e);
+ }
+ }
}
};
}
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ObserverTracker.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ObserverTracker.java?rev=1547592&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ObserverTracker.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/ObserverTracker.java
Tue Dec 3 21:28:15 2013
@@ -0,0 +1,70 @@
+package org.apache.jackrabbit.oak.osgi;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Maps.newHashMap;
+
+import java.io.Closeable;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.io.Closeables;
+import org.apache.jackrabbit.oak.spi.commit.Observable;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ObserverTracker implements ServiceTrackerCustomizer {
+ private final Observable observable;
+ private final Map<ServiceReference, Closeable> subscriptions =
newHashMap();
+
+ private BundleContext bundleContext;
+ private ServiceTracker tracker;
+
+ public ObserverTracker(@Nonnull Observable observable) {
+ this.observable = checkNotNull(observable);
+ }
+
+ public void start(@Nonnull BundleContext bundleContext) {
+ checkState(this.bundleContext == null);
+ this.bundleContext = checkNotNull(bundleContext);
+ tracker = new ServiceTracker(bundleContext, Observer.class.getName(),
this);
+ tracker.open();
+ }
+
+ public void stop() {
+ checkState(this.bundleContext != null);
+ tracker.close();
+ }
+
+ //------------------------< ServiceTrackerCustomizer
>----------------------
+
+ @Override
+ public Object addingService(ServiceReference reference) {
+ Object service = bundleContext.getService(reference);
+
+ if (service instanceof Observer) {
+ Closeable subscription = observable.addObserver((Observer)
service);
+ subscriptions.put(reference, subscription);
+ return service;
+ } else {
+ bundleContext.ungetService(reference);
+ return null;
+ }
+ }
+
+ @Override
+ public void modifiedService(ServiceReference reference, Object service) {
+ // nothing to do
+ }
+
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ Closeables.closeQuietly(subscriptions.get(reference));
+ bundleContext.ungetService(reference);
+ }
+
+}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreService.java?rev=1547592&r1=1547591&r2=1547592&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStoreService.java
Tue Dec 3 21:28:15 2013
@@ -18,16 +18,20 @@
*/
package org.apache.jackrabbit.oak.plugins.mongomk;
+import static
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import com.mongodb.DB;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
import org.apache.felix.scr.annotations.Property;
import org.apache.jackrabbit.oak.api.jmx.CacheStatsMBean;
+import org.apache.jackrabbit.oak.osgi.ObserverTracker;
import org.apache.jackrabbit.oak.plugins.mongomk.util.MongoConnection;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.spi.whiteboard.OsgiWhiteboard;
@@ -40,10 +44,6 @@ import org.osgi.service.component.annota
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.mongodb.DB;
-
-import static
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
-
/**
* The OSGi service to start/stop a MongoNodeStore instance.
*/
@@ -76,6 +76,7 @@ public class MongoNodeStoreService {
private ServiceRegistration reg;
private MongoNodeStore store;
+ private ObserverTracker observerTracker;
private final List<Registration> registrations = new
ArrayList<Registration>();
@Activate
@@ -101,7 +102,7 @@ public class MongoNodeStoreService {
store = mk.getNodeStore();
registerJMXBeans(mk, context);
-
+ observerTracker = new ObserverTracker(store);
reg = context.registerService(NodeStore.class.getName(), store, new
Properties());
}
@@ -151,6 +152,7 @@ public class MongoNodeStoreService {
@Deactivate
private void deactivate() {
+ observerTracker.stop();
for (Registration r : registrations) {
r.unregister();
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java?rev=1547592&r1=1547591&r2=1547592&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
Tue Dec 3 21:28:15 2013
@@ -26,8 +26,6 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import com.google.common.base.Preconditions;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.ConfigurationPolicy;
@@ -36,10 +34,11 @@ import org.apache.felix.scr.annotations.
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.spi.commit.Observable;
+import org.apache.jackrabbit.oak.osgi.ObserverTracker;
import org.apache.jackrabbit.oak.plugins.segment.file.FileStore;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.Observable;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -69,7 +68,9 @@ public class SegmentNodeStoreService imp
private SegmentStore store;
- private NodeStore delegate;
+ private SegmentNodeStore delegate;
+
+ private ObserverTracker observerTracker;
private synchronized NodeStore getDelegate() {
assert delegate != null : "service must be activated when used";
@@ -103,6 +104,8 @@ public class SegmentNodeStoreService imp
Integer.parseInt(size), "64".equals(mode));
delegate = new SegmentNodeStore(store);
+ observerTracker = new ObserverTracker(delegate);
+ observerTracker.start(context.getBundleContext());
}
private static String lookup(ComponentContext context, String property) {
@@ -117,6 +120,7 @@ public class SegmentNodeStoreService imp
@Deactivate
public synchronized void deactivate() {
+ observerTracker.stop();
delegate = null;
store.close();
@@ -127,7 +131,6 @@ public class SegmentNodeStoreService imp
@Override
public Closeable addObserver(Observer observer) {
- Preconditions.checkState(delegate instanceof Observable);
return ((Observable) getDelegate()).addObserver(observer);
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java?rev=1547592&r1=1547591&r2=1547592&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/whiteboard/WhiteboardUtils.java
Tue Dec 3 21:28:15 2013
@@ -16,13 +16,18 @@
*/
package org.apache.jackrabbit.oak.spi.whiteboard;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyMap;
+
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nonnull;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
public class WhiteboardUtils {
@@ -62,4 +67,11 @@ public class WhiteboardUtils {
}
}
+ public static Registration registerObserver(
+ @Nonnull Whiteboard whiteboard,
+ @Nonnull Observer observer) {
+ return checkNotNull(whiteboard)
+ .register(Observer.class, checkNotNull(observer), emptyMap());
+ }
+
}