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 2008/03/28 16:35:29 UTC
svn commit: r642265 [3/11] - in /felix/trunk/ipojo: ./ annotations/ ant/
ant/src/main/java/org/apache/felix/ipojo/task/ arch/
arch/src/main/java/org/apache/felix/ipojo/arch/ arch/src/main/resources/
composite/ composite/src/ composite/src/main/ composi...
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java Fri Mar 28 08:33:36 2008
@@ -29,11 +29,6 @@
* Serialization Id.
*/
private static final long serialVersionUID = 1L;
-
- /**
- * Message.
- */
- private String m_message;
/**
* Component Type on which the error occurs.
@@ -46,8 +41,8 @@
* @param typ : component type
*/
ConfigurationException(String mes, String typ) {
+ super(mes);
m_type = typ;
- m_message = mes;
}
/**
@@ -55,7 +50,7 @@
* @param mes : message
*/
public ConfigurationException(String mes) {
- m_message = mes;
+ super(mes);
}
/**
@@ -64,10 +59,10 @@
* @see java.lang.Throwable#getMessage()
*/
public String getMessage() {
- if (m_type != null) {
- return "The configuration is not correct for the type " + m_type + " : " + m_message;
+ if (m_type == null) {
+ return super.getMessage();
} else {
- return m_message;
+ return "The configuration is not correct for the type " + m_type + " : " + super.getMessage();
}
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java Fri Mar 28 08:33:36 2008
@@ -19,20 +19,27 @@
package org.apache.felix.ipojo;
import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.ManifestMetadataParser;
import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
-import org.osgi.service.log.LogService;
/**
* iPOJO Extender.
@@ -42,39 +49,52 @@
public class Extender implements SynchronousBundleListener, BundleActivator {
/**
- * iPOJO Manifest header.
+ * iPOJO Component Type and Instance declaration header.
*/
private static final String IPOJO_HEADER = "iPOJO-Components";
-
+
+ /**
+ * iPOJO Extension declaration header.
+ */
+ private static final String IPOJO_EXTENSION = "IPOJO-Extension";
+
+ /**
+ * iPOJO Extender logger.
+ */
+ private Logger m_logger;
+
/**
* iPOJO Bundle Context.
*/
private BundleContext m_context;
-
+
+ /**
+ * Declared instance manager.
+ */
+ private InstanceCreator m_creator;
+
/**
- * Dictionary of [BundleId, Factory List].
+ * iPOJO Bundle.
*/
- private Dictionary m_components;
-
+ private Bundle m_bundle;
+
/**
- * Dictionary of [BundleId, Instance Creator].
+ * List of factory types.
*/
- private Dictionary m_creators;
-
+ private List m_factoryTypes = new ArrayList();
+
/**
- * iPOJO Bundle Id.
+ * List of unbound types.
*/
- private long m_bundleId;
-
+ private final List m_unboundTypes = new ArrayList();
+
/**
* Bundle Listener Notification.
* @param event : the bundle event.
* @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
*/
public synchronized void bundleChanged(BundleEvent event) {
- if (event.getBundle().getBundleId() == m_bundleId) {
- return;
- }
+ if (event.getBundle() == m_bundle) { return; }
switch (event.getType()) {
case BundleEvent.STARTED:
@@ -83,7 +103,7 @@
case BundleEvent.STOPPING:
closeManagementFor(event.getBundle());
break;
- default:
+ default:
break;
}
@@ -94,42 +114,109 @@
* @param bundle : the bundle.
*/
private void closeManagementFor(Bundle bundle) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
- InstanceCreator creator = (InstanceCreator) m_creators.get(bundle);
- if (cfs == null && creator == null) { return; }
- for (int i = 0; cfs != null && i < cfs.length; i++) {
- ComponentFactory factory = cfs[i];
- factory.stop();
- }
- if (creator != null) { creator.stop(); }
-
- m_components.remove(bundle);
- m_creators.remove(bundle);
-
+ List toRemove = new ArrayList();
+ for (int k = 0; k < m_factoryTypes.size(); k++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+ // Delete instances declared in the leaving bundle.
+ m_creator.removeInstancesFromBundle(bundle.getBundleId());
+
+ // Look for component type created from this bundle.
+ if (mft.m_created != null) {
+ List cfs = (List) mft.m_created.remove(bundle);
+ for (int i = 0; cfs != null && i < cfs.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) cfs.get(i);
+ m_creator.removeFactory(factory);
+ factory.stop();
+ }
+ }
+
+ // If the leaving bundle has declared mft : destroy all created factories.
+ if (mft.m_bundle == bundle) {
+ if (mft.m_created != null) {
+ Iterator iterator = mft.m_created.keySet().iterator();
+ while (iterator.hasNext()) {
+ Bundle key = (Bundle) iterator.next();
+ List list = (List) mft.m_created.get(key);
+ for (int i = 0; i < list.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) list.get(i);
+ factory.stop();
+ m_unboundTypes.add(new UnboundComponentType(mft.m_type, factory.m_componentMetadata, factory.getBundleContext()
+ .getBundle()));
+ }
+ }
+ }
+ toRemove.add(mft);
+ }
+ }
+
+ for (int i = 0; i < toRemove.size(); i++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) toRemove.get(i);
+ m_logger.log(Logger.WARNING, "The factory type available: " + mft.m_type + " is no more available");
+ mft.m_bundle = null;
+ mft.m_clazz = null;
+ mft.m_created = null;
+ mft.m_type = null;
+ m_factoryTypes.remove(mft);
+ }
}
/**
- * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true.
+ * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true.
* @param bundle : the bundle to check.
*/
private void startManagementFor(Bundle bundle) {
- // Check bundle
Dictionary dict = bundle.getHeaders();
+ // Check for abstract factory type
+ String typeHeader = (String) dict.get(IPOJO_EXTENSION);
+ if (typeHeader != null) {
+ parseAbstractFactoryType(bundle, typeHeader);
+ }
+
+ // Check bundle
String header = (String) dict.get(IPOJO_HEADER);
- if (header == null) {
- return;
- } else {
+ if (header != null) {
try {
parse(bundle, header);
} catch (IOException e) {
- err("An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+ m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
} catch (ParseException e) {
- err("A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+ m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
}
}
-
}
-
+
+ /**
+ * Parse an IPOJO-Extension manifest header.
+ * @param bundle : bundle containing the header.
+ * @param header : header to parse.
+ */
+ private void parseAbstractFactoryType(Bundle bundle, String header) {
+ String[] arr = ParseUtils.split(header, ",");
+ for (int i = 0; arr != null && i < arr.length; i++) {
+ String[] arr2 = ParseUtils.split(arr[i], ":");
+ String type = arr2[0];
+ Class clazz;
+ try {
+ clazz = bundle.loadClass(arr2[1]);
+ } catch (ClassNotFoundException e) {
+ m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);
+ return;
+ }
+ ManagedAbstractFactoryType mft = new ManagedAbstractFactoryType(clazz, type, bundle);
+ m_factoryTypes.add(mft);
+ m_logger.log(Logger.WARNING, "New factory type available: " + type);
+
+ for (int j = m_unboundTypes.size() - 1; j >= 0; j--) {
+ UnboundComponentType unbound = (UnboundComponentType) m_unboundTypes.get(j);
+ if (unbound.m_type.equals(type)) {
+ createAbstractFactory(unbound.m_bundle, unbound.m_description);
+ m_unboundTypes.remove(unbound);
+ }
+ }
+ }
+ }
+
/**
* Parse the internal metadata (from the manifest (in the iPOJO-Components property)).
* @param bundle : the owner bundle.
@@ -140,35 +227,40 @@
private void parse(Bundle bundle, String components) throws IOException, ParseException {
ManifestMetadataParser parser = new ManifestMetadataParser();
parser.parseHeader(components);
-
- Element[] componentsMetadata = parser.getComponentsMetadata(); // Get the component type declaration
- for (int i = 0; i < componentsMetadata.length; i++) { addComponentFactory(bundle, componentsMetadata[i]); }
-
- start(bundle, parser.getInstances());
+
+ Element[] metadata = parser.getComponentsMetadata(); // Get the component type declaration
+ for (int i = 0; i < metadata.length; i++) {
+ createAbstractFactory(bundle, metadata[i]);
+ }
+
+ Dictionary[] instances = parser.getInstances();
+ for (int i = 0; instances != null && i < instances.length; i++) {
+ m_creator.addInstance(instances[i], bundle.getBundleId());
+ }
}
/**
* iPOJO Starting method.
- * @param bc : iPOJO bundle context.
- * @throws Exception : the start method failed.
+ * @param context : iPOJO bundle context.
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
- public void start(BundleContext bc) throws Exception {
- m_context = bc;
- m_bundleId = bc.getBundle().getBundleId();
- m_components = new Hashtable();
- m_creators = new Hashtable();
+ public void start(BundleContext context) {
+ m_context = context;
+ m_bundle = context.getBundle();
+ m_creator = new InstanceCreator(context);
+
+ m_logger = new Logger(m_context, "IPOJO Extender");
// Begin by initializing core handlers
- startManagementFor(bc.getBundle());
+ startManagementFor(m_bundle);
synchronized (this) {
// listen to any changes in bundles.
m_context.addBundleListener(this);
// compute already started bundles.
- for (int i = 0; i < bc.getBundles().length; i++) {
- if (bc.getBundles()[i].getState() == Bundle.ACTIVE) {
- startManagementFor(bc.getBundles()[i]);
+ for (int i = 0; i < context.getBundles().length; i++) {
+ if (context.getBundles()[i].getState() == Bundle.ACTIVE) {
+ startManagementFor(context.getBundles()[i]);
}
}
}
@@ -176,96 +268,238 @@
/**
* Stop the iPOJO Management.
- * @param bc : bundle context.
- * @throws Exception : the stop method failed.
+ * @param context : bundle context.
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
- public void stop(BundleContext bc) throws Exception {
+ public void stop(BundleContext context) {
m_context.removeBundleListener(this);
- Enumeration e = m_components.keys();
- while (e.hasMoreElements()) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(e.nextElement());
- for (int i = 0; i < cfs.length; i++) {
- cfs[i].stop();
- }
- }
- m_components = null;
- Enumeration e2 = m_creators.keys();
- while (e2.hasMoreElements()) {
- InstanceCreator creator = (InstanceCreator) m_creators.remove(e2.nextElement());
- creator.stop();
+
+ for (int k = 0; k < m_factoryTypes.size(); k++) {
+ ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+ if (mft.m_created != null) {
+ Iterator iterator = mft.m_created.keySet().iterator();
+ while (iterator.hasNext()) {
+ Bundle key = (Bundle) iterator.next();
+ List list = (List) mft.m_created.get(key);
+ for (int i = 0; i < list.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) list.get(i);
+ m_creator.removeFactory(factory);
+ factory.dispose();
+ }
+ }
+ }
}
- m_creators = null;
+
+ m_factoryTypes = null;
+ m_creator = null;
}
-
+
/**
* Add a component factory to the factory list.
- * @param cm : the new component metadata.
+ * @param metadata : the new component metadata.
* @param bundle : the bundle.
*/
- private void addComponentFactory(Bundle bundle, Element cm) {
- ComponentFactory factory = null;
- if (cm.getName().equalsIgnoreCase("component")) {
- factory = new ComponentFactory(bundle.getBundleContext(), cm);
- } else if (cm.getName().equalsIgnoreCase("composite")) {
- factory = new CompositeFactory(bundle.getBundleContext(), cm);
- } else if (cm.getName().equalsIgnoreCase("handler")) {
- factory = new HandlerFactory(bundle.getBundleContext(), cm);
- } else {
- err("Not recognized element type : " + cm.getName(), null);
- }
-
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-
- // If the factory array is not empty add the new factory at the end
- if (cfs != null && cfs.length != 0) {
- ComponentFactory[] newFactory = new ComponentFactory[cfs.length + 1];
- System.arraycopy(cfs, 0, newFactory, 0, cfs.length);
- newFactory[cfs.length] = factory;
- cfs = newFactory;
- m_components.put(bundle, cfs);
- } else {
- m_components.put(bundle, new ComponentFactory[] {factory}); // Else create an array of size one with the new Factory
- }
- }
-
- /**
- * Start the management of factories and create instances.
- * @param bundle : the bundle.
- * @param confs : the instances to create.
- */
- private void start(Bundle bundle, Dictionary[] confs) {
- ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-
- // Start the factories
- if (cfs != null) {
- for (int j = 0; j < cfs.length; j++) {
- cfs[j].start();
+ private void createAbstractFactory(Bundle bundle, Element metadata) {
+ ManagedAbstractFactoryType factoryType = null;
+ // First, look for factory-type (component, handler, composite ...)
+ for (int i = 0; i < m_factoryTypes.size(); i++) {
+ ManagedAbstractFactoryType type = (ManagedAbstractFactoryType) m_factoryTypes.get(i);
+ if (type.m_type.equals(metadata.getName())) {
+ factoryType = type;
+ break;
+ }
+ }
+
+ // If not found, return. It will wait for a new component type factory.
+ if (factoryType == null) {
+ m_logger.log(Logger.WARNING, "Type of component not yet recognized : " + metadata.getName());
+ m_unboundTypes.add(new UnboundComponentType(metadata.getName(), metadata, bundle));
+ return;
+ }
+
+ // Once found, we invoke the AbstractFactory constructor to create the component factory.
+ Class clazz = factoryType.m_clazz;
+ try {
+ // Look for the constructor, and invoke it.
+ Constructor cst = clazz.getConstructor(new Class[] { BundleContext.class, Element.class });
+ IPojoFactory factory = (IPojoFactory) cst.newInstance(new Object[] { getBundleContext(bundle), metadata });
+
+ // Add the created factory in the m_createdFactories map.
+ if (factoryType.m_created == null) {
+ factoryType.m_created = new HashMap();
+ List list = new ArrayList();
+ list.add(factory);
+ factoryType.m_created.put(bundle, list);
+ } else {
+ List list = (List) factoryType.m_created.get(bundle);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(factory);
+ factoryType.m_created.put(bundle, list);
+ } else {
+ list.add(factory);
+ }
+ }
+
+ // Start the created factory.
+ factory.start();
+ // Then add the factory to the instance creator.
+ m_creator.addFactory(factory);
+
+ } catch (SecurityException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (NoSuchMethodException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName() + ": the given class constructor cannot be found");
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (InstantiationException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+ } catch (InvocationTargetException e) {
+ m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e.getTargetException());
+ }
+ }
+
+ /**
+ * Structure storing an iPOJO extension.
+ */
+ private final class ManagedAbstractFactoryType {
+ /**
+ * TYpe (i.e.) name of the extension.
+ */
+ String m_type;
+
+ /**
+ * Abstract Factory class.
+ */
+ Class m_clazz;
+
+ /**
+ * Bundle object containing the declaration of the extension.
+ */
+ Bundle m_bundle;
+
+ /**
+ * Factories created by this extension.
+ */
+ private Map m_created;
+
+ /**
+ * Constructor.
+ * @param factory : abstract factory class.
+ * @param type : name of the extension.
+ * @param bundle : bundle declaring the extension.
+ */
+ protected ManagedAbstractFactoryType(Class factory, String type, Bundle bundle) {
+ m_bundle = bundle;
+ m_clazz = factory;
+ m_type = type;
+ }
+ }
+
+ /**
+ * Structure storing unbound component type declaration.
+ * Unbound means that there is no extension able to manage it.
+ */
+ private final class UnboundComponentType {
+ /**
+ * Component type description.
+ */
+ private final Element m_description;
+
+ /**
+ * Bundle declaring this type.
+ */
+ private final Bundle m_bundle;
+
+ /**
+ * Required extension name.
+ */
+ private final String m_type;
+
+ /**
+ * Constructor.
+ * @param description : description of the component type.
+ * @param bundle : bundle declaring this type.
+ * @param type : required extension name.
+ */
+ protected UnboundComponentType(String type, Element description, Bundle bundle) {
+ m_type = type;
+ m_description = description;
+ m_bundle = bundle;
+ }
+ }
+
+ /**
+ * Compute the bundle context from the bundle class by introspection.
+ * @param bundle : bundle.
+ * @return the bundle context object or null if not found.
+ */
+ public BundleContext getBundleContext(Bundle bundle) {
+ if (bundle == null) { return null; }
+
+ // getBundleContext (OSGi 4.1)
+ Method meth = null;
+ try {
+ meth = bundle.getClass().getMethod("getBundleContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try the Equinox method
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try the Equinox method
+ }
+
+ // try Equinox getContext if not found.
+ if (meth == null) {
+ try {
+ meth = bundle.getClass().getMethod("getContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try field inspection
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try field inspection
+ }
+ }
+
+ if (meth != null) {
+ if (! meth.isAccessible()) {
+ // If not accessible, try to set the accessibility.
+ meth.setAccessible(true);
+ }
+ try {
+ return (BundleContext) meth.invoke(bundle, new Object[0]);
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (InvocationTargetException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e.getTargetException());
+ return null;
}
}
- // Create the instance creator if needed.
- if (confs.length > 0) {
- m_creators.put(bundle, new InstanceCreator(bundle.getBundleContext(), confs, cfs));
- }
- }
-
- /**
- * Log an error message in a log service (if available) and display the message in the console.
- * @param message : the message to log
- * @param t : an attached error (can be null)
- */
- private void err(String message, Throwable t) {
- ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
- if (ref != null) {
- LogService log = (LogService) m_context.getService(ref);
- log.log(LogService.LOG_ERROR, message, t);
- m_context.ungetService(ref);
- }
- if (t != null) {
- System.err.println("[iPOJO-Core] " + message + " : " + t.getMessage());
- } else {
- System.err.println("[iPOJO-Core] " + message);
+ // Else : Field inspection (KF and Prosyst)
+ Field[] fields = bundle.getClass().getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (BundleContext.class.isAssignableFrom(fields[i].getType())) {
+ if (!fields[i].isAccessible()) {
+ fields[i].setAccessible(true);
+ }
+ try {
+ return (BundleContext) fields[i].get(bundle);
+ } catch (IllegalArgumentException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ }
+ }
}
+ m_logger.log(Logger.ERROR, "Cannot find the BundleContext for " + bundle.getSymbolicName(), null);
+ return null;
}
+
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java Fri Mar 28 08:33:36 2008
@@ -21,7 +21,7 @@
import java.util.Dictionary;
import java.util.List;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.osgi.framework.BundleContext;
@@ -72,7 +72,7 @@
* Get the component type description.
* @return the component type description object
*/
- ComponentDescription getComponentDescription();
+ ComponentTypeDescription getComponentDescription();
/**
* Check if the given configuration is acceptable as a configuration of a component instance.
@@ -97,15 +97,15 @@
/**
* Add a factory state listener on the current factory.
- * @param l : the listener to add
+ * @param listener : the listener to add
*/
- void addFactoryStateListener(FactoryStateListener l);
+ void addFactoryStateListener(FactoryStateListener listener);
/**
* Remove the given factory state listener from the listener list.
- * @param l : the listener to remove
+ * @param listener : the listener to remove
*/
- void removeFactoryStateListener(FactoryStateListener l);
+ void removeFactoryStateListener(FactoryStateListener listener);
/**
* Get the list of missing handlers.
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java Fri Mar 28 08:33:36 2008
@@ -20,7 +20,7 @@
import java.util.Dictionary;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.Logger;
@@ -31,17 +31,17 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class Handler {
-
+
/**
* Handler namespace property.
*/
public static final String HANDLER_NAMESPACE_PROPERTY = "handler.namespace";
-
+
/**
* Handler name property.
*/
public static final String HANDLER_NAME_PROPERTY = "handler.name";
-
+
/**
* Handler type property.
*/
@@ -51,39 +51,73 @@
* Handler priority.
*/
public static final String HANDLER_LEVEL_PROPERTY = "handler.level";
-
+
/**
- * Handler logger.
+ * Handler validity.
*/
- private Logger m_logger;
-
+ protected boolean m_isValid = true;
+
+ /**
+ * HandlerManager managing the current handler.
+ */
+ protected HandlerManager m_instance;
+
+ /**
+ * Set the factory attached to this handler object.
+ * This method must be override to depend on each component factory type.
+ * @param factory : the factory.
+ */
+ public abstract void setFactory(Factory factory);
+
/**
- * Set the logger use by this handler.
- * @param logger : the logger object to use.
+ * Get the logger to use in the handler.
+ * This method must be override to depend on each component factory type logging policy.
+ * @return the logger.
*/
- final void setLogger(Logger logger) {
- m_logger = logger;
+ public abstract Logger getLogger();
+
+ /**
+ * Log method (warning).
+ * @param message : message to log
+ */
+ public final void warn(String message) {
+ getLogger().log(Logger.WARNING, message);
}
-
+
/**
- * Log method.
- * @param level : message level (Logger class constant)
+ * Log method (error).
* @param message : message to log
*/
- public final void log(int level, String message) {
- m_logger.log(level, message);
+ public final void error(String message) {
+ getLogger().log(Logger.ERROR, message);
}
-
+
/**
- * Log method.
- * @param level : message level (Logger class constant)
+ * Log method (info).
* @param message : message to log
- * @param ex : exception to attach to the message
*/
- public final void log(int level, String message, Throwable ex) {
- m_logger.log(level, message, ex);
+ public final void info(String message) {
+ getLogger().log(Logger.INFO, message);
}
-
+
+ /**
+ * Log method (warning).
+ * @param message : message to log
+ * @param exception : exception to attach to the message
+ */
+ public final void warn(String message, Throwable exception) {
+ getLogger().log(Logger.WARNING, message, exception);
+ }
+
+ /**
+ * Log method (error).
+ * @param message : message to log
+ * @param exception : exception to attach to the message
+ */
+ public final void error(String message, Throwable exception) {
+ getLogger().log(Logger.ERROR, message, exception);
+ }
+
/**
* Get a plugged handler of the same container.
* This method must be call only in the start method (or after).
@@ -93,41 +127,65 @@
* @return the handler object or null if the handler is not found.
*/
public abstract Handler getHandler(String name);
-
+
/**
* Attach the current handler object to the given component instance.
* An attached handler becomes a part of the instance container.
- * @param ci : the component instance on which the current handler will be attached.
+ * @param instance : the component instance on which the current handler will be attached.
*/
- protected abstract void attach(ComponentInstance ci);
-
+ protected abstract void attach(ComponentInstance instance);
+
/**
* Check if the current handler is valid.
+ * This check test the handlers validity.
* This method must not be override.
* @return true if the handler is valid.
*/
public final boolean isValid() {
return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
}
-
-
+
+ /**
+ * Set the validity of the current handler.
+ * @param isValid : if true the handler becomes valid, else it becomes invalid.
+ */
+ public final void setValidity(boolean isValid) {
+ if (m_isValid != isValid) {
+ m_isValid = isValid;
+ HandlerManager instance = getHandlerManager();
+ if (isValid) {
+ instance.stateChanged(instance, ComponentInstance.VALID);
+ } else {
+ instance.stateChanged(instance, ComponentInstance.INVALID);
+ }
+ }
+ }
+
+ public final boolean getValidity() {
+ return m_isValid;
+ }
+
/**
* Get the component instance of the current handler.
* @return : the component instance.
*/
- public final ComponentInstance getInstance() {
- return ((Pojo) this).getComponentInstance();
+ public final HandlerManager getHandlerManager() {
+ if (m_instance != null) { return m_instance; }
+ m_instance = (HandlerManager) ((Pojo) this).getComponentInstance();
+ return m_instance;
}
-
+
/**
* Initialize component factory.
* This method aims to gather component factory properties. Each handler wanting to contribute need to override this
* method and add properties to the given component description.
- * @param cd : component description.
+ * @param typeDesc : component description.
* @param metadata : component type metadata.
* @throws ConfigurationException : if the metadata are not correct (early detection).
*/
- public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException { }
+ public void initializeComponentFactory(ComponentTypeDescription typeDesc, Element metadata) throws ConfigurationException {
+ // The default implementation does nothing.
+ }
/**
* Configure the handler.
@@ -151,7 +209,9 @@
* This method is called when the component state changed.
* @param state : the new state
*/
- public void stateChanged(int state) { }
+ public void stateChanged(int state) {
+ // The default implementation does nothing.
+ }
/**
* Return the current handler description.
@@ -166,5 +226,7 @@
* The instance is reconfiguring.
* @param configuration : New instance configuration.
*/
- public void reconfigure(Dictionary configuration) { }
+ public void reconfigure(Dictionary configuration) {
+ // The default implementation does nothing.
+ }
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java Fri Mar 28 08:33:36 2008
@@ -18,20 +18,12 @@
*/
package org.apache.felix.ipojo;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Dictionary;
-import java.util.Iterator;
-import java.util.List;
import java.util.Properties;
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceRegistration;
/**
* The component factory manages component instance objects. This management
@@ -43,20 +35,20 @@
public class HandlerFactory extends ComponentFactory implements Factory {
/**
- * Service Registration of this factory (Factory & ManagedServiceFactory).
+ * iPOJO Default Namespace.
*/
- private ServiceRegistration m_sr;
-
+ public static final String IPOJO_NAMESPACE = "org.apache.felix.ipojo";
+
/**
* Handler type (composite|primitive).
* Default: handler.
*/
private String m_type = "primitive";
-
+
/**
* Default iPOJO Namespace.
*/
- private String m_namespace = IPojoConfiguration.IPOJO_NAMESPACE;
+ private String m_namespace = IPOJO_NAMESPACE;
/**
* Get the handler start level.
@@ -67,114 +59,67 @@
/**
* Create a composite factory.
- * @param bc : bundle context
- * @param cm : metadata of the component to create
+ * @param context : bundle context
+ * @param metadata : metadata of the component to create
+ * @throws ConfigurationException occurs when the element describing the factory is malformed.
*/
- public HandlerFactory(BundleContext bc, Element cm) {
- super(bc, cm);
-
+ public HandlerFactory(BundleContext context, Element metadata) throws ConfigurationException {
+ super(context, metadata);
+
// Get the name
- m_factoryName = cm.getAttribute("name").toLowerCase();
- if (m_factoryName == null) {
- System.err.println("An Handler needs a name");
- return;
- }
-
+ m_factoryName = metadata.getAttribute("name");
+ if (m_factoryName == null) { throw new ConfigurationException("An Handler needs a name"); }
+
// Get the type
- String t = cm.getAttribute("type");
- if (t != null) {
- m_type = t;
+ String type = metadata.getAttribute("type");
+ if (type != null) {
+ m_type = type;
}
-
- String l = cm.getAttribute("level");
- if (l != null) {
- m_level = new Integer(l).intValue();
+
+ String level = metadata.getAttribute("level");
+ if (level != null) {
+ m_level = new Integer(level).intValue();
}
-
+
// Get the namespace
- String ns = cm.getAttribute("namespace");
- if (ns != null) {
- m_namespace = ns.toLowerCase();
- }
+ String namespace = metadata.getAttribute("namespace");
+ if (namespace != null) {
+ m_namespace = namespace.toLowerCase();
+ }
}
-
+
public String getNamespace() {
return m_namespace;
}
-
+
public String getHandlerName() {
return m_namespace + ":" + getName();
}
-
+
public String getType() {
return m_type;
}
-
+
public int getStartLevel() {
return m_level;
}
- /**
- * Start all the instance managers.
- */
- public synchronized void start() {
- if (m_sr != null) { // Already started.
- return;
- }
-
- if (m_handlerIdentifiers.size() != 0) {
- try {
- String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")"
- + "(factory.state=1)"
- + ")";
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
- stop();
- return;
- }
- }
-
- try {
- computeFactoryState();
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "Cannot initilize the factory " + e.getMessage());
- stop();
- return;
- }
-
- // Exposition of the factory service (always public for handlers)
- m_sr = m_context.registerService(new String[] { Factory.class.getName()}, this, getProperties());
+ public ComponentTypeDescription getComponentTypeDescription() {
+ return new HandlerTypeDescription(this);
}
-
+
/**
* Stop the factory.
* This method does not disposed created instances.
* These instances will be disposed by the instance managers.
*/
- public synchronized void stop() {
- if (m_sr != null) {
- m_sr.unregister();
- m_sr = null;
- }
-
+ public synchronized void stopping() {
if (m_tracker != null) {
m_tracker.close();
m_tracker = null;
}
-
- // Release each handler
- for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
- ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
- }
-
- m_handlerIdentifiers.clear();
- m_listeners.clear();
- m_state = INVALID;
}
-
-
+
/**
* Compute factory service properties.
* This method add three mandatory handler factory properties (name, namespace and type)
@@ -183,164 +128,53 @@
*/
protected Properties getProperties() {
Properties props = new Properties();
-
- // Add factory state
- props.put("factory.state", "" + m_state);
-
- props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
- props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
- props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
- if (m_level != Integer.MAX_VALUE) {
- props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
- }
-
+
return props;
}
-
- /**
- * Compute handler factory state.
- * @throws ConfigurationException : occurs when an handler cannot be initialized.
- */
- protected void computeFactoryState() throws ConfigurationException {
- boolean isValid = true;
- for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
- HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
- isValid = hi.getReference() != null;
- }
-
- if (isValid) {
- if (m_state == INVALID) {
- m_state = VALID;
-
- if (m_sr == null) {
- 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);
- hm.getHandler();
- Handler ch = hm.getHandler();
- ch.setLogger(getLogger());
- ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
- ((Pojo) ch).getComponentInstance().dispose();
- }
- }
-
- 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();
-
- if (m_sr != null) {
- m_sr.setProperties(getProperties());
- }
-
- return;
- }
- }
- }
-
+
/**
* 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.
+ * @param context : the service context to push for this instance.
+ * @param handlers : handler array to used.
* @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 synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
- if (m_state == Factory.INVALID) {
- throw new MissingHandlerException(getMissingHandlers());
- }
-
- if (configuration == null) {
- configuration = new Properties();
- }
-
- String in = null;
- if (configuration.get("name") != null) {
- in = (String) configuration.get("name");
- } else {
- in = generateName();
- configuration.put("name", in);
- }
-
- if (m_instancesName.contains(in)) {
- throw new UnacceptableConfiguration("Name already used : " + in);
- } else {
- m_instancesName.add(in);
- }
-
- 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));
- }
-
- HandlerManager instance = new HandlerManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[handlers.size()]));
+ public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException {
+ HandlerManager instance = new HandlerManager(this, context, handlers);
instance.configure(m_componentMetadata, configuration);
-
- m_componentInstances.put(in, instance);
-
-
return instance;
}
-
- /**
- * Return an handler object.
- * @param hi : handler to create.
- * @param sc : service context in which create the handler (instance context).
- * @return the Handler 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;
+
+ private class HandlerTypeDescription extends ComponentTypeDescription {
+
+ /**
+ * Constructor.
+ * @param factory : factory.
+ */
+ public HandlerTypeDescription(Factory factory) {
+ super(factory);
+ }
+
+ /**
+ * Add properties to publish :
+ * handler.name, handler.namespace, handler.type and handler.level if the level is not Integer.MAX.
+ * @return return the dictionary to publish.
+ * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+ */
+ public Dictionary getPropertiesToPublish() {
+ Dictionary props = super.getPropertiesToPublish();
+
+ props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
+ props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
+ props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
+ if (m_level != Integer.MAX_VALUE) {
+ props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
+ }
+ return props;
}
}
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java Fri Mar 28 08:33:36 2008
@@ -24,12 +24,12 @@
import org.osgi.framework.BundleContext;
/**
-* The handler manager manages an handler instance.
-*
-* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
-*/
+ * The handler manager manages an handler instance.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
public class HandlerManager extends InstanceManager {
-
+
/**
* Handler object (contained).
*/
@@ -38,13 +38,13 @@
/**
* Constructor.
* @param factory : handler factory
- * @param bc : bundle context
+ * @param context : bundle context
* @param handlers : handler array
*/
- public HandlerManager(ComponentFactory factory, BundleContext bc, HandlerManager[] handlers) {
- super(factory, bc, handlers);
+ public HandlerManager(ComponentFactory factory, BundleContext context, HandlerManager[] handlers) {
+ super(factory, context, handlers);
}
-
+
/**
* Get the contained handler object.
* If not already created it creates the object.
@@ -56,73 +56,68 @@
}
return m_handler;
}
-
+
/**
* Create and initialize the handler object.
- * @param ci : component instance on which the handler will be attached.
- * @param cm : component metadata.
+ * @param instance : component instance on which the handler will be attached.
+ * @param metadata : component metadata.
* @param configuration : instance configuration.
* @throws ConfigurationException if the handler configuration failed.
*/
- public void init(ComponentInstance ci, Element cm, Dictionary configuration) throws ConfigurationException {
+ public void init(ComponentInstance instance, Element metadata, Dictionary configuration) throws ConfigurationException {
createHandlerObject();
- m_handler.attach(ci);
- m_handler.configure(cm, configuration);
+ m_handler.setFactory(instance.getFactory());
+ m_handler.attach(instance);
+ m_handler.configure(metadata, configuration);
}
-
+
/**
* Create the handler object.
* This method does nothing if the object is already created.
*/
private void createHandlerObject() {
if (m_handler != null) { return; }
- Handler h = (Handler) createPojoObject();
- if (h instanceof PrimitiveHandler) {
- m_handler = (PrimitiveHandler) h;
- } else {
- m_handler = (CompositeHandler) h;
- }
+ m_handler = (Handler) createPojoObject();
}
-
+
/**
* Start the instance manager.
*/
public synchronized void start() {
- if (m_state != STOPPED) {
- return;
- } // Instance already started
+ if (m_state != STOPPED) { return; } // Instance already started
for (int i = 0; i < m_handlers.length; i++) {
m_handlers[i].addInstanceStateListener(this);
m_handlers[i].start();
}
-
+
m_handler.start(); // Call the handler start method.
-
+
for (int i = 0; i < m_handlers.length; i++) {
- if (! m_handlers[i].getHandler().isValid()) {
+ if (!m_handlers[i].getHandler().isValid()) {
setState(INVALID);
return;
}
}
- setState(VALID);
+ if (m_handler.getValidity()) {
+ setState(VALID);
+ } else {
+ setState(INVALID);
+ }
}
-
+
/**
* Stop the instance manager.
*/
public synchronized void stop() {
- if (m_state == STOPPED) {
- return;
- } // Instance already stopped
-
+ if (m_state == STOPPED) { return; } // Instance already stopped
setState(INVALID);
-
+
if (m_handler != null) {
m_handler.stop();
}
-
+
// Stop all the handlers
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].removeInstanceStateListener(this);
@@ -130,13 +125,13 @@
}
m_state = STOPPED;
- if (m_instanceListeners != null) {
- for (int i = 0; i < m_instanceListeners.size(); i++) {
- ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+ if (m_listeners != null) {
+ for (int i = 0; i < m_listeners.size(); i++) {
+ ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, STOPPED);
}
}
}
-
+
/**
* Dispose the instance.
* @see org.apache.felix.ipojo.ComponentInstance#dispose()
@@ -145,7 +140,7 @@
super.dispose();
m_handler = null;
}
-
+
/**
* Kill the current instance.
* Only the factory of this instance can call this method.
@@ -153,6 +148,33 @@
protected void kill() {
super.dispose();
m_handler = null;
+ }
+
+ /**
+ * State Change listener callback.
+ * This method is notified at each time a plugged handler becomes invalid.
+ * @param instance : changing instance
+ * @param newState : new state
+ * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
+ */
+ public synchronized void stateChanged(ComponentInstance instance, int newState) {
+ if (m_state <= STOPPED) { return; }
+
+ // Update the component state if necessary
+ if (newState == INVALID && m_state == VALID) {
+ // Need to update the state to UNRESOLVED
+ setState(INVALID);
+ return;
+ }
+ if (newState == VALID && m_state == INVALID) {
+ // An handler becomes valid => check if all handlers are valid
+ if (!m_handler.getValidity()) { return; }
+ for (int i = 0; i < m_handlers.length; i++) {
+ if (m_handlers[i].getState() != VALID) { return; }
+ }
+ setState(VALID);
+ return;
+ }
}
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java Fri Mar 28 08:33:36 2008
@@ -54,25 +54,24 @@
/**
* Constructor. Used when the service context = the bundle context
*
- * @param bc : bundle context
+ * @param context : bundle context
*/
- public IPojoContext(BundleContext bc) {
- m_bundleContext = bc;
+ public IPojoContext(BundleContext context) {
+ m_bundleContext = context;
}
/**
* Constructor. Used when the service context and the bundle context are
* different
*
- * @param bc : bundle context
- * @param sc : service context
+ * @param bundleContext : bundle context
+ * @param serviceContext : service context
*/
- public IPojoContext(BundleContext bc, ServiceContext sc) {
- m_bundleContext = bc;
- m_serviceContext = sc;
+ public IPojoContext(BundleContext bundleContext, ServiceContext serviceContext) {
+ m_bundleContext = bundleContext;
+ m_serviceContext = serviceContext;
}
-
/**
* Add a bundle listener.
* @param listener : the listener to add
@@ -119,7 +118,6 @@
}
}
-
/**
* Create a Filter object.
* @param filter : the string form of the LDAP filter to create
@@ -158,12 +156,12 @@
/**
* Get the bundle object with the given id.
- * @param id : bundle id
+ * @param bundleId : bundle id
* @return the bundle object
* @see org.osgi.framework.BundleContext#getBundle(long)
*/
- public Bundle getBundle(long id) {
- return m_bundleContext.getBundle(id);
+ public Bundle getBundle(long bundleId) {
+ return m_bundleContext.getBundle(bundleId);
}
/**
@@ -175,7 +173,6 @@
return m_bundleContext.getBundles();
}
-
/**
* Get a data file.
* @param filename : File name.
@@ -340,7 +337,7 @@
return m_serviceContext.ungetService(reference);
}
}
-
+
/**
* Get the global context, i.e. the bundle context of the factory.
* @return the global bundle context.
@@ -348,15 +345,12 @@
public BundleContext getGlobalContext() {
return m_bundleContext;
}
-
+
/**
* Get the service context, i.e. the composite context.
* @return the service context.
*/
public ServiceContext getServiceContext() {
- if (m_serviceContext == null) {
- return this;
- }
return m_serviceContext;
}
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java Fri Mar 28 08:33:36 2008
@@ -18,208 +18,204 @@
*/
package org.apache.felix.ipojo;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
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.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
/**
- * An instance creator aims to create instances and to track their factories.
- * It's allow to create instance from outside factories.
- *
+ * An instance creator aims to create instances and to track their factories. It's allow to create instance from outside factories.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class InstanceCreator implements TrackerCustomizer, FactoryStateListener {
- /**
- * Bundle Context.
- */
- private BundleContext m_context;
+public class InstanceCreator implements FactoryStateListener {
/**
* Logger to log messages if error occurs.
*/
private Logger m_logger;
-
+
/**
- * Private factories.
+ * Configurations to create and maintains.
*/
- private ComponentFactory[] m_factories;
+ private List m_idle = new ArrayList();
/**
- * This structure aims to manage a configuration. It stores all necessary
- * information to create an instance and to track the factory.
+ * Map storing created instance. [AbstractFactory, List [ManagedInstance]]
*/
- private class ManagedConfiguration {
- /**
- * Configuration of the instance to create.
- */
- private Dictionary m_configuration;
+ private Map m_attached = new HashMap();
- /**
- * Factory name.
- */
- private String m_factoryName;
+ /**
+ * Abstract Factory list.
+ */
+ private List m_factories = new ArrayList();
- /**
- * Created instance.
- */
- private ComponentInstance m_instance;
+ /**
+ * Constructor.
+ * @param context : iPOJO bundle context.
+ */
+ public InstanceCreator(BundleContext context) {
+ m_logger = new Logger(context, "iPOJO Instance Creator");
+ }
- /**
- * Constructor.
- *
- * @param conf : the configuration to create.
- */
- ManagedConfiguration(Dictionary conf) {
- m_configuration = conf;
+ /**
+ * Add an instance to manage.
+ * @param instance : instance configuration
+ * @param bundle : bundle id declaring the instance
+ */
+ synchronized void addInstance(Dictionary instance, long bundle) {
+ ManagedInstance managed = new ManagedInstance(instance, bundle);
+ for (int i = 0; i < m_factories.size(); i++) {
+ IPojoFactory factory = (IPojoFactory) m_factories.get(i);
+ if (factory.getState() == Factory.VALID && managed.match(factory)) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ // Subscribe to the factory state change
+ factory.addFactoryStateListener(this);
+ } else {
+ list.add(managed);
+ }
+ return;
+ }
}
+ // If there is no matching factory, add the instance to the idle list
+ m_idle.add(managed);
+ }
- /**
- * Return the managed configuration.
- * @return the configuration.
- */
- Dictionary getConfiguration() {
- return m_configuration;
+ /**
+ * Dispose and stop to manage all instances declared by the given bundle.
+ * @param bundle : bundle.
+ */
+ void removeInstancesFromBundle(long bundle) {
+ // Disposes instance from attached instances
+ Collection col = m_attached.keySet();
+ Iterator iterator = col.iterator();
+ List instanceToRemove = new ArrayList();
+ List factoryToRemove = new ArrayList();
+ while (iterator.hasNext()) {
+ IPojoFactory factory = (IPojoFactory) iterator.next();
+ List list = (List) m_attached.get(factory);
+ for (int i = 0; i < list.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) list.get(i);
+ if (managed.m_bundleId == bundle) {
+ managed.dispose();
+ instanceToRemove.add(managed);
+ }
+ }
+ if (!instanceToRemove.isEmpty()) {
+ list.removeAll(instanceToRemove);
+ if (list.isEmpty()) {
+ factory.removeFactoryStateListener(this);
+ factoryToRemove.add(factory);
+ }
+ }
}
- /**
- * Return the used factory name.
- * @return the factory
- */
- String getFactory() {
- return m_factoryName;
+ for (int i = 0; i < factoryToRemove.size(); i++) {
+ m_attached.remove(factoryToRemove.get(i));
}
- /**
- * Return the created instance.
- * @return the instance (or null if no instance are created).
- */
- ComponentInstance getInstance() {
- return m_instance;
+ // Delete idle instances
+ instanceToRemove.clear();
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.m_bundleId == bundle) {
+ instanceToRemove.add(managed);
+ }
}
+ m_idle.removeAll(instanceToRemove);
+ }
- /**
- * Set the factory name.
- *
- * @param name : the factory name.
- */
- void setFactory(String name) {
- m_factoryName = name;
+ /**
+ * A new factory appears.
+ * @param factory : the new factory.
+ */
+ public synchronized void addFactory(IPojoFactory factory) {
+ List createdInstances = new ArrayList(1);
+ m_factories.add(factory);
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.match(factory)) {
+ // We have to subscribe to the factory.
+ factory.addFactoryStateListener(this);
+ if (factory.getState() == Factory.VALID) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ } else {
+ list.add(managed);
+ }
+ createdInstances.add(managed);
+ }
+ }
}
-
- /**
- * Set the instance object.
- *
- * @param instance : the instance
- */
- void setInstance(ComponentInstance instance) {
- m_instance = instance;
+ if (!createdInstances.isEmpty()) {
+ m_idle.removeAll(createdInstances);
}
}
/**
- * Configurations to create and maintains.
+ * A factory is leaving.
+ * @param factory : the leaving factory
*/
- private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
+ void removeFactory(IPojoFactory factory) {
+ factory.removeFactoryStateListener(this);
+ m_factories.remove(factory);
+ onInvalidation(factory);
+ m_attached.remove(factory);
+ }
/**
- * Service Tracker tracking factories.
+ * The given factory becomes valid.
+ * @param factory : the factory becoming valid.
*/
- private Tracker m_tracker;
-
- /**
- * Constructor.
- *
- * @param context : the bundle context.
- * @param configurations : configuration set to create and maintain.
- * @param factories : private factories.
- */
- public InstanceCreator(BundleContext context, Dictionary[] configurations, ComponentFactory[] factories) {
- m_context = context;
- m_logger = new Logger(context, "InstanceCreator" + context.getBundle().getBundleId(), Logger.WARNING);
-
- m_configurations = new ManagedConfiguration[configurations.length];
- m_factories = factories;
-
- for (int i = 0; i < configurations.length; i++) {
- ManagedConfiguration conf = new ManagedConfiguration(configurations[i]);
- m_configurations[i] = conf;
- // Get the component type name :
- String componentType = (String) conf.getConfiguration().get("component");
-
- boolean found = false;
- for (int j = 0; m_factories != null && !found && j < m_factories.length; j++) {
- if (m_factories[j].m_state == Factory.VALID && (m_factories[j].getName().equals(componentType) || (m_factories[j].getComponentClassName() != null && m_factories[j].getComponentClassName().equals(componentType)))) {
- createInstance(m_factories[j], conf);
- found = true;
+ private void onValidation(IPojoFactory factory) {
+ List toRemove = new ArrayList();
+ for (int i = 0; i < m_idle.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+ if (managed.match(factory)) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ } else {
+ list.add(managed);
}
+ toRemove.add(managed);
}
}
-
- for (int i = 0; m_factories != null && i < m_factories.length; i++) {
- m_factories[i].addFactoryStateListener(this);
- }
-
-
- String filter = "(&(objectclass=" + Factory.class.getName() + ")(factory.state=1))";
- try {
- m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
- m_tracker.open();
- } catch (InvalidSyntaxException e) {
- e.printStackTrace();
- return;
- }
- }
-
- /**
- * Create an instance using the given factory and the given configuration.
- *
- * @param fact : the factory name to used.
- * @param config : the configuration.
- */
- private void createInstance(Factory fact, ManagedConfiguration config) {
- Dictionary conf = config.getConfiguration();
- try {
- config.setInstance(fact.createComponentInstance(conf));
- config.setFactory(fact.getName());
- } catch (UnacceptableConfiguration e) {
- m_logger.log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
- stop();
- } catch (MissingHandlerException e) {
- m_logger.log(Logger.ERROR, "The instance creation has failed, at least one handler is missing", e);
- stop();
- } catch (ConfigurationException e) {
- m_logger.log(Logger.ERROR, "The instance creation has failed, an error during the configuration has occured", e);
- stop();
+ if (!toRemove.isEmpty()) {
+ m_idle.removeAll(toRemove);
}
}
/**
- * Stop all created instances.
+ * The given factory becomes invalid.
+ * @param factory : factory which becomes invalid.
*/
- public synchronized void stop() {
- m_tracker.close();
-
- for (int i = 0; m_factories != null && i < m_factories.length; i++) {
- m_factories[i].removeFactoryStateListener(this);
- }
-
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null) {
- m_configurations[i].getInstance().dispose();
+ private void onInvalidation(IPojoFactory factory) {
+ List instances = (List) m_attached.remove(factory);
+ if (instances != null) {
+ for (int i = 0; i < instances.size(); i++) {
+ ManagedInstance managed = (ManagedInstance) instances.get(i);
+ managed.dispose();
+ m_idle.add(managed);
}
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
}
-
- m_factories = null;
- m_tracker = null;
- m_logger = null;
- m_configurations = null;
}
/**
@@ -230,88 +226,116 @@
*/
public void stateChanged(Factory factory, int newState) {
if (newState == Factory.VALID) {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null
- && (m_configurations[i].getConfiguration().get("component").equals(factory.getName()) || m_configurations[i].getConfiguration().get(
- "component").equals(((ComponentFactory) factory).getComponentClassName()))) {
- Factory fact = factory;
- createInstance(fact, m_configurations[i]);
- }
- }
- return;
+ onValidation((IPojoFactory) factory);
} else {
- // newState == INVALID
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factory.getName())) {
- m_configurations[i].setInstance(null);
- m_configurations[i].setFactory(null);
- }
- }
- return;
+ onInvalidation((IPojoFactory) factory);
}
}
/**
- * A new factory has been detected.
- * @param ref : the factory service reference.
- * @return true if the factory can be used to create a managed instance.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
- */
- public boolean addingService(ServiceReference ref) {
- String factoryName = (String) ref.getProperty("factory.name");
- String componentClass = (String) ref.getProperty("component.class");
- boolean isValid = ((String) ref.getProperty("factory.state")).equals("" + Factory.VALID);
- Factory fact = (Factory) m_tracker.getService(ref);
-
- boolean used = false;
- if (isValid) {
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getInstance() == null
- && (m_configurations[i].getConfiguration().get("component").equals(factoryName) || m_configurations[i].getConfiguration().get("component").equals(componentClass))) {
- createInstance(fact, m_configurations[i]);
- used = true;
+ * This structure aims to manage a configuration. It stores all necessary information to create an instance and to track the factory.
+ */
+ private class ManagedInstance {
+ /**
+ * Configuration of the instance to create.
+ */
+ private Dictionary m_configuration;
+
+ /**
+ * Bundle which create the instance.
+ */
+ private long m_bundleId;
+
+ /**
+ * Factory used to create the instance.
+ */
+ private IPojoFactory m_factory;
+
+ /**
+ * Created instance.
+ */
+ private ComponentInstance m_instance;
+
+ /**
+ * Constructor.
+ * @param conf : the configuration to create.
+ * @param bundle : the bundle in which the instance is declared.
+ */
+ ManagedInstance(Dictionary conf, long bundle) {
+ m_configuration = conf;
+ m_bundleId = bundle;
+ }
+
+ /**
+ * Return the used factory name.
+ * @return the factory
+ */
+ IPojoFactory getFactory() {
+ return m_factory;
+ }
+
+ /**
+ * Return the created instance.
+ * @return the instance (or null if no instance are created).
+ */
+ ComponentInstance getInstance() {
+ return m_instance;
+ }
+
+ /**
+ * Test if the given factory match with the factory required by this instance. A factory matches if its name or its class name is equals to
+ * the 'component' property of the instance. Then the acceptability of the configuration is checked.
+ * @param factory : the factory to confront against the current instance.
+ * @return true if the factory match.
+ */
+ public boolean match(IPojoFactory factory) {
+ // Test factory name (and classname)
+ String component = (String) m_configuration.get("component");
+ if (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component)) {
+ // Test factory accessibility
+ if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
+ // Test the configuration validity.
+ if (factory.isAcceptable(m_configuration)) {
+ return true;
+ } else {
+ m_logger.log(Logger.ERROR, "An instance can be bound to a matching factory, however the configuration seems unacceptable : "
+ + m_configuration);
+ }
}
}
+ return false;
}
- return used;
- }
-
- /**
- * A matching service has been added to the tracker.
- * Nothing to do, as all action are computed in the adding method.
- * @param ref : added reference.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
- */
- public void addedService(ServiceReference ref) { }
-
- /**
- * A used factory is modified.
- * @param ref : modified reference.
- * @param obj : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void modifiedService(ServiceReference ref, Object obj) { }
-
- /**
- * A used factory disappears.
- * All created instance are disposed.
- * @param ref : service reference.
- * @param obj : factory object.
- * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
- */
- public void removedService(ServiceReference ref, Object obj) {
- String name = (String) ref.getProperty("factory.name");
- if (name == null) { return; }
- for (int i = 0; i < m_configurations.length; i++) {
- if (m_configurations[i].getFactory() != null && m_configurations[i].getFactory().equals(name)) {
- if (m_configurations[i].getInstance() != null) {
- m_configurations[i].getInstance().dispose();
- m_configurations[i].setInstance(null);
- }
- m_configurations[i].setFactory(null);
+
+ /**
+ * Create the instance by using the given factory.
+ * @param factory : the factory to use to create the instance. The factory must match.
+ */
+ public void create(IPojoFactory factory) {
+ try {
+ m_factory = factory;
+ m_instance = m_factory.createComponentInstance(m_configuration);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
+ } catch (MissingHandlerException e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
+ } catch (ConfigurationException e) {
+ m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+ + e.getMessage());
+ }
+ }
+
+ /**
+ * Dispose the current instance.
+ */
+ public void dispose() {
+ if (m_instance != null) {
+ m_instance.dispose();
}
+ m_instance = null;
+ m_factory = null;
}
- m_tracker.ungetService(ref);
}
}