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 2009/08/24 16:58:51 UTC

svn commit: r807258 - in /sling/trunk/installer/jcr/jcrinstall: ./ src/main/java/org/apache/sling/jcr/jcrinstall/impl/ src/main/java/org/apache/sling/jcr/jcrinstall/jcr/ src/main/resources/OSGI-INF/metatype/ src/test/java/org/apache/sling/jcr/jcrinstal...

Author: bdelacretaz
Date: Mon Aug 24 14:58:50 2009
New Revision: 807258

URL: http://svn.apache.org/viewvc?rev=807258&view=rev
Log:
SLING-1078 - jcrinstall partially adapted to new osgicontroller, work in progress

Added:
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/ConfigNodeConverter.java
      - copied, changed from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ConfigNodeConverter.java
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverter.java
      - copied, changed from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverter.java
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilter.java
      - copied, changed from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RunModeRegexpFilter.java
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java   (with props)
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java
      - copied, changed from r807140, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java
      - copied, changed from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolderCreationListener.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverterTest.java
      - copied, changed from r807132, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverterTest.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java   (with props)
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java   (with props)
Removed:
    sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverterTest.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MiscHelper.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockRepositoryObserver.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceOverrideRulesImplTest.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RunModeRegexpFilterTest.java
Modified:
    sling/trunk/installer/jcr/jcrinstall/pom.xml
    sling/trunk/installer/jcr/jcrinstall/src/main/resources/OSGI-INF/metatype/metatype.properties
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java
    sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java

Modified: sling/trunk/installer/jcr/jcrinstall/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/pom.xml?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/pom.xml (original)
+++ sling/trunk/installer/jcr/jcrinstall/pom.xml Mon Aug 24 14:58:50 2009
@@ -28,7 +28,7 @@
   </parent>
 
   <artifactId>org.apache.sling.jcr.jcrinstall</artifactId>
-  <version>2.0.3-SNAPSHOT</version>
+  <version>3.0.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <name>Apache Sling Jcrinstall Service</name>
@@ -38,9 +38,9 @@
   </description>
 
   <scm>
-    <connection> scm:svn:http://svn.apache.org/repos/asf/sling/whiteboard/jcrinstall</connection>
-    <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/whiteboard/jcrinstall</developerConnection>
-    <url> http://svn.apache.org/viewvc/sling/whiteboard/jcrinstall</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/jcr/jcrinstall</connection>
+    <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/jcr/jcrinstall</developerConnection>
+    <url>http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/</url>
   </scm>
   
   <build>
@@ -55,23 +55,12 @@
         <extensions>true</extensions>
         <configuration>
             <instructions>
-                <Export-Package>
-                    org.apache.sling.jcr.jcrinstall.jcr
-                </Export-Package>
-                <Private-Package>org.apache.sling.jcr.jcrinstall.jcr.impl</Private-Package>
+                <Private-Package>org.apache.sling.jcr.jcrinstall.impl.*</Private-Package>
                 <Sling-Nodetypes>SLING-INF/nodetypes/osgiconfig.cnd</Sling-Nodetypes>
                 <Sling-Namespaces>sling=http://sling.apache.org/jcr/sling/1.0</Sling-Namespaces>
             </instructions>
         </configuration>
       </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <skipTests>true</skipTests>
-        </configuration>
-      </plugin>
-      
     </plugins>
   </build>
   
@@ -86,6 +75,11 @@
     </dependency>
     <dependency>
       <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.jcr.resource</artifactId>
+      <version>2.0.2-incubator</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.jcr.api</artifactId>
       <version>2.0.2-incubator</version>
     </dependency>
@@ -115,7 +109,7 @@
     <dependency>
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.osgi.installer</artifactId>
-      <version>2.0.3-SNAPSHOT</version>
+      <version>3.0.0-SNAPSHOT</version>
     </dependency>
   </dependencies>
 </project>

Copied: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/ConfigNodeConverter.java (from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ConfigNodeConverter.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/ConfigNodeConverter.java?p2=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/ConfigNodeConverter.java&p1=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ConfigNodeConverter.java&r1=807132&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ConfigNodeConverter.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/ConfigNodeConverter.java Mon Aug 24 14:58:50 2009
@@ -16,13 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
 
 import java.lang.reflect.Array;
 import java.util.Dictionary;
 import java.util.Hashtable;
-import java.util.SortedSet;
-import java.util.TreeSet;
 
 import javax.jcr.Node;
 import javax.jcr.Property;
@@ -31,38 +29,25 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 
-import org.apache.sling.jcr.jcrinstall.jcr.NodeConverter;
-import org.apache.sling.osgi.installer.DictionaryInstallableData;
-import org.apache.sling.osgi.installer.InstallableData;
-import org.apache.sling.runmode.RunMode;
+import org.apache.sling.osgi.installer.InstallableResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** Converts configuration nodes to InstallableData, taking
- * 	RunMode into account.
- */
-class ConfigNodeConverter implements NodeConverter {
-	
-	private final Logger log = LoggerFactory.getLogger(getClass());
+/** Converts configuration nodes to InstallableData */
+class ConfigNodeConverter implements JcrInstaller.NodeConverter {
 	
 	public static final String CONFIG_NODE_TYPE = "sling:OsgiConfig";
-	
-	/**	TODO making this dynamic and optional would be better, but
-	 * 	that would probably create issues at startup 
-	 * 	@scr.reference 
-	 */
-	private RunMode runMode;
+	private final Logger log = LoggerFactory.getLogger(getClass());
 	
 	/** Convert n to an InstallableData, or return null
 	 * 	if we don't know how to convert it.
 	 */
-	public InstallableData convertNode(Node n) throws Exception {
-		InstallableData result = null;
+	public InstallableResource convertNode(String urlScheme, Node n) throws Exception {
+		InstallableResource result = null;
 
 		// We only consider CONFIG_NODE_TYPE nodes
 		if(n.isNodeType(CONFIG_NODE_TYPE)) {
-			final Dictionary<String, Object> config = load(n);
-			result = new DictionaryInstallableData(config);
+			result = new InstallableResource(urlScheme + ":" + n.getPath(), load(n));
 			log.debug("Converted node {} to {}", n.getPath(), result);
 		} else {
 			log.debug("Node is not a {} node, ignored:{}", CONFIG_NODE_TYPE, n.getPath());
@@ -80,22 +65,6 @@
         log.debug("Loading {} properties", n.getPath());
         loadProperties(result, n);
         
-        if(runMode != null) {
-            final String [] modeStr = runMode.getCurrentRunModes();
-            final SortedSet<String> modes = new TreeSet<String>();
-            for(String s : modeStr) {
-                modes.add(s);
-            }
-            for(String mode : modes) {
-                if(n.hasNode(mode)) {
-                    log.debug(
-                            "Loading {}/{} properties for current run mode, overriding previous values", 
-                            n.getPath(), mode);
-                    loadProperties(result, n.getNode(mode));
-                }
-            }
-        }
-        
         return result;
     }
     

Copied: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverter.java (from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverter.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverter.java?p2=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverter.java&p1=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverter.java&r1=807132&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverter.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverter.java Mon Aug 24 14:58:50 2009
@@ -14,45 +14,70 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.regex.Pattern;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 
-import org.apache.sling.jcr.jcrinstall.jcr.NodeConverter;
-import org.apache.sling.osgi.installer.InstallableData;
+import org.apache.sling.osgi.installer.InstallableResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** Convert a Node that is a file to a FileInstallableData */ 
- public class FileNodeConverter implements NodeConverter {
+/** Convert a Node that is a file to an InstallableResource that wraps an InputStream */ 
+ public class FileNodeConverter implements JcrInstaller.NodeConverter {
     // regexp for filenames that we accept
     public static final String FILENAME_REGEXP = "[a-zA-Z0-9].*\\.(jar|cfg|properties)";
     
-    private final RegexpFilter filenameFilter = new RegexpFilter(FILENAME_REGEXP);
-    private final Logger log = LoggerFactory.getLogger(getClass());
-    private final int bundleStartLevel;
+    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;
     
-    public FileNodeConverter(int bundleStartLevel) {
-        this.bundleStartLevel = bundleStartLevel;
-    }
+    private final Pattern namePattern = Pattern.compile(FILENAME_REGEXP);
+    private final Logger log = LoggerFactory.getLogger(getClass());
     
-	public InstallableData convertNode(Node n) throws RepositoryException {
-		InstallableData result = null;
-		if(n.hasProperty(FileInstallableData.JCR_CONTENT_DATA) && n.hasProperty(FileInstallableData.JCR_CONTENT_LAST_MODIFIED)) {
+	public InstallableResource convertNode(String urlScheme, Node n) throws RepositoryException {
+		InstallableResource result = null;
+		if(n.hasProperty(JCR_CONTENT_DATA) && n.hasProperty(JCR_CONTENT_LAST_MODIFIED)) {
 			if(acceptNodeName(n.getName())) {
-				result = new FileInstallableData(n, bundleStartLevel);
+				try {
+					result = convert(urlScheme, n, n.getPath());
+				} catch(IOException ioe) {
+					log.info("Conversion failed, node {} ignored ({})", n.getPath(), ioe);
+				}
 			} else {
-				log.debug("Node {} ignored due to {}", n.getPath(), filenameFilter);
+				log.debug("Node {} ignored due to {}", n.getPath(), namePattern);
 			}
 			return result;
 		}
 		log.debug("Node {} has no {} properties, ignored", n.getPath(), 
-				FileInstallableData.JCR_CONTENT_DATA + " or " + FileInstallableData.JCR_CONTENT_LAST_MODIFIED);
+				JCR_CONTENT_DATA + " or " + JCR_CONTENT_LAST_MODIFIED);
 		return null;
 	}
 	
+	private InstallableResource convert(String urlScheme, Node n, String path) throws IOException, RepositoryException {
+		String digest = null;
+        if (n.hasProperty(JCR_CONTENT_LAST_MODIFIED)) {
+        	digest = String.valueOf(n.getProperty(JCR_CONTENT_LAST_MODIFIED).getDate().getTimeInMillis());
+        } else {
+        	throw new IOException("Missing " + JCR_CONTENT_LAST_MODIFIED + " property");
+	    }
+	    
+        InputStream is = null;
+        if(n.hasProperty(JCR_CONTENT_DATA)) {
+        	is = n.getProperty(JCR_CONTENT_DATA).getStream();
+        } else {
+        	throw new IOException("Missing " + JCR_CONTENT_DATA + " property");
+        }
+		
+        return new InstallableResource(urlScheme + ":" + path, is, digest);
+	}
+	
 	boolean acceptNodeName(String name) {
-	    return filenameFilter.accept(name);
+		return namePattern.matcher(name).matches();
 	}
 }
\ No newline at end of file

Copied: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilter.java (from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RunModeRegexpFilter.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilter.java?p2=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilter.java&p1=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RunModeRegexpFilter.java&r1=807132&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/RunModeRegexpFilter.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilter.java Mon Aug 24 14:58:50 2009
@@ -16,35 +16,63 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
 
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
 import org.apache.sling.runmode.RunMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/** A RegexpFilter that is RunMode-aware: accepts names with a 
- *  prefix that matches the supplied regexp, and suffixes that 
- *  match the list of run mode strings provided by a RunMode service.
+/** Defines which folders are watched by JcrInstaller, based on
+ * 	their names. To be accepted, a folder must have a name that
+ *  matches the expression, followed by optional suffixes based
+ *  on the current RunMode.
+ *  
+ *  See {@link FolderNameFilterTest} for details.    
  */
-class RunModeRegexpFilter extends RegexpFilter {
+class FolderNameFilter {
+    private final Pattern pattern;
+    private final String regexp;
     private final RunMode runMode;
+    private Map<String, Integer> rootPriorities = new HashMap<String, Integer>();
     private final Logger log = LoggerFactory.getLogger(getClass());
     
-    RunModeRegexpFilter(String regexp, RunMode runMode) {
-        super(regexp);
+    /** getPriority computes priorities as follows: each root gets (N+1) * ROOT_PRIORITY_FACTOR,
+     * 	where N is the index in the roots array, and paths that match one or several
+     * 	run level get an additional RUNMODE_PRIORITY_OFFSET per matched run level
+     */
+    public static final int ROOT_PRIORITY_FACTOR = 100;
+    public static final int RUNMODE_PRIORITY_BOOST = 1;
+    
+    FolderNameFilter(String [] roots, String regexp, RunMode runMode) {
+        this.regexp = regexp;
+        this.pattern = Pattern.compile(regexp);
         this.runMode = runMode;
+        
+        // Assign priorities to our root folders
+        for(int i = 0; i < roots.length; i++) {
+        	rootPriorities.put(roots[i], new Integer((i + 1) * ROOT_PRIORITY_FACTOR));
+        }
     }
     
-    @Override
-    boolean accept(final String path) {
+    /** If a folder at given path can contain installable resources
+     * 	(according to our regexp and current RunMode), return the
+     * 	priority to use for InstallableResource found in that folder.
+     * 
+     * 	@return -1 if path is not an installable folder, else resource priority  
+     */
+    int getPriority(final String path) {
+    	int result = 0;
+    	
         // If path contains dots, remove suffixes starting with
         // dots until path matches regexp, and accept if all suffixes
         // are included in our list of runmodes
         final char DOT = '.';
-        boolean result = false;
         
         if(path.indexOf(DOT) > 0) {
             int pos = 0;
@@ -53,18 +81,20 @@
             while( (pos = prefix.lastIndexOf(DOT)) >= 0) {
                 modes.add(prefix.substring(pos + 1));
                 prefix = prefix.substring(0, pos);
-                if(super.accept(prefix)) {
-                    result = true;
+                if(pattern.matcher(prefix).matches()) {
+                    result = getRootPriority(path);
                     break;
                 }
             }
             
             // If path prefix matches, check that all our runmodes match
-            if(result) {
+            if(result > 0) {
                 for(String m : modes) {
                     final String [] toTest = { m };
-                    if(!runMode.isActive(toTest)) {
-                        result = false;
+                    if(runMode.isActive(toTest)) {
+                    	result += RUNMODE_PRIORITY_BOOST;
+                    } else {
+                        result = 0;
                         break;
                     }
                 }
@@ -74,15 +104,22 @@
                 log.debug("accept(" + path + ")=" + result + " (prefix=" + prefix + ", modes=" + modes + ")");
             }
             
-        } else {
-            result = super.accept(path);
+        } else if(pattern.matcher(path).matches()) {
+        	result = getRootPriority(path);
         }
         return result;
     }
+    
+    int getRootPriority(String path) {
+    	for(Map.Entry<String, Integer> e : rootPriorities.entrySet()) {
+    		if(path.startsWith(e.getKey())) {
+    			return e.getValue().intValue();
+    		}
+    	}
+    	return 0;
+    }
 
-    @Override
     public String toString() {
-        return super.toString() + ", RunMode=" + runMode;
+        return getClass().getSimpleName() + " (" + regexp + "), RunMode=" + runMode;
     }
-
-}
+}
\ No newline at end of file

Added: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java?rev=807258&view=auto
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java (added)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java Mon Aug 24 14:58:50 2009
@@ -0,0 +1,251 @@
+/*
+ * 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.jcrinstall.impl;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.osgi.installer.InstallableResource;
+import org.apache.sling.osgi.installer.OsgiInstaller;
+import org.apache.sling.runmode.RunMode;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Main class of jcrinstall, runs as a service, observes the
+ * 	repository for changes in folders having names that match
+ * 	configurable regular expressions, and registers resources
+ *  found in those folders with the OSGi installer for installation.
+ *
+ * @scr.component
+ *  label="%jcrinstall.name"
+ *  description="%jcrinstall.description"
+ *  immediate="true"
+ *  @scr.service
+ *  @scr.property
+ *      name="service.description"
+ *      value="Sling Jcrinstall Service"
+ *  @scr.property
+ *      name="service.vendor"
+ *      value="The Apache Software Foundation"
+ */
+public class JcrInstaller implements Serializable {
+	private static final long serialVersionUID = 1L;
+	public static final String URL_SCHEME = "jcrinstall";
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    /**	This class watches the repository for installable resources  
+     * @scr.reference 
+     */
+    private SlingRepository repository;
+    
+    /** Additional installation folders are activated based
+     *  on the current RunMode. For example, /libs/foo/install.dev
+     *  if the current run mode is "dev".
+     *  @scr.reference
+     */
+    private RunMode runMode;
+
+    /**	The OsgiInstaller installs resources in the OSGi framework. 
+     * 	@scr.reference 
+     */
+    private OsgiInstaller installer;
+    
+    /**	This class looks for installable resources under the search
+     * 	paths of the Sling ResourceResolver (by default: /libs and /apps)
+     * 	@scr.reference
+     */
+    private JcrResourceResolverFactory resourceResolverFactory;
+    
+    /** Default regexp for watched folders */
+    public static final String DEFAULT_FOLDER_NAME_REGEXP = ".*/install$";
+
+    /** ComponentContext property that overrides the folder name regexp 
+     * 	@scr.property valueRef="DEFAULT_FOLDER_NAME_REGEXP"
+     */
+    public static final String FOLDER_NAME_REGEXP_PROPERTY = "sling.jcrinstall.folder.name.regexp";
+    
+    /** Configurable max. path depth for watched folders
+     *  @scr.property valueRef="DEFAULT_FOLDER_MAX_DEPTH" type="Integer"
+     */
+    public static final String PROP_INSTALL_FOLDER_MAX_DEPTH = "sling.jcrinstall.folder.max.depth";
+
+    public static final int DEFAULT_FOLDER_MAX_DEPTH = 4;
+    private int maxWatchedFolderDepth;
+
+    /** Filter for folder names */
+    private FolderNameFilter folderNameFilter;
+    
+    /** List of watched folders */
+    private List<WatchedFolder> watchedFolders;
+    
+    /** Session shared by all WatchedFolder */
+    private Session session;
+    
+    /** Convert Nodes to InstallableResources */
+    static interface NodeConverter {
+    	InstallableResource convertNode(String urlScheme, Node n) throws Exception;
+    }
+    
+    /** Our NodeConverters*/
+    private final Collection <NodeConverter> converters = new ArrayList<NodeConverter>();
+    
+    protected void activate(ComponentContext context) throws Exception {
+    	
+    	session = repository.loginAdministrative(repository.getDefaultWorkspace());
+    	
+    	// Setup converters
+    	converters.add(new FileNodeConverter());
+    	converters.add(new ConfigNodeConverter());
+    	
+    	// Get root paths for installable resources, from ResourceResolver
+    	final ResourceResolver rr = resourceResolverFactory.getResourceResolver(session);
+    	final String [] roots = rr.getSearchPath();
+    	for(int i=0; i < roots.length; i++) {
+    		if(!roots[i].startsWith("/")) {
+    			roots[i] = "/" + roots[i];
+     		}
+    		log.info("Using root folder {} (provided by ResourceResolver)", roots[i]);
+    	}
+    	
+    	// Configurable max depth, system property (via bundle context) overrides default value
+    	Object obj = getPropertyValue(context, PROP_INSTALL_FOLDER_MAX_DEPTH);
+    	if(obj != null) {
+    		// depending on where it's coming from, obj might be a string or integer
+    		maxWatchedFolderDepth = Integer.valueOf(String.valueOf(obj)).intValue();
+            log.info("Using configured ({}) folder name max depth '{}'", PROP_INSTALL_FOLDER_MAX_DEPTH, maxWatchedFolderDepth);
+    	} else {
+            maxWatchedFolderDepth = DEFAULT_FOLDER_MAX_DEPTH;
+            log.info("Using default folder max depth {}, not provided by {}", maxWatchedFolderDepth, PROP_INSTALL_FOLDER_MAX_DEPTH);
+    	}
+        
+    	// Configurable folder regexp, system property overrides default value
+    	String folderNameRegexp = (String)getPropertyValue(context, FOLDER_NAME_REGEXP_PROPERTY);
+    	if(folderNameRegexp != null) {
+            log.info("Using configured ({}) folder name regexp {}", FOLDER_NAME_REGEXP_PROPERTY, folderNameRegexp);
+    	} else {
+    	    folderNameRegexp = DEFAULT_FOLDER_NAME_REGEXP;
+            log.info("Using default folder name regexp '{}', not provided by {}", folderNameRegexp, FOLDER_NAME_REGEXP_PROPERTY);
+    	}
+    	
+    	// Find paths to watch and create WatchedFolders to manage them
+    	folderNameFilter = new FolderNameFilter(roots, folderNameRegexp, runMode);
+    	watchedFolders = new LinkedList<WatchedFolder>();
+    	for(String root : roots) {
+    		findPathsToWatch(root, watchedFolders);
+    	}
+    	
+    	// Scan watchedFolders and register resources with installer
+    	final List<InstallableResource> resources = new LinkedList<InstallableResource>();
+    	for(WatchedFolder f : watchedFolders) {
+    		final Collection<InstallableResource> c = f.scan();
+    		log.debug("Startup: {} provides resources {}", f, c);
+    		resources.addAll(c);
+    	}
+    	
+    	log.info("Registering {} resources with OSGi installer", resources.size());
+    	installer.registerResources(resources, URL_SCHEME);
+    }
+    
+    protected void deactivate(ComponentContext context) {
+    	folderNameFilter = null;
+    	watchedFolders = null;
+    	converters.clear();
+    	if(session != null) {
+    		session.logout();
+    		session = null;
+    	}
+    }
+    
+    /** Get a property value from the component context or bundle context */
+    protected Object getPropertyValue(ComponentContext ctx, String name) {
+        Object result = ctx.getProperties().get(name);
+        if(result == null) {
+            result = ctx.getBundleContext().getProperty(name);
+        }
+        return result;
+    }
+
+    /** Find the paths to watch under rootPath, according to our folderNameFilter,
+     * 	and add them to result */
+    void findPathsToWatch(String rootPath, List<WatchedFolder> result) throws RepositoryException {
+        Session s = null;
+
+        try {
+            s = repository.loginAdministrative(repository.getDefaultWorkspace());
+            if (!s.getRootNode().hasNode(relPath(rootPath))) {
+                log.info("Bundles root node {} not found, ignored", rootPath);
+            } else {
+                log.debug("Bundles root node {} found, looking for bundle folders inside it", rootPath);
+                final Node n = s.getRootNode().getNode(relPath(rootPath));
+                findAndAddPaths(n, result);
+            }
+        } finally {
+            if (s != null) {
+                s.logout();
+            }
+        }
+    }
+
+    /**
+     * Add n to result if it is a folder that we must watch, and recurse into its children
+     * to do the same.
+     */
+    void findAndAddPaths(Node n, List<WatchedFolder> result) throws RepositoryException
+    {
+        final String path = n.getPath();
+        final int priority = folderNameFilter.getPriority(path); 
+        if (priority > 0) {
+            result.add(new WatchedFolder(session, path, priority, URL_SCHEME, converters));
+        }
+        final int depth = path.split("/").length;
+        if(depth > maxWatchedFolderDepth) {
+            log.debug("Not recursing into {} due to maxWatchedFolderDepth={}", path, maxWatchedFolderDepth);
+            return;
+        } else {
+            final NodeIterator it = n.getNodes();
+            while (it.hasNext()) {
+                findAndAddPaths(it.nextNode(), result);
+            }
+        }
+    }
+    
+    /**
+     * Return the relative path for supplied path
+     */
+    static String relPath(String path) {
+        if (path.startsWith("/")) {
+            return path.substring(1);
+        }
+        return path;
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java (from r807140, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java?p2=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java&p1=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java&r1=807140&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolder.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java Mon Aug 24 14:58:50 2009
@@ -16,13 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -33,43 +31,35 @@
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 
-import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.jcr.jcrinstall.jcr.NodeConverter;
-import org.apache.sling.osgi.installer.InstallableData;
-import org.apache.sling.osgi.installer.JcrInstallException;
-import org.apache.sling.osgi.installer.OsgiController;
-import org.apache.sling.osgi.installer.ResourceOverrideRules;
+import org.apache.sling.osgi.installer.InstallableResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /** Watch a single folder in the JCR Repository, detecting changes
- *  to it (non-recursively) and sending the appropriate messages
- *  to the OsgiController service.
+ *  to it and providing InstallableData for its contents.
  */
-class WatchedFolder implements EventListener, Comparable<Object> {
+class WatchedFolder implements EventListener{
     private final String path;
-    private final OsgiController controller;
-    private long nextScan;
+    private final int priority;
     private final Session session;
-    private final ResourceOverrideRules roRules;
+    private static long nextScanTime;
+    private boolean needsScan;
+    private final String urlScheme;
+    private final Collection <JcrInstaller.NodeConverter> converters;
     protected final Logger log = LoggerFactory.getLogger(getClass());
     
-    private static List<WatchedFolder> allFolders = new ArrayList<WatchedFolder>();
+    // WatchedFolders that need a rescan will be scanned
+    // once no JCR events have been received for this amount of time.
+    public static final long SCAN_DELAY_MSEC = 500L;
     
-    /**
-     * After receiving JCR events, we wait for this many msec before
-     * re-scanning the folder, as events often come in bursts.
-     */
-    private final long scanDelayMsec;
-
-    WatchedFolder(SlingRepository repository, String path, OsgiController ctrl, 
-            RegexpFilter filenameFilter, long scanDelayMsec, ResourceOverrideRules ror) throws RepositoryException {
+    WatchedFolder(Session session, String path, int priority, 
+    		String urlScheme, Collection<JcrInstaller.NodeConverter> converters) throws RepositoryException {
         this.path = path;
-        this.controller = ctrl;
-        this.scanDelayMsec = scanDelayMsec;
-        this.roRules = ror;
+        this.converters = converters;
+        this.priority = priority;
+        this.urlScheme = urlScheme;
         
-        session = repository.loginAdministrative(repository.getDefaultWorkspace());
+        this.session = session;
         
         // observe any changes in our folder (and under it, as changes to properties
         // might be lower in the hierarchy)
@@ -80,19 +70,12 @@
         session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, path,
                 isDeep, null, null, noLocal);
 
-        synchronized(allFolders) {
-            allFolders.add(this);
-        }
         log.info("Watching folder " + path);
     }
     
     void cleanup() {
-        synchronized(allFolders) {
-            allFolders.remove(this);
-        }
     	try {
 	    	session.getWorkspace().getObservationManager().removeEventListener(this);
-	    	session.logout();
     	} catch(RepositoryException re) {
     		log.warn("RepositoryException in cleanup()", re);
     	}
@@ -103,62 +86,29 @@
     	return getClass().getSimpleName() + ":" + path;
     }
     
-    @Override
-    public boolean equals(Object obj) {
-        if (!(obj instanceof WatchedFolder)) {
-            return false;
-        }
-
-        final WatchedFolder other = (WatchedFolder) obj;
-        return path.equals(other.path);
-    }
-    
-    public int compareTo(Object obj) {
-        if (!(obj instanceof WatchedFolder)) {
-            return 1;
-        }
-        final WatchedFolder other = (WatchedFolder) obj;
-		return path.compareTo(other.path);
-	}
-
-	@Override
-    public int hashCode() {
-        return path.hashCode();
-    }
-    
     String getPath() {
         return path;
     }
     
-    /** Set our timer whenever an event occurs, to wait
-     * 	a bit before processing event bursts.
-     */
+    /** Set a static "timer" whenever an event occurs */
     public void onEvent(EventIterator it) {
-        scheduleScan();
+    	nextScanTime = System.currentTimeMillis() + SCAN_DELAY_MSEC; 
+    	needsScan = true;
+    	log.debug("Event received, scheduling scan of {}", path);
     }
     
-    /** Trigger a scan, after the usual delay */
-    void scheduleScan() {
-        nextScan = System.currentTimeMillis() + scanDelayMsec;
-    }
-    
-    /**
-     * 	If our timer allows it, scan our folder Node for updates
-     * 	and deletes.
-     */
-    void scanIfNeeded(Collection<NodeConverter> converters) throws Exception {
-        if (nextScan != -1 && System.currentTimeMillis() > nextScan) {
-            nextScan = -1;
-            scan(converters);
-        }
+    boolean needsScan() {
+    	return needsScan;
+    }
+    
+    long getNextScanTime() {
+    	return nextScanTime;
     }
     
-    /** Scan our folder and inform OsgiController of any changes */
-    protected void scan(Collection<NodeConverter> converters) throws Exception {
+    /** Scan the contents of our folder and return the corresponding InstallableResource */
+    List<InstallableResource> scan() throws Exception {
         log.debug("Scanning {}", path);
         
-        checkDeletions(controller.getInstalledUris());
-        
         Node folder = null;
         if(session.itemExists(path)) {
         	Item i = session.getItem(path);
@@ -169,80 +119,24 @@
         
         if(folder == null) {
         	log.info("Folder {} does not exist (or not anymore), cannot scan", path);
-        	return;
+        	return null;
         }
         
-        // Check adds and updates, for all child nodes for which we have a NodeConverter
+        // Return an InstallableResource for all child nodes for which we have a NodeConverter
+        final List<InstallableResource> result = new ArrayList<InstallableResource>();
         final NodeIterator it = folder.getNodes();
         while(it.hasNext()) {
         	final Node n = it.nextNode();
-        	for(NodeConverter nc : converters) {
-        		final InstallableData d = nc.convertNode(n);
-        		if(d != null) {
-        			log.debug("Installing or updating {}", d);
-            		// a single failure must not block the whole thing (SLING-655)
-            		try {
-            			installOrUpdate(n.getPath(), d);
-            		} catch(JcrInstallException jie) {
-            			log.warn("Failed to install resource " + n.getPath(), jie);
-            		}
-            		break;
+        	for(JcrInstaller.NodeConverter nc : converters) {
+        		final InstallableResource r = nc.convertNode(urlScheme, n);
+        		if(r != null) {
+        			r.setPriority(priority);
+        			result.add(r);
+        			break;
         		}
         	}
         }
-    }
-    
-    /** Check for deleted resources and uninstall them */
-    void checkDeletions(Set<String> installedUri) throws Exception {
-        // Check deletions
-        int count = 0;
-        for(String uri : installedUri) {
-            if(uri.startsWith(path)) {
-                if(!session.itemExists(uri)) {
-                    count++;
-                    log.info("Resource {} has been deleted, uninstalling", uri);
-            		// a single failure must not block the whole thing (SLING-655)
-                    try {
-                    	controller.scheduleUninstall(uri);
-                    } catch(JcrInstallException jie) {
-                    	log.warn("Failed to uninstall " + uri, jie);
-                    }
-                }
-            }
-        }
-
-        // If any deletions, resources in lower/higher priority folders might need to
-        // be re-installed
-        if(count > 0 && roRules!=null) {
-            for(String str : roRules.getLowerPriorityResources(path)) {
-                rescanFoldersForPath(str, "Scheduling scan of lower priority {} folder after deletes in {} folder");
-            }
-            for(String str : roRules.getHigherPriorityResources(path)) {
-                rescanFoldersForPath(str, "Scheduling scan of higher priority {} folder after deletes in {} folder");
-            }
-        }
-    }
-    
-    private void rescanFoldersForPath(String pathToScan, String logFormat) {
-        for(WatchedFolder wf : allFolders) {
-            if(pathToScan.equals(wf.path)) {
-                log.info(logFormat, wf.path, pathToScan);
-                wf.scheduleScan();
-            }
-        }
-    }
-    
-    /** Install or update the given resource, as needed */ 
-    protected void installOrUpdate(String path, InstallableData fdp) throws IOException, JcrInstallException {
-    	final String digest = controller.getDigest(path);
-    	if(digest == null) {
-    		log.info("Resource {} was not installed yet, installing in OsgiController", path);
-    		controller.scheduleInstallOrUpdate(path, fdp);
-    	} else if(!digest.equals(fdp.getDigest())) {
-    		log.info("Resource {} has been updated, updating in OsgiController", path);
-    		controller.scheduleInstallOrUpdate(path, fdp);
-    	} else {
-    		log.info("Resource {} not modified, ignoring", path);
-    	}
+        
+        return result;
     }
 }

Copied: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java (from r807132, sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolderCreationListener.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java?p2=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java&p1=sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolderCreationListener.java&r1=807132&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/jcr/impl/WatchedFolderCreationListener.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java Mon Aug 24 14:58:50 2009
@@ -16,13 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
 
 import java.util.HashSet;
 import java.util.Set;
 
-import javax.jcr.RepositoryException;
-import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 
@@ -31,16 +29,12 @@
 
 /** Listen for JCR events to find out when new WatchedFolders
  * 	must be created.
+ * 	TODO reactivate
  */
 class WatchedFolderCreationListener implements EventListener {
     protected final Logger log = LoggerFactory.getLogger(this.getClass());
-    private final RegexpFilter folderNameFilter;
     private Set<String> paths = new HashSet<String>();
     
-    WatchedFolderCreationListener(RegexpFilter fnf) {
-    	folderNameFilter = fnf;
-	}
-    
     /** Return our saved paths and clear the list
      * 	@return null if no paths have been saved 
      */
@@ -58,6 +52,7 @@
     
     /** Store the paths of new WatchedFolders to create */
     public void onEvent(EventIterator it) {
+    	/*
         try {
             while(it.hasNext()) {
                 final Event e = it.nextEvent();
@@ -70,6 +65,7 @@
         } catch(RepositoryException re) {
             log.warn("RepositoryException in onEvent", re);
         }
+        */
     }
 
 }

Modified: sling/trunk/installer/jcr/jcrinstall/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/resources/OSGI-INF/metatype/metatype.properties Mon Aug 24 14:58:50 2009
@@ -27,6 +27,13 @@
 jcrinstall.description = Installs OSGi bundles and configurations found \
  in the JCR Repository. 
  
-installFolder.maxDepth.name = Max hierarchy depth of install folders
-installFolder.maxDepth.description = Folders that are nested deeper than \
-  this value under the repository root are ignored
\ No newline at end of file
+sling.jcrinstall.folder.max.depth.name = Max hierarchy depth of install folders
+sling.jcrinstall.folder.max.depth.description = Folders that are nested deeper than \
+  this value under the repository root are ignored
+  
+sling.jcrinstall.folder.name.regexp.name = Installation folders name regexp
+sling.jcrinstall.folder.name.regexp.description = JCRInstall looks in repository folders \
+  having a name that match this regular expression (under the root paths, which are defined \  
+  by the ResourceResolver search path) for resources to install. Folders having names \
+  that match this expression, followed by dotted run mode selectors (like "install.author.production") \
+  are also included.   
\ No newline at end of file

Copied: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverterTest.java (from r807132, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverterTest.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverterTest.java?p2=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverterTest.java&p1=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverterTest.java&r1=807132&r2=807258&rev=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FileNodeConverterTest.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FileNodeConverterTest.java Mon Aug 24 14:58:50 2009
@@ -14,12 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.jcr.jcrinstall.jcr.impl;
+package org.apache.sling.jcr.jcrinstall.impl;
 
 import junit.framework.TestCase;
 
 public class FileNodeConverterTest extends TestCase {
-    private final FileNodeConverter fc = new FileNodeConverter(0);
+    private final FileNodeConverter fc = new FileNodeConverter();
     
     public void testAcceptedFilenames() {
         final String [] filenames = {

Added: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java?rev=807258&view=auto
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java (added)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java Mon Aug 24 14:58:50 2009
@@ -0,0 +1,84 @@
+/*
+ * 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.jcrinstall.impl;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+
+public class FolderNameFilterTest {
+    public static final String DEFAULT_REGEXP =  ".*/install$";
+    public static final String [] ROOTS = { "/libs", "/apps" };
+
+    @Test
+    public void testNoRunMode() {
+        final FolderNameFilter f = new FolderNameFilter(ROOTS, DEFAULT_REGEXP, new MockRunMode(new String[0]));
+        assertTrue("Test 1", f.getPriority("/libs/install") > 0);
+        assertFalse("Test 2", f.getPriority("/libs/install.bar") > 0);
+    }
+    
+    public void testSingleMode() {
+        final String [] m = { "dev" };
+        final FolderNameFilter f = new FolderNameFilter(ROOTS, DEFAULT_REGEXP, new MockRunMode(m));
+        assertTrue("Test 1", f.getPriority("/libs/install") > 0);
+        assertFalse("Test 2", f.getPriority("/libs/install.bar") > 0);
+        assertTrue("Test 3", f.getPriority("/libs/install.dev") > 0);
+        assertFalse("Test 4", f.getPriority("/libs/install/dev") > 0);
+        assertTrue("Test 5", f.getPriority("/libs/install.dev.dev") > 0);
+        assertFalse("Test 6", f.getPriority("/libs/install.dev.bar") > 0);
+        assertFalse("Test 7", f.getPriority("/libs/install.bar.dev") > 0);
+    }
+    
+    public void testThreeModes() {
+        final String [] m = { "dev", "web", "staging" };
+        final FolderNameFilter f = new FolderNameFilter(ROOTS, DEFAULT_REGEXP, new MockRunMode(m));
+        assertTrue("Test 1",f.getPriority("/libs/install") > 0);
+        assertFalse("Test 2",f.getPriority("/libs/install.bar") > 0);
+        assertTrue("Test 3",f.getPriority("/libs/install.dev") > 0);
+        assertTrue("Test 4",f.getPriority("/libs/install.web") > 0);
+        assertTrue("Test 5",f.getPriority("/libs/install.staging") > 0);
+        assertFalse("Test 6",f.getPriority("/libs/install/dev") > 0);
+        assertTrue("Test 7",f.getPriority("/libs/install.dev.web.staging") > 0);
+        assertTrue("Test 8",f.getPriority("/libs/install.web.dev.staging") > 0);
+        assertTrue("Test 9",f.getPriority("/libs/install.staging.web.dev") > 0);
+        assertTrue("Test 10",f.getPriority("/libs/install.staging.dev.web") > 0);
+        assertTrue("Test 11",f.getPriority("/libs/install.dev.dev.web.staging.web") > 0);
+        assertFalse("Test 12",f.getPriority("/libs/install.dev.bar") > 0);
+        assertFalse("Test 13",f.getPriority("/libs/install.bar.dev") > 0);
+    }
+    
+    public void testRootPriorities() {
+        final String [] m = { "dev" };
+        final FolderNameFilter f = new FolderNameFilter(ROOTS, DEFAULT_REGEXP, new MockRunMode(m));
+    	assertEquals("/libs root", new Integer(100), f.getPriority("/libs/install"));
+    	assertEquals("/apps root", new Integer(200), f.getPriority("/apps/install"));
+    }
+    
+    public void testRunModePriorities() {
+        final String [] m = { "dev", "prod", "staging" };
+        final FolderNameFilter f = new FolderNameFilter(ROOTS, DEFAULT_REGEXP, new MockRunMode(m));
+    	assertEquals("Matches no runmode", new Integer(100), f.getPriority("/libs/install"));
+    	assertEquals("Matches dev runmode", new Integer(201), f.getPriority("/apps/install.dev"));
+    	assertEquals("Matches staging runmode", new Integer(201), f.getPriority("/apps/install.staging"));
+    	assertEquals("Matches three runmodes (A)", new Integer(203), f.getPriority("/apps/install.dev.staging.prod"));
+    	assertEquals("Matches three runmodes (B)", new Integer(203), f.getPriority("/apps/install.dev.prod.staging"));
+    	assertEquals("Matches three runmodes (C)", new Integer(103), f.getPriority("/libs/install.dev.prod.staging"));
+    }
+}

Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FolderNameFilterTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java?rev=807258&view=auto
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java (added)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java Mon Aug 24 14:58:50 2009
@@ -0,0 +1,50 @@
+/*
+ * 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.jcrinstall.impl;
+
+import org.apache.sling.runmode.RunMode;
+
+class MockRunMode implements RunMode {
+
+    private final String[] modes;
+    
+    MockRunMode(String [] modes) {
+        this.modes = modes;
+    }
+    
+    public String[] getCurrentRunModes() {
+        return modes;
+    }
+
+    public boolean isActive(String[] runModes) {
+        boolean result = false;
+        
+        main:
+        for(String a : runModes) {
+            for(String b : modes) {
+                if(b.equals(a)) {
+                    result = true;
+                    break main;
+                }
+            }
+        }
+        
+        return result;
+    }
+}

Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockRunMode.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java Mon Aug 24 14:58:50 2009
@@ -25,6 +25,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
+/** TODO adapt or remove */
 class ContentHelper {
     public static final String NT_FOLDER = "nt:folder";
     public static final String NT_FILE = "nt:file";
@@ -85,7 +86,9 @@
     }
     
     void createOrUpdateFile(String path, MockInstallableData d) throws RepositoryException {
+    	/*
     	createOrUpdateFile(path, d.adaptTo(InputStream.class), d.getLastModified());
+    	*/
     }
     
     void createOrUpdateFile(String path, InputStream data, long lastModified) throws RepositoryException {

Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java Mon Aug 24 14:58:50 2009
@@ -28,6 +28,7 @@
 /** Used by tests to wait until JCR notification events
  * 	have been delivered.
  */
+/** TODO remove if not needed for new tests */
 class EventHelper implements EventListener {
 	private final Session session;
 	private int eventCount;

Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java Mon Aug 24 14:58:50 2009
@@ -18,21 +18,16 @@
  */
 package org.apache.sling.jcr.jcrinstall.jcr.impl;
 
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.jcr.Session;
-
 import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
-import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.osgi.installer.OsgiController;
-import org.apache.sling.osgi.installer.ResourceOverrideRules;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
 
-/** Test the "find watched folders" feature of the RepositoryObserver */
+/** Test the "find watched folders" feature of the RepositoryObserver 
+ * 	TODO adapt or remove
+ * */
 public class FindWatchedFoldersTest extends RepositoryTestBase {
     
+	public void testNothing() {}
+	
+	/*
     SlingRepository repo;
     Session session;
     private EventHelper eventHelper; 
@@ -99,5 +94,6 @@
             ro.addNewWatchedFolders();
             assertTrue(newPath + " must be watched before calling addNewWatchedFolders()", ro.folderIsWatched(newPath));
         }
-    }   
+    }
+    */   
 }
\ No newline at end of file

Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java Mon Aug 24 14:58:50 2009
@@ -18,13 +18,11 @@
  */
 package org.apache.sling.jcr.jcrinstall.jcr.impl;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
 
-import org.apache.sling.osgi.installer.InstallableData;
-
-public class MockInstallableData implements InstallableData {
+/** TODO adapt or remove */
+public class MockInstallableData /* implements InstallableData */ {
 
+	/*
 	private final InputStream inputStream;
 	private long lastModified;
 	private String digest;
@@ -78,4 +76,5 @@
     public int getBundleStartLevel() {
         return 0;
     }
+    */
 }

Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java?rev=807258&r1=807257&r2=807258&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ResourceDetectionTest.java Mon Aug 24 14:58:50 2009
@@ -18,31 +18,15 @@
  */
 package org.apache.sling.jcr.jcrinstall.jcr.impl;
 
-import java.io.File;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
 import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
-import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.osgi.installer.InstallableData;
-import org.apache.sling.osgi.installer.JcrInstallException;
-import org.apache.sling.osgi.installer.OsgiController;
-import org.apache.sling.osgi.installer.ResourceOverrideRules;
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.Sequence;
 
 /** Test that added/updated/removed resources are
  * 	correctly translated to OsgiController calls.
  */
+/** TODO adapt or remove */
 public class ResourceDetectionTest extends RepositoryTestBase {
+	public void testNothing() {}
+	/*
     SlingRepository repo;
     Session session;
     private EventHelper eventHelper; 
@@ -84,10 +68,6 @@
         return "jcrinstall://" + uri;
     }
     
-    /** Add, update and remove resources from the repository
-     *  and verify that the OsgiController receives the
-     *  correct messages
-     */
     public void testSingleResourceDetection() throws Exception {
         contentHelper.setupContent();
         
@@ -329,7 +309,6 @@
         mockery.assertIsSatisfied();
     }
     
-    /** Verify that resources are correctly uninstalled if the folder name regexp changes */
     public void testFolderRegexpChange() throws Exception {
         final File serviceDataFile = File.createTempFile(getClass().getName(), ".properties");
         serviceDataFile.deleteOnExit();
@@ -398,4 +377,5 @@
         ro.runOneCycle();
         mockery.assertIsSatisfied();
     }
+    */
 }
\ No newline at end of file