Author: bdelacretaz
Date: Tue Jul 29 09:22:17 2008
New Revision: 680753

URL: http://svn.apache.org/viewvc?rev=680753&view=rev
Log:
SLING-587 - bundles and configs are now uninstalled from the OSGi framework 
when deleted from the Sling repository

Modified:
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundlesFolder.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
 Tue Jul 29 09:22:17 2008
@@ -18,7 +18,7 @@
  */
 package org.apache.sling.jcr.jcrbundles;
 
-import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_NODES_BASE_PATH;
+import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_BASE_PATH;
 
 import java.io.InputStream;
 import java.util.Calendar;
@@ -66,7 +66,7 @@
        /** Return the Node to use to store status of given fileNode.
         *      Session is not saved if status node is created */
        protected Node getStatusNode(Node fileNode, boolean createIfNotFound) 
throws RepositoryException {
-               final String path = STATUS_NODES_BASE_PATH + fileNode.getPath();
+               final String path = STATUS_BASE_PATH + fileNode.getPath();
                final Session s = fileNode.getSession();
                Node result = null;
                
@@ -85,6 +85,24 @@
                return result;
        }
        
+       /** Find the path of the node in the main tree that corresponds to the 
given status node path */
+       protected String getMainNodePath(String statusNodePath) {
+               return statusNodePath.substring(STATUS_BASE_PATH.length());
+       }
+       
+       /** Find the node in the main tree that corresponds to the given status 
node */
+       protected Node getMainNode(Node statusNode) throws RepositoryException {
+               final String path = getMainNodePath(statusNode.getPath());
+               final Session s = statusNode.getSession();
+               Node result = null;
+               
+               if(s.itemExists(path)) {
+                       result = (Node)s.getItem(path);
+               }
+               
+               return result;
+       }
+       
        protected Calendar getLastModified(Node fileNode) throws 
RepositoryException {
                if(fileNode.hasProperty(JCR_CONTENT_LAST_MODIFIED)) {
                        return 
fileNode.getProperty(JCR_CONTENT_LAST_MODIFIED).getDate();

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
 Tue Jul 29 09:22:17 2008
@@ -57,7 +57,7 @@
 
                // We have data - install, update or do nothing with bundle
                // TODO handle deletes (store a list of bundles that were 
installed)
-        final String location = JCRBUNDLES_NAME_PREFIX + n.getPath();
+        final String location = getBundleLocation(n.getPath());
                try {
                final Node status = getStatusNode(n, true);
                        final Bundle oldBundle = getBundleByLocation(location);
@@ -118,7 +118,33 @@
                        }
                }
        }
-       
+
+       /** Check if the given statusNode still has an equivalent in the main 
tree, and if not
+        *      uninstall the corresponding bundle, if found. Do the same thing 
for statusNodes' children */
+    public void checkDeletions(Node statusNode, Map<String, Boolean> flags) 
throws Exception {
+       final Node mainNode = getMainNode(statusNode);
+       if(mainNode == null) {
+               final String mainPath = getMainNodePath(statusNode.getPath());
+               final String location = getBundleLocation(mainPath);
+               final Bundle b = getBundleByLocation(location);
+               if(b == null) {
+                       log.info("Node {} has been deleted, but corresponding 
bundle {} not found - deleting status node only", 
+                                       mainPath, location);
+               } else {
+                       try {
+                               b.uninstall();
+                       flags.put("refresh.packages", Boolean.TRUE);
+                               log.info("Node {} has been deleted, bundle {} 
uninstalled", mainPath, location);
+                       } catch(Exception e) {
+                               log.error("Exception while trying to uninstall 
bundle " + location, e); 
+                       }
+               }
+               
+               statusNode.remove();
+               statusNode.getSession().save();
+       }
+    }
+
     private boolean isFragment(Bundle bundle) {
         return padmin.getBundleType(bundle) == 
PackageAdmin.BUNDLE_TYPE_FRAGMENT;
     }
@@ -136,4 +162,8 @@
         }
         return null;
     }
+    
+    protected String getBundleLocation(String bundleNodePath) {
+       return JCRBUNDLES_NAME_PREFIX + bundleNodePath;
+    }
 }
\ No newline at end of file

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundlesFolder.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundlesFolder.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundlesFolder.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundlesFolder.java
 Tue Jul 29 09:22:17 2008
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.jcr.jcrbundles;
 
+import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_BASE_PATH;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -167,26 +168,51 @@
         if(nextScan != -1 && System.currentTimeMillis() > nextScan) {
             nextScan = -1;
             log.debug("Timer expired, scanning {}", path);
-            
-            if(session.getRootNode().hasNode(relPath(path))) {
-                final Node n = session.getRootNode().getNode(relPath(path));
-                processNode(n, flags);
-            } else {
-               log.info("Bundles folder {} does not exist anymore", path);
-            }
+            checkDeletions(flags);
+            checkUpdatesAndDeletes(flags);
         }
     }
     
-    /** Let the first NodeProcessor that accepts n process it, and
-     *         recurse into n's children to do the same */
-    protected void processNode(Node n, Map<String, Boolean> flags) throws 
Exception {
+    /** Let our processors handle all nodes under the main tree */
+    void checkUpdatesAndDeletes(Map<String, Boolean> flags) throws Exception {
+           if(session.getRootNode().hasNode(relPath(path))) {
+               final Node n = session.getRootNode().getNode(relPath(path));
+               processNode(n, flags, false);
+           } else {
+               log.info("Bundles folder {} does not exist anymore", path);
+           }
+    }
+    
+    /** Check for nodes in the status tree that have disappeared from their 
main
+     *         locations, and let the processors handle these deletes.
+     */
+    void checkDeletions(Map<String, Boolean> flags) throws Exception {
+       final String statusPath = STATUS_BASE_PATH + path;
+        if(session.getRootNode().hasNode(relPath(statusPath))) {
+            final Node n = session.getRootNode().getNode(relPath(statusPath));
+            processNode(n, flags, true);
+        } else {
+               log.info("Status folder {} does not exist, checkDeletions does 
nothing");
+        }
+    }
+    
+    /** Let the first NodeProcessor that accepts n process it (for normal 
processing
+     *         or deletions), and recurse into n's children to do the same 
+     */
+    protected void processNode(Node n, Map<String, Boolean> flags, boolean 
checkDeletions) throws Exception {
         
         boolean accepted = false;
+        final String path = n.getPath();
+        final Session s = n.getSession();
         
         for(NodeProcessor p : processors) {
             if(p.accepts(n)) {
                 accepted = true;
-                p.process(n, flags);
+                if(checkDeletions) {
+                       p.checkDeletions(n, flags);
+                } else {
+                       p.process(n, flags);
+                }
                 break;
             }
         }
@@ -195,9 +221,12 @@
             log.debug("No NodeProcessor found for node {}, ignored", 
n.getPath());
         }
         
-        final NodeIterator it = n.getNodes();
-        while(it.hasNext()) {
-            processNode(it.nextNode(), flags);
+        // n might have been deleted above, if it's a status done
+        if(s.itemExists(path)) {
+               final NodeIterator it = n.getNodes();
+               while(it.hasNext()) {
+                   processNode(it.nextNode(), flags, checkDeletions);
+               }
         }
     }
     

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
 Tue Jul 29 09:22:17 2008
@@ -73,7 +73,7 @@
                
                @Override
                public String toString() {
-                       return "ConfigPid: configPid=" + configPid + ", 
factoryPid=" + factoryPid;
+                       return "Configuration (configPid=" + configPid + ", 
factoryPid=" + factoryPid + ")";
                }
        };
        
@@ -134,15 +134,35 @@
         }
 
         // get or create configuration
-        Configuration config = getConfiguration(pid);
+        Configuration config = getConfiguration(pid, true);
         if (config.getBundleLocation() != null) {
             config.setBundleLocation(null);
         }
         config.update(ht);
-        log.info("Config {} created or updated", config.getPid());
+        log.info("Configuration {} created or updated", config.getPid());
        }
        
-    Configuration getConfiguration(ConfigPid cp) throws IOException, 
InvalidSyntaxException {
+    public void checkDeletions(Node statusNode, Map<String, Boolean> flags) 
throws Exception {
+       final Node mainNode = getMainNode(statusNode);
+       if(mainNode == null) {
+               final String mainPath = getMainNodePath(statusNode.getPath());
+               final ConfigPid pid = new ConfigPid(mainPath);
+               final Configuration config = getConfiguration(pid, false);
+               if(config == null) {
+                       log.info("Node {} has been deleted, but {} not found - 
deleting status node only", 
+                                       mainPath, pid);
+               } else {
+                       config.delete();
+                       log.info("Node {} has been deleted: {} deleted", 
+                                       mainPath, pid);
+               }
+               
+               statusNode.remove();
+               statusNode.getSession().save();
+       }
+    }
+
+    Configuration getConfiguration(ConfigPid cp, boolean createIfNeeded) 
throws IOException, InvalidSyntaxException {
        Configuration result = null;
        
         if (cp.factoryPid == null) {
@@ -153,7 +173,9 @@
                 + "))");
             
             if (configs == null || configs.length == 0) {
-                result = cadmin.createFactoryConfiguration(cp.configPid, null);
+               if(createIfNeeded) {
+                       result = 
cadmin.createFactoryConfiguration(cp.configPid, null);
+               }
             } else {
                result = configs[0];
             }

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
 Tue Jul 29 09:22:17 2008
@@ -20,6 +20,6 @@
 
 /** Constants for this module */
 public class JcrBundlesConstants {
-       public static final String STATUS_NODES_BASE_PATH = 
"/system/sling/jcrbundles/status";
+       public static final String STATUS_BASE_PATH = 
"/system/sling/jcrbundles/status";
        public static final String JCRBUNDLES_NAME_PREFIX = "jcrbundles:";
 }

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesManager.java
 Tue Jul 29 09:22:17 2008
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.jcr.jcrbundles;
 
+import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_BASE_PATH;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -93,7 +94,11 @@
             }
 
             public void process(Node n, Map<String, Boolean> flags) throws 
RepositoryException {
-                log.debug("Node {} ignored, no NodeProcessor accepts it", 
n.getPath());
+                log.debug("Node {} ignored in process() call, no NodeProcessor 
accepts it", n.getPath());
+            }
+            
+            public void checkDeletions(Node statusNode, Map<String, Boolean> 
flags) throws Exception {
+                log.debug("Node {} ignored in checkDeletions() call, no 
NodeProcessor accepts it", statusNode.getPath());
             }
             
         });
@@ -133,6 +138,25 @@
         log.info("{} thread {} starts", getClass().getSimpleName(), 
Thread.currentThread().getName());
         Session s = null;
         
+        // First check for deletions, using the status folder root path
+        BundlesFolder statusFolder = null;
+        try {
+               statusFolder = new BundlesFolder(repository, STATUS_BASE_PATH, 
processors);
+               final Map<String, Boolean> flags = new HashMap<String, 
Boolean>();
+               statusFolder.checkDeletions(flags);
+            refreshPackagesIfNeeded(flags);
+        } catch(Exception e) {
+               log.error("Exception during initial scanning of " + 
STATUS_BASE_PATH, e);
+        } finally {
+               if(statusFolder != null) {
+                       try {
+                               statusFolder.cleanup();
+                       } catch(Exception e) {
+                       log.error("Exception during BundlesFolder cleanup of " 
+ STATUS_BASE_PATH, e);
+                       }
+               }
+        }
+        
         // We could use the scheduler service but that makes things harder to 
test
         while(running) {
             try {
@@ -163,7 +187,6 @@
     
     /** Run one cycle of processing our scanTimes queue */
     void runOneCycle(Session s) throws Exception {
-       boolean refreshPackages = false;
        final Map<String, Boolean> flags = new HashMap<String, Boolean>();
        
         for(BundlesFolder bf : folders) {
@@ -171,12 +194,14 @@
                        break;
                }
             bf.scanIfNeeded(flags);
-            refreshPackages |= 
Boolean.TRUE.equals(flags.get("refresh.packages"));
         }
-        
-        if(refreshPackages) {
-               log.info("Refreshing PackageAdmin packages");
+        refreshPackagesIfNeeded(flags);
+    }
+    
+    void refreshPackagesIfNeeded(Map<String, Boolean> flags) {
+       if(Boolean.TRUE.equals(flags.get("refresh.packages"))) {
+               log.info("Refreshing packages");
                padmin.refreshPackages(null);
-        }
+       }
     }
 }
\ No newline at end of file

Modified: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java
URL: 
http://svn.apache.org/viewvc/incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java?rev=680753&r1=680752&r2=680753&view=diff
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java
 (original)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java
 Tue Jul 29 09:22:17 2008
@@ -28,4 +28,5 @@
 interface NodeProcessor {
     boolean accepts(Node n) throws RepositoryException;
     void process(Node n, Map<String, Boolean> flags) throws Exception;
+    void checkDeletions(Node statusNode, Map<String, Boolean> flags) throws 
Exception;
 }


Reply via email to