You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2007/12/21 20:28:13 UTC
svn commit: r606280 [4/6] - in /felix/sandbox/clement/ipojo: composite/
composite/src/ composite/src/main/ composite/src/main/java/
composite/src/main/java/org/ composite/src/main/java/org/apache/
composite/src/main/java/org/apache/felix/ composite/src...
Modified: felix/sandbox/clement/ipojo/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/pom.xml?rev=606280&r1=606279&r2=606280&view=diff
==============================================================================
--- felix/sandbox/clement/ipojo/core/pom.xml (original)
+++ felix/sandbox/clement/ipojo/core/pom.xml Fri Dec 21 11:28:07 2007
@@ -45,6 +45,7 @@
<Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
<Bundle-Description> iPOJO </Bundle-Description>
<Bundle-Activator>org.apache.felix.ipojo.Extender</Bundle-Activator>
+ <IPOJO-Extension>component:org.apache.felix.ipojo.ComponentFactory, handler:org.apache.felix.ipojo.HandlerFactory</IPOJO-Extension>
<Import-Package>
org.osgi.framework,
org.osgi.service.cm,
@@ -52,17 +53,11 @@
!org.objectweb.asm*
</Import-Package>
<Private-Package>
- org.apache.felix.ipojo.manipulation,
- org.apache.felix.ipojo.composite.architecture,
- org.apache.felix.ipojo.composite.service*,
- org.apache.felix.ipojo.composite.instance,
org.apache.felix.ipojo.handlers.architecture,
org.apache.felix.ipojo.handlers.configuration,
- org.apache.felix.ipojo.handlers.dependency.nullable,
org.apache.felix.ipojo.handlers.lifecycle.callback,
org.apache.felix.ipojo.handlers.lifecycle.controller,
- !org.objectweb.asm.xml*,
- org.objectweb.asm*;-split-package:=merge-first
+ org.objectweb.asm
</Private-Package>
<Export-Package>
org.apache.felix.ipojo; version="0.7.6",
@@ -72,7 +67,7 @@
org.apache.felix.ipojo.util; version="0.7.6",
org.apache.felix.ipojo.handlers.dependency; version="0.7.6",
org.apache.felix.ipojo.handlers.providedservice; version="0.7.6",
- org.apache.felix.ipojo.composite; version="0.7.6",
+ org.apache.felix.ipojo.context; version="0.7.6",
org.osgi.service.cm,
org.osgi.service.log
</Export-Package>
Added: felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java (added)
+++ felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,807 @@
+/*
+ * 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.ipojo;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * This class abstracts iPOJO factories.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class AbstractFactory implements Factory, ManagedServiceFactory {
+
+ /**
+ * List of the managed instance name. This list is shared by all factories.
+ */
+ protected static List m_instancesName = new ArrayList();
+
+ /**
+ * Component-Type description exposed by the factory service.
+ */
+ protected ComponentTypeDescription m_componentDesc;
+
+ /**
+ * List of the managed instance managers. The key of this map is the
+ * name (i.e. instance names) of the created instance
+ */
+ protected Map m_componentInstances = new HashMap();
+
+ /**
+ * Component Type provided by this factory.
+ */
+ protected Element m_componentMetadata;
+
+ /**
+ * The bundle context reference.
+ */
+ protected BundleContext m_context = null;
+
+ /**
+ * Factory Name. Could be the component class name if the
+ * factory name is not set.
+ */
+ protected String m_factoryName;
+
+ /**
+ * List of required handler.
+ */
+ protected List m_requiredHandlers = new ArrayList();
+
+ /**
+ * List of listeners.
+ */
+ protected List m_listeners = new ArrayList(2);
+
+ /**
+ * Logger for the factory (and all component instance).
+ */
+ protected Logger m_logger;
+
+ /**
+ * Is the factory public (expose as a service).
+ */
+ protected boolean m_isPublic;
+
+ /**
+ * Service Registration of this factory (Factory & ManagedServiceFactory).
+ */
+ protected ServiceRegistration m_sr;
+
+ /**
+ * Factory state.
+ */
+ protected int m_state = Factory.INVALID;
+
+ /**
+ * Index used to generate instance name if not set.
+ */
+ private long m_index = 0;
+
+ /**
+ * Flag indicating if this factory has already a computed description or not.
+ */
+ private boolean m_described;
+
+ /**
+ * Constructor.
+ * @param bc : bundle context of the bundle containing the factory.
+ * @param cm : description of the component type.
+ */
+ public AbstractFactory(BundleContext bc, Element cm) {
+ m_context = bc;
+ m_componentMetadata = cm;
+ m_factoryName = getFactoryName();
+ String fac = cm.getAttribute("factory");
+ m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
+ m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
+ m_requiredHandlers = getRequiredHandlerList();
+ }
+
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new ComponentTypeDescription(this);
+ }
+
+ /**
+ * Add a factory listener.
+ * @param l : the factory listener to add.
+ * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+ */
+ public void addFactoryStateListener(FactoryStateListener l) {
+ synchronized (m_listeners) {
+ m_listeners.add(l);
+ }
+ }
+
+ /**
+ * Get the logger used by instances of he current factory.
+ * @return the factory logger.
+ */
+ public Logger getLogger() {
+ return m_logger;
+ }
+
+ /**
+ * Compute the factory name.
+ * @return the factory name.
+ */
+ public abstract String getFactoryName();
+
+ /**
+ * Compute the required handler list.
+ * @return the required handler list
+ */
+ public abstract List getRequiredHandlerList();
+
+ /**
+ * Create an instance.
+ * @param configuration : instance configuration
+ * @param context : ipojo context to use
+ * @param handlers : handler array to use
+ * @return the new component instance.
+ * @throws ConfigurationException : occurs when the instance creation failed during the configuration process.
+ */
+ public abstract ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException;
+
+
+ /**
+ * Create an instance. The given configuration needs to contain the 'name'
+ * property.
+ * @param configuration : configuration of the created instance.
+ * @return the created component instance.
+ * @throws UnacceptableConfiguration : occurs if the given configuration is
+ * not consistent with the component type of this factory.
+ * @throws MissingHandlerException : occurs if an handler is unavailable when the instance is created.
+ * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
+ * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ */
+ public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+ return createComponentInstance(configuration, null);
+ }
+
+ /**
+ * Create an instance. The given configuration needs to contain the 'name'
+ * property.
+ * @param configuration : configuration of the created instance.
+ * @param serviceContext : the service context to push for this instance.
+ * @return the created component instance.
+ * @throws UnacceptableConfiguration : occurs if the given configuration is
+ * not consistent with the component type of this factory.
+ * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
+ * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
+ * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ */
+ public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+ if (configuration == null) {
+ configuration = new Properties();
+ }
+
+ try {
+ checkAcceptability(configuration);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
+ }
+
+
+ String n = null;
+ if (configuration.get("name") != null) {
+ n = (String) configuration.get("name");
+ if (m_instancesName.contains(n)) {
+ throw new UnacceptableConfiguration("Name already used : " + n);
+ }
+ } else {
+ n = generateName();
+ configuration.put("name", n);
+ }
+ m_instancesName.add(n);
+
+ IPojoContext context = null;
+ if (serviceContext == null) {
+ context = new IPojoContext(m_context);
+ } else {
+ context = new IPojoContext(m_context, serviceContext);
+ }
+
+ HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
+ for (int i = 0; i < handlers.length; i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ handlers[i] = getHandler(hi, serviceContext);
+ }
+
+ ComponentInstance instance = createInstance(configuration, context, handlers);
+
+ m_componentInstances.put(n, instance);
+
+ return instance;
+ }
+
+ public BundleContext getBundleContext() {
+ return m_context;
+ }
+
+ /**
+ * Get the factory class name.
+ * @return the factory classname.
+ * @see org.apache.felix.ipojo.Factory#getClassName()
+ */
+ public abstract String getClassName();
+
+ /**
+ * Get the component type description.
+ * @return the component type description object. Null if not already computed.
+ */
+ public ComponentTypeDescription getComponentDescription() {
+ return m_componentDesc;
+ }
+
+ /**
+ * Get the component type description (Element-Attribute form).
+ * @return the component type description.
+ * @see org.apache.felix.ipojo.Factory#getDescription()
+ */
+ public Element getDescription() {
+ if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
+ return m_componentDesc.getDescription();
+ }
+
+ /**
+ * Compute the list of missing handlers.
+ * @return list of missing handlers.
+ * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
+ */
+ public List getMissingHandlers() {
+ List l = new ArrayList();
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ if (hi.getReference() == null) {
+ l.add(hi.getFullName());
+ }
+ }
+ return l;
+ }
+
+ public String getName() {
+ return m_factoryName;
+ }
+
+ /**
+ * Get the list of required handlers.
+ * @return list of required handlers.
+ * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
+ */
+ public List getRequiredHandlers() {
+ List l = new ArrayList();
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ l.add(hi.getFullName());
+ }
+ return l;
+ }
+
+ public int getState() {
+ return m_state;
+ }
+
+ /**
+ * Check if the configuration is acceptable.
+ * @param conf : the configuration to test.
+ * @return true if the configuration is acceptable.
+ * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)
+ */
+ public boolean isAcceptable(Dictionary conf) {
+ if (m_state == Factory.INVALID) {
+ return false;
+ }
+
+ List props = m_componentDesc.getRequiredProperties();
+ for (int i = 0; i < props.size(); i++) {
+ // Failed if the props has no default value and the configuration does not push a value
+ if (conf.get(props.get(i)) == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check if the configuration is acceptable.
+ * @param conf : the configuration to test.
+ * @throws UnacceptableConfiguration occurs if the configuration is unacceptable.
+ * @throws MissingHandlerException occurs if an handler is missing.
+ */
+ public void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
+ if (m_state == Factory.INVALID) {
+ throw new MissingHandlerException(getMissingHandlers());
+ }
+
+ List props = m_componentDesc.getRequiredProperties();
+ for (int i = 0; i < props.size(); i++) {
+ // Failed if the props has no default value and the configuration does not push a value
+ if (conf.get(props.get(i)) == null) {
+ throw new UnacceptableConfiguration("The property " + props.get(i) + " is missing");
+ }
+ }
+ }
+
+ /**
+ * Reconfigure an existing instance.
+ * @param properties : the new configuration to push.
+ * @throws UnacceptableConfiguration : occurs if the new configuration is
+ * not consistent with the component type.
+ * @throws MissingHandlerException : occurs if the current factory is not valid.
+ * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
+ */
+ public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
+ if (properties == null || properties.get("name") == null) {
+ throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
+ }
+ String name = (String) properties.get("name");
+ ComponentInstance cm = (ComponentInstance) m_componentInstances.get(name);
+
+ if (cm == null) {
+ return; // The instance does not exist.
+ } else {
+ checkAcceptability(properties); // Test if the configuration is acceptable
+ cm.reconfigure(properties); // re-configure the component
+ }
+ }
+
+ /**
+ * Remove a factory listener.
+ * @param l : the factory listener to remove.
+ * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+ */
+ public void removeFactoryStateListener(FactoryStateListener l) {
+ synchronized (m_listeners) {
+ m_listeners.remove(l);
+ }
+ }
+
+ /**
+ * Stopping method.
+ * This method is call when the factory is stopping.
+ */
+ public abstract void stopping();
+
+ /**
+ * Stop all the instance managers.
+ */
+ public synchronized void stop() {
+ if (m_sr != null) {
+ m_sr.unregister();
+ m_sr = null;
+ }
+
+ stopping();
+
+ if (m_state == VALID) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ }
+ }
+ m_state = INVALID;
+
+
+ // Dispose created instances.
+ Set col = m_componentInstances.keySet();
+ String[] keys = (String[]) col.toArray(new String[col.size()]);
+ for (int i = 0; i < keys.length; i++) {
+ ComponentInstance ci = (ComponentInstance) m_componentInstances.get(keys[i]);
+ if (ci.getState() != ComponentInstance.DISPOSED) {
+ ci.dispose();
+ }
+ }
+
+ // Release each handler
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ ((RequiredHandler) m_requiredHandlers.get(i)).unRef();
+ }
+
+ m_described = false;
+ m_componentDesc = null;
+ }
+
+ /**
+ * Starting method.
+ * This method is called when the factory is starting.
+ */
+ public abstract void starting();
+
+ /**
+ * Start the factory.
+ */
+ public synchronized void start() {
+ if (m_described) { // Already started.
+ return;
+ }
+
+ m_componentDesc = getComponentTypeDescription();
+
+ starting();
+
+ try {
+ computeFactoryState();
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+ stop();
+ return;
+ }
+
+ if (m_isPublic) {
+ // Exposition of the factory service
+ m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, m_componentDesc.getPropertiesToPublish());
+ }
+ }
+
+ /**
+ * Create of update an instance.
+ * @param in : name of the instance
+ * @param properties : configuration of the instance
+ * @throws org.osgi.service.cm.ConfigurationException : if the configuration is not consistent
+ * for this component type
+ * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
+ * java.util.Dictionary)
+ */
+ public synchronized void updated(String in, Dictionary properties) throws org.osgi.service.cm.ConfigurationException {
+ final InstanceManager cm = (InstanceManager) m_componentInstances.get(in);
+ if (cm == null) {
+ try {
+ properties.put("name", in); // Add the name in the configuration
+ createComponentInstance(properties);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ }
+ } else {
+ try {
+ properties.put("name", in); // Add the name in the configuration
+ reconfigure(properties); // re-configure the component
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
+ throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Delete an instance.
+ * @param in : name of the instance to delete
+ * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+ */
+ public synchronized void deleted(String in) {
+ m_instancesName.remove(in);
+ ComponentInstance cm = (ComponentInstance) m_componentInstances.remove(in);
+ if (cm != null) {
+ cm.dispose();
+ }
+ }
+
+ /**
+ * Callback called by instance when disposed.
+ * @param ci : the destroyed instance
+ */
+ public void disposed(ComponentInstance ci) {
+ String name = ci.getInstanceName();
+ m_instancesName.remove(name);
+ m_componentInstances.remove(name);
+ }
+
+ /**
+ * Compute the component type description.
+ * The factory must be valid when calling this method.
+ * @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
+ */
+ protected void computeDescription() throws org.apache.felix.ipojo.ConfigurationException {
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ HandlerManager hm = getHandler(hi, null);
+ Handler ch = hm.getHandler();
+ try {
+ ch.setLogger(getLogger());
+ ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
+ ((Pojo) ch).getComponentInstance().dispose();
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ ((Pojo) ch).getComponentInstance().dispose();
+ throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
+ }
+ }
+ }
+
+ /**
+ * Compute factory state.
+ * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the component type cannot be initialize.
+ */
+ protected void computeFactoryState() throws org.apache.felix.ipojo.ConfigurationException {
+ boolean isValid = true;
+ for (int i = 0; isValid && i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ isValid = hi.getReference() != null;
+ }
+
+ if (isValid) {
+ if (m_state == INVALID) {
+
+ if (!m_described) {
+ computeDescription();
+ m_described = true;
+ }
+
+ m_state = VALID;
+ if (m_sr != null) {
+ m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
+ }
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
+ }
+ return;
+ }
+ } else {
+ if (m_state == VALID) {
+ m_state = INVALID;
+
+ // Notify listeners.
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+ }
+
+ // Dispose created instances.
+ Set col = m_componentInstances.keySet();
+ String[] keys = (String[]) col.toArray(new String[col.size()]);
+ for (int i = 0; i < keys.length; i++) {
+ ComponentInstance ci = (ComponentInstance) m_componentInstances.get(keys[i]);
+ if (ci.getState() != ComponentInstance.DISPOSED) {
+ ci.dispose();
+ }
+ m_instancesName.remove(ci.getInstanceName());
+ }
+
+ m_componentInstances.clear();
+
+ if (m_sr != null) {
+ m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
+ }
+
+ return;
+ }
+ }
+ }
+
+ /**
+ * Check if the given handler identifier and the service reference can match.
+ * @param hi : the handler identifier.
+ * @param ref : the service reference.
+ * @return true if the service reference can fulfill the handler requirement
+ */
+ protected boolean match(RequiredHandler hi, ServiceReference ref) {
+ String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
+ String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
+ if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
+ return name.equals(hi.getName()) && hi.getNamespace() == null;
+ }
+ return name.equals(hi.getName()) && ns.equals(hi.getNamespace());
+ }
+
+ /**
+ * Return the handler object for the given required handler.
+ * The handler is instantiated in the given service context.
+ * @param hi : handler to create.
+ * @param sc : service context in which create the handler (instance context).
+ * @return the Handler object.
+ */
+ protected HandlerManager getHandler(RequiredHandler hi, ServiceContext sc) {
+ try {
+ return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
+ stop();
+ return null;
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
+ stop();
+ return null;
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
+ stop();
+ return null;
+ }
+ }
+
+
+ /**
+ * Helping method generating a new unique name.
+ * @return an non already used name
+ */
+ protected synchronized String generateName() {
+ String name = m_factoryName + "-" + m_index;
+ while (m_instancesName.contains(name)) {
+ m_index = m_index + 1;
+ name = m_factoryName + "-" + m_index;
+ }
+ return name;
+ }
+
+ /**
+ * Structure storing required handlers.
+ */
+ protected class RequiredHandler implements Comparable {
+ /**
+ * Factory to create this handler.
+ */
+ private HandlerFactory m_factory;
+
+ /**
+ * Handler name.
+ */
+ private String m_name;
+
+ /**
+ * Handler start level.
+ */
+ private int m_level = Integer.MAX_VALUE;
+
+ /**
+ * Handler namespace.
+ */
+ private String m_namespace;
+
+ /**
+ * Service Reference of the handler factory.
+ */
+ private ServiceReference m_reference;
+
+ /**
+ * Constructor.
+ * @param n : handler name.
+ * @param ns : handler namespace.
+ */
+ public RequiredHandler(String n, String ns) {
+ m_name = n;
+ m_namespace = ns;
+ }
+
+ /**
+ * Equals method.
+ * Two handlers are equals if they have same name and namespace or they share the same service reference.
+ * @param o : object to compare to the current object.
+ * @return : true if the two compared object are equals
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object o) {
+ if (m_namespace == null) {
+ return ((RequiredHandler) o).m_name.equalsIgnoreCase(m_name) && ((RequiredHandler) o).m_namespace == null;
+ } else {
+ return ((RequiredHandler) o).m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(((RequiredHandler) o).m_namespace);
+ }
+ }
+
+ /**
+ * Get the factory object used for this handler.
+ * The object is get when used for the first time.
+ * @return the factory object.
+ */
+ public HandlerFactory getFactory() {
+ if (m_reference == null) {
+ return null;
+ }
+ if (m_factory == null) {
+ m_factory = (HandlerFactory) m_context.getService(getReference());
+ }
+ return m_factory;
+ }
+
+ /**
+ * Get the handler full name (namespace:name).
+ * @return the handler full name
+ */
+ public String getFullName() {
+ if (m_namespace == null) {
+ return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
+ } else {
+ return m_namespace + ":" + m_name;
+ }
+ }
+
+ public String getName() {
+ return m_name;
+ }
+
+ public String getNamespace() {
+ return m_namespace;
+ }
+
+ public ServiceReference getReference() {
+ return m_reference;
+ }
+
+ public int getLevel() {
+ return m_level;
+ }
+
+ /**
+ * Release the reference of the used factory.
+ */
+ public void unRef() {
+ if (m_reference != null) {
+ m_context.ungetService(m_reference);
+ m_factory = null;
+ m_reference = null;
+ }
+ }
+
+ /**
+ * Set the service reference.
+ * If the new service reference is null, it unget the used factory (if already get).
+ * @param ref : new service reference.
+ */
+ public void setReference(ServiceReference ref) {
+ m_reference = ref;
+ Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
+ if (p != null) {
+ m_level = p.intValue();
+ }
+ }
+
+ /**
+ * Start level Comparison.
+ * This method is used to sort the handler array.
+ * @param o : object on which compare.
+ * @return -1, 0, +1 according to the comparison of their start level.
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object o) {
+ if (o instanceof RequiredHandler) {
+ RequiredHandler hi = (RequiredHandler) o;
+ if (this.m_level == hi.m_level) {
+ return 0;
+ } else if (this.m_level < hi.m_level) {
+ return -1;
+ } else {
+ return +1;
+ }
+ }
+ return 0;
+ }
+ }
+
+
+
+}
Modified: felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java?rev=606280&r1=606279&r2=606280&view=diff
==============================================================================
--- felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java (original)
+++ felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java Fri Dec 21 11:28:07 2007
@@ -21,27 +21,21 @@
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.Logger;
import org.apache.felix.ipojo.util.Tracker;
import org.apache.felix.ipojo.util.TrackerCustomizer;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
/**
* The component factory manages component instance objects. This management
@@ -50,59 +44,7 @@
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class ComponentFactory implements Factory, ManagedServiceFactory, TrackerCustomizer {
-
- /**
- * List of the managed instance name. This list is shared by all factories.
- */
- protected static List m_instancesName = new ArrayList();
-
- /**
- * Component-Type description exposed by the factory service.
- */
- protected ComponentDescription m_componentDesc;
-
- /**
- * List of the managed instance managers. The key of this map is the
- * name (i.e. instance names) of the created instance
- */
- protected Map m_componentInstances = new HashMap();
-
- /**
- * Component Type provided by this factory.
- */
- protected Element m_componentMetadata;
-
- /**
- * The bundle context reference.
- */
- protected BundleContext m_context = null;
-
- /**
- * Factory Name. Could be the component class name if the
- * factory name is not set.
- */
- protected String m_factoryName;
-
- /**
- * List of required handler.
- */
- protected List m_handlerIdentifiers = new ArrayList();
-
- /**
- * List of listeners.
- */
- protected List m_listeners = new ArrayList(5);
-
- /**
- * Logger for the factory (and all component instance).
- */
- protected Logger m_logger;
-
- /**
- * Factory state.
- */
- protected int m_state = Factory.INVALID;
+public class ComponentFactory extends AbstractFactory implements TrackerCustomizer {
/**
* Tracker used to track required handler factories.
@@ -110,11 +52,6 @@
protected Tracker m_tracker;
/**
- * Is the factory public (expose as a service).
- */
- protected boolean m_isPublic;
-
- /**
* Class loader to delegate loading.
*/
private FactoryClassloader m_classLoader = null;
@@ -130,16 +67,6 @@
private String m_componentClassName = null;
/**
- * Index used to generate instance name if not set.
- */
- private long m_index = 0;
-
- /**
- * Service Registration of this factory (Factory & ManagedServiceFactory).
- */
- private ServiceRegistration m_sr;
-
- /**
* Create a instance manager factory. The class is given in parameter. The
* component type is not a composite.
* @param bc : bundle context
@@ -157,72 +84,15 @@
* @param cm : metadata of the component to create
*/
public ComponentFactory(BundleContext bc, Element cm) {
- m_context = bc;
- m_componentMetadata = cm;
+ super(bc, cm);
if (! check(cm)) {
return;
- }
-
- computeFactoryName();
- m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
-
- String fac = cm.getAttribute("factory");
- m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
-
- computeRequiredHandlers();
-
- }
-
- /**
- * Add a factory listener.
- * @param l : the factory listener to add
- * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void addFactoryStateListener(FactoryStateListener l) {
- synchronized (m_listeners) {
- m_listeners.add(l);
- }
- // TODO do we need to notify the actual state of the factory to the new listener ?
- }
-
- /**
- * A new handler factory is detected.
- * Test if the factory can be used or not.
- * @param reference : the new service reference.
- * @return true if the given factory reference match with a required handler.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference reference) {
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.m_reference == null && match(hi, reference)) {
- int oldP = hi.m_level;
- hi.setReference(reference);
- // If the priority has changed, sort the list.
- if (oldP != hi.m_level) {
- Collections.sort(m_handlerIdentifiers);
- }
- return true;
- }
- }
- return false;
+ }
}
- /**
- * A matching service has been added to the tracker, we can no compute the factory state.
- * @param reference : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference reference) {
- if (m_state == INVALID) {
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- }
- }
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new PrimitiveTypeDescription(this);
}
/**
@@ -239,83 +109,29 @@
} else {
return true;
}
- }
-
- /**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs if an handler is unavailable when the instance is created.
- * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
- */
- public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- return createComponentInstance(configuration, null);
+ }
+
+ public String getClassName() {
+ return m_componentClassName;
}
/**
- * Create an instance. The given configuration needs to contain the 'name'
- * property.
- * @param configuration : configuration of the created instance.
- * @param serviceContext : the service context to push for this instance.
- * @return the created component instance.
- * @throws UnacceptableConfiguration : occurs if the given configuration is
- * not consistent with the component type of this factory.
- * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
- * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
- * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+ * Create a primitive instance.
+ * @param configuration : instance configuration
+ * @param context : service context.
+ * @param handlers : handler to use
+ * @return the created instance
+ * @throws org.apache.felix.ipojo.ConfigurationException : if the configuration process failed.
+ * @see org.apache.felix.ipojo.AbstractFactory#createInstance(java.util.Dictionary, org.apache.felix.ipojo.IPojoContext, org.apache.felix.ipojo.HandlerManager[])
*/
- public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- if (configuration == null) {
- configuration = new Properties();
- }
-
- try {
- checkAcceptability(configuration);
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
- }
-
-
- String n = null;
- if (configuration.get("name") != null) {
- n = (String) configuration.get("name");
- if (m_instancesName.contains(n)) {
- throw new UnacceptableConfiguration("Name already used : " + n);
- }
- } else {
- n = generateName();
- configuration.put("name", n);
- }
- m_instancesName.add(n);
-
- BundleContext context = null;
- if (serviceContext == null) {
- context = new IPojoContext(m_context);
- } else {
- context = new IPojoContext(m_context, serviceContext);
- }
-
- List handlers = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- handlers.add(getHandlerInstance(hi, serviceContext));
- }
-
- InstanceManager instance = new InstanceManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[m_handlerIdentifiers.size()]));
+ public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws org.apache.felix.ipojo.ConfigurationException {
+ InstanceManager instance = new InstanceManager(this, context, handlers);
try {
instance.configure(m_componentMetadata, configuration);
+ instance.start();
} catch (org.apache.felix.ipojo.ConfigurationException e) {
throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
}
-
- m_componentInstances.put(n, instance);
- instance.start();
-
return instance;
}
@@ -334,95 +150,6 @@
}
/**
- * Delete an instance.
- * @param in : name of the instance to delete
- * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
- */
- public synchronized void deleted(String in) {
- m_instancesName.remove(in);
- final ComponentInstance cm = (ComponentInstance) m_componentInstances.remove(in);
- if (cm == null) {
- return; // do nothing, the component does not exist !
- } else {
- cm.dispose();
- }
- }
-
- /**
- * Get the component type description.
- * @return the component type description object. Null if not already computed.
- */
- public ComponentDescription getComponentDescription() {
- return m_componentDesc;
- }
-
- /**
- * Get the component type description attached to this factory.
- * @return : the component type description
- * @see org.apache.felix.ipojo.Factory#getDescription()
- */
- public Element getDescription() {
- if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
- return m_componentDesc.getDescription();
- }
-
- /**
- * Get the logger used by instances of he current factory.
- * @return the factory logger.
- */
- public Logger getLogger() {
- return m_logger;
- }
-
- /**
- * Get the list of missing handlers.
- * @return the list of missing handlers (namespace:name)
- * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
- */
- public List getMissingHandlers() {
- List l = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (hi.m_reference == null) {
- l.add(hi.getFullName());
- }
- }
- return l;
- }
-
- /**
- * Get the name of this factory.
- *
- * @return the name of this factory
- * @see org.apache.felix.ipojo.Factory#getName()
- */
- public String getName() {
- return m_factoryName;
- }
-
- /**
- * Get the list of required handlers.
- * @return the list of required handlers (namespace:name)
- * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
- */
- public List getRequiredHandlers() {
- List l = new ArrayList();
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- l.add(hi.getFullName());
- }
- return l;
- }
-
- public String getClassName() {
- return m_componentClassName;
- }
-
- public int getState() {
- return m_state;
- }
-
- /**
* Return the URL of a resource.
* @param resName : resource name
* @return the URL of the resource
@@ -432,24 +159,6 @@
}
/**
- * Check if the given configuration is acceptable as a component instance
- * configuration. This method checks that if all the configurable properties
- * have a value.
- * @param conf : the configuration to check
- * @return true when the configuration seems to be acceptable
- */
- public boolean isAcceptable(Dictionary conf) {
- try {
- checkAcceptability(conf);
- } catch (UnacceptableConfiguration e) {
- return false;
- } catch (MissingHandlerException e) {
- return false;
- }
- return true;
- }
-
- /**
* Load a class.
* @param className : name of the class to load
* @return the resulting Class object
@@ -472,85 +181,14 @@
return m_context.getBundle().loadClass(className);
}
- /**
- * A used handler factory is modified.
- * @param reference : the service reference
- * @param service : the Factory object (if already get)
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference reference, Object service) {
- // Noting to do
- }
-
- /**
- * Reconfigure an existing instance.
- * @param properties : the new configuration to push.
- * @throws UnacceptableConfiguration : occurs if the new configuration is
- * not consistent with the component type.
- * @throws MissingHandlerException : occurs if the current factory is not valid.
- * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
- */
- public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
- if (properties == null || properties.get("name") == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
- }
- final String name = (String) properties.get("name");
- InstanceManager cm = (InstanceManager) m_componentInstances.get(name);
-
- if (cm == null) {
- return; // The instance does not exist.
- } else {
- checkAcceptability(properties); // Test if the configuration is acceptable
- cm.reconfigure(properties); // re-configure the component
- }
- }
-
- /**
- * A used factory disappears.
- * @param reference : service reference.
- * @param service : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference reference, Object service) {
- // Look for the implied reference and invalid the handler identifier
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- if (reference.equals(hi.getReference())) {
- hi.unRef(); // This method will unget the service.
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- }
- return; // The factory can be used only once.
- }
- }
- }
-
- /**
- * Remove a factory listener.
- * @param l : the factory listener to remove
- * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
- */
- public void removeFactoryStateListener(FactoryStateListener l) {
- synchronized (m_listeners) {
- m_listeners.remove(l);
- }
- }
/**
* Start the factory.
*/
- public synchronized void start() {
- if (m_componentDesc != null) { // Already started.
- return;
- }
-
- if (m_handlerIdentifiers.size() != 0) {
+ public synchronized void starting() {
+ if (m_requiredHandlers.size() != 0) {
try {
- String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
- + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
+ String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
+ "(factory.state=1)"
+ ")";
m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
@@ -561,485 +199,134 @@
return;
}
}
-
- try {
- computeFactoryState();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
- stop();
- return;
- }
-
- if (m_isPublic) {
- // Exposition of the factory service
- m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, getProperties());
- }
}
/**
* Stop all the instance managers.
*/
- public synchronized void stop() {
- if (m_sr != null) {
- m_sr.unregister();
- m_sr = null;
- }
-
- if (m_tracker != null) {
- m_tracker.close();
- }
-
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.getInstanceName());
- }
-
- m_componentInstances.clear();
-
- // Release each handler
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
- }
-
- m_tracker = null;
- m_componentDesc = null;
+ public synchronized void stopping() {
m_classLoader = null;
m_clazz = null;
- m_state = INVALID;
}
- /**
- * Create of update an instance.
- * @param in : name of the instance
- * @param properties : configuration of the instance
- * @throws ConfigurationException : if the configuration is not consistent
- * for this component type
- * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
- * java.util.Dictionary)
- */
- public synchronized void updated(String in, Dictionary properties) throws ConfigurationException {
- final InstanceManager cm = (InstanceManager) m_componentInstances.get(in);
- if (cm == null) {
- try {
- properties.put("name", in); // Add the name in the configuration
- createComponentInstance(properties);
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- }
- } else {
- try {
- properties.put("name", in); // Add the name in the configuration
- reconfigure(properties); // re-configure the component
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
- throw new ConfigurationException(properties.toString(), e.getMessage());
- }
- }
- }
-
- /**
- * Test is a configuration is acceptable for the factory.
- * @param conf : the configuration to test.
- * @throws UnacceptableConfiguration : the configuration is not acceptable.
- * @throws MissingHandlerException : the factory is not valid.
- */
- protected void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
- if (m_state == Factory.INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
- List props = m_componentDesc.getRequiredProperties();
- for (int i = 0; i < props.size(); i++) {
- // Failed if the props has no default value and the configuration does not push a value
- if (conf.get(props.get(i)) == null) {
- throw new UnacceptableConfiguration("The configuration does not contains the \"" + props.get(i) + "\" property");
- }
- }
- }
-
- /**
- * Compute the component type description.
- * The factory must be valid when calling this method.
- * @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
- */
- protected void computeDescription() throws org.apache.felix.ipojo.ConfigurationException {
- m_componentDesc = new ComponentDescription(this);
-
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- HandlerManager hm = getHandlerInstance(hi, null);
- Handler ch = hm.getHandler();
- try {
- ch.setLogger(getLogger());
- ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
- ((Pojo) ch).getComponentInstance().dispose();
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- ((Pojo) ch).getComponentInstance().dispose();
- throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
- }
- }
- }
/**
* Compute the factory name.
+ * @return the factory name.
*/
- protected void computeFactoryName() {
- m_factoryName = m_componentMetadata.getAttribute("name");
- if (m_factoryName == null) { // No factory name, try with factory attribute
- m_factoryName = m_componentMetadata.getAttribute("factory");
- if (m_factoryName == null || m_factoryName.equalsIgnoreCase("true") || m_factoryName.equalsIgnoreCase("false")) { // Avoid boolean case
- m_factoryName = m_componentMetadata.getAttribute("className");
- }
- }
- }
-
- /**
- * Compute factory state.
- * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the component type cannot be initialize.
- */
- protected void computeFactoryState() throws org.apache.felix.ipojo.ConfigurationException {
- boolean isValid = true;
- for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- isValid = hi.m_reference != null;
- }
-
- if (isValid) {
- if (m_state == INVALID) {
-
- if (m_componentDesc == null) {
- computeDescription();
- }
-
- m_state = VALID;
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
- }
- return;
- }
- } else {
- if (m_state == VALID) {
- m_state = INVALID;
-
- // Notify listeners.
- for (int i = 0; i < m_listeners.size(); i++) {
- ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
- }
-
- // Dispose created instances.
- final Collection col = m_componentInstances.values();
- final Iterator it = col.iterator();
- while (it.hasNext()) {
- InstanceManager ci = (InstanceManager) it.next();
- if (ci.getState() != ComponentInstance.DISPOSED) {
- ci.kill();
- }
- m_instancesName.remove(ci.m_name);
- }
-
- m_componentInstances.clear();
-
- // Update service properties TODO : really useful ?
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
-
- return;
+ public String getFactoryName() {
+ String s = m_componentMetadata.getAttribute("name");
+ if (s == null) { // No factory name, try with factory attribute
+ s = m_componentMetadata.getAttribute("factory");
+ if (s == null || s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false")) { // Avoid boolean case
+ s = m_componentMetadata.getAttribute("className");
}
}
+ return s;
}
/**
* Compute required handlers.
+ * @return the required handler list.
*/
- protected void computeRequiredHandlers() {
+ public List getRequiredHandlerList() {
+ List list = new ArrayList();
Element[] elems = m_componentMetadata.getElements();
for (int i = 0; i < elems.length; i++) {
Element current = elems[i];
if (current.getName().equals("manipulation")) { continue; }
- HandlerIdentifier hi = new HandlerIdentifier(current.getName(), current.getNameSpace());
- if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
+ RequiredHandler hi = new RequiredHandler(current.getName(), current.getNameSpace());
+ if (! list.contains(hi)) { list.add(hi); }
}
// Add architecture if architecture != 'false'
- HandlerIdentifier hi = new HandlerIdentifier("architecture", null);
+ RequiredHandler hi = new RequiredHandler("architecture", null);
String arch = m_componentMetadata.getAttribute("architecture");
if (arch == null || arch.equalsIgnoreCase("true")) {
- m_handlerIdentifiers.add(hi);
+ list.add(hi);
}
// Add lifecycle callback if immediate = true
- HandlerIdentifier hi2 = new HandlerIdentifier("callback", null);
+ RequiredHandler hi2 = new RequiredHandler("callback", null);
String imm = m_componentMetadata.getAttribute("immediate");
- if (! m_handlerIdentifiers.contains(hi2) && imm != null && imm.equalsIgnoreCase("true")) {
- m_handlerIdentifiers.add(hi2);
+ if (! list.contains(hi2) && imm != null && imm.equalsIgnoreCase("true")) {
+ list.add(hi2);
}
- }
-
- /**
- * Callback called by instance when disposed.
- * @param ci : the destroyed instance
- */
- protected void disposed(ComponentInstance ci) {
- String name = ci.getInstanceName();
- m_instancesName.remove(name);
- m_componentInstances.remove(name);
+
+ return list;
}
/**
- * Generate an instance name.
- * @return an non already used name
+ * A new handler factory is detected.
+ * Test if the factory can be used or not.
+ * @param reference : the new service reference.
+ * @return true if the given factory reference match with a required handler.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
*/
- protected synchronized String generateName() {
- String name = m_factoryName + "-" + m_index;
- while (m_instancesName.contains(name)) {
- m_index = m_index + 1;
- name = m_factoryName + "-" + m_index;
+ public boolean addingService(ServiceReference reference) {
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ if (hi.getReference() == null && match(hi, reference)) {
+ int oldP = hi.getLevel();
+ hi.setReference(reference);
+ // If the priority has changed, sort the list.
+ if (oldP != hi.getLevel()) {
+ Collections.sort(m_requiredHandlers);
+ }
+ return true;
+ }
}
- return name;
+ return false;
}
/**
- * Return the bundle context.
- * @return the Bundle Context.
- */
- public BundleContext getBundleContext() {
- return m_context;
- }
-
- /**
- * Get the implementation class of the component type.
- *
- * @return the name of the component-type implementation class.
- */
- protected String getComponentClassName() {
- return m_componentClassName;
- }
-
- /**
- * Compute factory properties.
- * @return the properties.
+ * A matching service has been added to the tracker, we can no compute the factory state.
+ * @param reference : added reference.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
*/
- protected Properties getProperties() {
- final Properties props = new Properties();
-
- props.put("component.class", m_componentClassName);
-
- props.put("factory.name", m_factoryName);
- props.put(Constants.SERVICE_PID, m_factoryName); // Service PID is required for the integration in the configuration admin.
-
- if (m_componentDesc != null) {
- props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
- props.put("component.properties", m_componentDesc.getProperties());
- props.put("component.description", m_componentDesc);
+ public void addedService(ServiceReference reference) {
+ if (m_state == INVALID) {
+ try {
+ computeFactoryState();
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+ stop();
+ }
}
-
- // Add factory state
- props.put("factory.state", "" + m_state);
-
- return props;
}
/**
- * Check if the given handler identifier and the service reference can match.
- * @param hi : the handler identifier.
- * @param ref : the service reference.
- * @return true if the service reference can fulfill the handler requirement
- */
- protected boolean match(HandlerIdentifier hi, ServiceReference ref) {
- String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
- String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
- if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
- return name.equals(hi.m_name) && hi.m_namespace == null;
- }
- return name.equals(hi.m_name) && ns.equals(hi.m_namespace);
- }
-
- /**
- * Return an handler object.
- * @param hi : handler to create.
- * @param sc : service context in which create the handler (instance context).
- * @return the Handler object.
+ * A used factory disappears.
+ * @param reference : service reference.
+ * @param service : factory object.
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
*/
- private HandlerManager getHandlerInstance(HandlerIdentifier hi, ServiceContext sc) {
- try {
- return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
- stop();
- return null;
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
- stop();
- return null;
- } catch (org.apache.felix.ipojo.ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
- stop();
- return null;
+ public void removedService(ServiceReference reference, Object service) {
+ // Look for the implied reference and invalid the handler identifier
+ for (int i = 0; i < m_requiredHandlers.size(); i++) {
+ RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+ if (reference.equals(hi.getReference())) {
+ hi.unRef(); // This method will unget the service.
+ try {
+ computeFactoryState();
+ } catch (org.apache.felix.ipojo.ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+ stop();
+ }
+ return; // The factory can be used only once.
+ }
}
}
-
+
/**
- * Structure storing required handlers.
+ * A used handler factory is modified.
+ * @param reference : the service reference
+ * @param service : the Factory object (if already get)
+ * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
*/
- class HandlerIdentifier implements Comparable {
- /**
- * Factory to create this handler.
- */
- private HandlerFactory m_factory;
-
- /**
- * Handler name.
- */
- private String m_name;
-
- /**
- * Handler start level.
- */
- private int m_level = Integer.MAX_VALUE;
-
- /**
- * Handler namespace.
- */
- private String m_namespace;
-
- /**
- * Service Reference of the handler factory.
- */
- private ServiceReference m_reference;
-
- /**
- * Constructor.
- * @param n : handler name.
- * @param ns : handler namespace.
- */
- public HandlerIdentifier(String n, String ns) {
- m_name = n;
- m_namespace = ns;
- }
-
- /**
- * Equals method.
- * Two handlers are equals if they have same name and namespace or they share the same service reference.
- * @param o : object to compare to the current object.
- * @return : true if the two compared object are equals
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object o) {
- if (m_namespace == null) {
- return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && ((HandlerIdentifier) o).m_namespace == null;
- } else {
- return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(((HandlerIdentifier) o).m_namespace);
- }
- }
-
- /**
- * Get the factory object used for this handler.
- * The object is get when used for the first time.
- * @return the factory object.
- */
- public HandlerFactory getFactory() {
- if (m_reference == null) {
- return null;
- }
- if (m_factory == null) {
- m_factory = (HandlerFactory) m_tracker.getService(getReference());
- }
- return m_factory;
- }
-
- /**
- * Get the handler full name (namespace:name).
- * @return the handler full name
- */
- public String getFullName() {
- if (m_namespace == null) {
- return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
- } else {
- return m_namespace + ":" + m_name;
- }
- }
-
- public String getName() {
- return m_name;
- }
-
- public String getNamespace() {
- return m_namespace;
- }
-
- public ServiceReference getReference() {
- return m_reference;
- }
-
- public int getLevel() {
- return m_level;
- }
-
- /**
- * Release the reference of the used factory.
- */
- public void unRef() {
- if (m_reference != null) {
- m_tracker.ungetService(m_reference);
- m_factory = null;
- m_reference = null;
- }
- }
-
- /**
- * Set the service reference.
- * If the new service reference is null, it unget the used factory (if already get).
- * @param ref : new service reference.
- */
- public void setReference(ServiceReference ref) {
- m_reference = ref;
- Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
- if (p != null) {
- m_level = p.intValue();
- }
- }
-
- /**
- * Start level Comparison.
- * This method is used to sort the handler array.
- * @param o : object on which compare.
- * @return -1, 0, +1 according to the comparison of their start level.
- * @see java.lang.Comparable#compareTo(java.lang.Object)
- */
- public int compareTo(Object o) {
- if (o instanceof HandlerIdentifier) {
- HandlerIdentifier hi = (HandlerIdentifier) o;
- if (this.m_level == hi.m_level) {
- return 0;
- } else if (this.m_level < hi.m_level) {
- return -1;
- } else {
- return +1;
- }
- }
- return 0;
- }
+ public void modifiedService(ServiceReference reference, Object service) {
+ // Noting to do
}
-
/**
* FactoryClassloader.
*/
@@ -1086,6 +373,42 @@
*/
protected Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
return m_context.getBundle().loadClass(name);
+ }
+ }
+
+ private final class PrimitiveTypeDescription extends ComponentTypeDescription {
+
+ /**
+ * Constructor.
+ * @param factory : the represented factory.
+ */
+ private PrimitiveTypeDescription(Factory factory) {
+ super(factory);
+ }
+
+ /**
+ * Compute the properties to publish :
+ * component.class contains the pojo class name.
+ * @return the dictionary of properties to publish
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+ */
+ public Dictionary getPropertiesToPublish() {
+ Dictionary dict = super.getPropertiesToPublish();
+ if (m_componentClassName != null) {
+ dict.put("component.class", m_componentClassName);
+ }
+ return dict;
+ }
+
+ /**
+ * Add the "implementation-class" attribute to the type description.
+ * @return the component type description.
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription()
+ */
+ public Element getDescription() {
+ Element elem = super.getDescription();
+ elem.addAttribute(new Attribute("Implementation-Class", m_componentClassName));
+ return elem;
}
}
}