incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1076166 - in /sling/trunk/installer: core/src/main/java/org/apache/sling/installer/api/ core/src/main/java/org/apache/sling/installer/core/impl/ providers/jcr/ providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/ provi...
Date Wed, 02 Mar 2011 10:53:37 GMT
Author: cziegeler
Date: Wed Mar  2 10:53:34 2011
New Revision: 1076166

URL: http://svn.apache.org/viewvc?rev=1076166&view=rev
Log:
SLING-1971 : Persist configuration (and bundle) changes not made through the installer

Added:
    sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java   (with props)
Modified:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/ResourceChangeListener.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
    sling/trunk/installer/providers/jcr/pom.xml
    sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilter.java
    sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
    sling/trunk/installer/providers/jcr/src/main/resources/OSGI-INF/metatype/metatype.properties
    sling/trunk/installer/providers/jcr/src/test/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilterTest.java

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/ResourceChangeListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/ResourceChangeListener.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/ResourceChangeListener.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/api/ResourceChangeListener.java Wed Mar  2 10:53:34 2011
@@ -37,20 +37,20 @@ public interface ResourceChangeListener 
      * Inform the installer about an added or updated
      * resource
      * @param resourceType The resource type
-     * @param resourceId   The resource id (symbolic name etc.)
+     * @param entityId     The entity id (symbolic name etc.)
      * @param is           Input stream or
      * @param dict         Dictionary
      */
     void resourceAddedOrUpdated(final String resourceType,
-            final String resourceId,
+            final String entityId,
             final InputStream is,
             final Dictionary<String, Object> dict);
 
     /**
      * Inform the installer about a removed resource
      * @param resourceType The resource type
-     * @param resourceId   The resource id (symbolic name etc.)
+     * @param entityId     The entity id (symbolic name etc.)
      */
     void resourceRemoved(final String resourceType,
-            final String resourceId);
+            final String entityId);
 }
\ No newline at end of file

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java Wed Mar  2 10:53:34 2011
@@ -256,7 +256,7 @@ public class FileDataStore {
                 }
             }
 
-            bos.flush();
+            oos.flush();
             d.update(bos.toByteArray());
             return digestToString(d);
         } catch (Exception ignore) {

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java Wed Mar  2 10:53:34 2011
@@ -175,16 +175,22 @@ public class OsgiInstallerImpl
 
             this.mergeNewlyRegisteredResources();
 
-            // invoke transformers
-            this.transformResources();
+            // invoke transformers - sync as we change state
+            synchronized ( this.resourcesLock ) {
+                this.transformResources();
+            }
 
             // execute tasks
             final SortedSet<InstallTask> tasks = this.computeTasks();
             final boolean tasksCreated = !tasks.isEmpty();
-            this.executeTasks(tasks);
 
-            // clean up and save
-            this.cleanupInstallableResources();
+            // sync as we might change state
+            synchronized ( this.resourcesLock ) {
+                this.executeTasks(tasks);
+
+                // clean up and save
+                this.cleanupInstallableResources();
+            }
 
             // if we don't have any tasks, we go to sleep
             if (!tasksCreated) {
@@ -663,19 +669,19 @@ public class OsgiInstallerImpl
      * @see org.apache.sling.installer.api.ResourceChangeListener#resourceAddedOrUpdated(java.lang.String, java.lang.String, java.io.InputStream, java.util.Dictionary)
      */
     public void resourceAddedOrUpdated(final String resourceType,
-            String resourceId,
+            String entityId,
             final InputStream is,
             final Dictionary<String, Object> dict) {
-        String key = resourceType + ':' + resourceId;
+        String key = resourceType + ':' + entityId;
         try {
             final ResourceData data = ResourceData.create(is, dict);
             synchronized ( this.resourcesLock ) {
                 final EntityResourceList erl = this.persistentList.getEntityResourceList(key);
                 if ( erl != null ) {
-                    resourceId = erl.getResourceId();
-                    key = resourceType + ':' + resourceId;
+                    entityId = erl.getResourceId();
+                    key = resourceType + ':' + entityId;
                 }
-                logger.info("Added or updated {}:{}: {}", new Object[] {resourceType, resourceId, erl});
+                logger.debug("Added or updated {} : {}", key, erl);
 
                 // we first check for update
                 boolean updated = false;
@@ -685,28 +691,51 @@ public class OsgiInstallerImpl
                     if ( dict != null ) {
                         final String digest = FileDataStore.computeDigest(dict);
                         if ( tr.getState() == ResourceState.INSTALLED && tr.getDigest().equals(digest) ) {
-                            logger.debug("Resource did not change {}:{}", resourceType, resourceId);
+                            logger.debug("Resource did not change {}", key);
                             return;
                         }
                     }
                     final UpdateHandler handler = this.findHandler(tr.getScheme());
                     if ( handler == null ) {
-                        logger.info("No handler found to handle update of resource with scheme {}", tr.getScheme());
+                        logger.debug("No handler found to handle update of resource with scheme {}", tr.getScheme());
                     } else {
                         final InputStream localIS = data.getInputStream();
                         try {
-                            final UpdateResult result = handler.handleUpdate(resourceType, resourceId, tr.getURL(), localIS, data.getDictionary());
+                            final UpdateResult result = handler.handleUpdate(resourceType, entityId, tr.getURL(), localIS, data.getDictionary());
                             if ( result != null ) {
-                                ((RegisteredResourceImpl)tr).update(
-                                        data.getDataFile(), data.getDictionary(),
-                                        data.getDigest(result.getURL(), result.getDigest()),
-                                        result.getPriority());
-                                // TODO : Handle move and add
+                                if ( !result.getURL().equals(tr.getURL()) && !result.getResourceIsMoved() ) {
+                                    // resource has been added!
+                                    final InternalResource internalResource = new InternalResource(result.getScheme(),
+                                            result.getResourceId(),
+                                            null,
+                                            data.getDictionary(),
+                                            (data.getDictionary() != null ? InstallableResource.TYPE_PROPERTIES : InstallableResource.TYPE_FILE),
+                                            data.getDigest(result.getURL(), result.getDigest()),
+                                            result.getPriority(),
+                                            data.getDataFile());
+                                    final RegisteredResource rr = this.persistentList.addOrUpdate(internalResource);
+                                    final TransformationResult transRes = new TransformationResult();
+                                    transRes.setId(entityId);
+                                    transRes.setResourceType(resourceType);
+                                    this.persistentList.transform(rr, new TransformationResult[] {
+                                            transRes
+                                    });
+                                    final EntityResourceList newGroup = this.persistentList.getEntityResourceList(key);
+                                    newGroup.setFinishState(ResourceState.INSTALLED);
+                                    newGroup.compact();
+                                } else {
+                                    // resource has been updated or moved
+                                    ((RegisteredResourceImpl)tr).update(
+                                            data.getDataFile(), data.getDictionary(),
+                                            data.getDigest(result.getURL(), result.getDigest()),
+                                            result.getPriority(),
+                                            result.getURL());
+                                    // We first set the state of the resource to install to make setFinishState work in all cases
+                                    ((RegisteredResourceImpl)tr).setState(ResourceState.INSTALL);
+                                    erl.setFinishState(ResourceState.INSTALLED);
+                                    erl.compact();
+                                }
                                 updated = true;
-                                // We first set the state of the resource to install to make setFinishState work in all cases
-                                ((RegisteredResourceImpl)tr).setState(ResourceState.INSTALL);
-                                erl.setFinishState(ResourceState.INSTALLED);
-                                erl.compact();
                                 this.persistentList.save();
                                 this.wakeUp();
                             }
@@ -731,7 +760,7 @@ public class OsgiInstallerImpl
                     for(final UpdateHandler handler : handlerList) {
                         final InputStream localIS = data.getInputStream();
                         try {
-                            final UpdateResult result = handler.handleUpdate(resourceType, resourceId, null, localIS, data.getDictionary());
+                            final UpdateResult result = handler.handleUpdate(resourceType, entityId, null, localIS, data.getDictionary());
                             if ( result != null ) {
                                 final InternalResource internalResource = new InternalResource(result.getScheme(),
                                         result.getResourceId(),
@@ -743,11 +772,14 @@ public class OsgiInstallerImpl
                                         data.getDataFile());
                                 final RegisteredResource rr = this.persistentList.addOrUpdate(internalResource);
                                 final TransformationResult transRes = new TransformationResult();
-                                transRes.setId(resourceId);
+                                transRes.setId(entityId);
                                 transRes.setResourceType(resourceType);
                                 this.persistentList.transform(rr, new TransformationResult[] {
                                         transRes
                                 });
+                                final EntityResourceList newGroup = this.persistentList.getEntityResourceList(key);
+                                newGroup.setFinishState(ResourceState.INSTALLED);
+                                newGroup.compact();
                                 this.persistentList.save();
                                 created = true;
                                 this.wakeUp();
@@ -765,7 +797,7 @@ public class OsgiInstallerImpl
                         }
                     }
                     if ( !created ) {
-                        logger.info("No handler found to handle creation of resource {}:{}", resourceType, resourceId);
+                        logger.debug("No handler found to handle creation of resource {}", key);
                     }
                 }
 
@@ -791,7 +823,7 @@ public class OsgiInstallerImpl
         String key = resourceType + ':' + resourceId;
         synchronized ( this.resourcesLock ) {
             final EntityResourceList erl = this.persistentList.getEntityResourceList(key);
-            logger.info("Removed {}:{}: {}", new Object[] {resourceType, resourceId, erl});
+            logger.debug("Removed {} : {}", key, erl);
             // if this is not registered at all, we can simply ignore this
             if ( erl != null ) {
                 resourceId = erl.getResourceId();
@@ -801,7 +833,7 @@ public class OsgiInstallerImpl
                     if ( tr.getState() != ResourceState.IGNORED ) {
                         final UpdateHandler handler = this.findHandler(tr.getScheme());
                         if ( handler == null ) {
-                            logger.info("No handler found to handle remove of resource with scheme {}", tr.getScheme());
+                            logger.debug("No handler found to handle remove of resource with scheme {}", tr.getScheme());
                         } else {
                             // we don't need to check the result, we just check if a result is returned
                             if ( handler.handleUpdate(resourceType, resourceId, tr.getURL(), null, null) != null ) {
@@ -812,7 +844,7 @@ public class OsgiInstallerImpl
                                 this.persistentList.save();
                                 this.wakeUp();
                             } else {
-                                logger.info("No handler found to handle remove of resource with scheme {}", tr.getScheme());
+                                logger.debug("No handler found to handle remove of resource with scheme {}", tr.getScheme());
                             }
                         }
                     } else {

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java Wed Mar  2 10:53:34 2011
@@ -50,10 +50,10 @@ public class RegisteredResourceImpl
     private static final int VERSION = 2;
 
     /** The resource url. */
-    private final String url;
+    private String url;
 
     /** The installer scheme. */
-	private final String urlScheme;
+	private String urlScheme;
 
 	/** The digest for the resource. */
 	private String digest;
@@ -507,7 +507,8 @@ public class RegisteredResourceImpl
     public void update(final File file,
             final Dictionary<String, Object> dict,
             final String digest,
-            final int priority) {
+            final int priority,
+            final String url) {
         this.removeDataFile();
         if ( file != null ) {
             this.dataFile = file;
@@ -523,5 +524,8 @@ public class RegisteredResourceImpl
         }
         this.digest = digest;
         this.priority = priority;
+        this.url = url;
+        final int pos = url.indexOf(':');
+        this.urlScheme = url.substring(0, pos);
     }
 }
\ No newline at end of file

Modified: sling/trunk/installer/providers/jcr/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/pom.xml?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/providers/jcr/pom.xml (original)
+++ sling/trunk/installer/providers/jcr/pom.xml Wed Mar  2 10:53:34 2011
@@ -72,6 +72,10 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.settings</artifactId>
             <version>1.0.0</version>
@@ -80,7 +84,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.installer.core</artifactId>
-            <version>3.0.0</version>
+            <version>3.1.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilter.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilter.java (original)
+++ sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilter.java Wed Mar  2 10:53:34 2011
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.installer.provider.jcr.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -51,6 +53,7 @@ class FolderNameFilter {
     public static final int DEFAULT_ROOT_PRIORITY = 99;
 
     FolderNameFilter(final String [] rootsConfig, final String regexp, final Set<String> runModes) {
+        final List<RootPathInfo> rootPathInfos = new ArrayList<RootPathInfo>();
         this.regexp = regexp;
         this.pattern = Pattern.compile(regexp);
         this.runModes = runModes;
@@ -58,10 +61,10 @@ class FolderNameFilter {
         // Each entry in rootsConfig is like /libs:100, where 100
         // is the priority.
         // Break that up into paths and priorities
-        rootPaths = new String[rootsConfig.length];
+        this.rootPaths = new String[rootsConfig.length];
         for(int i = 0; i < rootsConfig.length; i++) {
         	final String [] parts = rootsConfig[i].split(":");
-        	rootPaths[i] = cleanupRootPath(parts[0]);
+        	this.rootPaths[i] = cleanupRootPath(parts[0]);
         	Integer priority = new Integer(DEFAULT_ROOT_PRIORITY);
         	if(parts.length > 1) {
         		try {
@@ -70,14 +73,41 @@ class FolderNameFilter {
         			log.warn("Invalid priority in path definition '{}'", rootsConfig[i]);
         		}
         	}
-        	rootPriorities.put(rootPaths[i], priority);
-        	log.debug("Root path {} has priority {}", rootPaths[i], priority);
+        	rootPriorities.put(this.rootPaths[i], priority);
+        	rootPathInfos.add(new RootPathInfo(this.rootPaths[i], priority));
+        	log.debug("Root path {} has priority {}", this.rootPaths[i], priority);
+        }
+        // sort root paths by priority
+        Collections.sort(rootPathInfos);
+        int index = 0;
+        for(final RootPathInfo rpi : rootPathInfos) {
+            this.rootPaths[index++] = rpi.path;
+        }
+    }
+
+    private static final class RootPathInfo implements Comparable<RootPathInfo> {
+
+        public final String path;
+        private final Integer priority;
+
+        public RootPathInfo(final String path, final Integer prio) {
+            this.path = path;
+            this.priority = prio;
+        }
+
+        public int compareTo(RootPathInfo o) {
+            int result = -this.priority.compareTo(o.priority);
+            if ( result == 0 ) {
+                result = this.path.compareTo(o.path);
+            }
+            return result;
         }
     }
 
     /**
      * Return the list of root paths.
-     * Every entry in the list starts with a slash
+     * Every entry in the list starts with a slash and the entries are
+     * sorted by priority - highest priority first
      */
     String [] getRootPaths() {
     	return rootPaths;

Modified: sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java (original)
+++ sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java Wed Mar  2 10:53:34 2011
@@ -18,8 +18,10 @@
  */
 package org.apache.sling.installer.provider.jcr.impl;
 
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Dictionary;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -31,9 +33,17 @@ import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.installer.api.InstallableResource;
 import org.apache.sling.installer.api.OsgiInstaller;
+import org.apache.sling.installer.api.UpdateHandler;
+import org.apache.sling.installer.api.UpdateResult;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.settings.SlingSettingsService;
 import org.osgi.service.component.ComponentConstants;
@@ -41,27 +51,26 @@ import org.osgi.service.component.Compon
 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.property
- *      name="service.description"
- *      value="Sling Jcrinstall Service"
- *  @scr.property
- *      name="service.vendor"
- *      value="The Apache Software Foundation"
+/**
+ * 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.
  */
-public class JcrInstaller implements EventListener {
+@Component(label="%jcrinstall.name", description="%jcrinstall.description", immediate=true, metatype=true)
+@Properties({
+    @Property(name="service.description", value="Sling Jcrinstall Service"),
+    @Property(name="service.vendor", value="The Apache Software Foundation"),
+    @Property(name=UpdateHandler.PROPERTY_SCHEMES, value=JcrInstaller.URL_SCHEME),
+    @Property(name="service.ranking", intValue=100)
+})
+@Service(value=UpdateHandler.class)
+public class JcrInstaller implements EventListener, UpdateHandler {
+
 	public static final long RUN_LOOP_DELAY_MSEC = 500L;
 	public static final String URL_SCHEME = "jcrinstall";
 
-	private final Logger log = LoggerFactory.getLogger(getClass());
+	private final Logger logger = LoggerFactory.getLogger(getClass());
 
 	/** Counters, used for statistics and testing */
 	private final long [] counters = new long[COUNTERS_COUNT];
@@ -70,46 +79,52 @@ public class JcrInstaller implements Eve
     public static final int RUN_LOOP_COUNTER = 2;
     public static final int COUNTERS_COUNT = 3;
 
-    /**	This class watches the repository for installable resources
-     * @scr.reference
+    /**
+     * This class watches the repository for installable resources
      */
+    @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
+    /**
+     * Additional installation folders are activated based
+     * on the current RunMode. For example, /libs/foo/install.dev
+     * if the current run mode is "dev".
      */
+    @Reference
     private SlingSettingsService settings;
 
-    /**	The OsgiInstaller installs resources in the OSGi framework.
-     * 	@scr.reference
+    /**
+     * The OsgiInstaller installs resources in the OSGi framework.
      */
+    @Reference
     private OsgiInstaller installer;
 
     /** 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"
+    /**
+     * ComponentContext property that overrides the folder name regexp
      */
+    @Property(value=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 int DEFAULT_FOLDER_MAX_DEPTH = 4;
+
+    /**
+     * Configurable max. path depth for watched folders
      */
+    @Property(intValue=DEFAULT_FOLDER_MAX_DEPTH)
     public static final String PROP_INSTALL_FOLDER_MAX_DEPTH = "sling.jcrinstall.folder.max.depth";
 
-    /**	Configurable search path, with per-path priorities.
-     *  We could get it from the ResourceResolver, but introducing a dependency on this just to get those
-     *  values is too much for this module that's meant to bootstrap other services.
-     *
-     * 	@scr.property values.1="/libs:100" values.2="/apps:200"
+    /**
+     * Configurable search path, with per-path priorities.
+     * We could get it from the ResourceResolver, but introducing a dependency on this just to get those
+     * values is too much for this module that's meant to bootstrap other services.
      */
+    @Property(value={"/libs:100", "/apps:200"}, unbounded=PropertyUnbounded.ARRAY)
     public static final String PROP_SEARCH_PATH = "sling.jcrinstall.search.path";
     public static final String [] DEFAULT_SEARCH_PATH = { "/libs:100", "/apps:200" };
 
-    public static final int DEFAULT_FOLDER_MAX_DEPTH = 4;
     private int maxWatchedFolderDepth;
 
     /** Filter for folder names */
@@ -126,6 +141,20 @@ public class JcrInstaller implements Eve
 
     private ComponentContext componentContext;
 
+    private static final String DEFAULT_NEW_CONFIG_PATH = "/apps/sling/config";
+    @Property(value=DEFAULT_NEW_CONFIG_PATH)
+    private static final String PROP_NEW_CONFIG_PATH = "sling.jcrinstall.new.config.path";
+
+    /** The path for new configurations. */
+    private String newConfigPath;
+
+    private static final boolean DEFAULT_ENABLE_WRITEBACK = true;
+    @Property(boolValue=DEFAULT_ENABLE_WRITEBACK)
+    private static final String PROP_ENABLE_WRITEBACK = "sling.jcrinstall.enable.writeback";
+
+    /** Write back enabled? */
+    private boolean writeBack;
+
     /** Convert Nodes to InstallableResources */
     static interface NodeConverter {
     	InstallableResource convertNode(Node n, int priority)
@@ -154,14 +183,14 @@ public class JcrInstaller implements Eve
 
         @Override
         public final void run() {
-            log.info("Background thread {} starting", Thread.currentThread().getName());
+            logger.info("Background thread {} starting", Thread.currentThread().getName());
             try {
                 // open session
                 session = repository.loginAdministrative(repository.getDefaultWorkspace());
 
                 for (String path : roots) {
                     listeners.add(new RootFolderListener(session, folderNameFilter, path, updateFoldersListTimer));
-                    log.debug("Configured root folder: {}", path);
+                    logger.debug("Configured root folder: {}", path);
                 }
 
                 // Watch for events on the root - that might be one of our root folders
@@ -172,7 +201,7 @@ public class JcrInstaller implements Eve
                         null,
                         null,
                         true); // noLocal
-                log.debug("Watching for node events on / to detect removal/add of our root folders");
+                logger.debug("Watching for node events on / to detect removal/add of our root folders");
 
 
                 // Find paths to watch and create WatchedFolders to manage them
@@ -185,14 +214,14 @@ public class JcrInstaller implements Eve
                 final List<InstallableResource> resources = new LinkedList<InstallableResource>();
                 for(WatchedFolder f : watchedFolders) {
                     final WatchedFolder.ScanResult r = f.scan();
-                    log.debug("Startup: {} provides resources {}", f, r.toAdd);
+                    logger.debug("Startup: {} provides resources {}", f, r.toAdd);
                     resources.addAll(r.toAdd);
                 }
 
-                log.debug("Registering {} resources with OSGi installer: {}", resources.size(), resources);
+                logger.debug("Registering {} resources with OSGi installer: {}", resources.size(), resources);
                 installer.registerResources(URL_SCHEME, resources.toArray(new InstallableResource[resources.size()]));
             } catch (final RepositoryException re) {
-                log.error("Repository exception during startup - deactivating installer!", re);
+                logger.error("Repository exception during startup - deactivating installer!", re);
                 active = false;
                 final ComponentContext ctx = componentContext;
                 if ( ctx  != null ) {
@@ -204,7 +233,7 @@ public class JcrInstaller implements Eve
             while (active) {
                 runOneCycle();
             }
-            log.info("Background thread {} done", Thread.currentThread().getName());
+            logger.info("Background thread {} done", Thread.currentThread().getName());
             counters[RUN_LOOP_COUNTER] = -1;
         }
     };
@@ -218,7 +247,13 @@ public class JcrInstaller implements Eve
             throw new IllegalStateException("Expected backgroundThread to be null in activate()");
         }
         this.componentContext = context;
-        log.info("Activating Apache Sling JCR Installer");
+        logger.info("Activating Apache Sling JCR Installer");
+
+        this.newConfigPath = OsgiUtil.toString(context.getProperties().get(PROP_NEW_CONFIG_PATH), DEFAULT_NEW_CONFIG_PATH);
+        if ( !newConfigPath.endsWith("/") ) {
+            this.newConfigPath = this.newConfigPath.concat("/");
+        }
+        this.writeBack = OsgiUtil.toBoolean(context.getProperties().get(PROP_ENABLE_WRITEBACK), DEFAULT_ENABLE_WRITEBACK);
 
     	// Setup converters
     	converters.add(new FileNodeConverter());
@@ -229,20 +264,20 @@ public class JcrInstaller implements Eve
     	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.debug("Using configured ({}) folder name max depth '{}'", PROP_INSTALL_FOLDER_MAX_DEPTH, maxWatchedFolderDepth);
+            logger.debug("Using configured ({}) folder name max depth '{}'", PROP_INSTALL_FOLDER_MAX_DEPTH, maxWatchedFolderDepth);
     	} else {
             maxWatchedFolderDepth = DEFAULT_FOLDER_MAX_DEPTH;
-            log.debug("Using default folder max depth {}, not provided by {}", maxWatchedFolderDepth, PROP_INSTALL_FOLDER_MAX_DEPTH);
+            logger.debug("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) {
     		folderNameRegexp = folderNameRegexp.trim();
-            log.debug("Using configured ({}) folder name regexp '{}'", FOLDER_NAME_REGEXP_PROPERTY, folderNameRegexp);
+            logger.debug("Using configured ({}) folder name regexp '{}'", FOLDER_NAME_REGEXP_PROPERTY, folderNameRegexp);
     	} else {
     	    folderNameRegexp = DEFAULT_FOLDER_NAME_REGEXP;
-            log.debug("Using default folder name regexp '{}', not provided by {}", folderNameRegexp, FOLDER_NAME_REGEXP_PROPERTY);
+            logger.debug("Using default folder name regexp '{}', not provided by {}", folderNameRegexp, FOLDER_NAME_REGEXP_PROPERTY);
     	}
 
     	// Setup folder filtering and watching
@@ -257,11 +292,11 @@ public class JcrInstaller implements Eve
      * Deactivate this component
      */
     protected void deactivate(final ComponentContext context) {
-    	log.info("Deactivating Apache Sling JCR Installer");
+    	logger.info("Deactivating Apache Sling JCR Installer");
 
     	final long timeout = 30000L;
         backgroundThread.active = false;
-        log.debug("Waiting for " + backgroundThread.getName() + " Thread to end...");
+        logger.debug("Waiting for " + backgroundThread.getName() + " Thread to end...");
         backgroundThread.interrupt();
     	try {
             backgroundThread.join(timeout);
@@ -281,7 +316,7 @@ public class JcrInstaller implements Eve
                 session.getWorkspace().getObservationManager().removeEventListener(this);
             }
         } catch (final RepositoryException e) {
-            log.warn("Exception in deactivate()", e);
+            logger.warn("Exception in deactivate()", e);
         }
         if ( session != null ) {
             session.logout();
@@ -308,9 +343,9 @@ public class JcrInstaller implements Eve
         try {
             s = repository.loginAdministrative(repository.getDefaultWorkspace());
             if (!s.itemExists(rootPath) || !s.getItem(rootPath).isNode() ) {
-                log.info("Bundles root node {} not found, ignored", rootPath);
+                logger.info("Bundles root node {} not found, ignored", rootPath);
             } else {
-                log.debug("Bundles root node {} found, looking for bundle folders inside it", rootPath);
+                logger.debug("Bundles root node {} found, looking for bundle folders inside it", rootPath);
                 final Node n = (Node)s.getItem(rootPath);
                 findPathsUnderNode(n, result);
             }
@@ -333,7 +368,7 @@ public class JcrInstaller implements Eve
         }
         final int depth = path.split("/").length;
         if(depth > maxWatchedFolderDepth) {
-            log.debug("Not recursing into {} due to maxWatchedFolderDepth={}", path, maxWatchedFolderDepth);
+            logger.debug("Not recursing into {} due to maxWatchedFolderDepth={}", path, maxWatchedFolderDepth);
             return;
         }
         final NodeIterator it = n.getNodes();
@@ -364,7 +399,7 @@ public class JcrInstaller implements Eve
      *  	for folders that have been removed
      */
     private List<String> updateFoldersList() throws Exception {
-        log.debug("Updating folder list.");
+        logger.debug("Updating folder list.");
 
         final List<String> result = new LinkedList<String>();
 
@@ -379,7 +414,7 @@ public class JcrInstaller implements Eve
         // Check all WatchedFolder, in case some were deleted
         final List<WatchedFolder> toRemove = new ArrayList<WatchedFolder>();
         for(WatchedFolder wf : watchedFolders) {
-            log.debug("Item {} exists? {}", wf.getPath(), session.itemExists(wf.getPath()));
+            logger.debug("Item {} exists? {}", wf.getPath(), session.itemExists(wf.getPath()));
 
             if(!session.itemExists(wf.getPath())) {
                 result.addAll(wf.scan().toRemove);
@@ -388,7 +423,7 @@ public class JcrInstaller implements Eve
             }
         }
         for(WatchedFolder wf : toRemove) {
-            log.info("Deleting {}, path does not exist anymore", wf);
+            logger.info("Deleting {}, path does not exist anymore", wf);
             watchedFolders.remove(wf);
         }
 
@@ -401,23 +436,23 @@ public class JcrInstaller implements Eve
         try {
             while(it.hasNext()) {
                 final Event e = it.nextEvent();
-                log.debug("Got event {}", e);
+                logger.debug("Got event {}", e);
 
                 for(String root : roots) {
                     if (e.getPath().startsWith(root)) {
-                        log.info("Got event for root {}, scheduling scanning of new folders", root);
+                        logger.info("Got event for root {}, scheduling scanning of new folders", root);
                         updateFoldersListTimer.scheduleScan();
                     }
                 }
             }
         } catch(RepositoryException re) {
-            log.warn("RepositoryException in onEvent", re);
+            logger.warn("RepositoryException in onEvent", re);
         }
     }
 
     /** Run periodic scans of our watched folders, and watch for folders creations/deletions */
     public void runOneCycle() {
-        log.debug("Running watch cycle.");
+        logger.debug("Running watch cycle.");
 
         try {
             boolean didRefresh = true;
@@ -434,8 +469,8 @@ public class JcrInstaller implements Eve
                     WatchedFolder.getRescanTimer().reset();
                     counters[SCAN_FOLDERS_COUNTER]++;
                     final WatchedFolder.ScanResult sr = wf.scan();
-                    log.info("Registering resource with OSGi installer: {}",sr.toAdd);
-                    log.info("Removing resource from OSGi installer: {}", sr.toRemove);
+                    logger.info("Registering resource with OSGi installer: {}",sr.toAdd);
+                    logger.info("Removing resource from OSGi installer: {}", sr.toRemove);
                     installer.updateResources(URL_SCHEME, sr.toAdd.toArray(new InstallableResource[sr.toAdd.size()]),
                             sr.toRemove.toArray(new String[sr.toRemove.size()]));
                 }
@@ -451,7 +486,7 @@ public class JcrInstaller implements Eve
                 updateFoldersListTimer.reset();
                 counters[UPDATE_FOLDERS_LIST_COUNTER]++;
                 final List<String> toRemove = updateFoldersList();
-                log.info("Removing resource from OSGi installer (folder deleted): {}", toRemove);
+                logger.info("Removing resource from OSGi installer (folder deleted): {}", toRemove);
                 installer.updateResources(URL_SCHEME, null,
                         toRemove.toArray(new String[toRemove.size()]));
             }
@@ -462,7 +497,7 @@ public class JcrInstaller implements Eve
             }
 
         } catch(Exception e) {
-            log.warn("Exception in run()", e);
+            logger.warn("Exception in run()", e);
             try {
                 Thread.sleep(RUN_LOOP_DELAY_MSEC);
             } catch(InterruptedException ignore) {
@@ -475,4 +510,87 @@ public class JcrInstaller implements Eve
         return counters;
     }
 
+    /**
+     * @see org.apache.sling.installer.api.UpdateHandler#handleUpdate(java.lang.String, java.lang.String, String, java.io.InputStream, java.util.Dictionary)
+     */
+    public UpdateResult handleUpdate(final String resourceType,
+            final String id,
+            final String url,
+            final InputStream is,
+            final Dictionary<String, Object> dict) {
+        if ( !this.writeBack ) {
+            return null;
+        }
+
+        if ( is == null && dict == null ) {
+            final int pos = url.indexOf(':');
+            final String path = url.substring(pos + 1);
+            // remove
+            logger.debug("Removal of {}", path);
+            Session session = null;
+            try {
+                session = this.repository.loginAdministrative(null);
+                if ( session.nodeExists(path) ) {
+                    session.getNode(path).remove();
+                    session.save();
+                }
+            } catch (final RepositoryException re) {
+                logger.error("Unable to remove resource from " + path, re);
+                return null;
+            } finally {
+                if ( session != null ) {
+                    session.logout();
+                }
+            }
+            return new UpdateResult(url);
+        }
+        // we only handle add and remove for configs for now
+        if ( !resourceType.equals(InstallableResource.TYPE_CONFIG) ) {
+            return null;
+        }
+
+        final String path;
+        boolean resourceIsMoved = true;
+        if ( url != null ) {
+            // update
+            final int pos = url.indexOf(':');
+            final String oldPath = url.substring(pos + 1);
+            // check root path, we use the path with highest prio
+            final String rootPath = this.folderNameFilter.getRootPaths()[0] + '/';
+            if ( !oldPath.startsWith(rootPath) ) {
+                final int slashPos = oldPath.indexOf('/', 1);
+                path = rootPath + oldPath.substring(slashPos + 1);
+                resourceIsMoved = false;
+            } else {
+                path = oldPath;
+            }
+            logger.debug("Update of {} at {}", resourceType, path);
+        } else {
+            // add
+            path = this.newConfigPath + id;
+            logger.debug("Add of {} at {}", resourceType, path);
+        }
+
+        Session session = null;
+        try {
+            session = this.repository.loginAdministrative(null);
+            final Node configNode = JcrUtil.createPath(session, path, ConfigNodeConverter.CONFIG_NODE_TYPE);
+            JcrUtil.removeAllProperties(configNode);
+            JcrUtil.saveProperties(configNode, dict);
+            session.save();
+
+            final UpdateResult result = new UpdateResult(JcrInstaller.URL_SCHEME + ':' + path);
+            // priority
+            result.setPriority(this.folderNameFilter.getPriority(path));
+            result.setResourceIsMoved(resourceIsMoved);
+            return result;
+        } catch (final RepositoryException re) {
+            logger.error("Unable to remove resource from " + path, re);
+            return null;
+        } finally {
+            if ( session != null ) {
+                session.logout();
+            }
+        }
+    }
 }
\ No newline at end of file

Added: sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java?rev=1076166&view=auto
==============================================================================
--- sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java (added)
+++ sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java Wed Mar  2 10:53:34 2011
@@ -0,0 +1,174 @@
+/*
+ * 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.installer.provider.jcr.impl;
+
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+/**
+ * The <code>JcrUtil</code> class provides helper methods used
+ * throughout this bundle.
+ */
+public abstract class JcrUtil {
+
+    private static final String FOLDER_NODE_TYPE = "sling:Folder";
+
+    /**
+     * Creates a {@link javax.jcr.Value JCR Value} for the given object with
+     * the given Session.
+     * Selects the the {@link javax.jcr.PropertyType PropertyType} according
+     * the instance of the object's Class
+     *
+     * @param value object
+     * @param session to create value for
+     * @return the value or null if not convertible to a valid PropertyType
+     * @throws RepositoryException in case of error, accessing the Repository
+     */
+    public static Value createValue(Object value, Session session)
+            throws RepositoryException {
+        Value val;
+        ValueFactory fac = session.getValueFactory();
+        if(value instanceof Calendar) {
+            val = fac.createValue((Calendar)value);
+        } else if (value instanceof InputStream) {
+            val = fac.createValue((InputStream)value);
+        } else if (value instanceof Node) {
+            val = fac.createValue((Node)value);
+        } else if (value instanceof Long) {
+            val = fac.createValue((Long)value);
+        } else if (value instanceof Integer) {
+            val = fac.createValue(((Integer)value));
+        } else if (value instanceof Number) {
+            val = fac.createValue(((Number)value).doubleValue());
+        } else if (value instanceof Boolean) {
+            val = fac.createValue((Boolean) value);
+        } else if ( value instanceof String ){
+            val = fac.createValue((String)value);
+        } else {
+            val = null;
+        }
+        return val;
+    }
+
+    /**
+     * Sets the value of the property.
+     * Selects the {@link javax.jcr.PropertyType PropertyType} according
+     * to the instance of the object's class.
+     * @param node         The node where the property will be set on.
+     * @param propertyName The name of the property.
+     * @param propertyValue The value for the property.
+     */
+    public static void setProperty(final Node node,
+                                   final String propertyName,
+                                   final Object propertyValue)
+    throws RepositoryException {
+        if ( propertyValue == null ) {
+            node.setProperty(propertyName, (String)null);
+        } else if ( propertyValue.getClass().isArray() ) {
+            final Object[] values = (Object[])propertyValue;
+            final Value[] setValues = new Value[values.length];
+            for(int i=0; i<values.length; i++) {
+                setValues[i] = createValue(values[i], node.getSession());
+            }
+            node.setProperty(propertyName, setValues);
+        } else {
+            node.setProperty(propertyName, createValue(propertyValue, node.getSession()));
+        }
+    }
+
+    /**
+     * Creates or gets the {@link javax.jcr.Node Node} at the given Path.
+     *
+     * @param session The session to use for node creation
+     * @param absolutePath absolute node path
+     * @param nodeType to use for creation of the final node
+     * @return the Node at path
+     * @throws RepositoryException in case of exception accessing the Repository
+     */
+    public static Node createPath(final Session session,
+                                  final String absolutePath,
+                                  final String nodeType)
+    throws RepositoryException {
+        final Node parentNode = session.getRootNode();
+        String relativePath = absolutePath.substring(1);
+        if (!parentNode.hasNode(relativePath)) {
+            Node node = parentNode;
+            int pos = relativePath.lastIndexOf('/');
+            if ( pos != -1 ) {
+                final StringTokenizer st = new StringTokenizer(relativePath.substring(0, pos), "/");
+                while ( st.hasMoreTokens() ) {
+                    final String token = st.nextToken();
+                    if ( !node.hasNode(token) ) {
+                        try {
+                            node.addNode(token, FOLDER_NODE_TYPE);
+                        } catch (RepositoryException re) {
+                            // we ignore this as this folder might be created from a different task
+                            node.refresh(false);
+                        }
+                    }
+                    node = node.getNode(token);
+                }
+                relativePath = relativePath.substring(pos + 1);
+            }
+            if ( !node.hasNode(relativePath) ) {
+                node.addNode(relativePath, nodeType);
+            }
+            return node.getNode(relativePath);
+        }
+        return parentNode.getNode(relativePath);
+    }
+
+    /**
+     * Remove all properties from the node.
+     * All properties without a namespace are removed.
+     * @param node The node
+     * @throws RepositoryException
+     */
+    public static void removeAllProperties(final Node node)
+    throws RepositoryException {
+        final PropertyIterator pI = node.getProperties();
+        while ( pI.hasNext() ) {
+            final javax.jcr.Property prop = pI.nextProperty();
+            if ( !prop.getName().contains(":") ) {
+                prop.remove();
+            }
+        }
+    }
+
+    public static void saveProperties(final Node configNode,
+                                      final Dictionary<String, Object> dict)
+    throws RepositoryException {
+        final Enumeration<String> keys = dict.keys();
+        while ( keys.hasMoreElements() ) {
+            final String key = keys.nextElement();
+
+            JcrUtil.setProperty(configNode, key, dict.get(key));
+        }
+    }
+}

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

Propchange: sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/providers/jcr/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/providers/jcr/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/providers/jcr/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ sling/trunk/installer/providers/jcr/src/main/resources/OSGI-INF/metatype/metatype.properties Wed Mar  2 10:53:34 2011
@@ -43,4 +43,11 @@ sling.jcrinstall.search.path.description
   for installable resources. Combined with the installations folders name regexp \
   to select folders for scanning. Each path is followed by a colon and the priority \
   of resources found under that path, resources with higher values override resources \
-  with lower values which represent the same OSGi entity (configuration, bundle, etc). 
\ No newline at end of file
+  with lower values which represent the same OSGi entity (configuration, bundle, etc). 
+  
+sling.jcrinstall.new.config.path.name = New Config Path
+sling.jcrinstall.new.config.path.description = New configurations are stored at this location.
+
+sling.jcrinstall.enable.writeback.name = Enable Write Back
+sling.jcrinstall.enable.writeback.description = Enable writing back of changes done through other \
+ tools like writing back configurations changed in the web console etc.
\ No newline at end of file

Modified: sling/trunk/installer/providers/jcr/src/test/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilterTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/providers/jcr/src/test/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilterTest.java?rev=1076166&r1=1076165&r2=1076166&view=diff
==============================================================================
--- sling/trunk/installer/providers/jcr/src/test/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilterTest.java (original)
+++ sling/trunk/installer/providers/jcr/src/test/java/org/apache/sling/installer/provider/jcr/impl/FolderNameFilterTest.java Wed Mar  2 10:53:34 2011
@@ -25,8 +25,6 @@ import static org.junit.Assert.assertTru
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.sling.installer.provider.jcr.impl.FolderNameFilter;
-import org.apache.sling.installer.provider.jcr.impl.JcrInstaller;
 import org.junit.Test;
 
 public class FolderNameFilterTest {
@@ -47,16 +45,16 @@ public class FolderNameFilterTest {
     	{
     		final String [] paths = { "a:100", "/b/: 200 " };
             final FolderNameFilter f = new FolderNameFilter(paths, DEFAULT_REGEXP, new HashSet<String>());
-            assertEquals("/a", f.getRootPaths()[0]);
-            assertEquals("/b", f.getRootPaths()[1]);
+            assertEquals("/b", f.getRootPaths()[0]);
+            assertEquals("/a", f.getRootPaths()[1]);
             assertEquals(100, f.getRootPriority("/a/foo"));
             assertEquals(200, f.getRootPriority("/b/foo"));
     	}
     	{
     		final String [] paths = { "a/:NOT_AN_INTEGER", "/b/: 200 " };
             final FolderNameFilter f = new FolderNameFilter(paths, DEFAULT_REGEXP, new HashSet<String>());
-            assertEquals("/a", f.getRootPaths()[0]);
-            assertEquals("/b", f.getRootPaths()[1]);
+            assertEquals("/b", f.getRootPaths()[0]);
+            assertEquals("/a", f.getRootPaths()[1]);
             assertEquals(FolderNameFilter.DEFAULT_ROOT_PRIORITY, f.getRootPriority("/a/foo"));
             assertEquals(200, f.getRootPriority("/b/foo"));
     	}



Mime
View raw message