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) {