You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/07/29 18:22:19 UTC

svn commit: r680753 - /incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/

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;
 }