You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2012/08/24 11:54:34 UTC
svn commit: r1376876 - in /sling/trunk/bundles/jcr/resource/src:
main/java/org/apache/sling/jcr/resource/internal/
main/java/org/apache/sling/jcr/resource/internal/helper/jcr/
test/java/org/apache/sling/jcr/resource/internal/
Author: cziegeler
Date: Fri Aug 24 09:54:34 2012
New Revision: 1376876
URL: http://svn.apache.org/viewvc?rev=1376876&view=rev
Log:
SLING-2573 : JcrResourceListener activation is failing with NPE
Modified:
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderFactory.java
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java
Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java?rev=1376876&r1=1376875&r2=1376876&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java Fri Aug 24 09:54:34 2012
@@ -34,22 +34,18 @@ import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.jackrabbit.api.observation.JackrabbitEvent;
import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.osgi.framework.Constants;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
+import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,34 +54,26 @@ import org.slf4j.LoggerFactory;
* events and creates resource events which are sent through the
* OSGi event admin.
*/
-@Component(immediate = true)
-@Properties({
- @Property(name = Constants.SERVICE_DESCRIPTION, value = "Apache Sling JcrResourceListener"),
- @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation")
-
-})
public class JcrResourceListener implements EventListener {
/** Logger */
private final Logger logger = LoggerFactory.getLogger(JcrResourceListener.class);
- @Reference(policy=ReferencePolicy.DYNAMIC)
- private EventAdmin eventAdmin;
+ private final ServiceTracker eventAdminTracker;
- @Reference
- private ResourceResolverFactory resourceResolverFactory;
+ private ServiceReference resourceResolverFactoryReference;
/** The admin resource resolver. */
private ResourceResolver resourceResolver;
/** The session for observation. */
- private Session session;
+ private final Session session;
/** Everything below this path is observed. */
- private String startPath;
+ private final String startPath;
/** The repository is mounted under this path. */
- private String mountPrefix;
+ private final String mountPrefix;
/** Is the Jackrabbit event class available? */
private final boolean hasJackrabbitEventClass;
@@ -96,7 +84,9 @@ public class JcrResourceListener impleme
* waiting for actual dispatching to the OSGi Event Admin in
* {@link #processOsgiEventQueue()}
*/
- private LinkedBlockingQueue<Dictionary<String, Object>> osgiEventQueue;
+ private final LinkedBlockingQueue<Dictionary<String, Object>> osgiEventQueue;
+
+ private final BundleContext bundleContext;
/**
* Marker event for {@link #processOsgiEventQueue()} to be signaled to
@@ -104,7 +94,11 @@ public class JcrResourceListener impleme
*/
private final Dictionary<String, Object> TERMINATE_PROCESSING = new Hashtable<String, Object>(1);
- public JcrResourceListener() {
+ public JcrResourceListener(final String startPath,
+ final String mountPrefix,
+ final SlingRepository repository,
+ final BundleContext bundleContext)
+ throws RepositoryException {
boolean foundClass = false;
try {
this.getClass().getClassLoader().loadClass(JackrabbitEvent.class.getName());
@@ -113,58 +107,36 @@ public class JcrResourceListener impleme
// we ignore this
}
this.hasJackrabbitEventClass = foundClass;
- }
+ this.startPath = startPath;
+ this.mountPrefix = mountPrefix;
+ this.bundleContext = bundleContext;
- @Activate
- protected void activate() throws LoginException {
- this.resourceResolver = this.resourceResolverFactory.getAdministrativeResourceResolver(null);
- this.startPath = "/";
- this.mountPrefix = null;
+ this.eventAdminTracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
+ this.eventAdminTracker.open();
+
+ this.session = repository.loginAdministrative(null);
+ try {
+ session.getWorkspace().getObservationManager().addEventListener(this,
+ Event.NODE_ADDED|Event.NODE_REMOVED|Event.PROPERTY_ADDED|Event.PROPERTY_CHANGED|Event.PROPERTY_REMOVED,
+ this.startPath, true, null, null, false);
+ } catch (final RepositoryException re) {
+ session.logout();
+ throw re;
+ }
this.osgiEventQueue = new LinkedBlockingQueue<Dictionary<String,Object>>();
final Thread oeqt = new Thread(new Runnable() {
public void run() {
- init();
processOsgiEventQueue();
}
- }, "JCR Resource Event Queue Processor");
+ }, "Apche Sling JCR Resource Event Queue Processor for path '" + this.startPath + "'");
oeqt.start();
-
- }
-
- private void init() {
- // lazy polling
- Session session = null;
- ResourceResolver resolver = this.resourceResolver;
- while ( resolver != null && session == null ) {
- session = this.resourceResolver.adaptTo(Session.class);
- if ( session == null ) {
- try {
- Thread.sleep(100);
- } catch (final InterruptedException ignore) {
- // we ignore this
- }
- resolver = this.resourceResolver;
- }
- }
- if ( session != null ) {
- try {
- session.getWorkspace().getObservationManager().addEventListener(this,
- Event.NODE_ADDED|Event.NODE_REMOVED|Event.PROPERTY_ADDED|Event.PROPERTY_CHANGED|Event.PROPERTY_REMOVED,
- this.startPath, true, null, null, false);
- this.session = session;
- } catch (final RepositoryException re) {
- logger.error("Unable to register event listener.", re);
- this.deactivate();
- }
- }
}
/**
* Dispose this listener.
*/
- @Deactivate
- protected void deactivate() {
+ public void deactivate() {
// unregister from observations
if ( this.session != null ) {
try {
@@ -178,9 +150,17 @@ public class JcrResourceListener impleme
this.resourceResolver = null;
}
+ if ( this.resourceResolverFactoryReference != null ) {
+ this.bundleContext.ungetService(this.resourceResolverFactoryReference);
+ }
+
// drop any remaining OSGi Events not processed yet
this.osgiEventQueue.clear();
this.osgiEventQueue.offer(TERMINATE_PROCESSING);
+
+ if ( this.eventAdminTracker != null ) {
+ this.eventAdminTracker.close();
+ }
}
/**
@@ -188,7 +168,7 @@ public class JcrResourceListener impleme
*/
public void onEvent(final EventIterator events) {
// if the event admin is currently not available, we just skip this
- final EventAdmin localEA = this.eventAdmin;
+ final EventAdmin localEA = (EventAdmin) this.eventAdminTracker.getService();
if ( localEA == null ) {
return;
}
@@ -338,6 +318,28 @@ public class JcrResourceListener impleme
}
/**
+ * Get a resource resolver.
+ * We don't need any syncing as this is called from the process osgi thread.
+ */
+ private ResourceResolver getResourceResolver() {
+ if ( this.resourceResolver == null ) {
+ final ServiceReference ref = this.bundleContext.getServiceReference(ResourceResolverFactory.class.getName());
+ if ( ref != null ) {
+ final ResourceResolverFactory factory = (ResourceResolverFactory) this.bundleContext.getService(ref);
+ if ( factory != null ) {
+ try {
+ this.resourceResolver = factory.getAdministrativeResourceResolver(null);
+ this.resourceResolverFactoryReference = ref;
+ } catch (final LoginException le) {
+ logger.error("Unable to get administrative resource resolver.", le);
+ this.bundleContext.ungetService(ref);
+ }
+ }
+ }
+ }
+ return this.resourceResolver;
+ }
+ /**
* Called by the Runnable.run method of the JCR Event Queue processor to
* process the {@link #osgiEventQueue} until the
* {@link #TERMINATE_PROCESSING} event is received.
@@ -357,11 +359,12 @@ public class JcrResourceListener impleme
}
try {
- final EventAdmin localEa = this.eventAdmin;
- if (localEa != null) {
+ final EventAdmin localEa = (EventAdmin) this.eventAdminTracker.getService();
+ final ResourceResolver resolver = this.getResourceResolver();
+ if (localEa != null && resolver != null ) {
final String topic = (String) event.remove(EventConstants.EVENT_TOPIC);
final String path = (String) event.get(SlingConstants.PROPERTY_PATH);
- Resource resource = this.resourceResolver.getResource(path);
+ Resource resource = resolver.getResource(path);
boolean sendEvent = true;
if (!SlingConstants.TOPIC_RESOURCE_REMOVED.equals(topic)) {
if (resource != null) {
Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderFactory.java?rev=1376876&r1=1376875&r2=1376876&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderFactory.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderFactory.java Fri Aug 24 09:54:34 2012
@@ -27,7 +27,9 @@ import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.query.Query;
+import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
@@ -41,9 +43,12 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceConstants;
+import org.apache.sling.jcr.resource.internal.JcrResourceListener;
import org.osgi.framework.Constants;
+import org.osgi.service.component.ComponentContext;
/**
* The <code>JcrResourceProviderFactory</code> creates
@@ -67,6 +72,24 @@ public class JcrResourceProviderFactory
@Reference
private SlingRepository repository;
+ /** The jcr resource listner. */
+ private JcrResourceListener listener;
+
+ @Activate
+ protected void activate(final ComponentContext context)
+ throws RepositoryException {
+ final String root = PropertiesUtil.toString(context.getProperties().get(ResourceProvider.ROOTS), "/");
+ this.listener = new JcrResourceListener(root, null, this.repository, context.getBundleContext());
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ if ( this.listener != null ) {
+ this.listener.deactivate();
+ this.listener = null;
+ }
+ }
+
/** Get the dynamic class loader if available */
ClassLoader getDynamicClassLoader() {
final DynamicClassLoaderManager dclm = this.dynamicClassLoaderManager;
Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java?rev=1376876&r1=1376875&r2=1376876&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceListenerTest.java Fri Aug 24 09:54:34 2012
@@ -16,6 +16,10 @@
*/
package org.apache.sling.jcr.resource.internal;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -36,8 +40,10 @@ import org.apache.sling.commons.testing.
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
import org.apache.sling.commons.testing.jcr.RepositoryUtil;
import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResource;
+import org.osgi.framework.BundleContext;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
/**
* Test of JcrResourceListener.
@@ -52,16 +58,16 @@ public class JcrResourceListenerTest ext
@Override
protected void tearDown() throws Exception {
super.tearDown();
- RepositoryUtil.startRepository();
- final Session adminSession = RepositoryUtil.getRepository().loginAdministrative(null);
- RepositoryUtil.registerSlingNodeTypes(adminSession);
- adminSession.logout();
+ RepositoryUtil.stopRepository();
}
@Override
protected void setUp() throws Exception {
super.setUp();
- RepositoryUtil.stopRepository();
+ RepositoryUtil.startRepository();
+ final Session adminSession = RepositoryUtil.getRepository().loginAdministrative(null);
+ RepositoryUtil.registerSlingNodeTypes(adminSession);
+ adminSession.logout();
}
public void testDefaultWorkspace() throws Exception {
@@ -264,7 +270,16 @@ public class JcrResourceListenerTest ext
}
};
- SynchronousJcrResourceListener listener = new SynchronousJcrResourceListener(factory, mockEA);
+ final ServiceTracker tracker = mock(ServiceTracker.class);
+ when(tracker.getService()).thenReturn(mockEA);
+
+ final BundleContext bundleContext = mock(BundleContext.class);
+ when(bundleContext.createFilter(any(String.class))).thenReturn(null);
+ when(bundleContext.getServiceReference(any(String.class))).thenReturn(null);
+ when(bundleContext.getService(null)).thenReturn(mockEA);
+
+ SynchronousJcrResourceListener listener = new SynchronousJcrResourceListener(factory, getRepository(),
+ bundleContext, resolver, tracker);
createdPath = createTestPath();
createNode(session, createdPath);
Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java?rev=1376876&r1=1376875&r2=1376876&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/SynchronousJcrResourceListener.java Fri Aug 24 09:54:34 2012
@@ -22,8 +22,11 @@ import junitx.util.PrivateAccessor;
import org.apache.jackrabbit.core.observation.SynchronousEventListener;
import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.osgi.service.event.EventAdmin;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
/**
* This class is used to ensure that events are handled during the test.
@@ -35,11 +38,15 @@ import org.osgi.service.event.EventAdmin
public class SynchronousJcrResourceListener extends JcrResourceListener implements SynchronousEventListener {
public SynchronousJcrResourceListener(
- ResourceResolverFactory factory, EventAdmin eventAdmin)
+ ResourceResolverFactory factory,
+ SlingRepository repo,
+ BundleContext bundleContext,
+ final ResourceResolver resolver,
+ final ServiceTracker tracker)
throws LoginException, RepositoryException, NoSuchFieldException {
- PrivateAccessor.setField(this, "resourceResolverFactory", factory);
- PrivateAccessor.setField(this, "eventAdmin", eventAdmin);
- this.activate();
+ super("/", null, repo, bundleContext);
+ PrivateAccessor.setField(this, "resourceResolver", resolver);
+ PrivateAccessor.setField(this, "eventAdminTracker", tracker);
}
public void dispose() {