Author: cziegeler
Date: Tue Mar 10 10:28:48 2015
New Revision: 1665447

URL: http://svn.apache.org/r1665447
Log:
SLING-4486 : Potential NPE when service is deactivate immediately

Modified:
    
sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java

Modified: 
sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java?rev=1665447&r1=1665446&r2=1665447&view=diff
==============================================================================
--- 
sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
 (original)
+++ 
sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
 Tue Mar 10 10:28:48 2015
@@ -148,42 +148,42 @@ public class JcrInstaller implements Eve
     public static final String PROP_SEARCH_PATH = 
"sling.jcrinstall.search.path";
     public static final String [] DEFAULT_SEARCH_PATH = { "/libs:100", 
"/apps:200" };
 
-    private int maxWatchedFolderDepth;
+    private volatile int maxWatchedFolderDepth;
 
     /** Filter for folder names */
-    private FolderNameFilter folderNameFilter;
+    private volatile FolderNameFilter folderNameFilter;
 
     /** List of watched folders */
-    private List<WatchedFolder> watchedFolders;
+    private volatile List<WatchedFolder> watchedFolders;
 
     /** Session shared by all WatchedFolder */
-    private Session session;
+    private volatile Session session;
 
     /** The root folders that we watch */
-    private String [] roots;
+    private volatile String [] roots;
 
     /** The component context. */
-    private ComponentContext componentContext;
+    private volatile ComponentContext componentContext;
 
     /** Service reg for managed service. */
-    private ServiceRegistration managedServiceRef;
+    private volatile ServiceRegistration managedServiceRef;
 
     /** Configuration from managed service (old pid) */
-    private Dictionary<?, ?> oldConfiguration;
+    private volatile Dictionary<?, ?> oldConfiguration;
 
     private static final String DEFAULT_NEW_CONFIG_PATH = "sling/install";
     @Property(value=DEFAULT_NEW_CONFIG_PATH)
     private static final String PROP_NEW_CONFIG_PATH = 
"sling.jcrinstall.new.config.path";
 
     /** The path for new configurations. */
-    private String newConfigPath;
+    private volatile String newConfigPath;
 
     public static final String PAUSE_SCAN_NODE_PATH = 
"/system/sling/installer/jcr/pauseInstallation";
     @Property(value= PAUSE_SCAN_NODE_PATH)
     private static final String PROP_SCAN_PROP_PATH = 
"sling.jcrinstall.signal.path";
 
     /** The path for pauseInstallation property */
-    private String pauseScanNodePath;
+    private volatile String pauseScanNodePath;
 
     private volatile boolean pauseMessageLogged = false;
 
@@ -192,9 +192,9 @@ public class JcrInstaller implements Eve
     private static final String PROP_ENABLE_WRITEBACK = 
"sling.jcrinstall.enable.writeback";
 
     /** Write back enabled? */
-    private boolean writeBack;
+    private volatile boolean writeBack;
 
-    private EventListener moveEventListener;
+    private volatile EventListener moveEventListener;
 
     /** Convert Nodes to InstallableResources */
     static interface NodeConverter {
@@ -212,7 +212,7 @@ public class JcrInstaller implements Eve
     private final RescanTimer updateFoldersListTimer = new RescanTimer();
 
     /** Thread that can be cleanly stopped with a flag */
-    static int bgThreadCounter;
+    static volatile int bgThreadCounter;
     class StoppableThread extends Thread {
 
         /** Used for synchronizing. */
@@ -229,80 +229,100 @@ public class JcrInstaller implements Eve
         @Override
         public final void run() {
             logger.info("Background thread {} starting", 
Thread.currentThread().getName());
-            try {
-                // open session
-                session = 
repository.loginAdministrative(repository.getDefaultWorkspace());
-
-                for (String path : roots) {
-                    listeners.add(new RootFolderListener(session, 
folderNameFilter, path, updateFoldersListTimer));
-                    logger.debug("Configured root folder: {}", path);
-                }
+            synchronized ( this.lock ) {
+                if ( this.active ) {
+                    try {
+                        // open session
+                        session = 
repository.loginAdministrative(repository.getDefaultWorkspace());
+
+                        for (String path : roots) {
+                            listeners.add(new RootFolderListener(session, 
folderNameFilter, path, updateFoldersListTimer));
+                            logger.debug("Configured root folder: {}", path);
+                        }
 
-                // Watch for events on the root - that might be one of our 
root folders
-                
session.getWorkspace().getObservationManager().addEventListener(JcrInstaller.this,
-                        Event.NODE_ADDED | Event.NODE_REMOVED,
-                        "/",
-                        false, // isDeep
-                        null,
-                        null,
-                        true); // noLocal
-                // add special observation listener for move events
-                JcrInstaller.this.moveEventListener = new EventListener() {
-
-                    /**
-                     * @see 
javax.jcr.observation.EventListener#onEvent(javax.jcr.observation.EventIterator)
-                     */
-                    public void onEvent(final EventIterator events) {
-                        try {
-                            while (events.hasNext()) {
-                                final Event e = events.nextEvent();
-                                
JcrInstaller.this.checkChanges(e.getIdentifier());
-                                JcrInstaller.this.checkChanges(e.getPath());
+                        // Watch for events on the root - that might be one of 
our root folders
+                        
session.getWorkspace().getObservationManager().addEventListener(JcrInstaller.this,
+                                Event.NODE_ADDED | Event.NODE_REMOVED,
+                                "/",
+                                false, // isDeep
+                                null,
+                                null,
+                                true); // noLocal
+                        // add special observation listener for move events
+                        JcrInstaller.this.moveEventListener = new 
EventListener() {
+
+                            /**
+                             * @see 
javax.jcr.observation.EventListener#onEvent(javax.jcr.observation.EventIterator)
+                             */
+                            public void onEvent(final EventIterator events) {
+                                try {
+                                    while (events.hasNext()) {
+                                        final Event e = events.nextEvent();
+                                        
JcrInstaller.this.checkChanges(e.getIdentifier());
+                                        
JcrInstaller.this.checkChanges(e.getPath());
+                                    }
+                                } catch (final RepositoryException re) {
+                                    logger.warn("RepositoryException in 
onEvent", re);
+                                }
                             }
-                        } catch (final RepositoryException re) {
-                            logger.warn("RepositoryException in onEvent", re);
+                        };
+                        
session.getWorkspace().getObservationManager().addEventListener(
+                                moveEventListener,
+                                Event.NODE_MOVED,
+                                "/",
+                                true, // isDeep
+                                null,
+                                null,
+                                true); // noLocal
+
+                        logger.debug("Watching for node events on / to detect 
removal/add of our root folders");
+
+
+                        // Find paths to watch and create WatchedFolders to 
manage them
+                        watchedFolders = new LinkedList<WatchedFolder>();
+                        for(String root : roots) {
+                            findPathsToWatch(root, watchedFolders);
+                        }
+
+                        // Scan watchedFolders and register resources with 
installer
+                        for(final WatchedFolder f : watchedFolders) {
+                            f.start();
+                        }
+                    } catch (final RepositoryException re) {
+                        logger.error("Repository exception during startup - 
deactivating installer!", re);
+                        active = false;
+                        final ComponentContext ctx = componentContext;
+                        if ( ctx  != null ) {
+                            final String name = (String) 
componentContext.getProperties().get(
+                                    ComponentConstants.COMPONENT_NAME);
+                            ctx.disableComponent(name);
                         }
                     }
-                };
-                
session.getWorkspace().getObservationManager().addEventListener(
-                        moveEventListener,
-                        Event.NODE_MOVED,
-                        "/",
-                        true, // isDeep
-                        null,
-                        null,
-                        true); // noLocal
-
-                logger.debug("Watching for node events on / to detect 
removal/add of our root folders");
-
-
-                // Find paths to watch and create WatchedFolders to manage them
-                watchedFolders = new LinkedList<WatchedFolder>();
-                for(String root : roots) {
-                    findPathsToWatch(root, watchedFolders);
                 }
+            }
 
-                // Scan watchedFolders and register resources with installer
+            if ( this.active ) {
                 final List<InstallableResource> resources = new 
LinkedList<InstallableResource>();
-                for(WatchedFolder f : watchedFolders) {
-                    f.start();
-                    final WatchedFolder.ScanResult r = f.scan();
-                    logger.debug("Startup: {} provides resources {}", f, 
r.toAdd);
-                    resources.addAll(r.toAdd);
+                for(final WatchedFolder f : watchedFolders) {
+                    if ( this.active ) {
+                        try {
+                            final WatchedFolder.ScanResult r = f.scan();
+                            logger.debug("Startup: {} provides resources {}", 
f, r.toAdd);
+                            resources.addAll(r.toAdd);
+                        } catch (final RepositoryException re) {
+                            if ( this.active ) {
+                                logger.error("Repository exception during 
scanning.", re);
+                            }
+                        }
+                    }
                 }
 
-                logger.debug("Registering {} resources with OSGi installer: 
{}", resources.size(), resources);
-                installer.registerResources(URL_SCHEME, resources.toArray(new 
InstallableResource[resources.size()]));
-            } catch (final RepositoryException re) {
-                logger.error("Repository exception during startup - 
deactivating installer!", re);
-                active = false;
-                final ComponentContext ctx = componentContext;
-                if ( ctx  != null ) {
-                    final String name = (String) 
componentContext.getProperties().get(
-                            ComponentConstants.COMPONENT_NAME);
-                    ctx.disableComponent(name);
+                if ( this.active ) {
+                    logger.debug("Registering {} resources with OSGi 
installer: {}", resources.size(), resources);
+                    installer.registerResources(URL_SCHEME, 
resources.toArray(new InstallableResource[resources.size()]));
                 }
             }
+
             while (active) {
                 runOneCycle();
             }
@@ -310,15 +330,12 @@ public class JcrInstaller implements Eve
             counters[RUN_LOOP_COUNTER] = -1;
         }
     };
-    private StoppableThread backgroundThread;
+    private volatile StoppableThread backgroundThread;
 
     /**
      * Activate this component.
      */
     protected void activate(final ComponentContext context) {
-        if (backgroundThread != null) {
-            throw new IllegalStateException("Expected backgroundThread to be 
null in activate()");
-        }
         this.componentContext = context;
         this.start();
         final Dictionary<String, Object> props = new Hashtable<String, 
Object>();
@@ -403,9 +420,6 @@ public class JcrInstaller implements Eve
             backgroundThread = null;
        }
 
-        folderNameFilter = null;
-        watchedFolders = null;
-        converters.clear();
         try {
             if (session != null) {
                 for(RootFolderListener wfc : listeners) {
@@ -425,6 +439,10 @@ public class JcrInstaller implements Eve
             session = null;
         }
         listeners.clear();
+
+        folderNameFilter = null;
+        watchedFolders = null;
+        converters.clear();
     }
 
 


Reply via email to