Author: bdelacretaz
Date: Tue Jul 29 05:35:23 2008
New Revision: 680684

URL: http://svn.apache.org/viewvc?rev=680684&view=rev
Log:
SLING-587 - adding and updating bundles works (but no removing yet)

Added:
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
   (with props)
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
   (with props)
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
   (with props)
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
   (with props)
Modified:
    
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/JcrBundlesManager.java
    
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/NodeProcessor.java

Added: 
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=680684&view=auto
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
 (added)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
 Tue Jul 29 05:35:23 2008
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.jcrbundles;
+
+import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.STATUS_NODES_BASE_PATH;
+
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.regex.Pattern;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** NodeProcessor that accepts nodes based on a regexp on
+ *     their name, but does nothing with them */ 
+abstract class AbstractNodeProcessor implements NodeProcessor {
+       
+    /** The relative path of the data and last modified date of an nt:file 
node */
+       public static final String JCR_CONTENT = "jcr:content";
+    public static final String JCR_CONTENT_DATA = JCR_CONTENT + "/jcr:data";
+    public static final String JCR_LAST_MODIFIED = "jcr:lastModified";
+    public static final String JCR_CONTENT_LAST_MODIFIED = JCR_CONTENT + "/" + 
JCR_LAST_MODIFIED;
+
+    protected final Logger log = LoggerFactory.getLogger(this.getClass());
+       private final Pattern pattern;
+       
+       AbstractNodeProcessor(String regexp) {
+               pattern = Pattern.compile(regexp);
+       }
+
+       public boolean accepts(Node n) throws RepositoryException {
+               boolean result = pattern.matcher(n.getName()).matches();
+               if(result) {
+                       log.debug("Node {} accepted by {}", n.getPath(), 
getClass().getName());
+               }
+               return result;
+       }
+       
+       static InputStream getInputStream(Node fileNode) throws 
RepositoryException 
+    {
+       Property prop = fileNode.getProperty(JCR_CONTENT_DATA);
+       return prop.getStream();
+    }
+       
+       /** 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 Session s = fileNode.getSession();
+               Node result = null;
+               
+               if(s.itemExists(path)) {
+                       result = (Node)s.getItem(path);
+               } else if(createIfNotFound) {
+                       result = deepCreate(s, path);
+               }
+               
+               if(result != null) {
+                       log.debug("Status node for {} is at {}", 
fileNode.getPath(), result.getPath());
+               } else {
+                       log.debug("No status node found for {}", 
fileNode.getPath());
+               }
+               
+               return result;
+       }
+       
+       protected Calendar getLastModified(Node fileNode) throws 
RepositoryException {
+               if(fileNode.hasProperty(JCR_CONTENT_LAST_MODIFIED)) {
+                       return 
fileNode.getProperty(JCR_CONTENT_LAST_MODIFIED).getDate();
+               }
+               return null;
+       }
+       
+       protected Node deepCreate(Session s, String path) throws 
RepositoryException {
+               if(path.startsWith("/")) {
+                       path = path.substring(1);
+               }
+               final String [] names = path.split("/");
+               String currentPath = "";
+               
+               for(int i=0; i < names.length; i++) {
+                       currentPath += "/" + names[i];
+                       if(!s.itemExists(currentPath)) {
+                               
s.getRootNode().addNode(currentPath.substring(1));
+                       }
+               }
+
+               return (Node)s.getItem("/" + path);
+       }
+}

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/AbstractNodeProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: 
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=680684&view=auto
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
 (added)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
 Tue Jul 29 05:35:23 2008
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.jcrbundles;
+
+import static 
org.apache.sling.jcr.jcrbundles.JcrBundlesConstants.JCRBUNDLES_NAME_PREFIX;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/** Process nodes that look like bundles, based on their node name */
+class BundleNodeProcessor extends AbstractNodeProcessor {
+    private final ComponentContext context;
+    private final PackageAdmin padmin; 
+       
+       public BundleNodeProcessor(ComponentContext ctx, PackageAdmin pa) {
+               super("[a-zA-Z0-9].*\\.jar$");
+               context = ctx;
+               padmin = pa;
+       }
+       
+       public void process(Node n, Map<String, Boolean> flags) throws 
RepositoryException {
+               
+               // Do we have file data?
+               InputStream is = null;
+               try {
+                       is = getInputStream(n);
+               } catch(Exception e) {
+                       log.info("Unable to get InputStream on Node {}, will be 
ignored ({})", n.getPath(), e);
+                       return;
+               }
+
+               // 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();
+               try {
+               final Node status = getStatusNode(n, true);
+                       final Bundle oldBundle = getBundleByLocation(location);
+                       final Calendar lastModified = getLastModified(n);
+                       Bundle newBundle = null;
+                       boolean changed = false;
+                       
+                       if(oldBundle == null) {
+                               // Bundle not installed yet, install it
+                               changed = true;
+                               newBundle = 
getBundleContext().installBundle(location, is);
+                       if (!isFragment(newBundle)) {
+                               newBundle.start();
+                               log.info("Bundle {} successfully installed and 
started", location);
+                       } else {
+                               log.info("Fragment bundle {} successfully 
installed", location);
+                       }
+                       status.setProperty("status", "installed");
+                       
+                       } else {
+                               // Bundle already installed, did it change?
+                               Calendar savedLastModified = null;
+                               if(status.hasProperty(JCR_LAST_MODIFIED)) {
+                                       savedLastModified = 
status.getProperty(JCR_LAST_MODIFIED).getDate();
+                               }
+                               
+                               changed = 
+                                       savedLastModified == null 
+                                       || lastModified == null 
+                                       || 
!(lastModified.equals(savedLastModified))
+                               ;
+                               
+                               if(changed) {
+                                       oldBundle.update(is);
+                               log.info("Bundle {} successfully updated", 
location);
+                               status.setProperty("status", "updated");
+                               } else {
+                               log.debug("Bundle {} unchanged, no update 
needed", location);
+                               }
+                       }
+                       
+                       if(changed) {
+                       flags.put("refresh.packages", Boolean.TRUE);
+                       if(lastModified != null) {
+                               status.setProperty(JCR_LAST_MODIFIED, 
lastModified);
+                       }
+                       n.getSession().save();
+                       }
+               
+               } catch(Exception e) {
+                       log.warn("Exception while processing bundle {}", e);
+                       
+               } finally {
+                       try {
+                               is.close();
+                       } catch(IOException ioe) {
+                               log.error("IOException on closing InputStream", 
ioe);
+                       }
+               }
+       }
+       
+    private boolean isFragment(Bundle bundle) {
+        return padmin.getBundleType(bundle) == 
PackageAdmin.BUNDLE_TYPE_FRAGMENT;
+    }
+
+    private BundleContext getBundleContext() {
+        return context.getBundleContext();
+    }
+
+    protected Bundle getBundleByLocation(String location) {
+        Bundle bundles[] = getBundleContext().getBundles();
+        for(Bundle b : bundles) {
+               if(location.equals(b.getLocation())) {
+                       return b;
+               }
+        }
+        return null;
+    }
+}
\ No newline at end of file

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/BundleNodeProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

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=680684&r1=680683&r2=680684&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 05:35:23 2008
@@ -20,6 +20,7 @@
 
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.Node;
@@ -162,27 +163,30 @@
     
     /** If our timer allows it, recursively call processNode 
      *  on our Node and its children */
-    void scanIfNeeded() throws RepositoryException {
+    void scanIfNeeded(Map<String, Boolean> flags) throws RepositoryException {
         if(nextScan != -1 && System.currentTimeMillis() > nextScan) {
             nextScan = -1;
             log.debug("Timer expired, scanning {}", path);
             
-            // TODO handle case where folder disappears
-            final Node n = session.getRootNode().getNode(relPath(path));
-            processNode(n);
+            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);
+            }
         }
     }
     
-    /** Install/update/remove the bundle or config that Node n
-     *  represents, if any. */
-    protected void processNode(Node n) throws RepositoryException {
+    /** 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 
RepositoryException {
         
         boolean accepted = false;
         
         for(NodeProcessor p : processors) {
             if(p.accepts(n)) {
                 accepted = true;
-                p.process(n);
+                p.process(n, flags);
                 break;
             }
         }
@@ -193,10 +197,11 @@
         
         final NodeIterator it = n.getNodes();
         while(it.hasNext()) {
-            processNode(it.nextNode());
+            processNode(it.nextNode(), flags);
         }
     }
     
+    /** Return the relative path for supplied path */
     static String relPath(String path) {
         if(path.startsWith("/")) {
             return path.substring(1);

Added: 
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=680684&view=auto
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
 (added)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
 Tue Jul 29 05:35:23 2008
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.jcrbundles;
+
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+/** Process nodes that look like configs, based on their node name */
+class ConfigNodeProcessor extends AbstractNodeProcessor {
+       public ConfigNodeProcessor() {
+               super("[a-zA-Z0-9].*\\.cfg$");
+       }
+       
+       public void process(Node n, Map<String, Boolean> flags) throws 
RepositoryException {
+       }
+}

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/ConfigNodeProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: 
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=680684&view=auto
==============================================================================
--- 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
 (added)
+++ 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
 Tue Jul 29 05:35:23 2008
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.jcrbundles;
+
+/** Constants for this module */
+public class JcrBundlesConstants {
+       public static final String STATUS_NODES_BASE_PATH = 
"/system/sling/jcrbundles/status";
+       public static final String JCRBUNDLES_NAME_PREFIX = "jcrbundles:";
+}

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
incubator/sling/whiteboard/jcrbundles/src/main/java/org/apache/sling/jcr/jcrbundles/JcrBundlesConstants.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

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=680684&r1=680683&r2=680684&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 05:35:23 2008
@@ -18,9 +18,11 @@
  */
 package org.apache.sling.jcr.jcrbundles;
 
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.Node;
@@ -29,6 +31,7 @@
 
 import org.apache.sling.jcr.api.SlingRepository;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.packageadmin.PackageAdmin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,8 +68,11 @@
     /** @scr.reference */
     private SlingRepository repository;
     
-    /** Default log. */
+    /** @scr.reference */
+    private PackageAdmin padmin;
+
     protected final Logger log = LoggerFactory.getLogger(this.getClass());
+    private boolean running;
     
     /** When activated, collect the list of bundle folders to scan
      *  and register as a listener for future updates.
@@ -75,13 +81,15 @@
 
         // setup our processors
         processors = new LinkedList<NodeProcessor>();
+        processors.add(new BundleNodeProcessor(context, padmin));
+        processors.add(new ConfigNodeProcessor());
         processors.add(new NodeProcessor() {
             public boolean accepts(Node n) throws RepositoryException {
                 return true;
             }
 
-            public void process(Node n) throws RepositoryException {
-                log.debug("Dummy NodeProcessor would process Node {}", 
n.getPath());
+            public void process(Node n, Map<String, Boolean> flags) throws 
RepositoryException {
+                log.debug("Node {} ignored, no NodeProcessor accepts it", 
n.getPath());
             }
             
         });
@@ -95,13 +103,16 @@
         // TODO: should listen for any new "bundles" folders created after 
activation
         
         // start queue processing
-        final Thread t = new Thread(this, getClass().getSimpleName());
+        final Thread t = new Thread(this, getClass().getSimpleName() + "_" + 
System.currentTimeMillis());
         t.setDaemon(true);
+        running = true;
         t.start();
     }
     
     /** Cleanup */
     protected void deactivate(ComponentContext oldContext) {
+       running = false;
+       
         for(BundlesFolder bf : folders) {
             try {
                 bf.cleanup();
@@ -115,18 +126,21 @@
     
     /** Scan paths once their timer expires */
     public void run() {
+        log.info("{} thread {} starts", getClass().getSimpleName(), 
Thread.currentThread().getName());
         Session s = null;
         
         // We could use the scheduler service but that makes things harder to 
test
-        while(true) {
+        while(running) {
             try {
-                s = 
repository.loginAdministrative(repository.getDefaultWorkspace());
-                runOneCycle(s);
+                       s = 
repository.loginAdministrative(repository.getDefaultWorkspace());
+                       runOneCycle(s);
             } catch(IllegalArgumentException ie) {
                 log.warn("IllegalArgumentException  in " + 
getClass().getSimpleName(), ie);
             } catch(RepositoryException re) {
                 log.warn("RepositoryException in " + 
getClass().getSimpleName(), re);
-                
+            } catch(Throwable t) {
+                log.error("Unhandled Throwable in runOneCycle() - " 
+                               + getClass().getSimpleName() + " thread will be 
stopped", t);
             } finally {
                 if(s!= null) {
                     s.logout();
@@ -140,12 +154,25 @@
             }
         }
         
+        log.info("{} thread {} ends", getClass().getSimpleName(), 
Thread.currentThread().getName());
     }
     
     /** Run one cycle of processing our scanTimes queue */
     void runOneCycle(Session s) throws RepositoryException {
+       boolean refreshPackages = false;
+       final Map<String, Boolean> flags = new HashMap<String, Boolean>();
+       
         for(BundlesFolder bf : folders) {
-            bf.scanIfNeeded();
+               if(!running) {
+                       break;
+               }
+            bf.scanIfNeeded(flags);
+            refreshPackages |= 
Boolean.TRUE.equals(flags.get("refresh.packages"));
+        }
+        
+        if(refreshPackages) {
+               log.info("Refreshing PackageAdmin 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=680684&r1=680683&r2=680684&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 05:35:23 2008
@@ -1,5 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.sling.jcr.jcrbundles;
 
+import java.util.Map;
+
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
@@ -7,5 +27,5 @@
 
 interface NodeProcessor {
     boolean accepts(Node n) throws RepositoryException;
-    void process(Node n) throws RepositoryException;
+    void process(Node n, Map<String, Boolean> flags) throws 
RepositoryException;
 }


Reply via email to