Author: jawi
Date: Fri Jan 15 13:34:41 2016
New Revision: 1724802
URL: http://svn.apache.org/viewvc?rev=1724802&view=rev
Log:
Code review:
- cleaned up the code to use more recent Java constructs, such as foreach
loops;
- cleaned up the test cases to make them a bit more readable and easier to
maintain by folding some duplicate code into helper methods;
- fixed a corner case in which an AutoConf resource drops a configuration while
updating existing ones at the same time. A NPE could be thrown in this
situation due ConfigurationAdmin not being present;
- fixed a corner case in which a resource is dropped twice. A IOException could
be thrown;
- moved some really specific MetaType code to a utility class;
- added some test cases for PersistencyManager;
- applied the code formatting guidelines for Apache Felix.
Added:
felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java
(with props)
felix/trunk/deploymentadmin/autoconf/src/test/java/org/apache/felix/deployment/rp/autoconf/PersistencyManagerTest.java
(with props)
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
felix/trunk/deploymentadmin/autoconf/src/test/java/org/apache/felix/deployment/rp/autoconf/AutoConfResourceProcessorTest.java
felix/trunk/deploymentadmin/autoconf/src/test/java/org/apache/felix/deployment/rp/autoconf/DefaultNullObject.java
felix/trunk/deploymentadmin/autoconf/src/test/java/org/apache/felix/deployment/rp/autoconf/Utils.java
Modified: felix/trunk/deploymentadmin/autoconf/pom.xml
URL:
http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/pom.xml?rev=1724802&r1=1724801&r2=1724802&view=diff
==============================================================================
--- felix/trunk/deploymentadmin/autoconf/pom.xml (original)
+++ felix/trunk/deploymentadmin/autoconf/pom.xml Fri Jan 15 13:34:41 2016
@@ -85,9 +85,19 @@
<Bundle-Name>Apache Felix AutoConf Resource
Processor</Bundle-Name>
<Bundle-Description>A customizer bundle that publishes
a Resource Processor service that processes configuration resources shipped in
a Deployment Package.</Bundle-Description>
<Bundle-Vendor>The Apache Software
Foundation</Bundle-Vendor>
-
<Private-Package>org.apache.felix.deployment.rp.autoconf,
org.apache.felix.metatype, org.apache.felix.metatype.internal.l10n,
org.apache.felix.metatype.internal, org.kxml2.io;-split-package:=merge-first,
org.xmlpull.v1;-split-package:=merge-first,
org.osgi.service.metatype;-split-package:=merge-first</Private-Package>
-
<Import-Package>org.apache.felix.dm,org.osgi.service.deploymentadmin,org.osgi.service.deploymentadmin.spi,org.osgi.service.event,org.osgi.service.log,*</Import-Package>
-
<Export-Package>org.osgi.service.deploymentadmin.spi;version="1.0",org.osgi.service.metatype;version="1.2"</Export-Package>
+ <Private-Package>
+ org.apache.felix.deployment.rp.autoconf,
+ org.apache.felix.metatype,
+ org.apache.felix.metatype.internal.l10n,
+ org.apache.felix.metatype.internal,
+ org.kxml2.io; -split-package:=merge-first,
+ org.xmlpull.v1; -split-package:=merge-first,
+ org.osgi.service.metatype;
-split-package:=merge-first
+ </Private-Package>
+ <Export-Package>
+ org.osgi.service.deploymentadmin.spi;
-split-package:=merge-last;version="1.0",
+ org.osgi.service.metatype;
-split-package:=merge-last;version="1.2"
+ </Export-Package>
<DeploymentPackage-Customizer>true</DeploymentPackage-Customizer>
<Deployment-ProvidesResourceProcessor>org.osgi.deployment.rp.autoconf</Deployment-ProvidesResourceProcessor>
</instructions>
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=1724802&r1=1724801&r2=1724802&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
Fri Jan 15 13:34:41 2016
@@ -38,7 +38,7 @@ 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");
-
+
AutoConfResourceProcessor processor = new AutoConfResourceProcessor();
manager.add(createComponent()
.setInterface(ResourceProcessor.class.getName(), properties)
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=1724802&r1=1724801&r2=1724802&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
Fri Jan 15 13:34:41 2016
@@ -18,95 +18,146 @@
*/
package org.apache.felix.deployment.rp.autoconf;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Dictionary;
-public class AutoConfResource implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- private final String m_pid;
- private final String m_factoryPid;
- private final Dictionary m_properties;
- 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, String filter) {
- m_name = name;
- m_pid = pid;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class AutoConfResource implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ private final String m_pid;
+ private final String m_factoryPid;
+ private final Dictionary m_properties;
+ private final String m_bundleLoc;
+ private final boolean m_merge;
+ private final String m_name;
+
+ private transient Filter m_filter;
+ private String m_alias = null;
+
+ public AutoConfResource(String name, String pid, String factoryPid, String
bundleLocation, boolean merge, Dictionary properties, Filter filter)
+ {
+ m_name = name;
+ m_pid = pid;
m_filter = filter;
- m_factoryPid = (factoryPid == null) ? "" : factoryPid;
- m_bundleLoc = bundleLocation;
- m_merge = merge;
- m_properties = properties;
- }
-
- public String getName() {
- return m_name;
- }
-
- public String getPid() {
- return m_pid;
- }
-
- public String getFilter() {
+ m_factoryPid = (factoryPid == null) ? "" : factoryPid;
+ m_bundleLoc = bundleLocation;
+ m_merge = merge;
+ m_properties = properties;
+ }
+
+ public String getName()
+ {
+ return m_name;
+ }
+
+ public String getPid()
+ {
+ return m_pid;
+ }
+
+ public Filter getFilter()
+ {
return m_filter;
}
- /**
- * Returns empty string if this configuration is not a factory
configuration, otherwise the factory
- * PID is returned.
- *
- * @return Empty string if this is not a factory configuration
resource, else the factory PID is returned.
- */
- public String getFactoryPid() {
- return m_factoryPid;
- }
-
- public Dictionary getProperties() {
- return m_properties;
- }
-
- public String getBundleLocation() {
- return m_bundleLoc;
- }
-
- public boolean isMerge() {
- return m_merge;
- }
-
- public boolean isFactoryConfig() {
- return !(m_factoryPid == null || "".equals(m_factoryPid));
- }
-
- public void setGeneratedPid(String alias) {
- m_alias = alias;
- }
-
- public String getGeneratedPid() {
- if (m_alias == null) {
- throw new IllegalStateException("Must set an alias
first.");
- }
- return m_alias;
- }
-
- /**
- * Determine if the specified <code>AutoConfResource</code> is meant to
be used for the same <code>Configuration</code> as this object.
- *
- * @param resource The <code>AutoConfResource</code> to compare with.
- * @return Returns <code>true</code> if the two resources are meant to
be used for the same <code>Configuration</code> object, false otherwise.
- */
- public boolean equalsTargetConfiguration(AutoConfResource resource) {
- if (isFactoryConfig()) {
- return m_pid.equals(resource.getPid()) &&
m_factoryPid.equals(resource.getFactoryPid());
- }
- else {
- return m_pid.equals(resource.getPid());
- }
- }
+ /**
+ * Returns empty string if this configuration is not a factory
configuration, otherwise the factory
+ * PID is returned.
+ *
+ * @return Empty string if this is not a factory configuration resource,
else the factory PID is returned.
+ */
+ public String getFactoryPid()
+ {
+ return m_factoryPid;
+ }
+
+ public Dictionary getProperties()
+ {
+ return m_properties;
+ }
+
+ public String getBundleLocation()
+ {
+ return m_bundleLoc;
+ }
+
+ public boolean isMerge()
+ {
+ return m_merge;
+ }
+
+ public boolean isFactoryConfig()
+ {
+ return !(m_factoryPid == null || "".equals(m_factoryPid));
+ }
+
+ public void setGeneratedPid(String alias)
+ {
+ m_alias = alias;
+ }
+
+ public String getGeneratedPid()
+ {
+ if (m_alias == null)
+ {
+ throw new IllegalStateException("Must set an alias first.");
+ }
+ return m_alias;
+ }
+
+ /**
+ * Determine if the specified <code>AutoConfResource</code> is meant to be
used for the same <code>Configuration</code> as this object.
+ *
+ * @param resource The <code>AutoConfResource</code> to compare with.
+ * @return Returns <code>true</code> if the two resources are meant to be
used for the same <code>Configuration</code> object, false otherwise.
+ */
+ public boolean equalsTargetConfiguration(AutoConfResource resource)
+ {
+ if (isFactoryConfig())
+ {
+ return m_pid.equals(resource.getPid()) &&
m_factoryPid.equals(resource.getFactoryPid());
+ }
+ else
+ {
+ return m_pid.equals(resource.getPid());
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException
+ {
+ out.defaultWriteObject();
+ if (m_filter != null)
+ {
+ out.writeUTF(m_filter.toString());
+ }
+ else
+ {
+ out.writeUTF("");
+ }
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException
+ {
+ in.defaultReadObject();
+ String filter = in.readUTF();
+ if (!"".equals(filter))
+ {
+ try
+ {
+ m_filter = FrameworkUtil.createFilter(filter);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ throw new IOException("Unable to parse serialized filter: " +
e.getMessage());
+ }
+ }
+ }
}
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=1724802&r1=1724801&r2=1724802&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
Fri Jan 15 13:34:41 2016
@@ -18,33 +18,32 @@
*/
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.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.Set;
-import java.util.Vector;
+import java.util.concurrent.atomic.AtomicReference;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.metatype.Attribute;
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.BundleContext;
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;
@@ -56,386 +55,495 @@ 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.AttributeDefinition;
import org.osgi.service.metatype.MetaTypeInformation;
import org.osgi.service.metatype.MetaTypeService;
import org.osgi.service.metatype.ObjectClassDefinition;
-public class AutoConfResourceProcessor implements ResourceProcessor,
EventHandler {
- private static final int CODE_OTHER_ERROR =
ResourceProcessorException.CODE_OTHER_ERROR;
- private static final String LOCATION_PREFIX = "osgi-dp:";
+public class AutoConfResourceProcessor implements ResourceProcessor,
EventHandler
+{
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 static final String LOCATION_PREFIX = "osgi-dp:";
+
+ // dependencies injected by Dependency Manager
+ private volatile LogService m_log;
+ private volatile MetaTypeService m_metaService;
private volatile DependencyManager m_dm;
-
- private Component m_component;
-
- private final Object m_lock = new Object(); // protects the members
below
-
- private DeploymentSession m_session = null;
- private final Map m_toBeInstalled = new HashMap(); // Map<String,
List<AutoConfResource>>
- private final Map m_toBeDeleted = new HashMap();
-
- private PersistencyManager m_persistencyManager;
-
- public void start() throws IOException {
- File root = m_bc.getDataFile("");
- if (root == null) {
- throw new IOException("No file system support");
- }
- m_persistencyManager = new PersistencyManager(root);
- }
-
- public void begin(DeploymentSession session) {
+ // 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) {
- if (m_session != null) {
+
+ 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) {
+ 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) {
+ 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_session = session;
+ m_sessionRef.set(session);
}
}
-
- public void process(String name, InputStream stream) throws
ResourceProcessorException {
- m_log.log(LogService.LOG_DEBUG, "processing " + name);
- // initial validation
- synchronized (m_lock) {
- if (m_session == null) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Can
not process resource without a Deployment 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,
org.apache.felix.deploymentadmin.Constants.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);
}
- MetaDataReader reader = new MetaDataReader();
- MetaData data = null;
- try {
- data = reader.parse(stream);
+ catch (IOException ioe)
+ {
+ throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to
drop resource: " + name, ioe);
}
- catch (IOException e) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to
process resource.", e);
+
+ synchronized (m_lock)
+ {
+ m_toBeDeleted.putAll(toBeDeleted);
}
- if (data == null) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Supplied
configuration is not conform the metatype xml specification.");
+
+ 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);
}
- // process resources
- String filter = null;
- Map optionalAttributes = data.getOptionalAttributes();
- if (optionalAttributes != null) {
- filter = (String)
optionalAttributes.get(AutoConfResourceProcessor.CONFIGURATION_ADMIN_FILTER_ATTRIBUTE);
+
+ 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 (!m_toBeInstalled.containsKey(name)) {
- m_toBeInstalled.put(name, new ArrayList());
+ if (!toBeInstalled.containsKey(name))
+ {
+ toBeInstalled.put(name, new ArrayList<AutoConfResource>());
}
- List designates = data.getDesignates();
- if (designates == null || designates.isEmpty()) {
+
+ 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 localOcds = data.getObjectClassDefinitions();
- if (localOcds == null) {
- localOcds = Collections.EMPTY_MAP;
- }
- Iterator i = designates.iterator();
- while (i.hasNext()) {
- Designate designate = (Designate) i.next();
-
+
+ Map<String, OCD> localOcds = data.getObjectClassDefinitions();
+ if (localOcds == null)
+ {
+ localOcds = Collections.emptyMap();
+ }
+
+ for (Designate designate : designates)
+ {
// check object
- if (designate.getObject() == null) {
+ DesignateObject objectDef = designate.getObject();
+ if (objectDef == null)
+ {
throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Designate Object child missing or invalid");
}
-
+
// check attributes
- if (designate.getObject().getAttributes() == null ||
designate.getObject().getAttributes().size() == 0) {
+ if (objectDef.getAttributes() == null ||
objectDef.getAttributes().isEmpty())
+ {
throw new ResourceProcessorException(CODE_OTHER_ERROR, "Object
Attributes child missing or invalid");
}
-
+
// check ocdRef
- String ocdRef = designate.getObject().getOcdRef();
- if (ocdRef == null || "".equals(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 = (OCD) localOcds.get(ocdRef);
+ 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) {
+ 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 = getProperties(designate, ocd);
- if (dict == null) {
+ Dictionary dict = MetaTypeUtil.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));
- }
- m_log.log(LogService.LOG_DEBUG, "processing " + name + " done");
- }
- public void dropped(String name) throws ResourceProcessorException {
- m_log.log(LogService.LOG_DEBUG, "dropped " + name);
- synchronized (m_lock) {
- if (m_session == null) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Can not process resource without a Deployment Session");
- }
- }
- try {
- List resources = m_persistencyManager.load(name);
- if (!m_toBeDeleted.containsKey(name)) {
- m_toBeDeleted.put(name, new ArrayList());
- }
- ((List) m_toBeDeleted.get(name)).addAll(resources);
- }
- catch (IOException ioe) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable
to drop resource: " + name, ioe);
- }
- m_log.log(LogService.LOG_DEBUG, "dropped " + name + " done");
- }
+ AutoConfResource resource = new AutoConfResource(name,
designate.getPid(), designate.getFactoryPid(), designate.getBundleLocation(),
designate.isMerge(), dict, filter);
+
+ toBeInstalled.get(name).add(resource);
+ }
- public void dropAllResources() throws ResourceProcessorException {
- m_log.log(LogService.LOG_DEBUG, "drop all resources");
- synchronized (m_lock) {
- if (m_session == null) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Can not drop all resources without a Deployment Session");
- }
- }
-
- File basedir = m_bc.getDataFile("");
- if (basedir != null && basedir.isDirectory()) {
- String[] files = basedir.list();
- for (int i = 0; i < files.length; i++) {
- dropped(files[i]);
- }
- }
- else {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable
to drop resources, data area is not accessible");
- }
- m_log.log(LogService.LOG_DEBUG, "drop all resources done");
- }
-
- private List m_configurationAdminTasks = new ArrayList();
- private List m_postCommitTasks = new ArrayList();
+ synchronized (m_lock)
+ {
+ m_toBeInstalled.putAll(toBeInstalled);
+ }
- public void prepare() throws ResourceProcessorException {
- m_log.log(LogService.LOG_DEBUG, "prepare");
- synchronized (m_lock) {
- if (m_session == null) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Can not process resource without a Deployment Session");
- }
- }
- try {
- m_log.log(LogService.LOG_DEBUG, "prepare delete");
- // delete dropped resources
- for (Iterator i = m_toBeDeleted.keySet().iterator();
i.hasNext();) {
- String name = (String) i.next();
- List resources = (List) m_toBeDeleted.get(name);
- for (Iterator j = resources.iterator(); j.hasNext();) {
- AutoConfResource resource = (AutoConfResource)
j.next();
- m_configurationAdminTasks.add(new
DropResourceTask(resource));
- }
- m_postCommitTasks.add(new DeleteResourceTask(name));
- }
-
- m_log.log(LogService.LOG_DEBUG, "prepare install/update");
- // install new/updated resources
- for (Iterator j = m_toBeInstalled.keySet().iterator();
j.hasNext();) {
- String name = (String) j.next();
- List 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 resources = (List) m_toBeInstalled.get(name);
- for (Iterator iterator = resources.iterator();
iterator.hasNext();) {
- AutoConfResource resource = (AutoConfResource)
iterator.next();
- m_configurationAdminTasks.add(new
InstallOrUpdateResourceTask(resource));
- }
- // 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();
- Configuration configuration = null;
- if (existingResource.isFactoryConfig()) {
- configuration =
m_configAdmin.getConfiguration(existingResource.getGeneratedPid(),
existingResource.getBundleLocation());
- } else {
- configuration =
m_configAdmin.getConfiguration(existingResource.getPid(),
existingResource.getBundleLocation());
- }
- configuration.delete();
- }
- m_postCommitTasks.add(new StoreResourceTask(name,
resources));
- }
- }
- catch (IOException ioe) {
- m_toBeInstalled.clear();
- throw new
ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Unable to
prepare for commit for resource", ioe);
- }
- m_log.log(LogService.LOG_DEBUG, "prepare done");
+ m_log.log(LogService.LOG_DEBUG, "processing " + name + " done");
}
- public synchronized void commit() {
- m_log.log(LogService.LOG_DEBUG, "commit");
+ public void rollback()
+ {
+ m_log.log(LogService.LOG_DEBUG, "rollback");
- Dictionary properties = new Properties();
- properties.put(EventConstants.EVENT_TOPIC,
org.apache.felix.deploymentadmin.Constants.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);
+ Map<String, List<AutoConfResource>> toBeInstalled;
+ synchronized (m_lock)
+ {
+ toBeInstalled = new HashMap<String,
List<AutoConfResource>>(m_toBeInstalled);
+ }
- m_log.log(LogService.LOG_DEBUG, "commit done");
- }
-
- public void addConfigurationAdmin(ServiceReference ref, ConfigurationAdmin
ca) {
- m_log.log(LogService.LOG_DEBUG, "found configuration admin " + ref);
- 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);
- }
+ for (Map.Entry<String, List<AutoConfResource>> entry :
toBeInstalled.entrySet())
+ {
+ for (AutoConfResource resource : entry.getValue())
+ {
+ String name = resource.getName();
+ try
+ {
+ dropped(name);
}
- if (filter == null || filter != null && filter.match(ref)) {
- task.run(m_persistencyManager, ca);
+ catch (ResourceProcessorException e)
+ {
+ m_log.log(LogService.LOG_ERROR, "Unable to roll back
resource '" + name + "', reason: " + e.getMessage() + ", caused by: " +
e.getCause().getMessage());
}
- }
- 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 postcommit() {
- m_log.log(LogService.LOG_DEBUG, "post commit");
- 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);
+ break;
}
}
+
endSession();
- m_log.log(LogService.LOG_DEBUG, "post commit done");
+
+ m_log.log(LogService.LOG_DEBUG, "rollback done");
}
- private void endSession() {
- if (m_component != null) {
- m_dm.remove(m_component);
- m_component = null;
+ /**
+ * 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_toBeInstalled.clear();
- m_toBeDeleted.clear();
- m_postCommitTasks.clear();
- m_configurationAdminTasks.clear();
- m_session = null;
+ m_persistencyManager = new PersistencyManager(root);
}
- public void rollback() {
- m_log.log(LogService.LOG_DEBUG, "rollback");
- Set keys = m_toBeInstalled.keySet();
- for (Iterator i = keys.iterator(); i.hasNext();) {
- List configs = (List) m_toBeInstalled.get(i.next());
- for (Iterator j = configs.iterator(); j.hasNext();) {
- AutoConfResource resource = (AutoConfResource) j.next();
- 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");
+ 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);
+ }
+ }
}
- public void cancel() {
- m_log.log(LogService.LOG_DEBUG, "cancel");
- rollback();
+ 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);
+ }
}
- /**
- * Determines the actual configuration data based on the specified
designate and object class definition
- *
- * @param designate The designate object containing the values for the
properties
- * @param ocd The object class definition
- * @return A dictionary containing data as described in the designate and
ocd objects, or <code>null</code> if the designate does not match it's
- * definition and the designate was marked as optional.
- * @throws ResourceProcessorException If the designate does not match the
ocd and the designate is not marked as optional.
- */
- private Dictionary getProperties(Designate designate,
ObjectClassDefinition ocd) throws ResourceProcessorException {
- Dictionary properties = new Hashtable();
- AttributeDefinition[] attributeDefs =
ocd.getAttributeDefinitions(ObjectClassDefinition.ALL);
- List attributes = designate.getObject().getAttributes();
-
- for (Iterator i = attributes.iterator(); i.hasNext();) {
- Attribute attribute = (Attribute) i.next();
-
- String adRef = attribute.getAdRef();
- boolean found = false;
- for(int j = 0; j < attributeDefs.length; j++) {
- AttributeDefinition ad = attributeDefs[j];
- if (adRef.equals(ad.getID())) {
- // found attribute definition
- Object value = getValue(attribute, ad);
- if (value == null) {
- if (designate.isOptional()) {
- properties = null;
- break;
- }
- else {
- throw new
ResourceProcessorException(CODE_OTHER_ERROR, "Could not match attribute to it's
definition: adref=" + adRef);
- }
- }
- properties.put(adRef, value);
- found = true;
- break;
- }
- }
- if (!found) {
- if (designate.isOptional()) {
- properties = null;
- break;
- } else {
- throw new
ResourceProcessorException(CODE_OTHER_ERROR, "Could not find attribute
definition: adref=" + adRef);
- }
- }
- }
+ 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;
+ }
- return properties;
+ 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;
}
/**
@@ -446,198 +554,112 @@ public class AutoConfResourceProcessor i
* @return
* @throws ResourceProcessorException
*/
- private ObjectClassDefinition getMetaTypeOCD(MetaData data, Designate
designate) throws ResourceProcessorException {
- ObjectClassDefinition ocd = null;
- String ocdRef = designate.getObject().getOcdRef();
- Bundle bundle = getBundle(designate.getBundleLocation(),
isFactoryConfig(designate));
- if (bundle != null) {
- MetaTypeInformation mti =
m_metaService.getMetaTypeInformation(bundle);
- if (mti != null) {
- String pid = isFactoryConfig(designate) ? 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
- if (ocdRef.equals(tempOcd.getID())) {
- ocd = tempOcd;
- }
- }
- catch (IllegalArgumentException iae) {
- // let null be returned
- }
- }
- }
- return ocd;
- }
-
- private boolean isFactoryConfig(Designate designate) {
- String factoryPid = designate.getFactoryPid();
- return (factoryPid != null && !"".equals(factoryPid));
- }
-
- 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)) {
- bundle =
m_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_bc.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 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;
}
- /**
- * Determines the value of an attribute based on an attribute definition
- *
- * @param attribute The attribute containing value(s)
- * @param ad The attribute definition
- * @return An <code>Object</code> reflecting what was specified in the
attribute and it's definition or <code>null</code> if the value did not match
it's definition.
- * @throws ResourceProcessorException in case we're unable to parse the
value of an attribute.
- */
- private Object getValue(Attribute attribute, AttributeDefinition ad)
throws ResourceProcessorException {
- if (attribute == null || ad == null ||
!attribute.getAdRef().equals(ad.getID())) {
- // wrong attribute or definition
- return null;
- }
- String[] content = attribute.getContent();
-
- // verify correct type of the value(s)
- int type = ad.getType();
- Object[] typedContent = null;
- try {
- for (int i = 0; i < content.length; i++) {
- String value = content[i];
- switch (type) {
- case AttributeDefinition.BOOLEAN:
- typedContent = (typedContent == null) ?
new Boolean[content.length] : typedContent;
- typedContent[i] =
Boolean.valueOf(value);
- break;
- case AttributeDefinition.BYTE:
- typedContent = (typedContent == null) ?
new Byte[content.length] : typedContent;
- typedContent[i] = Byte.valueOf(value);
- break;
- case AttributeDefinition.CHARACTER:
- typedContent = (typedContent == null) ?
new Character[content.length] : typedContent;
- char[] charArray = value.toCharArray();
- if (charArray.length == 1) {
- typedContent[i] = new
Character(charArray[0]);
- }
- else {
- throw new
ResourceProcessorException(CODE_OTHER_ERROR, "Unable to parse value for
definition: adref=" + ad.getID());
- }
- break;
- case AttributeDefinition.DOUBLE:
- typedContent = (typedContent == null) ?
new Double[content.length] : typedContent;
- typedContent[i] = Double.valueOf(value);
- break;
- case AttributeDefinition.FLOAT:
- typedContent = (typedContent == null) ?
new Float[content.length] : typedContent;
- typedContent[i] = Float.valueOf(value);
- break;
- case AttributeDefinition.INTEGER:
- typedContent = (typedContent == null) ?
new Integer[content.length] : typedContent;
- typedContent[i] =
Integer.valueOf(value);
- break;
- case AttributeDefinition.LONG:
- typedContent = (typedContent == null) ?
new Long[content.length] : typedContent;
- typedContent[i] = Long.valueOf(value);
- break;
- case AttributeDefinition.SHORT:
- typedContent = (typedContent == null) ?
new Short[content.length] : typedContent;
- typedContent[i] = Short.valueOf(value);
- break;
- case AttributeDefinition.STRING:
- typedContent = (typedContent == null) ?
new String[content.length] : typedContent;
- typedContent[i] = value;
- break;
- default:
- // unsupported type
- throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Unsupported value-type for definition: adref=" + ad.getID());
- }
- }
- }
- catch (NumberFormatException nfe) {
- throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to
parse value for definition: adref=" + ad.getID());
- }
-
- // verify cardinality of value(s)
- int cardinality = ad.getCardinality();
- Object result = null;
- if (cardinality == 0) {
- if (typedContent.length == 1) {
- result = typedContent[0];
- }
- else {
- result = null;
- }
- }
- else if (cardinality == Integer.MIN_VALUE) {
- result = new Vector(Arrays.asList(typedContent));
- }
- else if (cardinality == Integer.MAX_VALUE) {
- result = typedContent;
- }
- else if (cardinality < 0) {
- if (typedContent.length <= Math.abs(cardinality)) {
- result = new Vector(Arrays.asList(typedContent));
- }
- else {
- result = null;
- }
- }
- else if (cardinality > 0) {
- if (typedContent.length <= cardinality) {
- result = typedContent;
- }
- else {
- result = null;
- }
- }
- return result;
- }
-
- public void handleEvent(Event event) {
- // regardless of the outcome, we simply invoke postcommit
- postcommit();
+ 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 String getFilter();
+interface ConfigurationAdminTask
+{
+ public Filter getFilter();
+
public void run(PersistencyManager persistencyManager, ConfigurationAdmin
configAdmin) throws Exception;
}
-interface PostCommitTask {
- public void run(PersistencyManager manager) 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 {
+class DropResourceTask implements ConfigurationAdminTask
+{
private final AutoConfResource m_resource;
- public DropResourceTask(AutoConfResource resource) {
+ public DropResourceTask(AutoConfResource resource)
+ {
m_resource = resource;
}
-
- public String getFilter() {
+
+ public Filter getFilter()
+ {
return m_resource.getFilter();
}
- public void run(PersistencyManager persistencyManager, ConfigurationAdmin
configAdmin) throws Exception {
+ public void run(PersistencyManager persistencyManager, ConfigurationAdmin
configAdmin) throws Exception
+ {
String pid;
- if (m_resource.isFactoryConfig()) {
+ if (m_resource.isFactoryConfig())
+ {
pid = m_resource.getGeneratedPid();
}
- else {
+ else
+ {
pid = m_resource.getPid();
}
Configuration configuration = configAdmin.getConfiguration(pid,
m_resource.getBundleLocation());
@@ -645,69 +667,87 @@ class DropResourceTask implements Config
}
}
-class InstallOrUpdateResourceTask implements ConfigurationAdminTask {
+class InstallOrUpdateResourceTask implements ConfigurationAdminTask
+{
private final AutoConfResource m_resource;
- public InstallOrUpdateResourceTask(AutoConfResource resource) {
+ public InstallOrUpdateResourceTask(AutoConfResource resource)
+ {
m_resource = resource;
}
- public String getFilter() {
+ public Filter getFilter()
+ {
return m_resource.getFilter();
}
- public void run(PersistencyManager persistencyManager, ConfigurationAdmin
configAdmin) throws Exception {
+ 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 {
+ try
+ {
existingResources = persistencyManager.load(name);
}
- catch (IOException ioe) {
+ catch (IOException ioe)
+ {
throw new
ResourceProcessorException(ResourceProcessorException.CODE_PREPARE, "Unable to
read existing resources for resource " + name, ioe);
}
-
+
// update configuration
- if (m_resource.isFactoryConfig()) {
+ if (m_resource.isFactoryConfig())
+ {
// check if this is an factory config instance update
- for (Iterator i = existingResources.iterator(); i.hasNext();) {
+ for (Iterator i = existingResources.iterator(); i.hasNext();)
+ {
AutoConfResource existingResource = (AutoConfResource)
i.next();
- if (m_resource.equalsTargetConfiguration(existingResource)) {
+ if (m_resource.equalsTargetConfiguration(existingResource))
+ {
// existing instance found
configuration =
configAdmin.getConfiguration(existingResource.getGeneratedPid(),
bundleLocation);
existingResources.remove(existingResource);
break;
}
}
- if (configuration == null) {
+ 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();) {
+ else
+ {
+ for (Iterator i = existingResources.iterator(); i.hasNext();)
+ {
AutoConfResource existingResource = (AutoConfResource)
i.next();
- if (m_resource.getPid().equals(existingResource.getPid())) {
+ 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())) {
+ 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);
+ throw new
ResourceProcessorException(ResourceProcessorException.CODE_PREPARE,
+ "Existing configuration was bound to " +
configuration.getBundleLocation() + " instead of " + bundleLocation);
}
}
- if (m_resource.isMerge()) {
+ if (m_resource.isMerge())
+ {
Dictionary existingProperties = configuration.getProperties();
- if (existingProperties != null) {
+ if (existingProperties != null)
+ {
Enumeration keys = existingProperties.keys();
- while (keys.hasMoreElements()) {
+ while (keys.hasMoreElements())
+ {
Object key = keys.nextElement();
properties.put(key, existingProperties.get(key));
}
@@ -717,28 +757,24 @@ class InstallOrUpdateResourceTask implem
}
}
-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);
- }
+interface PostCommitTask
+{
+ public void run(PersistencyManager manager) throws Exception;
}
-class StoreResourceTask implements PostCommitTask {
+class StoreResourceTask implements PostCommitTask
+{
private final String m_name;
private final List m_resources;
- public StoreResourceTask(String name, List resources) {
+ public StoreResourceTask(String name, List resources)
+ {
m_name = name;
m_resources = resources;
}
- public void run(PersistencyManager manager) throws Exception {
+ public void run(PersistencyManager manager) throws Exception
+ {
manager.store(m_name, m_resources);
}
}
\ No newline at end of file
Added:
felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java
URL:
http://svn.apache.org/viewvc/felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java?rev=1724802&view=auto
==============================================================================
---
felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java
(added)
+++
felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java
Fri Jan 15 13:34:41 2016
@@ -0,0 +1,233 @@
+/*
+ * 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.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.felix.metatype.Attribute;
+import org.apache.felix.metatype.Designate;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessorException;
+import org.osgi.service.metatype.AttributeDefinition;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+/**
+ * Convenience methods to work with MetaType structures.
+ */
+public class MetaTypeUtil
+{
+ private MetaTypeUtil()
+ {
+ // Nop
+ }
+
+ /**
+ * Determines the actual configuration data based on the specified
designate and object class definition
+ *
+ * @param designate The designate object containing the values for the
properties
+ * @param ocd The object class definition
+ * @return A dictionary containing data as described in the designate and
ocd objects, or <code>null</code> if the designate does not match it's
+ * definition and the designate was marked as optional.
+ * @throws ResourceProcessorException If the designate does not match the
ocd and the designate is not marked as optional.
+ */
+ public static Dictionary getProperties(Designate designate,
ObjectClassDefinition ocd) throws ResourceProcessorException
+ {
+ Dictionary properties = new Hashtable();
+ AttributeDefinition[] attributeDefs =
ocd.getAttributeDefinitions(ObjectClassDefinition.ALL);
+
+ List<Attribute> attributes = designate.getObject().getAttributes();
+ for (Attribute attribute : attributes)
+ {
+ String adRef = attribute.getAdRef();
+ boolean found = false;
+ for (int j = 0; j < attributeDefs.length; j++)
+ {
+ AttributeDefinition ad = attributeDefs[j];
+ if (adRef.equals(ad.getID()))
+ {
+ // found attribute definition
+ Object value = getValue(attribute, ad);
+ if (value == null)
+ {
+ if (designate.isOptional())
+ {
+ properties = null;
+ break;
+ }
+ else
+ {
+ throw new
ResourceProcessorException(CODE_OTHER_ERROR, "Could not match attribute to it's
definition: adref=" + adRef);
+ }
+ }
+ properties.put(adRef, value);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ if (designate.isOptional())
+ {
+ properties = null;
+ break;
+ }
+ else
+ {
+ throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Could not find attribute definition: adref=" + adRef);
+ }
+ }
+ }
+
+ return properties;
+ }
+
+ /**
+ * Determines the value of an attribute based on an attribute definition
+ *
+ * @param attribute The attribute containing value(s)
+ * @param ad The attribute definition
+ * @return An <code>Object</code> reflecting what was specified in the
attribute and it's definition or <code>null</code> if the value did not match
it's definition.
+ * @throws ResourceProcessorException in case we're unable to parse the
value of an attribute.
+ */
+ private static Object getValue(Attribute attribute, AttributeDefinition
ad) throws ResourceProcessorException
+ {
+ if (attribute == null || ad == null ||
!attribute.getAdRef().equals(ad.getID()))
+ {
+ // wrong attribute or definition
+ return null;
+ }
+ String[] content = attribute.getContent();
+
+ // verify correct type of the value(s)
+ int type = ad.getType();
+ Object[] typedContent = null;
+ try
+ {
+ for (int i = 0; i < content.length; i++)
+ {
+ String value = content[i];
+ switch (type)
+ {
+ case AttributeDefinition.BOOLEAN:
+ typedContent = (typedContent == null) ? new
Boolean[content.length] : typedContent;
+ typedContent[i] = Boolean.valueOf(value);
+ break;
+ case AttributeDefinition.BYTE:
+ typedContent = (typedContent == null) ? new
Byte[content.length] : typedContent;
+ typedContent[i] = Byte.valueOf(value);
+ break;
+ case AttributeDefinition.CHARACTER:
+ typedContent = (typedContent == null) ? new
Character[content.length] : typedContent;
+ char[] charArray = value.toCharArray();
+ if (charArray.length == 1)
+ {
+ typedContent[i] = new Character(charArray[0]);
+ }
+ else
+ {
+ throw new
ResourceProcessorException(CODE_OTHER_ERROR, "Unable to parse value for
definition: adref=" + ad.getID());
+ }
+ break;
+ case AttributeDefinition.DOUBLE:
+ typedContent = (typedContent == null) ? new
Double[content.length] : typedContent;
+ typedContent[i] = Double.valueOf(value);
+ break;
+ case AttributeDefinition.FLOAT:
+ typedContent = (typedContent == null) ? new
Float[content.length] : typedContent;
+ typedContent[i] = Float.valueOf(value);
+ break;
+ case AttributeDefinition.INTEGER:
+ typedContent = (typedContent == null) ? new
Integer[content.length] : typedContent;
+ typedContent[i] = Integer.valueOf(value);
+ break;
+ case AttributeDefinition.LONG:
+ typedContent = (typedContent == null) ? new
Long[content.length] : typedContent;
+ typedContent[i] = Long.valueOf(value);
+ break;
+ case AttributeDefinition.SHORT:
+ typedContent = (typedContent == null) ? new
Short[content.length] : typedContent;
+ typedContent[i] = Short.valueOf(value);
+ break;
+ case AttributeDefinition.STRING:
+ typedContent = (typedContent == null) ? new
String[content.length] : typedContent;
+ typedContent[i] = value;
+ break;
+ default:
+ // unsupported type
+ throw new ResourceProcessorException(CODE_OTHER_ERROR,
"Unsupported value-type for definition: adref=" + ad.getID());
+ }
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ throw new ResourceProcessorException(CODE_OTHER_ERROR, "Unable to
parse value for definition: adref=" + ad.getID());
+ }
+
+ // verify cardinality of value(s)
+ int cardinality = ad.getCardinality();
+ Object result = null;
+ if (cardinality == 0)
+ {
+ if (typedContent.length == 1)
+ {
+ result = typedContent[0];
+ }
+ else
+ {
+ result = null;
+ }
+ }
+ else if (cardinality == Integer.MIN_VALUE)
+ {
+ result = new Vector(Arrays.asList(typedContent));
+ }
+ else if (cardinality == Integer.MAX_VALUE)
+ {
+ result = typedContent;
+ }
+ else if (cardinality < 0)
+ {
+ if (typedContent.length <= Math.abs(cardinality))
+ {
+ result = new Vector(Arrays.asList(typedContent));
+ }
+ else
+ {
+ result = null;
+ }
+ }
+ else if (cardinality > 0)
+ {
+ if (typedContent.length <= cardinality)
+ {
+ result = typedContent;
+ }
+ else
+ {
+ result = null;
+ }
+ }
+ return result;
+ }
+}
Propchange:
felix/trunk/deploymentadmin/autoconf/src/main/java/org/apache/felix/deployment/rp/autoconf/MetaTypeUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1724802&r1=1724801&r2=1724802&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
Fri Jan 15 13:34:41 2016
@@ -19,6 +19,7 @@
package org.apache.felix.deployment.rp.autoconf;
import java.io.File;
+import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -28,104 +29,155 @@ import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
-public class PersistencyManager {
-
- private final File m_root;
-
- public PersistencyManager(File root) {
- m_root = root;
- }
-
- /**
- * Stores a resource.
- *
- * @param name Name of the resource.
- * @param configs List of <code>AutoConfResource</code>s representing
the specified resource.
- * @throws IOException If the resource could not be stored.
- */
- public void store(String name, List configs) throws IOException {
- File targetDir = m_root;
- name = name.replace('/', File.separatorChar);
-
- if (name.startsWith(File.separator)) {
- name = name.substring(1);
- }
- int lastSeparator = name.lastIndexOf(File.separator);
- File target = null;
- if (lastSeparator != -1) {
- targetDir = new File(targetDir, name.substring(0,
lastSeparator));
- targetDir.mkdirs();
- }
- target = new File(targetDir, name.substring(lastSeparator + 1));
-
- ObjectOutputStream out = null;
- try {
- out = new ObjectOutputStream(new
FileOutputStream(target));
- out.writeObject(configs);
- }
- finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception e) {
- // not much we can do
- }
- }
- }
- }
-
- /**
- * Deletes a resource.
- *
- * @param name Name of the resource.
- * @throws IOException If the resource could not be deleted.
- */
- public void delete(String name) throws IOException {
- name = name.replace('/', File.separatorChar);
- File target = new File(m_root, name);
- if (!target.delete()) {
- throw new IOException("Unable to delete file: " +
target.getAbsolutePath());
- }
- while (target.getParentFile().list().length == 0 &&
!target.getParentFile().getAbsolutePath().equals(m_root.getAbsolutePath())) {
- target = target.getParentFile();
- target.delete();
- }
- }
-
- /**
- * Loads a stored resource.
- *
- * @param name Name of the resource.
- * @return List of <code>AutoConfResource</code>s representing the
specified resource, if the resource is unknown an empty list is returned.
- * @throws IOException If the resource could not be properly read.
- */
- public List load(String name) throws IOException {
- name = name.replace('/', File.separatorChar);
- List resources = new ArrayList();
- File resourcesFile = new File(m_root, name);
- if (resourcesFile.exists()) {
- ObjectInputStream in = null;
- try {
- in = new ObjectInputStream(new
FileInputStream(resourcesFile));
- resources = (List) in.readObject();
- }
- catch (FileNotFoundException fnfe) {
- throw new IOException("Resource does not exist:
" + name);
- }
- catch (ClassNotFoundException cnfe) {
- throw new IOException("Unable to recreate
persisted object from file: " + name);
- }
- finally {
- if (in != null) {
- try {
- in.close();
- }
- catch (Exception e) {
- // not much we can do
- }
- }
- }
- }
- return resources;
- }
+public class PersistencyManager
+{
+ private static final FileFilter FILES_ONLY_FILTER = new FileFilter()
+ {
+ public boolean accept(File pathname)
+ {
+ return pathname.isFile();
+ }
+ };
+
+ private final File m_root;
+
+ public PersistencyManager(File root)
+ {
+ m_root = root;
+ }
+
+ /**
+ * Deletes a resource.
+ *
+ * @param name Name of the resource.
+ * @throws IOException If the resource could not be deleted.
+ */
+ public void delete(String name) throws IOException
+ {
+ name = name.replace('/', File.separatorChar);
+ File target = new File(m_root, name);
+ if (target.exists() && !target.delete())
+ {
+ throw new IOException("Unable to delete file: " +
target.getAbsolutePath());
+ }
+ while (target.getParentFile().list().length == 0 &&
!target.getParentFile().getAbsolutePath().equals(m_root.getAbsolutePath()))
+ {
+ target = target.getParentFile();
+ target.delete();
+ }
+ }
+
+ /**
+ * Returns the names of all persisted resources.
+ * @return a list of resource names, never <code>null</code>.
+ */
+ public List<String> getResourceNames()
+ {
+ List<String> result = new ArrayList<String>();
+
+ File[] list = m_root.listFiles(FILES_ONLY_FILTER);
+ if (list != null && list.length > 0)
+ {
+ for (File resource : list)
+ {
+ result.add(resource.getName());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Loads a stored resource.
+ *
+ * @param name Name of the resource.
+ * @return List of <code>AutoConfResource</code>s representing the
specified resource, if the resource is unknown an empty list is returned.
+ * @throws IOException If the resource could not be properly read.
+ */
+ public List<AutoConfResource> load(String name) throws IOException
+ {
+ List<AutoConfResource> resources = new ArrayList<AutoConfResource>();
+ name = name.replace('/', File.separatorChar);
+ File resourcesFile = new File(m_root, name);
+ if (!resourcesFile.exists())
+ {
+ return resources;
+ }
+
+ ObjectInputStream in = null;
+ try
+ {
+ in = new ObjectInputStream(new FileInputStream(resourcesFile));
+ resources = (List<AutoConfResource>) in.readObject();
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new IOException("Resource does not exist: " + name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IOException("Unable to recreate persisted object from
file: " + name);
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (Exception e)
+ {
+ // not much we can do
+ }
+ }
+ }
+ return resources;
+ }
+
+ /**
+ * Stores a resource.
+ *
+ * @param name Name of the resource.
+ * @param configs List of <code>AutoConfResource</code>s representing the
specified resource.
+ * @throws IOException If the resource could not be stored.
+ */
+ public void store(String name, List<AutoConfResource> configs) throws
IOException
+ {
+ File targetDir = m_root;
+ name = name.replace('/', File.separatorChar);
+
+ if (name.startsWith(File.separator))
+ {
+ name = name.substring(1);
+ }
+ int lastSeparator = name.lastIndexOf(File.separator);
+ File target = null;
+ if (lastSeparator != -1)
+ {
+ targetDir = new File(targetDir, name.substring(0, lastSeparator));
+ targetDir.mkdirs();
+ }
+ target = new File(targetDir, name.substring(lastSeparator + 1));
+
+ ObjectOutputStream out = null;
+ try
+ {
+ out = new ObjectOutputStream(new FileOutputStream(target));
+ out.writeObject(configs);
+ }
+ finally
+ {
+ if (out != null)
+ {
+ try
+ {
+ out.close();
+ }
+ catch (Exception e)
+ {
+ // not much we can do
+ }
+ }
+ }
+ }
}