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/21 16:16:57 UTC

svn commit: r806566 - in /sling/trunk/installer/osgi: installer/src/main/java/org/apache/sling/osgi/installer/impl/ installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ installer/src/test/java/org/apache/sling/osgi/installer/impl/ it/src...

Author: bdelacretaz
Date: Fri Aug 21 14:16:56 2009
New Revision: 806566

URL: http://svn.apache.org/viewvc?rev=806566&view=rev
Log:
SLING-1078 - Configuration handling and tests

Added:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java   (with props)
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java   (with props)
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java
      - copied, changed from r806445, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallRemoveTask.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java   (with props)
    sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java
      - copied, changed from r806445, sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java
    sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java   (with props)
Removed:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallRemoveTask.java
Modified:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/BundleTaskCreator.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigurationPid.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskOrder.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskUtilities.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
    sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/BundleTaskCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/BundleTaskCreator.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/BundleTaskCreator.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/BundleTaskCreator.java Fri Aug 21 14:16:56 2009
@@ -32,7 +32,7 @@
 import org.osgi.service.log.LogService;
 
 /** TaskCreator that processes a list of bundle RegisteredResources */
-class BundleTaskCreator implements OsgiInstallerThread.TaskCreator {
+class BundleTaskCreator {
 
     public static final String MAVEN_SNAPSHOT_MARKER = "SNAPSHOT";
     

Added: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java?rev=806566&view=auto
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java (added)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java Fri Aug 21 14:16:56 2009
@@ -0,0 +1,75 @@
+/*
+ * 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.osgi.installer.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+
+import org.apache.sling.osgi.installer.impl.tasks.ConfigInstallTask;
+import org.apache.sling.osgi.installer.impl.tasks.ConfigRemoveTask;
+import org.osgi.service.log.LogService;
+
+/** TaskCreator that processes a list of config RegisteredResources */
+class ConfigTaskCreator {
+
+    /** Store digests of the installed configs, keyed by config pid */
+    private final Map<String, String> digests = new HashMap<String, String>();
+    
+	/** Create tasks for a set of RegisteredResource that all represent the same config PID.
+	 */
+	public void createTasks(OsgiInstallerContext ctx, SortedSet<RegisteredResource> resources, SortedSet<OsgiInstallerTask> tasks) {
+		
+		// Find the config that must be active: the resources collection is ordered according
+		// to priorities, so we just need to find the first one that is installable
+		RegisteredResource toActivate = null;
+		for(RegisteredResource r : resources) {
+			if(toActivate == null && r.isInstallable()) {
+				toActivate = r;
+				break;
+			}
+		}
+		
+		if(toActivate == null) {
+		    // None of our resources are installable, remove corresponding config
+		    // (task simply does nothing if config does not exist)
+		    tasks.add(new ConfigRemoveTask(resources.first()));
+		} else {
+		    final ConfigurationPid cp = (ConfigurationPid)toActivate.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
+		    if(cp == null) {
+		        throw new IllegalArgumentException("Resource does not provide a CONFIG_PID_ATTRIBUTE: " + toActivate);
+		    }
+		    final String pid = cp.getCompositePid();
+		    
+		    final String previousDigest = digests.get(pid);
+		    if(toActivate.getDigest().equals(previousDigest)) {
+		        if(ctx.getLogService() != null) {
+		            ctx.getLogService().log(LogService.LOG_DEBUG, "Configuration already installed, ignored: " + toActivate); 
+		        }
+		    } else {
+		        tasks.add(new ConfigInstallTask(toActivate));
+		        digests.put(pid, toActivate.getDigest());
+                if(ctx.getLogService() != null) {
+                    ctx.getLogService().log(LogService.LOG_DEBUG, 
+                            "Scheduling update/install of config " + toActivate + ", digest has changed or was absent");
+                }
+		    }
+		}
+	}
+}

Propchange: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigTaskCreator.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigurationPid.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigurationPid.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigurationPid.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/ConfigurationPid.java Fri Aug 21 14:16:56 2009
@@ -18,7 +18,7 @@
  */
 package org.apache.sling.osgi.installer.impl;
 
-import org.apache.sling.osgi.installer.impl.tasks.ConfigInstallRemoveTask;
+import org.apache.sling.osgi.installer.impl.tasks.ConfigInstallTask;
 
 /** Builds configration PIDs out of filenames, examples:
  *      o.a.s.foo.bar.cfg -> pid = o.a.s.foo.bar
@@ -37,7 +37,7 @@
         }
         
         // cut off extension if it's one of our config extensions
-        for(String ext : ConfigInstallRemoveTask.CONFIG_EXTENSIONS) {
+        for(String ext : ConfigInstallTask.CONFIG_EXTENSIONS) {
             if(pid.endsWith(ext)) {
                 final int lastDot = pid.lastIndexOf('.');
                 if(lastDot >= 0) {

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerThread.java Fri Aug 21 14:16:56 2009
@@ -59,16 +59,7 @@
         new HashMap<String, SortedSet<RegisteredResource>>();
     
     private final BundleTaskCreator bundleTaskCreator = new BundleTaskCreator();
-    
-    static interface TaskCreator {
-    	/** Add the required OsgiInstallerTasks to the tasks collection, so that the resources reach
-    	 * 	their desired states.
-    	 *  @param ctx used to find out which bundles and configs are currently active
-    	 * 	@param resources ordered set of RegisteredResource which all have the same entityId
-    	 * 	@param tasks lists of tasks, to which we'll add the ones computed by this method
-    	 */
-    	void createTasks(OsgiInstallerContext ctx, SortedSet<RegisteredResource> resources, SortedSet<OsgiInstallerTask> tasks);
-    }
+    private final ConfigTaskCreator configTaskCreator = new ConfigTaskCreator();
     
     OsgiInstallerThread(OsgiInstallerContext ctx) {
         setName(getClass().getSimpleName());
@@ -256,8 +247,11 @@
             if(group.isEmpty()) {
                 continue;
             }
-            if(group.first().getResourceType().equals(RegisteredResource.ResourceType.BUNDLE)) {
+            final RegisteredResource.ResourceType rt = group.first().getResourceType();  
+            if(rt.equals(RegisteredResource.ResourceType.BUNDLE)) {
                 bundleTaskCreator.createTasks(ctx, group, tasks);
+            } else if(rt.equals(RegisteredResource.ResourceType.CONFIG)) {
+                configTaskCreator.createTasks(ctx, group, tasks);
             } else {
                 throw new IllegalArgumentException("No TaskCreator for resource type "+ group.first().getResourceType());
             } 

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java Fri Aug 21 14:16:56 2009
@@ -62,4 +62,7 @@
      */
     String getEntityId();
     
+    /** Attribute key: configuration pid */
+    String CONFIG_PID_ATTRIBUTE = "config.pid";
+    
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResourceImpl.java Fri Aug 21 14:16:56 2009
@@ -116,7 +116,9 @@
                 }
     		} else {
                 dataFile = null;
-                entity = ENTITY_CONFIG_PREFIX + new ConfigurationPid(input.getUrl()).getCompositePid();
+                final ConfigurationPid pid = new ConfigurationPid(input.getUrl());
+                entity = ENTITY_CONFIG_PREFIX + pid.getCompositePid();
+                attributes.put(CONFIG_PID_ATTRIBUTE, pid);
                 if(input.getInputStream() == null) {
                     // config provided as a Dictionary
                     dictionary = copy(input.getDictionary());

Added: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java?rev=806566&view=auto
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java (added)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java Fri Aug 21 14:16:56 2009
@@ -0,0 +1,75 @@
+/*
+ * 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.osgi.installer.impl.tasks;
+
+import java.io.IOException;
+
+import org.apache.sling.osgi.installer.impl.ConfigurationPid;
+import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
+import org.apache.sling.osgi.installer.impl.OsgiInstallerTask;
+import org.apache.sling.osgi.installer.impl.RegisteredResource;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/** Base class for configuration-related tasks */
+abstract class AbstractConfigTask extends OsgiInstallerTask {
+
+    protected final ConfigurationPid pid;
+    protected final RegisteredResource resource;
+    
+    AbstractConfigTask(RegisteredResource r) {
+        resource = r;
+        pid = (ConfigurationPid)r.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE);
+        if(pid == null) {
+            throw new IllegalArgumentException("RegisteredResource does not have CONFIG_PID_ATTRIBUTE: " + r);
+        }
+    }
+    
+    protected Configuration getConfiguration(ConfigurationAdmin ca, 
+            ConfigurationPid cp, boolean createIfNeeded, OsgiInstallerContext ocs)
+    throws IOException, InvalidSyntaxException
+    {
+        Configuration result = null;
+
+        if (cp.getFactoryPid() == null) {
+            result = ca.getConfiguration(cp.getConfigPid(), null);
+        } else {
+            Configuration configs[] = ca.listConfigurations(
+                "(|(" + ConfigInstallTask.ALIAS_KEY
+                + "=" + cp.getFactoryPid() + ")(.alias_factory_pid=" + cp.getFactoryPid()
+                + "))");
+
+            if (configs == null || configs.length == 0) {
+                if(createIfNeeded) {
+                    result = ca.createFactoryConfiguration(cp.getConfigPid(), null);
+                }
+            } else {
+                result = configs[0];
+            }
+        }
+
+        return result;
+    }
+    
+    @Override
+    public boolean isExecutable(OsgiInstallerContext ctx) throws Exception {
+        return ctx.getConfigurationAdmin() != null;
+    }
+}

Propchange: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/AbstractConfigTask.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java (from r806445, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallRemoveTask.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java?p2=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java&p1=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallRemoveTask.java&r1=806445&r2=806566&rev=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallRemoveTask.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigInstallTask.java Fri Aug 21 14:16:56 2009
@@ -18,88 +18,82 @@
  */
 package org.apache.sling.osgi.installer.impl.tasks;
 
+import java.util.Dictionary;
+
+import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
+import org.apache.sling.osgi.installer.impl.RegisteredResource;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
 /** Install/remove task for configurations 
  *  TODO split into install / remove tasks and reimplement
  * */
-public class ConfigInstallRemoveTask {
+public class ConfigInstallTask extends AbstractConfigTask {
 
     static final String ALIAS_KEY = "_alias_factory_pid";
     static final String CONFIG_PATH_KEY = "_jcr_config_path";
     public static final String [] CONFIG_EXTENSIONS = { ".cfg", ".properties" };
     
-    /**
+    public ConfigInstallTask(RegisteredResource r) {
+        super(r);
+    }
+    
+    @Override
+    public String getSortKey() {
+        return TaskOrder.CONFIG_INSTALL_ORDER + pid.getCompositePid();
+    }
     
-	public ConfigInstallRemoveTask(String uri, RegisteredResource data, OsgiInstallerContext ocs) {
-		super(uri, data, ocs);
-	}
-	
-	@Override
-	public String getSortKey() {
-		if(isInstallOrUpdate()) {
-			return TaskOrder.CONFIG_INSTALL_ORDER + uri;
-		} else {
-			return TaskOrder.CONFIG_UNINSTALL_ORDER + uri;
-		}
-	}
-
-	@Override
-	protected boolean doInstallOrUpdate(OsgiInstallerContext tctx, Map<String, Object> attributes) throws Exception {
-    	// Convert data to a configuration Dictionary
-    	Dictionary dict = data.getDictionary();
-
-    	if (dict == null) {
-    		throw new IllegalArgumentException("Null Dictionary for uri=" + uri);
-    	}
-
-    	// Add pseudo-properties
-    	dict.put(CONFIG_PATH_KEY, uri);
-
-        // Get pids from node name
-        final ConfigurationPid pid = new ConfigurationPid(uri);
-        if(ocs.getLogService() != null) {
-    		ocs.getLogService().log(LogService.LOG_DEBUG,
-    				pid + " created for uri " + uri);
+    @Override
+    public String toString() {
+        return getClass().getName() + ": " + resource;
+    }
+
+    @Override
+    public void execute(OsgiInstallerContext ctx) throws Exception {
+        super.execute(ctx);
+        
+        final ConfigurationAdmin ca = ctx.getConfigurationAdmin();
+        if(ca == null) {
+            ctx.addTaskToNextCycle(this);
+            if(ctx.getLogService() != null) {
+                ctx.getLogService().log(LogService.LOG_DEBUG, 
+                        "ConfigurationAdmin not available, task will be retried later: " + this);
+            }
+            return;
         }
+        
+        // Convert data to a configuration Dictionary
+        Dictionary<String, Object> dict = resource.getDictionary();
 
+        if (dict == null) {
+            throw new IllegalArgumentException("Null Dictionary for resource " + resource);
+        }
+
+        // Add pseudo-properties
+        dict.put(CONFIG_PATH_KEY, resource.getUrl());
+
+        // Factory?
         if(pid.getFactoryPid() != null) {
             dict.put(ALIAS_KEY, pid.getFactoryPid());
         }
 
-        // get or create configuration
+        // Get or create configuration
         boolean created = false;
-        Configuration config = TaskUtilities.getConfiguration(pid, false, ocs);
+        Configuration config = getConfiguration(ca, pid, false, ctx);
         if(config == null) {
             created = true;
-            config = TaskUtilities.getConfiguration(pid, true, ocs);
+            config = getConfiguration(ca, pid, true, ctx);
         }
         if (config.getBundleLocation() != null) {
             config.setBundleLocation(null);
         }
         config.update(dict);
-        if(ocs.getLogService() != null) {
-    		ocs.getLogService().log(LogService.LOG_INFO,
-    				"Configuration " + config.getPid() + " " + (created ? "created" : "updated"));
-        }
-        return true;
-	}
-
-	@Override
-	protected void doUninstall(OsgiInstallerContext tctx, Map<String, Object> attributes) throws Exception {
-        final ConfigurationPid pid = new ConfigurationPid(uri);
-        final Configuration cfg = TaskUtilities.getConfiguration(pid, false, ocs);
-        // TODO defer delete if ConfigAdmin not available?
-        if(cfg == null) {
-            if(ocs.getLogService() != null) {
-        		ocs.getLogService().log(LogService.LOG_INFO,
-        				"Cannot delete config " + uri + ", pid " + pid + " not found, ignored");
-            }
-        } else {
-            if(ocs.getLogService() != null) {
-        		ocs.getLogService().log(LogService.LOG_INFO,
-        				"Deleting config " + pid + ", uri = " + uri);
-            }
-            cfg.delete();
+        if(ctx.getLogService() != null) {
+            ctx.getLogService().log(LogService.LOG_INFO,
+                    "Configuration " + config.getPid() 
+                    + " " + (created ? "created" : "updated") 
+                    + " from " + resource);
         }
-	}
-	*/
+    }
 }
\ No newline at end of file

Added: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java?rev=806566&view=auto
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java (added)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java Fri Aug 21 14:16:56 2009
@@ -0,0 +1,76 @@
+/*
+ * 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.osgi.installer.impl.tasks;
+
+import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
+import org.apache.sling.osgi.installer.impl.RegisteredResource;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+/** Remove a Configuration */
+ public class ConfigRemoveTask extends AbstractConfigTask {
+
+    static final String ALIAS_KEY = "_alias_factory_pid";
+    static final String CONFIG_PATH_KEY = "_jcr_config_path";
+    public static final String [] CONFIG_EXTENSIONS = { ".cfg", ".properties" };
+    
+    public ConfigRemoveTask(RegisteredResource r) {
+        super(r);
+    }
+    
+    @Override
+    public String getSortKey() {
+        return TaskOrder.CONFIG_REMOVE_ORDER + pid.getCompositePid();
+    }
+    
+    @Override
+    public String toString() {
+        return getClass().getName() + ": " + resource;
+    }
+
+    @Override
+    public void execute(OsgiInstallerContext ctx) throws Exception {
+        super.execute(ctx);
+        
+        final ConfigurationAdmin ca = ctx.getConfigurationAdmin();
+        if(ca == null) {
+            ctx.addTaskToNextCycle(this);
+            if(ctx.getLogService() != null) {
+                ctx.getLogService().log(LogService.LOG_DEBUG, 
+                        "ConfigurationAdmin not available, task will be retried later: " + this);
+            }
+            return;
+        }
+        
+        final Configuration cfg = getConfiguration(ca, pid, false, ctx);
+        if(cfg == null) {
+            if(ctx.getLogService() != null) {
+                ctx.getLogService().log(LogService.LOG_DEBUG,
+                        "Cannot delete config , pid=" + pid + " not found, ignored (" + resource + ")");
+            }
+        } else {
+            if(ctx.getLogService() != null) {
+                ctx.getLogService().log(LogService.LOG_INFO,
+                        "Deleting config " + pid + " (" + resource + ")");
+            }
+            cfg.delete();
+        }
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/ConfigRemoveTask.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskOrder.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskOrder.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskOrder.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskOrder.java Fri Aug 21 14:16:56 2009
@@ -20,7 +20,7 @@
 
 /** Define the basic ordering of tasks */
 class TaskOrder {
-	static final String CONFIG_UNINSTALL_ORDER = "10-";
+	static final String CONFIG_REMOVE_ORDER = "10-";
 	static final String CONFIG_INSTALL_ORDER = "20-";
 	static final String BUNDLE_REMOVE_ORDER = "30-";
     static final String BUNDLE_UPDATE_ORDER = "40-";

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskUtilities.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskUtilities.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskUtilities.java (original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/TaskUtilities.java Fri Aug 21 14:16:56 2009
@@ -2,13 +2,8 @@
 
 import java.io.IOException;
 
-import org.apache.sling.osgi.installer.impl.ConfigurationPid;
-import org.apache.sling.osgi.installer.impl.OsgiInstallerContext;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
 
 /** Misc.utilities for classes of this package */
 public class TaskUtilities {
@@ -45,35 +40,4 @@
 
     	return null;
     }
-
-    /** Get or create configuration */
-    public static Configuration getConfiguration(ConfigurationPid cp, boolean createIfNeeded, OsgiInstallerContext ocs)
-    throws IOException, InvalidSyntaxException
-    {
-    	final ConfigurationAdmin configurationAdmin = ocs.getConfigurationAdmin();
-    	if(configurationAdmin == null) {
-    		throw new IllegalStateException("Missing service: " + ConfigurationAdmin.class.getName());
-    	}
-
-        Configuration result = null;
-
-        if (cp.getFactoryPid() == null) {
-            result = configurationAdmin.getConfiguration(cp.getConfigPid(), null);
-        } else {
-            Configuration configs[] = configurationAdmin.listConfigurations(
-                "(|(" + ConfigInstallRemoveTask.ALIAS_KEY
-                + "=" + cp.getFactoryPid() + ")(.alias_factory_pid=" + cp.getFactoryPid()
-                + "))");
-
-            if (configs == null || configs.length == 0) {
-                if(createIfNeeded) {
-                    result = configurationAdmin.createFactoryConfiguration(cp.getConfigPid(), null);
-                }
-            } else {
-                result = configs[0];
-            }
-        }
-
-        return result;
-    }
 }

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java (original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java Fri Aug 21 14:16:56 2009
@@ -93,6 +93,7 @@
             final Dictionary<String, Object> d = r.getDictionary();
             assertNotNull("CONFIG resource provides a Dictionary", d);
             assertEquals("CONFIG resource dictionary has two properties", 2, d.size());
+            assertNotNull("CONFIG resource has a pid attribute", r.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE));
         }
         
         {
@@ -107,6 +108,7 @@
             final Dictionary<String, Object> d = r.getDictionary();
             assertNotNull("CONFIG resource provides a Dictionary", d);
             assertEquals("CONFIG resource dictionary has two properties", 2, d.size());
+            assertNotNull("CONFIG resource has a pid attribute", r.getAttributes().get(RegisteredResource.CONFIG_PID_ATTRIBUTE));
         }
     }
     

Copied: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java (from r806445, sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java?p2=sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java&p1=sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java&r1=806445&r2=806566&rev=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java (original)
+++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigInstallTest.java Fri Aug 21 14:16:56 2009
@@ -16,45 +16,68 @@
  */
 package org.apache.sling.osgi.installer.it;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.osgi.installer.InstallableResource;
+import org.apache.sling.osgi.installer.OsgiInstaller;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.service.cm.Configuration;
 
 @RunWith(JUnit4TestRunner.class)
+
 public class ConfigInstallTest extends OsgiInstallerTestBase {
+    
+    private final static long TIMEOUT = 2500L;
+    
     @org.ops4j.pax.exam.junit.Configuration
     public static Option[] configuration() {
-    	return defaultConfiguration();
+        return defaultConfiguration();
     }
     
-    @Test
-    public void TODOReactivateTests() {
+    @Before
+    public void setUp() {
+        setupInstaller();
+    }
+    
+    @After
+    public void tearDown() {
+        super.tearDown();
     }
     
-    /**
     @Test
     public void testInstallAndRemoveConfig() throws Exception {
-    	final OsgiInstaller c = getService(OsgiInstaller.class);
-    	final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
-    	cfgData.put("foo", "bar");
-    	final String cfgPid = getClass().getName() + "." + System.currentTimeMillis();
-    	
-    	assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));
-    	
-    	c.scheduleInstallOrUpdate(cfgPid, new DictionaryInstallableData(cfgData));
-    	assertNull("Config " + cfgPid + " must not be found right after scheduleInstall", findConfiguration(cfgPid));
-    	c.executeScheduledOperations();
-    	
-    	final Configuration cfg = findConfiguration(cfgPid);
-    	assertNotNull("Config " + cfgPid + " must be found right after executeScheduledOperations()", cfg);
-    	final String value = (String)cfg.getProperties().get("foo");
-    	assertEquals("Config value must match", "bar", value);
-    	
-    	c.scheduleUninstall(cfgPid);
-    	assertNotNull("Config " + cfgPid + " must still be found right after scheduleUninstall", cfg);
-    	c.executeScheduledOperations();
-    	assertNull("Config " + cfgPid + " must be gone after executeScheduledOperations", findConfiguration(cfgPid));
+        final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
+        cfgData.put("foo", "bar");
+        final String cfgPid = getClass().getSimpleName() + "." + System.currentTimeMillis();
+        final InstallableResource r = getInstallableResource(cfgPid, cfgData); 
+        
+        assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));
+        
+        resetCounters();
+        installer.addResource(r);
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        
+        final Configuration cfg = waitForConfiguration("After installing", cfgPid, TIMEOUT, true);
+        assertNotNull("Config " + cfgPid + " must be found after installing", cfg);
+        final String value = (String)cfg.getProperties().get("foo");
+        assertEquals("Config value must match", "bar", value);
+        
+        resetCounters();
+        installer.removeResource(r);
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        
+        waitForConfiguration("After removing", cfgPid, TIMEOUT, false);
     }
     
     @Test
@@ -71,28 +94,35 @@
     	assertNotNull(cfgName + " bundle must be found", configAdmin);
     	waitForConfigAdmin(true);
     	
-    	final OsgiInstaller c = getService(OsgiInstaller.class);
     	final Dictionary<String, Object> cfgData = new Hashtable<String, Object>();
     	cfgData.put("foo", "bar");
-    	final String cfgPid = getClass().getName() + ".deferred." + System.currentTimeMillis();
+    	final String cfgPid = getClass().getSimpleName() + ".deferred." + System.currentTimeMillis();
     	assertNull("Config " + cfgPid + " must not be found before test", findConfiguration(cfgPid));
-    	
-    	c.scheduleInstallOrUpdate(cfgPid, new DictionaryInstallableData(cfgData));
-    	assertNull("Config " + cfgPid + " must not be found right after scheduleInstall", findConfiguration(cfgPid));
-    	
+
     	// Config installs must be deferred if ConfigAdmin service is stopped
     	configAdmin.stop();
     	waitForConfigAdmin(false);
-    	c.executeScheduledOperations();
-    	configAdmin.start();
+        resetCounters();
+        final InstallableResource r = getInstallableResource(cfgPid, cfgData);
+        installer.addResource(r);
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        sleep(1000L);
+        configAdmin.start();
     	waitForConfigAdmin(true);
-    	assertNull("Config " + cfgPid + " must not be installed if ConfigAdmin was stopped", findConfiguration(cfgPid));
-    	
-    	// with configadmin back, executeScheduledOperations must install deferred configs
-    	c.executeScheduledOperations();
-    	assertNotNull("Config " + cfgPid + " must be installed after restarting ConfigAdmin", findConfiguration(cfgPid));
-    	findConfiguration(cfgPid).delete();
-    	assertNull("Config " + cfgPid + " must be gone after test", findConfiguration(cfgPid));
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        waitForConfiguration("Config must be installed once ConfigurationAdmin restarts", 
+                cfgPid, TIMEOUT, true);
+    	
+        configAdmin.stop();
+        waitForConfigAdmin(false);
+        resetCounters();
+        installer.removeResource(r);
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        sleep(1000L);
+        configAdmin.start();
+        waitForConfigAdmin(true);
+        waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1);
+        waitForConfiguration("Config must be removed once ConfigurationAdmin restarts", 
+                cfgPid, TIMEOUT, false);
     }
-    */    
 }

Added: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java?rev=806566&view=auto
==============================================================================
--- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java (added)
+++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java Fri Aug 21 14:16:56 2009
@@ -0,0 +1,91 @@
+/*
+ * 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.osgi.installer.it;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static org.junit.Assert.fail;
+import org.apache.sling.osgi.installer.InstallableResource;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.cm.Configuration;
+
+@RunWith(JUnit4TestRunner.class)
+public class ConfigPrioritiesTest extends OsgiInstallerTestBase {
+
+    private final static long TIMEOUT = 2500L;
+    
+    @org.ops4j.pax.exam.junit.Configuration
+    public static Option[] configuration() {
+        return defaultConfiguration();
+    }
+    
+    @Before
+    public void setUp() {
+        setupInstaller();
+    }
+    
+    @After
+    public void tearDown() {
+        super.tearDown();
+    }
+    
+    void assertConfigValue(String pid, String key, String value, long timeoutMsec) throws Exception {
+        boolean found = false;
+        final String info = pid + ": waiting for " + key + "=" + value;
+        final long end = System.currentTimeMillis() + timeoutMsec;
+        do {
+            final Configuration cfg = waitForConfiguration(info, pid, timeoutMsec, true);
+            if(value.equals(cfg.getProperties().get(key))) {
+                found = true;
+                break;
+            }
+        } while(System.currentTimeMillis() < end);
+        
+        if(!found) {
+            fail("Did not get expected value: " + info);
+        }
+    }
+    
+    public void testOverrideConfig() throws Exception {
+        final String pid = getClass().getSimpleName() + "." + System.currentTimeMillis();
+        final Dictionary<String, Object> data = new Hashtable<String, Object>();
+        
+        data.put("foo", "a");
+        final InstallableResource a = getInstallableResource(pid, data, InstallableResource.DEFAULT_PRIORITY - 1);
+        data.put("foo", "b");
+        final InstallableResource b = getInstallableResource(pid, data, InstallableResource.DEFAULT_PRIORITY);
+        data.put("foo", "c");
+        final InstallableResource c = getInstallableResource(pid, data, InstallableResource.DEFAULT_PRIORITY + 1);
+        
+        installer.addResource(b);
+        assertConfigValue(pid, "foo", "b", TIMEOUT);
+        installer.addResource(c);
+        assertConfigValue(pid, "foo", "c", TIMEOUT);
+        installer.addResource(a);
+        installer.removeResource(c);
+        assertConfigValue(pid, "foo", "b", TIMEOUT);
+        installer.removeResource(b);
+        assertConfigValue(pid, "foo", "a", TIMEOUT);
+        installer.removeResource(a);
+        waitForConfiguration("After removing all resources", pid, TIMEOUT, false);
+    }
+}

Propchange: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/ConfigPrioritiesTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java?rev=806566&r1=806565&r2=806566&view=diff
==============================================================================
--- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java (original)
+++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java Fri Aug 21 14:16:56 2009
@@ -32,6 +32,7 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Dictionary;
 
 import org.apache.sling.osgi.installer.InstallableResource;
 import org.apache.sling.osgi.installer.OsgiInstaller;
@@ -152,6 +153,34 @@
     	return null;
     }
     
+    protected Configuration waitForConfiguration(String info, String pid, long timeoutMsec, boolean shouldBePresent) throws Exception {
+        if(info == null) {
+            info = "";
+        } else {
+            info += ": ";
+        }
+        
+        Configuration result = null;
+        final long end = System.currentTimeMillis() + timeoutMsec;
+        do {
+            result = findConfiguration(pid);
+            if(result != null) {
+                break;
+            }
+            if(!shouldBePresent && result == null) {
+                break;
+            }
+            sleep(25);
+        } while(System.currentTimeMillis() < end);
+        
+        if(shouldBePresent && result == null) {
+            fail(info + "Configuration not found (" + pid + ")");
+        } else if(!shouldBePresent && result != null) {
+            fail(info + "Configuration is still present (" + pid + ")");
+        }
+        return result;
+    }
+    
     protected Bundle findBundle(String symbolicName) {
     	for(Bundle b : bundleContext.getBundles()) {
     		if(symbolicName.equals(b.getSymbolicName())) {
@@ -202,6 +231,16 @@
         return result;
     }
     
+    protected InstallableResource getInstallableResource(String configPid, Dictionary<String, Object> data) {
+        return getInstallableResource(configPid, data, InstallableResource.DEFAULT_PRIORITY);
+    }
+    
+    protected InstallableResource getInstallableResource(String configPid, Dictionary<String, Object> data, int priority) {
+        final InstallableResource result = new InstallableResource(URL_SCHEME + ":/" + configPid, data);
+        result.setPriority(priority);
+        return result;
+    }
+    
     protected void waitForConfigAdmin(boolean shouldBePresent) {
         if(configAdminTracker == null) {
             synchronized (this) {