Return-Path: X-Original-To: apmail-felix-commits-archive@www.apache.org Delivered-To: apmail-felix-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 15AD49D82 for ; Tue, 7 Feb 2012 19:18:00 +0000 (UTC) Received: (qmail 11041 invoked by uid 500); 7 Feb 2012 19:18:00 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 10909 invoked by uid 500); 7 Feb 2012 19:17:58 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 10901 invoked by uid 99); 7 Feb 2012 19:17:58 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Feb 2012 19:17:58 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Feb 2012 19:17:56 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 5AF132388865 for ; Tue, 7 Feb 2012 19:17:36 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1241558 - in /felix/trunk/deploymentadmin/autoconf: ./ src/main/java/org/apache/felix/deployment/rp/autoconf/ Date: Tue, 07 Feb 2012 19:17:36 -0000 To: commits@felix.apache.org From: marrs@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120207191736.5AF132388865@eris.apache.org> Author: marrs Date: Tue Feb 7 19:17:35 2012 New Revision: 1241558 URL: http://svn.apache.org/viewvc?rev=1241558&view=rev Log: FELIX-3329 FELIX-3330 Implemented support for deferred as well as multiple configuration admins. Deferred configuration admin services can be started and will be considered until the deployment session ends. Filtering can be done by adding an optional attribute to the tag with a filtercondition which will be applied on the configuration admin service. If it matches, or if there is no such filter, the configuration will be applied. Modified: felix/trunk/deploymentadmin/autoconf/pom.xml felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/Activator.java felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResource.java felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessor.java felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/PersistencyManager.java Modified: felix/trunk/deploymentadmin/autoconf/pom.xml URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/pom.xml?rev=1241558&r1=1241557&r2=1241558&view=diff ============================================================================== --- felix/trunk/deploymentadmin/autoconf/pom.xml (original) +++ felix/trunk/deploymentadmin/autoconf/pom.xml Tue Feb 7 19:17:35 2012 @@ -57,7 +57,7 @@ ${pom.groupId} org.apache.felix.metatype - 1.0.4 + 1.0.5-SNAPSHOT Modified: felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/Activator.java URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/Activator.java?rev=1241558&r1=1241557&r2=1241558&view=diff ============================================================================== --- felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/Activator.java (original) +++ felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/Activator.java Tue Feb 7 19:17:35 2012 @@ -25,8 +25,9 @@ import org.apache.felix.dm.DependencyAct import org.apache.felix.dm.DependencyManager; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; -import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.deploymentadmin.spi.ResourceProcessor; +import org.osgi.service.event.EventConstants; +import org.osgi.service.event.EventHandler; import org.osgi.service.log.LogService; import org.osgi.service.metatype.MetaTypeService; @@ -38,14 +39,12 @@ public class Activator extends Dependenc public void init(BundleContext context, DependencyManager manager) throws Exception { Dictionary properties = new Properties(); properties.put(Constants.SERVICE_PID, "org.osgi.deployment.rp.autoconf"); + properties.put(EventConstants.EVENT_TOPIC, org.apache.felix.deploymentadmin.Constants.EVENTTOPIC_COMPLETE); manager.add(createComponent() - .setInterface(ResourceProcessor.class.getName(), properties) + .setInterface(new String[] { ResourceProcessor.class.getName(), EventHandler.class.getName() }, properties) .setImplementation(AutoConfResourceProcessor.class) .add(createServiceDependency() - .setService(ConfigurationAdmin.class) - .setRequired(true)) - .add(createServiceDependency() .setService(MetaTypeService.class) .setRequired(false)) .add(createServiceDependency() Modified: felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResource.java URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResource.java?rev=1241558&r1=1241557&r2=1241558&view=diff ============================================================================== --- felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResource.java (original) +++ felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResource.java Tue Feb 7 19:17:35 2012 @@ -31,12 +31,15 @@ public class AutoConfResource implements private final String m_bundleLoc; private final boolean m_merge; private final String m_name; + private final String m_filter; private String m_alias = null; + - public AutoConfResource(String name, String pid, String factoryPid, String bundleLocation, boolean merge, Dictionary properties) { + public AutoConfResource(String name, String pid, String factoryPid, String bundleLocation, boolean merge, Dictionary properties, String filter) { m_name = name; m_pid = pid; + m_filter = filter; m_factoryPid = (factoryPid == null) ? "" : factoryPid; m_bundleLoc = bundleLocation; m_merge = merge; @@ -50,6 +53,10 @@ public class AutoConfResource implements public String getPid() { return m_pid; } + + public String getFilter() { + return m_filter; + } /** * Returns empty string if this configuration is not a factory configuration, otherwise the factory Modified: felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessor.java URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessor.java?rev=1241558&r1=1241557&r2=1241558&view=diff ============================================================================== --- felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessor.java (original) +++ felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessor.java Tue Feb 7 19:17:35 2012 @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; @@ -33,6 +34,10 @@ import java.util.Map; import java.util.Set; import java.util.Vector; +import org.apache.felix.deploymentadmin.Constants; +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.ServiceDependency; import org.apache.felix.metatype.Attribute; import org.apache.felix.metatype.Designate; import org.apache.felix.metatype.MetaData; @@ -40,11 +45,16 @@ import org.apache.felix.metatype.MetaDat import org.apache.felix.metatype.OCD; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.deploymentadmin.spi.DeploymentSession; import org.osgi.service.deploymentadmin.spi.ResourceProcessor; import org.osgi.service.deploymentadmin.spi.ResourceProcessorException; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventHandler; import org.osgi.service.log.LogService; import org.osgi.service.metatype.AttributeDefinition; import org.osgi.service.metatype.MetaTypeInformation; @@ -52,21 +62,27 @@ import org.osgi.service.metatype.MetaTyp import org.osgi.service.metatype.ObjectClassDefinition; import org.xmlpull.v1.XmlPullParserException; -public class AutoConfResourceProcessor implements ResourceProcessor { - - private static final String LOCATION_PREFIX = "osgi-dp:"; - - private volatile LogService m_log; // injected by dependency manager - private volatile ConfigurationAdmin m_configAdmin; // injected by dependency manager - private volatile MetaTypeService m_metaService; // injected by dependency manager - private volatile BundleContext m_bc; // injected by dependency manager +public class AutoConfResourceProcessor implements ResourceProcessor, EventHandler { + private static final String LOCATION_PREFIX = "osgi-dp:"; + public static final String CONFIGURATION_ADMIN_FILTER_ATTRIBUTE = "filter"; + + // dependencies injected by Dependency Manager + private volatile LogService m_log; + private volatile ConfigurationAdmin m_configAdmin; + private volatile MetaTypeService m_metaService; + private volatile BundleContext m_bc; + private volatile Component m_component; + private final Object LOCK = new Object(); // protects the members below + private DeploymentSession m_session = null; - private Map m_toBeInstalled = new HashMap(); // Map> - private Map m_toBeDeleted = new HashMap(); + private final Map m_toBeInstalled = new HashMap(); // Map> + private final Map m_toBeDeleted = new HashMap(); private PersistencyManager m_persistencyManager; + private ServiceDependency m_configurationAdminDependency; + public void start() throws IOException { File root = m_bc.getDataFile(""); if (root == null) { @@ -76,70 +92,89 @@ public class AutoConfResourceProcessor i } public void begin(DeploymentSession session) { - m_session = session; + synchronized (LOCK) { + if (m_session != null) { + throw new IllegalArgumentException("Trying to begin new deployment session while already in one."); + } + if (session == null) { + throw new IllegalArgumentException("Trying to begin new deployment session with a null session."); + } + m_session = session; + m_toBeInstalled.clear(); + m_toBeDeleted.clear(); + } } public void process(String name, InputStream stream) throws ResourceProcessorException { - - // initial validation - if (m_session == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); - } - MetaDataReader reader = new MetaDataReader(); - MetaData data = null; - try { - data = reader.parse(stream); - } catch (IOException e) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Unable to process resource.", e); - } catch (XmlPullParserException e) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Supplied configuration is not conform the metatype xml specification.", e); - } - if (data == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Supplied configuration is not conform the metatype xml specification."); - } - - // process resources - Map designates = data.getDesignates(); - if (designates == null) { - // if there are no designates, there's nothing to process - m_log.log(LogService.LOG_INFO, "No designates found in the resource, so there's nothing to process."); - return; - } - Map localOcds = data.getObjectClassDefinitions(); - Iterator i = designates.keySet().iterator(); - while (i.hasNext()) { - Designate designate = (Designate) designates.get(i.next()); - - // determine OCD - ObjectClassDefinition ocd = null; - String ocdRef = designate.getObject().getOcdRef(); - OCD localOcd = (OCD) localOcds.get(ocdRef); - // ask meta type service for matching OCD if no local OCD has been defined - ocd = (localOcd != null) ? new ObjectClassDefinitionImpl(localOcd) : getMetaTypeOCD(data, designate); - if (ocd == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "No Object Class Definition found with id=" + ocdRef); - } - - // determine configuration data based on the values and their type definition - Dictionary dict = getProperties(designate, ocd); - if (dict == null) { - // designate does not match it's definition, but was marked optional, ignore it - continue; - } - - // add to session data - if (!m_toBeInstalled.containsKey(name)) { - m_toBeInstalled.put(name, new ArrayList()); - } - List resources = (List) m_toBeInstalled.get(name); - resources.add(new AutoConfResource(name, designate.getPid(), designate.getFactoryPid(), designate.getBundleLocation(), designate.isMerge(), dict)); - } + // initial validation + synchronized (LOCK) { + if (m_session == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); + } + } + MetaDataReader reader = new MetaDataReader(); + MetaData data = null; + try { + data = reader.parse(stream); + } + catch (IOException e) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Unable to process resource.", e); + } + catch (XmlPullParserException e) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Supplied configuration is not conform the metatype xml specification.", e); + } + if (data == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Supplied configuration is not conform the metatype xml specification."); + } + // process resources + String filter = null; + Map optionalAttributes = data.getOptionalAttributes(); + if (optionalAttributes != null) { + filter = (String) optionalAttributes.get(AutoConfResourceProcessor.CONFIGURATION_ADMIN_FILTER_ATTRIBUTE); + } + // add to session data + if (!m_toBeInstalled.containsKey(name)) { + m_toBeInstalled.put(name, new ArrayList()); + } + Map designates = data.getDesignates(); + if (designates == null) { + // if there are no designates, there's nothing to process + m_log.log(LogService.LOG_INFO, "No designates found in the resource, so there's nothing to process."); + return; + } + Map localOcds = data.getObjectClassDefinitions(); + if (localOcds == null) { + localOcds = Collections.EMPTY_MAP; + } + Iterator i = designates.keySet().iterator(); + while (i.hasNext()) { + Designate designate = (Designate) designates.get(i.next()); + // determine OCD + ObjectClassDefinition ocd = null; + String ocdRef = designate.getObject().getOcdRef(); + OCD localOcd = (OCD) localOcds.get(ocdRef); + // ask meta type service for matching OCD if no local OCD has been defined + ocd = (localOcd != null) ? new ObjectClassDefinitionImpl(localOcd) : getMetaTypeOCD(data, designate); + if (ocd == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "No Object Class Definition found with id=" + ocdRef); + } + // determine configuration data based on the values and their type definition + Dictionary dict = getProperties(designate, ocd); + if (dict == null) { + // designate does not match it's definition, but was marked optional, ignore it + continue; + } + List resources = (List) m_toBeInstalled.get(name); + resources.add(new AutoConfResource(name, designate.getPid(), designate.getFactoryPid(), designate.getBundleLocation(), designate.isMerge(), dict, filter)); + } } public void dropped(String name) throws ResourceProcessorException { - if (m_session == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); - } + synchronized (LOCK) { + if (m_session == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); + } + } try { List resources = m_persistencyManager.load(name); if (!m_toBeDeleted.containsKey(name)) { @@ -153,9 +188,11 @@ public class AutoConfResourceProcessor i } public void dropAllResources() throws ResourceProcessorException { - if (m_session == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not drop all resources without a Deployment Session"); - } + synchronized (LOCK) { + if (m_session == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not drop all resources without a Deployment Session"); + } + } try { Map loadAll = m_persistencyManager.loadAll(); for (Iterator i = loadAll.keySet().iterator(); i.hasNext();) { @@ -178,12 +215,16 @@ public class AutoConfResourceProcessor i throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Unable to drop resources, data area is not accessible"); } } + + private List m_configurationAdminTasks = new ArrayList(); + private List m_postCommitTasks = new ArrayList(); public void prepare() throws ResourceProcessorException { - if (m_session == null) { - throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); - } - + synchronized (LOCK) { + if (m_session == null) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_OTHER_ERROR, "Can not process resource without a Deployment Session"); + } + } try { // delete dropped resources for (Iterator i = m_toBeDeleted.keySet().iterator(); i.hasNext();) { @@ -191,15 +232,9 @@ public class AutoConfResourceProcessor i List resources = (List) m_toBeDeleted.get(name); for (Iterator j = resources.iterator(); j.hasNext();) { AutoConfResource resource = (AutoConfResource) j.next(); - if (resource.isFactoryConfig()) { - Configuration configuration = m_configAdmin.getConfiguration(resource.getGeneratedPid(), resource.getBundleLocation()); - configuration.delete(); - } else { - Configuration configuration = m_configAdmin.getConfiguration(resource.getPid(), resource.getBundleLocation()); - configuration.delete(); - } + m_configurationAdminTasks.add(new DropResourceTask(resource)); } - m_persistencyManager.delete(name); + m_postCommitTasks.add(new DeleteResourceTask(name)); } // install new/updated resources @@ -208,63 +243,17 @@ public class AutoConfResourceProcessor i List existingResources = null; try { existingResources = m_persistencyManager.load(name); - } catch (IOException ioe) { + } + catch (IOException ioe) { throw new ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Unable to read existing resources for resource " + name, ioe); } List resources = (List) m_toBeInstalled.get(name); for (Iterator iterator = resources.iterator(); iterator.hasNext();) { AutoConfResource resource = (AutoConfResource) iterator.next(); + + m_configurationAdminTasks.add(new InstallOrUpdateResourceTask(resource)); - Dictionary properties = resource.getProperties(); - String bundleLocation = resource.getBundleLocation(); - Configuration configuration = null; - - // update configuration - if (resource.isFactoryConfig()) { - // check if this is an factory config instance update - for (Iterator i = existingResources.iterator(); i.hasNext();) { - AutoConfResource existingResource = (AutoConfResource) i.next(); - if (resource.equalsTargetConfiguration(existingResource)) { - // existing instance found - configuration = m_configAdmin.getConfiguration(existingResource.getGeneratedPid(), bundleLocation); - existingResources.remove(existingResource); - break; - } - } - if (configuration == null) { - // no existing instance, create new - configuration = m_configAdmin.createFactoryConfiguration(resource.getFactoryPid(), bundleLocation); - } - resource.setGeneratedPid(configuration.getPid()); - } - else { - for (Iterator i = existingResources.iterator(); i.hasNext();) { - AutoConfResource existingResource = (AutoConfResource) i.next(); - if (resource.getPid().equals(existingResource.getPid())) { - // existing resource found - existingResources.remove(existingResource); - break; - } - } - configuration = m_configAdmin.getConfiguration(resource.getPid(), bundleLocation); - if (!bundleLocation.equals(configuration.getBundleLocation())) { - // an existing configuration exists that is bound to a different location, which is not allowed - throw new ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Existing configuration was not unbound and not bound to the specified bundlelocation"); - } - } - if (resource.isMerge()) { - Dictionary existingProperties = configuration.getProperties(); - if (existingProperties != null) { - Enumeration keys = existingProperties.keys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - properties.put(key, existingProperties.get(key)); - } - } - } - configuration.update(properties); } - // remove existing configurations that were not in the new version of the resource for (Iterator i = existingResources.iterator(); i.hasNext();) { AutoConfResource existingResource = (AutoConfResource) i.next(); @@ -276,7 +265,7 @@ public class AutoConfResourceProcessor i } configuration.delete(); } - m_persistencyManager.store(name, resources); + m_postCommitTasks.add(new StoreResourceTask(name, resources)); } } catch (IOException ioe) { @@ -286,9 +275,57 @@ public class AutoConfResourceProcessor i } public synchronized void commit() { - m_toBeInstalled.clear(); - m_toBeDeleted.clear(); - m_session = null; + DependencyManager dm = m_component.getDependencyManager(); + m_configurationAdminDependency = dm.createServiceDependency() + .setService(ConfigurationAdmin.class) + .setCallbacks("addConfigurationAdmin", null) + .setRequired(false); + m_component.add(m_configurationAdminDependency); + } + + public void addConfigurationAdmin(ServiceReference ref, ConfigurationAdmin ca) { + Iterator iterator = m_configurationAdminTasks.iterator(); + while (iterator.hasNext()) { + ConfigurationAdminTask task = (ConfigurationAdminTask) iterator.next(); + try { + Filter filter = null; + String filterString = task.getFilter(); + if (filterString != null) { + try { + filter = m_bc.createFilter(filterString); + } + catch (InvalidSyntaxException e) { + m_log.log(LogService.LOG_ERROR, "Could not parse filter, ignoring it: " + filterString, e); + } + } + if (filter == null || filter != null && filter.match(ref)) { + task.run(m_persistencyManager, ca); + } + } + catch (Exception e) { + m_log.log(LogService.LOG_ERROR, "Exception during configuration to " + ca + ". Trying to continue.", e); + } + } + } + + public void postcommit() { + m_component.remove(m_configurationAdminDependency); + Iterator iterator = m_postCommitTasks.iterator(); + while (iterator.hasNext()) { + PostCommitTask task = (PostCommitTask) iterator.next(); + try { + task.run(m_persistencyManager); + } + catch (Exception e) { + m_log.log(LogService.LOG_ERROR, "Exception during post commit wrap-up. Trying to continue.", e); + } + } + m_toBeInstalled.clear(); + m_toBeDeleted.clear(); + m_postCommitTasks.clear(); + m_configurationAdminTasks.clear(); + m_session = null; + m_component.remove(m_configurationAdminDependency); } public void rollback() { @@ -533,4 +570,146 @@ public class AutoConfResourceProcessor i } return result; } + + public void handleEvent(Event event) { + Boolean result = (Boolean) event.getProperty(Constants.EVENTPROPERTY_SUCCESSFUL); + // check if successful + if (result.booleanValue()) { + postcommit(); + } + else { + postcommit(); + } + } } + +interface ConfigurationAdminTask { + public String getFilter(); + public void run(PersistencyManager persistencyManager, ConfigurationAdmin configAdmin) throws Exception; +} + +interface PostCommitTask { + public void run(PersistencyManager manager) throws Exception; +} + +class DropResourceTask implements ConfigurationAdminTask { + private final AutoConfResource m_resource; + + public DropResourceTask(AutoConfResource resource) { + m_resource = resource; + } + + public String getFilter() { + return m_resource.getFilter(); + } + + public void run(PersistencyManager persistencyManager, ConfigurationAdmin configAdmin) throws Exception { + String pid; + if (m_resource.isFactoryConfig()) { + pid = m_resource.getGeneratedPid(); + } + else { + pid = m_resource.getPid(); + } + Configuration configuration = configAdmin.getConfiguration(pid, m_resource.getBundleLocation()); + configuration.delete(); + } +} + +class InstallOrUpdateResourceTask implements ConfigurationAdminTask { + private final AutoConfResource m_resource; + + public InstallOrUpdateResourceTask(AutoConfResource resource) { + m_resource = resource; + } + + public String getFilter() { + return m_resource.getFilter(); + } + + public void run(PersistencyManager persistencyManager, ConfigurationAdmin configAdmin) throws Exception { + String name = m_resource.getName(); + Dictionary properties = m_resource.getProperties(); + String bundleLocation = m_resource.getBundleLocation(); + Configuration configuration = null; + + List existingResources = null; + try { + existingResources = persistencyManager.load(name); + } + catch (IOException ioe) { + throw new ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Unable to read existing resources for resource " + name, ioe); + } + + // update configuration + if (m_resource.isFactoryConfig()) { + // check if this is an factory config instance update + for (Iterator i = existingResources.iterator(); i.hasNext();) { + AutoConfResource existingResource = (AutoConfResource) i.next(); + if (m_resource.equalsTargetConfiguration(existingResource)) { + // existing instance found + configuration = configAdmin.getConfiguration(existingResource.getGeneratedPid(), bundleLocation); + existingResources.remove(existingResource); + break; + } + } + if (configuration == null) { + // no existing instance, create new + configuration = configAdmin.createFactoryConfiguration(m_resource.getFactoryPid(), bundleLocation); + } + m_resource.setGeneratedPid(configuration.getPid()); + } + else { + for (Iterator i = existingResources.iterator(); i.hasNext();) { + AutoConfResource existingResource = (AutoConfResource) i.next(); + if (m_resource.getPid().equals(existingResource.getPid())) { + // existing resource found + existingResources.remove(existingResource); + break; + } + } + configuration = configAdmin.getConfiguration(m_resource.getPid(), bundleLocation); + if (!bundleLocation.equals(configuration.getBundleLocation())) { + // an existing configuration exists that is bound to a different location, which is not allowed + throw new ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Existing configuration was bound to " + configuration.getBundleLocation() + " instead of " + bundleLocation); + } + } + if (m_resource.isMerge()) { + Dictionary existingProperties = configuration.getProperties(); + if (existingProperties != null) { + Enumeration keys = existingProperties.keys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + properties.put(key, existingProperties.get(key)); + } + } + } + configuration.update(properties); + } +} + +class DeleteResourceTask implements PostCommitTask { + private final String m_name; + + public DeleteResourceTask(String name) { + m_name = name; + } + + public void run(PersistencyManager manager) throws Exception { + manager.delete(m_name); + } +} + +class StoreResourceTask implements PostCommitTask { + private final String m_name; + private final List m_resources; + + public StoreResourceTask(String name, List resources) { + m_name = name; + m_resources = resources; + } + + public void run(PersistencyManager manager) throws Exception { + manager.store(m_name, m_resources); + } +} \ No newline at end of file Modified: felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/PersistencyManager.java URL: http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/PersistencyManager.java?rev=1241558&r1=1241557&r2=1241558&view=diff ============================================================================== --- felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/PersistencyManager.java (original) +++ felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/PersistencyManager.java Tue Feb 7 19:17:35 2012 @@ -46,9 +46,6 @@ public class PersistencyManager { * @throws IOException If the resource could not be stored. */ public void store(String name, List configs) throws IOException { - if (configs.isEmpty()) { - return; - } File targetDir = m_root; name = name.replace('/', File.separatorChar); @@ -67,7 +64,8 @@ public class PersistencyManager { try { out = new ObjectOutputStream(new FileOutputStream(target)); out.writeObject(configs); - } finally { + } + finally { if (out != null) { try { out.close();