| /* |
| * 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.felix.deployment.rp.autoconf; |
| |
| import static org.osgi.service.deploymentadmin.spi.ResourceProcessorException.CODE_OTHER_ERROR; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Dictionary; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| import org.apache.felix.dm.Component; |
| import org.apache.felix.dm.DependencyManager; |
| import org.apache.felix.metatype.Designate; |
| import org.apache.felix.metatype.DesignateObject; |
| import org.apache.felix.metatype.MetaData; |
| import org.apache.felix.metatype.MetaDataReader; |
| import org.apache.felix.metatype.OCD; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.Filter; |
| import org.osgi.framework.FrameworkUtil; |
| 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.EventConstants; |
| import org.osgi.service.event.EventHandler; |
| import org.osgi.service.log.LogService; |
| import org.osgi.service.metatype.MetaTypeInformation; |
| import org.osgi.service.metatype.MetaTypeService; |
| import org.osgi.service.metatype.ObjectClassDefinition; |
| |
| public class AutoConfResourceProcessor implements ResourceProcessor, EventHandler |
| { |
| public static final String CONFIGURATION_ADMIN_FILTER_ATTRIBUTE = "filter"; |
| |
| private static final String LOCATION_PREFIX = "osgi-dp:"; |
| /** FELIX-5169 - do not reference this constant from the Constants class in DA! */ |
| private static final String EVENTTOPIC_COMPLETE = "org/osgi/service/deployment/COMPLETE"; |
| |
| // dependencies injected by Dependency Manager |
| private volatile LogService m_log; |
| private volatile MetaTypeService m_metaService; |
| private volatile DependencyManager m_dm; |
| // Locally managed |
| private Component m_component; |
| private PersistencyManager m_persistencyManager; |
| |
| private final Object m_lock; // protects the members below |
| private final Map<String, List<AutoConfResource>> m_toBeInstalled; |
| private final Map<String, List<AutoConfResource>> m_toBeDeleted; |
| private final AtomicReference<DeploymentSession> m_sessionRef; |
| private final List<ConfigurationAdminTask> m_configurationAdminTasks; |
| private final List<PostCommitTask> m_postCommitTasks; |
| |
| public AutoConfResourceProcessor() |
| { |
| m_lock = new Object(); |
| m_sessionRef = new AtomicReference<DeploymentSession>(); |
| m_toBeInstalled = new HashMap<String, List<AutoConfResource>>(); |
| m_toBeDeleted = new HashMap<String, List<AutoConfResource>>(); |
| m_configurationAdminTasks = new ArrayList<ConfigurationAdminTask>(); |
| m_postCommitTasks = new ArrayList<PostCommitTask>(); |
| } |
| |
| /** |
| * Called by Felix DM for the component created in {@link #commit()}. |
| */ |
| public void addConfigurationAdmin(ServiceReference ref, ConfigurationAdmin ca) |
| { |
| m_log.log(LogService.LOG_DEBUG, "found configuration admin " + ref); |
| |
| List<ConfigurationAdminTask> configAdminTasks; |
| synchronized (m_lock) |
| { |
| configAdminTasks = new ArrayList<ConfigurationAdminTask>(m_configurationAdminTasks); |
| } |
| |
| for (ConfigurationAdminTask task : configAdminTasks) |
| { |
| try |
| { |
| Filter filter = task.getFilter(); |
| 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); |
| } |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "found configuration admin " + ref + " done"); |
| } |
| |
| public void begin(DeploymentSession session) |
| { |
| m_log.log(LogService.LOG_DEBUG, "beginning session " + session); |
| |
| synchronized (m_lock) |
| { |
| DeploymentSession current = m_sessionRef.get(); |
| if (current != 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."); |
| } |
| if (!m_toBeInstalled.isEmpty() || !m_toBeDeleted.isEmpty() || !m_configurationAdminTasks.isEmpty() || !m_postCommitTasks.isEmpty() || m_component != null) |
| { |
| throw new IllegalStateException("State not reset correctly at start of session."); |
| } |
| m_sessionRef.set(session); |
| } |
| } |
| |
| public void cancel() |
| { |
| m_log.log(LogService.LOG_DEBUG, "cancel"); |
| rollback(); |
| } |
| |
| public void commit() |
| { |
| m_log.log(LogService.LOG_DEBUG, "commit"); |
| |
| Dictionary properties = new Properties(); |
| properties.put(EventConstants.EVENT_TOPIC, EVENTTOPIC_COMPLETE); |
| m_component = m_dm.createComponent() |
| .setInterface(EventHandler.class.getName(), properties) |
| .setImplementation(this) |
| .setCallbacks(null, null, null, null) |
| .setAutoConfig(Component.class, false) |
| .add(m_dm.createServiceDependency() |
| .setService(ConfigurationAdmin.class) |
| .setCallbacks("addConfigurationAdmin", null) |
| .setRequired(false) |
| ); |
| m_dm.add(m_component); |
| |
| m_log.log(LogService.LOG_DEBUG, "commit done"); |
| } |
| |
| public void dropAllResources() throws ResourceProcessorException |
| { |
| m_log.log(LogService.LOG_DEBUG, "drop all resources"); |
| |
| assertInDeploymentSession("Can not drop all resources without a Deployment Session"); |
| |
| for (String name : m_persistencyManager.getResourceNames()) |
| { |
| dropped(name); |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "drop all resources done"); |
| } |
| |
| public void dropped(String name) throws ResourceProcessorException |
| { |
| m_log.log(LogService.LOG_DEBUG, "dropped " + name); |
| |
| assertInDeploymentSession("Can not drop resource without a Deployment Session"); |
| |
| Map<String, List<AutoConfResource>> toBeDeleted; |
| synchronized (m_lock) |
| { |
| toBeDeleted = new HashMap<String, List<AutoConfResource>>(m_toBeDeleted); |
| } |
| |
| try |
| { |
| List<AutoConfResource> resources = m_persistencyManager.load(name); |
| |
| if (!toBeDeleted.containsKey(name)) |
| { |
| toBeDeleted.put(name, new ArrayList()); |
| } |
| toBeDeleted.get(name).addAll(resources); |
| } |
| catch (IOException ioe) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to drop resource: " + name, ioe); |
| } |
| |
| synchronized (m_lock) |
| { |
| m_toBeDeleted.putAll(toBeDeleted); |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "dropped " + name + " done"); |
| } |
| |
| public void handleEvent(Event event) |
| { |
| // regardless of the outcome, we simply invoke postcommit |
| postcommit(); |
| } |
| |
| public void postcommit() |
| { |
| m_log.log(LogService.LOG_DEBUG, "post commit"); |
| |
| List<PostCommitTask> postCommitTasks; |
| synchronized (m_lock) |
| { |
| postCommitTasks = new ArrayList<PostCommitTask>(m_postCommitTasks); |
| } |
| |
| for (PostCommitTask task : postCommitTasks) |
| { |
| try |
| { |
| task.run(m_persistencyManager); |
| } |
| catch (Exception e) |
| { |
| m_log.log(LogService.LOG_ERROR, "Exception during post commit wrap-up. Trying to continue.", e); |
| } |
| } |
| |
| endSession(); |
| |
| m_log.log(LogService.LOG_DEBUG, "post commit done"); |
| } |
| |
| public void prepare() throws ResourceProcessorException |
| { |
| m_log.log(LogService.LOG_DEBUG, "prepare"); |
| |
| assertInDeploymentSession("Can not prepare resource without a Deployment Session"); |
| |
| Map<String, List<AutoConfResource>> toBeDeleted; |
| Map<String, List<AutoConfResource>> toBeInstalled; |
| synchronized (m_lock) |
| { |
| toBeDeleted = new HashMap<String, List<AutoConfResource>>(m_toBeDeleted); |
| toBeInstalled = new HashMap<String, List<AutoConfResource>>(m_toBeInstalled); |
| } |
| |
| List<ConfigurationAdminTask> configAdminTasks = new ArrayList<ConfigurationAdminTask>(); |
| List<PostCommitTask> postCommitTasks = new ArrayList<PostCommitTask>(); |
| |
| m_log.log(LogService.LOG_DEBUG, "prepare delete"); |
| // delete dropped resources |
| for (Map.Entry<String, List<AutoConfResource>> entry : toBeDeleted.entrySet()) |
| { |
| String name = entry.getKey(); |
| for (AutoConfResource resource : entry.getValue()) |
| { |
| configAdminTasks.add(new DropResourceTask(resource)); |
| } |
| postCommitTasks.add(new DeleteResourceTask(name)); |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "prepare install/update"); |
| // install new/updated resources |
| for (Map.Entry<String, List<AutoConfResource>> entry : toBeInstalled.entrySet()) |
| { |
| String name = entry.getKey(); |
| |
| List<AutoConfResource> existingResources = null; |
| try |
| { |
| existingResources = m_persistencyManager.load(name); |
| } |
| catch (IOException ioe) |
| { |
| throw new ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Unable to read existing resources for resource " + name, ioe); |
| } |
| |
| List<AutoConfResource> resources = entry.getValue(); |
| for (AutoConfResource resource : resources) |
| { |
| // When updating existing configurations, make sure that we delete the ones that have become obsolete... |
| if (existingResources != null) |
| { |
| Iterator<AutoConfResource> iter = existingResources.iterator(); |
| while (iter.hasNext()) |
| { |
| AutoConfResource existing = iter.next(); |
| if (existing.equalsTargetConfiguration(resource)) |
| { |
| iter.remove(); |
| } |
| } |
| } |
| |
| configAdminTasks.add(new InstallOrUpdateResourceTask(resource)); |
| } |
| // remove existing configurations that were not in the new version of the resource |
| for (AutoConfResource existingResource : existingResources) |
| { |
| configAdminTasks.add(new DropResourceTask(existingResource)); |
| } |
| |
| postCommitTasks.add(new StoreResourceTask(name, resources)); |
| } |
| |
| synchronized (m_lock) |
| { |
| m_configurationAdminTasks.addAll(configAdminTasks); |
| m_postCommitTasks.addAll(postCommitTasks); |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "prepare done"); |
| } |
| |
| public void process(String name, InputStream stream) throws ResourceProcessorException |
| { |
| m_log.log(LogService.LOG_DEBUG, "processing " + name); |
| |
| // initial validation |
| assertInDeploymentSession("Can not process resource without a Deployment Session"); |
| |
| Map<String, List<AutoConfResource>> toBeInstalled; |
| synchronized (m_lock) |
| { |
| toBeInstalled = new HashMap<String, List<AutoConfResource>>(m_toBeInstalled); |
| } |
| |
| MetaData data = parseAutoConfResource(stream); |
| // process resources |
| Filter filter = getFilter(data); |
| |
| // add to session data |
| if (!toBeInstalled.containsKey(name)) |
| { |
| toBeInstalled.put(name, new ArrayList<AutoConfResource>()); |
| } |
| |
| List<Designate> designates = data.getDesignates(); |
| if (designates == null || designates.isEmpty()) |
| { |
| // 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<String, OCD> localOcds = data.getObjectClassDefinitions(); |
| if (localOcds == null) |
| { |
| localOcds = Collections.emptyMap(); |
| } |
| |
| for (Designate designate : designates) |
| { |
| // check object |
| DesignateObject objectDef = designate.getObject(); |
| if (objectDef == null) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Designate Object child missing or invalid"); |
| } |
| |
| // check attributes |
| if (objectDef.getAttributes() == null || objectDef.getAttributes().isEmpty()) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Object Attributes child missing or invalid"); |
| } |
| |
| // check ocdRef |
| String ocdRef = objectDef.getOcdRef(); |
| if (ocdRef == null || "".equals(ocdRef)) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Object ocdRef attribute missing or invalid"); |
| } |
| |
| // determine OCD |
| ObjectClassDefinition ocd = null; |
| OCD localOcd = 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(CODE_OTHER_ERROR, "No Object Class Definition found with id=" + ocdRef); |
| } |
| |
| // determine configuration data based on the values and their type definition |
| Dictionary dict = MetaTypeUtil.getProperties(designate, ocd); |
| if (dict == null) |
| { |
| // designate does not match it's definition, but was marked optional, ignore it |
| continue; |
| } |
| |
| AutoConfResource resource = new AutoConfResource(name, designate.getPid(), designate.getFactoryPid(), designate.getBundleLocation(), designate.isMerge(), dict, filter); |
| |
| toBeInstalled.get(name).add(resource); |
| } |
| |
| synchronized (m_lock) |
| { |
| m_toBeInstalled.putAll(toBeInstalled); |
| } |
| |
| m_log.log(LogService.LOG_DEBUG, "processing " + name + " done"); |
| } |
| |
| public void rollback() |
| { |
| m_log.log(LogService.LOG_DEBUG, "rollback"); |
| |
| Map<String, List<AutoConfResource>> toBeInstalled; |
| synchronized (m_lock) |
| { |
| toBeInstalled = new HashMap<String, List<AutoConfResource>>(m_toBeInstalled); |
| } |
| |
| for (Map.Entry<String, List<AutoConfResource>> entry : toBeInstalled.entrySet()) |
| { |
| for (AutoConfResource resource : entry.getValue()) |
| { |
| String name = resource.getName(); |
| try |
| { |
| dropped(name); |
| } |
| catch (ResourceProcessorException e) |
| { |
| m_log.log(LogService.LOG_ERROR, "Unable to roll back resource '" + name + "', reason: " + e.getMessage() + ", caused by: " + e.getCause().getMessage()); |
| } |
| break; |
| } |
| } |
| |
| endSession(); |
| |
| m_log.log(LogService.LOG_DEBUG, "rollback done"); |
| } |
| |
| /** |
| * Called by Felix DM when starting this component. |
| */ |
| public void start() throws IOException |
| { |
| File root = m_dm.getBundleContext().getDataFile(""); |
| if (root == null) |
| { |
| throw new IOException("No file system support"); |
| } |
| m_persistencyManager = new PersistencyManager(root); |
| } |
| |
| private void assertInDeploymentSession(String msg) throws ResourceProcessorException |
| { |
| synchronized (m_lock) |
| { |
| DeploymentSession current = m_sessionRef.get(); |
| if (current == null) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, msg); |
| } |
| } |
| } |
| |
| private void endSession() |
| { |
| if (m_component != null) |
| { |
| m_dm.remove(m_component); |
| m_component = null; |
| } |
| synchronized (m_lock) |
| { |
| m_toBeInstalled.clear(); |
| m_toBeDeleted.clear(); |
| m_postCommitTasks.clear(); |
| m_configurationAdminTasks.clear(); |
| m_sessionRef.set(null); |
| } |
| } |
| |
| private Bundle getBundle(String bundleLocation, boolean isFactory) throws ResourceProcessorException |
| { |
| Bundle bundle = null; |
| if (!isFactory) |
| { |
| // singleton configuration, no foreign bundles allowed, use source deployment package to find specified bundle |
| if (bundleLocation.startsWith(LOCATION_PREFIX)) |
| { |
| DeploymentSession session = m_sessionRef.get(); |
| bundle = session.getSourceDeploymentPackage().getBundle(bundleLocation.substring(LOCATION_PREFIX.length())); |
| } |
| } |
| else |
| { |
| // factory configuration, foreign bundles allowed, use bundle context to find the specified bundle |
| Bundle[] bundles = m_dm.getBundleContext().getBundles(); |
| for (int i = 0; i < bundles.length; i++) |
| { |
| String location = bundles[i].getLocation(); |
| if (bundleLocation.equals(location)) |
| { |
| bundle = bundles[i]; |
| break; |
| } |
| } |
| } |
| return bundle; |
| } |
| |
| private Filter getFilter(MetaData data) throws ResourceProcessorException |
| { |
| Map optionalAttributes = data.getOptionalAttributes(); |
| if (optionalAttributes != null) |
| { |
| try |
| { |
| return FrameworkUtil.createFilter((String) optionalAttributes.get(AutoConfResourceProcessor.CONFIGURATION_ADMIN_FILTER_ATTRIBUTE)); |
| } |
| catch (InvalidSyntaxException e) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to create filter!", e); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Determines the object class definition matching the specified designate. |
| * |
| * @param data The meta data containing 'local' object class definitions. |
| * @param designate The designate whose object class definition should be determined. |
| * @return |
| * @throws ResourceProcessorException |
| */ |
| private ObjectClassDefinition getMetaTypeOCD(MetaData data, Designate designate) throws ResourceProcessorException |
| { |
| boolean isFactoryConfig = isFactoryConfig(designate); |
| |
| Bundle bundle = getBundle(designate.getBundleLocation(), isFactoryConfig); |
| if (bundle == null) |
| { |
| return null; |
| } |
| |
| MetaTypeInformation mti = m_metaService.getMetaTypeInformation(bundle); |
| if (mti == null) |
| { |
| return null; |
| } |
| |
| String pid = isFactoryConfig ? pid = designate.getFactoryPid() : designate.getPid(); |
| try |
| { |
| ObjectClassDefinition tempOcd = mti.getObjectClassDefinition(pid, null); |
| // tempOcd will always have a value, if pid was not known IAE will be thrown |
| String ocdRef = designate.getObject().getOcdRef(); |
| if (ocdRef.equals(tempOcd.getID())) |
| { |
| return tempOcd; |
| } |
| } |
| catch (IllegalArgumentException iae) |
| { |
| // let null be returned |
| } |
| |
| return null; |
| } |
| |
| private boolean isFactoryConfig(Designate designate) |
| { |
| String factoryPid = designate.getFactoryPid(); |
| return (factoryPid != null && !"".equals(factoryPid)); |
| } |
| |
| private MetaData parseAutoConfResource(InputStream stream) throws ResourceProcessorException |
| { |
| MetaDataReader reader = new MetaDataReader(); |
| MetaData data = null; |
| try |
| { |
| data = reader.parse(stream); |
| } |
| catch (IOException e) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to process resource.", e); |
| } |
| if (data == null) |
| { |
| throw new ResourceProcessorException(CODE_OTHER_ERROR, "Supplied configuration is not conform the metatype xml specification."); |
| } |
| return data; |
| } |
| } |
| |
| interface ConfigurationAdminTask |
| { |
| public Filter getFilter(); |
| |
| public void run(PersistencyManager persistencyManager, ConfigurationAdmin configAdmin) throws Exception; |
| } |
| |
| 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 DropResourceTask implements ConfigurationAdminTask |
| { |
| private final AutoConfResource m_resource; |
| |
| public DropResourceTask(AutoConfResource resource) |
| { |
| m_resource = resource; |
| } |
| |
| public Filter 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 Filter 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); |
| } |
| } |
| |
| interface PostCommitTask |
| { |
| public void run(PersistencyManager manager) throws Exception; |
| } |
| |
| 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); |
| } |
| } |