Applied patch (FELIX-289) to add support for having "glue code" components
inside composites.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@539496 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/pom.xml b/ipojo/pom.xml
index 9cc366f..d562295 100644
--- a/ipojo/pom.xml
+++ b/ipojo/pom.xml
@@ -17,6 +17,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>0.9.0-incubator-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>2.2.1</version>
@@ -39,13 +45,14 @@
<Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
<Bundle-Description> iPOJO </Bundle-Description>
<Import-Package>
- org.osgi.framework; version="1.3",
- org.osgi.service.cm; version="1.2",
- org.osgi.service.log; version="1.3"
+ org.osgi.framework,
+ org.osgi.service.cm,
+ org.osgi.service.log
</Import-Package>
<Private-Package>
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,
@@ -61,8 +68,8 @@
org.apache.felix.ipojo.handlers.dependency; version="0.7.1",
org.apache.felix.ipojo.handlers.providedservice; version="0.7.1",
org.apache.felix.ipojo.composite; version="0.7.1",
- org.osgi.service.cm; version="1.2",
- org.osgi.service.log; version="1.3"
+ org.osgi.service.cm,
+ org.osgi.service.log
</Export-Package>
</instructions>
</configuration>
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index 8fa9012..50db0fa 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -109,11 +109,6 @@
* Logger for the factory (and all component instance).
*/
private Logger m_logger;
-
- /**
- * True when the factory is active (non stopping and non starting).
- */
- private boolean m_active = false;
/**
* Index used to generate instance name if not set.
@@ -289,34 +284,36 @@
* Stop all the instance managers.
*/
public synchronized void stop() {
- m_active = false;
Collection col = m_componentInstances.values();
Iterator it = col.iterator();
while (it.hasNext()) {
ComponentInstance ci = (ComponentInstance) it.next();
if (ci.isStarted()) {
- ci.dispose();
+ if (ci instanceof CompositeManager) {
+ ((CompositeManager) ci).kill();
+ } else {
+ ((InstanceManager) ci).kill();
+ }
}
}
m_logger.stop();
-
+
m_componentInstances.clear();
if (m_sr != null) {
m_sr.unregister();
}
m_sr = null;
-
+ m_componentDesc = null;
}
/**
* Start all the instance managers.
*/
public synchronized void start() {
- if (m_active) {
+ if (m_componentDesc != null) { // Already started.
return;
- } // Already started
-
+ }
Properties props = new Properties();
// create a ghost component
@@ -354,19 +351,16 @@
props.put(Constants.SERVICE_PID, m_factoryName);
// Exposition of the factory service
- m_active = true;
m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, props);
}
/**
- * Callback called by instance when stopped.
+ * Callback called by instance when disposed.
*
- * @param ci : the instance stopping
+ * @param ci : the destroyed instance
*/
- protected synchronized void stopped(ComponentInstance ci) {
- if (m_active) {
- m_componentInstances.remove(ci.getInstanceName());
- }
+ protected synchronized void disposed(ComponentInstance ci) {
+ m_componentInstances.remove(ci.getInstanceName());
}
/**
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/ComponentInstance.java b/ipojo/src/main/java/org/apache/felix/ipojo/ComponentInstance.java
index 3dd5abe..4883c06 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/ComponentInstance.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/ComponentInstance.java
@@ -32,6 +32,11 @@
public interface ComponentInstance {
/**
+ * Component Instance State : DISPOSED. The instance was destroyed.
+ */
+ int DISPOSED = -1;
+
+ /**
* Component Instance State : STOPPED. The component instance is not
* started.
*/
@@ -116,5 +121,17 @@
* @param configuration : the new configuration.
*/
void reconfigure(Dictionary configuration);
+
+ /**
+ * Add an instance state listener on the current instance.
+ * @param listener : the listener to add.
+ */
+ void addInstanceStateListener(InstanceStateListener listener);
+
+ /**
+ * Remove an instance state listener on the current instance.
+ * @param listener : the listener to remove.
+ */
+ void removeInstanceStateListener(InstanceStateListener listener);
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/CompositeManager.java b/ipojo/src/main/java/org/apache/felix/ipojo/CompositeManager.java
index 19b461a..3d8f438 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/CompositeManager.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/CompositeManager.java
@@ -63,6 +63,12 @@
* Component state (STOPPED at the beginning).
*/
private int m_state = STOPPED;
+
+ /**
+ * Instance State Listener List.
+ */
+ private InstanceStateListener[] m_instanceListeners = new InstanceStateListener[0];
+
/**
* Component type information.
@@ -252,6 +258,10 @@
m_internalContext.stop(); // Turn off the factory tracking
m_state = STOPPED;
+
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, STOPPED);
+ }
}
/**
@@ -259,18 +269,39 @@
* @see org.apache.felix.ipojo.ComponentInstance#dispose()
*/
public void dispose() {
- if (m_state != STOPPED) {
+ if (m_state > STOPPED) {
stop();
}
- m_factory.stopped(this);
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, DISPOSED);
+ }
+
+ m_factory.disposed(this);
// Cleaning
- m_factory = null;
- m_name = null;
- m_context = null;
- m_handlers = null;
- m_componentDesc = null;
+ m_state = DISPOSED;
+ m_handlers = new CompositeHandler[0];
+ m_instanceListeners = new InstanceStateListener[0];
+ }
+
+ /**
+ * Kill the current instance.
+ * Only the factory of this instance can call this method.
+ */
+ protected void kill() {
+ if (m_state > STOPPED) {
+ stop();
+ }
+
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, DISPOSED);
+ }
+
+ // Cleaning
+ m_state = DISPOSED;
+ m_handlers = new CompositeHandler[0];
+ m_instanceListeners = new InstanceStateListener[0];
}
/**
@@ -294,6 +325,10 @@
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].stateChanged(state);
}
+
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, state);
+ }
}
}
@@ -314,6 +349,56 @@
public boolean isStarted() {
return m_state != STOPPED;
}
+
+ /**
+ * Add an instance to the created instance list.
+ * @param listener : the instance state listener to add.
+ * @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
+ */
+ public void addInstanceStateListener(InstanceStateListener listener) {
+ for (int i = 0; (m_instanceListeners != null) && (i < m_instanceListeners.length); i++) {
+ if (m_instanceListeners[i] == listener) {
+ return;
+ }
+ }
+
+ if (m_instanceListeners.length > 0) {
+ InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length + 1];
+ System.arraycopy(m_instanceListeners, 0, newInstances, 0, m_instanceListeners.length);
+ newInstances[m_instanceListeners.length] = listener;
+ m_instanceListeners = newInstances;
+ } else {
+ m_instanceListeners = new InstanceStateListener[] { listener };
+ }
+ }
+
+ /**
+ * Remove an instance state listener.
+ * @param listener : the listener to remove
+ * @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
+ */
+ public void removeInstanceStateListener(InstanceStateListener listener) {
+ int idx = -1;
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ if (m_instanceListeners[i] == listener) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx >= 0) {
+ if ((m_instanceListeners.length - 1) == 0) {
+ m_instanceListeners = new InstanceStateListener[0];
+ } else {
+ InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length - 1];
+ System.arraycopy(m_instanceListeners, 0, newInstances, 0, idx);
+ if (idx < newInstances.length) {
+ System.arraycopy(m_instanceListeners, idx + 1, newInstances, idx, newInstances.length - idx);
+ }
+ m_instanceListeners = newInstances;
+ }
+ }
+ }
// ===================== end Lifecycle management =====================
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java b/ipojo/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
index 706a767..ec6f56f 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.ipojo;
+import org.apache.felix.ipojo.composite.instance.InstanceHandler;
import org.apache.felix.ipojo.composite.service.importer.ImportExportHandler;
import org.apache.felix.ipojo.composite.service.instantiator.ServiceInstantiatorHandler;
import org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler;
@@ -56,6 +57,7 @@
public static final Class[] INTERNAL_COMPOSITE_HANDLERS = new Class[] {
ServiceInstantiatorHandler.class,
ImportExportHandler.class,
+ InstanceHandler.class,
org.apache.felix.ipojo.composite.service.provides.ProvidedServiceHandler.class,
org.apache.felix.ipojo.composite.architecture.ArchitectureHandler.class
};
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index 772c556..75f36a2 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -81,6 +81,11 @@
* Instances of the components.
*/
private Object[] m_pojoObjects = new Object[0];
+
+ /**
+ * Instance State Listener List.
+ */
+ private InstanceStateListener[] m_instanceListeners = new InstanceStateListener[0];
/**
* Component type information.
@@ -127,7 +132,7 @@
// Add the name
m_name = (String) configuration.get("name");
-
+
// Create the standard handlers and add these handlers to the list
for (int i = 0; i < IPojoConfiguration.INTERNAL_HANDLERS.length; i++) {
// Create a new instance
@@ -260,6 +265,9 @@
m_pojoObjects = new Object[0];
m_state = STOPPED;
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, STOPPED);
+ }
}
/**
@@ -267,22 +275,44 @@
* @see org.apache.felix.ipojo.ComponentInstance#dispose()
*/
public void dispose() {
- if (m_state != STOPPED) {
+ if (m_state > STOPPED) { // Valid or invalid
stop();
}
- m_factory.stopped(this);
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, DISPOSED);
+ }
+
+ m_factory.disposed(this);
// Cleaning
- m_factory = null;
- m_name = null;
- m_className = null;
- m_context = null;
- m_handlers = null;
- m_fieldRegistration = null;
+ m_handlers = new Handler[0];
+ m_fieldRegistration = new HashMap();
m_clazz = null;
- m_pojoObjects = null;
- m_componentDesc = null;
+ m_pojoObjects = new Object[0];
+ m_instanceListeners = new InstanceStateListener[0];
+ }
+
+ /**
+ * Kill the current instance.
+ * Only the factory of this instance can call this method.
+ */
+ protected void kill() {
+ if (m_state > STOPPED) {
+ stop();
+ }
+
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, DISPOSED);
+ }
+
+ // Cleaning
+ m_state = DISPOSED;
+ m_handlers = new Handler[0];
+ m_fieldRegistration = new HashMap();
+ m_clazz = null;
+ m_pojoObjects = new Object[0];
+ m_instanceListeners = new InstanceStateListener[0];
}
/**
@@ -306,6 +336,10 @@
for (int i = m_handlers.length - 1; i > -1; i--) {
m_handlers[i].stateChanged(state);
}
+
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ m_instanceListeners[i].stateChanged(this, state);
+ }
}
}
@@ -324,7 +358,57 @@
* @see org.apache.felix.ipojo.ComponentInstance#isStarted()
*/
public boolean isStarted() {
- return m_state != STOPPED;
+ return m_state > STOPPED;
+ }
+
+ /**
+ * Add an instance to the created instance list.
+ * @param listener : the instance state listener to add.
+ * @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
+ */
+ public void addInstanceStateListener(InstanceStateListener listener) {
+ for (int i = 0; (m_instanceListeners != null) && (i < m_instanceListeners.length); i++) {
+ if (m_instanceListeners[i] == listener) {
+ return;
+ }
+ }
+
+ if (m_instanceListeners.length > 0) {
+ InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length + 1];
+ System.arraycopy(m_instanceListeners, 0, newInstances, 0, m_instanceListeners.length);
+ newInstances[m_instanceListeners.length] = listener;
+ m_instanceListeners = newInstances;
+ } else {
+ m_instanceListeners = new InstanceStateListener[] { listener };
+ }
+ }
+
+ /**
+ * Remove an instance state listener.
+ * @param listener : the listener to remove
+ * @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
+ */
+ public void removeInstanceStateListener(InstanceStateListener listener) {
+ int idx = -1;
+ for (int i = 0; i < m_instanceListeners.length; i++) {
+ if (m_instanceListeners[i] == listener) {
+ idx = i;
+ break;
+ }
+ }
+
+ if (idx >= 0) {
+ if ((m_instanceListeners.length - 1) == 0) {
+ m_instanceListeners = new InstanceStateListener[0];
+ } else {
+ InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length - 1];
+ System.arraycopy(m_instanceListeners, 0, newInstances, 0, idx);
+ if (idx < newInstances.length) {
+ System.arraycopy(m_instanceListeners, idx + 1, newInstances, idx, newInstances.length - idx);
+ }
+ m_instanceListeners = newInstances;
+ }
+ }
}
// ===================== end Lifecycle management =====================
@@ -398,7 +482,7 @@
if (idx >= 0) {
if ((m_pojoObjects.length - 1) == 0) {
- m_pojoObjects = new Element[0];
+ m_pojoObjects = new Object[0];
} else {
Object[] newInstances = new Object[m_pojoObjects.length - 1];
System.arraycopy(m_pojoObjects, 0, newInstances, 0, idx);
@@ -479,8 +563,6 @@
e.printStackTrace();
}
- m_factory.getLogger().log(Logger.INFO, "[" + m_name + "] createInstance -> Return the instance " + instance);
-
// Register the new instance
addInstance(instance);
// Call createInstance on Handlers :
@@ -689,13 +771,14 @@
* Check the state of all handlers.
*/
public void checkInstanceState() {
- m_factory.getLogger().log(Logger.INFO, "[" + m_name + "] Check the instance state");
+ if (!isStarted()) { return; }
+
boolean isValid = true;
for (int i = 0; i < m_handlers.length; i++) {
boolean b = m_handlers[i].isValid();
isValid = isValid && b;
}
-
+
// Update the component state if necessary
if (!isValid && m_state == VALID) {
// Need to update the state to UNRESOLVED
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/InstanceStateListener.java b/ipojo/src/main/java/org/apache/felix/ipojo/InstanceStateListener.java
new file mode 100644
index 0000000..ca2659f
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/InstanceStateListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ * Instance state listener.
+ * This listener allows anyone to be notified when the listened instance state changes.
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface InstanceStateListener {
+
+ /**
+ * State change listener.
+ * Each time an instance state change, this method is called.
+ * @param instance : changing instance
+ * @param newState : new instance state
+ */
+ void stateChanged(ComponentInstance instance, int newState);
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java b/ipojo/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
index 2e6c55d..eef38a1 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
@@ -212,6 +212,9 @@
if (m_state == ComponentInstance.INVALID) {
instance.addAttribute(new Attribute("state", "invalid"));
}
+ if (m_state == ComponentInstance.DISPOSED) {
+ instance.addAttribute(new Attribute("state", "disposed"));
+ }
// Bundle
instance.addAttribute(new Attribute("bundle", "" + m_bundleId));
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java
index 857e123..0c2df57 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/ServiceRegistry.java
@@ -242,8 +242,7 @@
ServiceReference[] refs = getServiceReferences(clazz, null);
if (refs != null) {
return refs[0];
- } // If the refs != null we are sure that it exist one
- // references or more.
+ } // If the refs != null we are sure that it exists one reference or more.
} catch (InvalidSyntaxException ex) {
System.err.println("Scope Service Registry : Problem when look for service reference" + ex.getMessage());
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
new file mode 100644
index 0000000..568c985
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
@@ -0,0 +1,414 @@
+/*
+ * 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.composite.instance;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.CompositeHandler;
+import org.apache.felix.ipojo.CompositeManager;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.InstanceStateListener;
+import org.apache.felix.ipojo.ServiceContext;
+import org.apache.felix.ipojo.UnacceptableConfiguration;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Composite Instance Handler.
+ * This handler allo to create an instance inside a composite.
+ * This instance is determine by its type and a configuration.
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class InstanceHandler extends CompositeHandler implements ServiceListener, InstanceStateListener {
+
+ /**
+ * Bundle context.
+ */
+ private BundleContext m_context;
+
+ /**
+ * Internal context.
+ */
+ private ServiceContext m_scope;
+
+ /**
+ * Instance logger.
+ */
+ private Logger m_logger;
+
+ /**
+ * Composite Manager.
+ */
+ private CompositeManager m_manager;
+
+ /**
+ * IS the handler valid ?
+ */
+ private boolean m_validity = false;
+
+ /**
+ * This structure aims to manage a configuration. It stores all necessary
+ * information to create an instance and to track the factory.
+ */
+ private class ManagedConfiguration {
+ /**
+ * Configuration of the instance to create.
+ */
+ private Dictionary m_configuration;
+
+ /**
+ * Factory name.
+ */
+ private String m_factoryName;
+
+ /**
+ * Created instance.
+ */
+ private ComponentInstance m_instance;
+
+ /**
+ * Constructor.
+ *
+ * @param conf : the configuration to create.
+ */
+ ManagedConfiguration(Dictionary conf) {
+ m_configuration = conf;
+ }
+
+ /**
+ * Return the managed configuration.
+ * @return the configuration.
+ */
+ Dictionary getConfiguration() {
+ return m_configuration;
+ }
+
+ /**
+ * Return the used factory name.
+ * @return the factory
+ */
+ String getFactory() {
+ return m_factoryName;
+ }
+
+ /**
+ * Return the created instance.
+ * @return the instance (or null if no instance are created).
+ */
+ ComponentInstance getInstance() {
+ return m_instance;
+ }
+
+ /**
+ * Set the factory name.
+ *
+ * @param name : the factory name.
+ */
+ void setFactory(String name) {
+ m_factoryName = name;
+ }
+
+ /**
+ * Set the instance object.
+ *
+ * @param instance : the instance
+ */
+ void setInstance(ComponentInstance instance) {
+ m_instance = instance;
+ }
+ }
+
+ /**
+ * Configurations to create and maintains.
+ */
+ private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
+
+ /**
+ * Create an instance using the given factory and the given configuration.
+ *
+ * @param fact : the facotry name to used.
+ * @param config : the configuration.
+ */
+ private void createInstance(Factory fact, ManagedConfiguration config) {
+ Dictionary conf = config.getConfiguration();
+ try {
+ config.setInstance(fact.createComponentInstance(conf, m_scope));
+ config.setFactory(fact.getName());
+ config.getInstance().addInstanceStateListener(this);
+ } catch (UnacceptableConfiguration e) {
+ m_logger.log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
+ }
+ }
+
+ /**
+ * Service Listener implementation.
+ * @param ev : the service event
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent ev) {
+ ServiceReference ref = ev.getServiceReference();
+ String factoryName = (String) ref.getProperty(org.osgi.framework.Constants.SERVICE_PID);
+ String componentClass = (String) ref.getProperty("component.class");
+ boolean implicated = false;
+ if (ev.getType() == ServiceEvent.REGISTERED) {
+ 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))) {
+ Factory fact = (Factory) m_context.getService(ref);
+ createInstance(fact, m_configurations[i]);
+ implicated = true;
+ }
+ }
+ if (implicated && !m_validity && checkValidity()) {
+ m_manager.checkInstanceState();
+ }
+ return;
+ }
+
+ if (ev.getType() == ServiceEvent.UNREGISTERING) {
+ for (int i = 0; i < m_configurations.length; i++) {
+ if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factoryName)) {
+ m_configurations[i].setInstance(null);
+ m_configurations[i].setFactory(null);
+ m_context.ungetService(ref);
+ implicated = true;
+ }
+ }
+ if (implicated && m_validity && !checkValidity()) {
+ m_manager.checkInstanceState();
+ }
+ return;
+ }
+ }
+
+ /**
+ * Stop all created instances.
+ */
+ public synchronized void stop() {
+ m_context.removeServiceListener(this);
+ for (int i = 0; i < m_configurations.length; i++) {
+ if (m_configurations[i].getInstance() != null) {
+ m_configurations[i].getInstance().removeInstanceStateListener(this);
+ m_configurations[i].getInstance().dispose();
+ }
+ m_configurations[i].setInstance(null);
+ m_configurations[i].setFactory(null);
+ }
+ m_configurations = null;
+ }
+
+
+ /**
+ * Configrue method.
+ * @param im : instance manager.
+ * @param metadata : component type metadata.
+ * @param configuration : instance configuration.
+ * @see org.apache.felix.ipojo.CompositeHandler#configure(org.apache.felix.ipojo.CompositeManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ */
+ public void configure(CompositeManager im, Element metadata, Dictionary configuration) {
+ m_manager = im;
+ m_context = im.getContext();
+ m_logger = im.getFactory().getLogger();
+ m_scope = im.getServiceContext();
+ Element[] instances = metadata.getElements("instance");
+ m_configurations = new ManagedConfiguration[instances.length];
+ for (int i = 0; i < instances.length; i++) {
+ Dictionary conf = null;
+ try {
+ conf = parseInstance(instances[i]);
+ } catch (ParseException e) {
+ m_logger.log(Logger.ERROR, "An instance cannot be parsed correctly", e);
+ return;
+ }
+ m_configurations[i] = new ManagedConfiguration(conf);
+ }
+
+ if (m_configurations.length > 0) {
+ im.register(this);
+ }
+ }
+
+ /**
+ * Parse an Element to get a dictionary.
+ *
+ * @param instance : the Element describing an instance.
+ * @return : the resulting dictionary
+ * @throws ParseException : occurs when a configuration cannot be parse correctly.
+ */
+ private Dictionary parseInstance(Element instance) throws ParseException {
+ Dictionary dict = new Properties();
+ if (instance.containsAttribute("name")) {
+ dict.put("name", instance.getAttribute("name"));
+ }
+ if (!instance.containsAttribute("component")) {
+ throw new ParseException("An instance does not have the 'component' attribute");
+ }
+
+ dict.put("component", instance.getAttribute("component"));
+
+ for (int i = 0; i < instance.getElements("property").length; i++) {
+ parseProperty(instance.getElements("property")[i], dict);
+ }
+
+ return dict;
+ }
+
+ /**
+ * Parse a property.
+ * @param prop : the current element to parse
+ * @param dict : the dictionary to populate
+ * @throws ParseException : occurs if the proeprty cannot be parsed correctly
+ */
+ private void parseProperty(Element prop, Dictionary dict) throws ParseException {
+ // Check that the property has a name
+ if (!prop.containsAttribute("name")) {
+ throw new ParseException("A property does not have the 'name' attribute");
+ }
+ // Final case : the property element has a 'value' attribute
+ if (prop.containsAttribute("value")) {
+ dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
+ } else {
+ // Recursive case
+ // Check if there is 'property' element
+ Element[] subProps = prop.getElements("property");
+ if (subProps.length == 0) {
+ throw new ParseException("A complex property must have at least one 'property' sub-element");
+ }
+ Dictionary dict2 = new Properties();
+ for (int i = 0; i < subProps.length; i++) {
+ parseProperty(subProps[i], dict2);
+ dict.put(prop.getAttribute("name"), dict2);
+ }
+ }
+ }
+
+ /**
+ * Start method.
+ * @see org.apache.felix.ipojo.CompositeHandler#start()
+ */
+ public void start() {
+ for (int i = 0; i < m_configurations.length; i++) {
+
+ // Get the component type name :
+ String componentType = (String) m_configurations[i].getConfiguration().get("component");
+ Factory fact = null;
+
+ try {
+ String fil = "(|(" + org.osgi.framework.Constants.SERVICE_PID + "=" + componentType + ")(component.class=" + componentType + "))";
+ ServiceReference[] refs = m_context.getServiceReferences(org.apache.felix.ipojo.Factory.class.getName(), fil);
+ if (refs != null) {
+ fact = (Factory) m_context.getService(refs[0]);
+ createInstance(fact, m_configurations[i]);
+ }
+ } catch (InvalidSyntaxException e) {
+ m_logger.log(Logger.ERROR, "Invalid syntax filter for the type : " + componentType, e);
+ }
+ }
+
+ // Register a service listenner on Factory Service
+ try {
+ m_context.addServiceListener(this, "(objectClass=" + Factory.class.getName() + ")");
+ } catch (InvalidSyntaxException e) {
+ m_logger.log(Logger.ERROR, "Invalid syntax filter when registering a listener on Factory Service", e);
+ }
+
+ //Compute validity
+ checkValidity();
+ }
+
+ /**
+ * The handler is valid if all managed instances are created and are valid.
+ * @return true if all managed configuration have been instanciated and are valid.
+ * @see org.apache.felix.ipojo.CompositeHandler#isValid()
+ */
+ public boolean isValid() {
+ return m_validity;
+ }
+
+ /**
+ * Check handler validity.
+ * The method update the m_validity field.
+ * @return the new validity.
+ */
+ private boolean checkValidity() {
+ for (int i = 0; i < m_configurations.length; i++) {
+ if (m_configurations[i].getInstance() == null || m_configurations[i].getInstance().getState() != ComponentInstance.VALID) {
+ m_validity = false;
+ return false;
+ }
+ }
+ m_validity = true;
+ return true;
+ }
+
+ /** Instance state listener.
+ * This method listens when managed instance states change.
+ * @param instance : instance
+ * @param newState : the now state of the given instance
+ * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
+ */
+ public void stateChanged(ComponentInstance instance, int newState) {
+ switch(newState) {
+ case ComponentInstance.DISPOSED :
+ case ComponentInstance.STOPPED :
+ break; // Should not happen
+ case ComponentInstance.VALID :
+ if (! m_validity && checkValidity()) {
+ m_manager.checkInstanceState();
+ }
+ break;
+ case ComponentInstance.INVALID :
+ if (m_validity && ! checkValidity()) {
+ m_manager.checkInstanceState();
+ }
+ }
+ }
+
+ /**
+ * Method returning an instance object of the given componenet type.
+ * This method must be coalled only on 'primitive' type.
+ * @param type : type.
+ * @return an instance object or null if not found.
+ */
+ public Object getObjectFromInstance(String type) {
+ for (int i = 0; i < m_configurations.length; i++) {
+ if (m_configurations[i].getInstance() != null && type.equals(m_configurations[i].getFactory()) && m_configurations[i].getInstance().getState() == ComponentInstance.VALID) {
+ return ((InstanceManager) m_configurations[i].getInstance()).getPojoObject();
+ }
+ }
+ return null;
+ }
+
+ public HandlerDescription getDescription() {
+ //TODO
+ return null;
+ }
+
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
new file mode 100644
index 0000000..4e84b82
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
@@ -0,0 +1,81 @@
+/*
+ * 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.composite.instance;
+
+import java.util.List;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Description of the Instance Handler.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class InstanceHandlerDescription extends HandlerDescription {
+
+ /**
+ * List of managed instances.
+ */
+ private List m_instances;
+
+ /**
+ * Constructor.
+ *
+ * @param arg0 : name of the handler
+ * @param arg1 : validity of the handler
+ * @param insts : list of component instances
+ */
+ public InstanceHandlerDescription(String arg0, boolean arg1, List insts) {
+ super(arg0, arg1);
+ m_instances = insts;
+ }
+
+ /**
+ * Build service instantiator handler description.
+ * @return the handler description
+ * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
+ */
+ public Element getHandlerInfo() {
+ Element instances = super.getHandlerInfo();
+ for (int i = 0; i < m_instances.size(); i++) {
+ ComponentInstance inst = (ComponentInstance) m_instances.get(i);
+ Element instance = new Element("Instance", "");
+ instance.addAttribute(new Attribute("Name", inst.getInstanceName()));
+ String state = null;
+ switch(inst.getState()) {
+ case ComponentInstance.DISPOSED :
+ state = "disposed"; break;
+ case ComponentInstance.STOPPED :
+ state = "stopped"; break;
+ case ComponentInstance.VALID :
+ state = "valid"; break;
+ case ComponentInstance.INVALID :
+ state = "invalid"; break;
+ }
+ instance.addAttribute(new Attribute("State", state));
+ instance.addElement(inst.getInstanceDescription().getDescription());
+ instances.addElement(instances);
+ }
+ return instances;
+ }
+
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java
index d641cb0..b005b20 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorHandler.java
@@ -148,8 +148,8 @@
if (!m_isValid) {
if (isValid()) {
m_manager.checkInstanceState();
+ m_isValid = true;
}
- m_isValid = true;
}
}
@@ -160,8 +160,8 @@
if (m_isValid) {
if (!isValid()) {
m_manager.checkInstanceState();
+ m_isValid = false;
}
- m_isValid = false;
}
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
index 84f0221..57afd00 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
@@ -185,11 +185,10 @@
String k = (String) kk.nextElement();
p.put(k, m_configuration.get(k));
}
-
ComponentInstance instance = factory.createComponentInstance(p);
m_usedRef.put(ref, instance);
m_context.ungetService(ref);
- } catch (UnacceptableConfiguration e) {
+ } catch (Throwable e) {
m_handler.getManager().getFactory().getLogger().log(Logger.ERROR,
"A matching factory (" + ref.getProperty("service.pid") + ") seems to refuse the given configuration : " + e.getMessage());
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
index a2ae734..420190d 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
@@ -27,12 +27,16 @@
import java.util.Map;
import java.util.Set;
+import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.composite.service.provides.manipulation.Manipulator;
import org.apache.felix.ipojo.composite.service.provides.manipulation.POJOWriter;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
/**
* Check and build a compostion, i.e. a pojo containing the composition.
@@ -121,9 +125,34 @@
/**
* Build Available Mappings.
+ * @throws CompositionException : a factory is not available, the composition cannot be checked.
*/
- private void buildAvailableMappingList() {
+ private void buildAvailableMappingList() throws CompositionException {
int index = 0;
+
+ for (int i = 0; i < m_handler.getInstanceType().size(); i++) {
+ String type = (String) m_handler.getInstanceType().get(i);
+ try {
+ ServiceReference[] refs = m_context.getServiceReferences(Factory.class.getName(), "(" + Constants.SERVICE_PID + "=" + type + ")");
+ if (refs == null) {
+ m_handler.getManager().getFactory().getLogger().log(Logger.ERROR, "The factory " + type + " is not available, cannot check the composition");
+ throw new CompositionException("The factory " + type + " needs to be available to check the composition");
+ } else {
+ String className = (String) refs[0].getProperty("component.class");
+ Class impl = m_context.getBundle().loadClass(className);
+ SpecificationMetadata spec = new SpecificationMetadata(impl, type, m_handler);
+ FieldMetadata field = new FieldMetadata(spec);
+ field.setName("_field" + index);
+ Mapping map = new Mapping(spec, field);
+ m_mappings.add(map);
+ index++;
+ }
+ } catch (InvalidSyntaxException e) {
+ m_handler.getManager().getFactory().getLogger().log(Logger.ERROR, "A LDAP filter is not valid : " + e.getMessage());
+ } catch (ClassNotFoundException e) {
+ m_handler.getManager().getFactory().getLogger().log(Logger.ERROR, "The implementation class of a component cannot be loaded : " + e.getMessage());
+ }
+ }
for (int i = 0; i < m_handler.getSpecifications().size(); i++) {
SpecificationMetadata spec = (SpecificationMetadata) m_handler.getSpecifications().get(i);
@@ -140,6 +169,7 @@
index++;
}
}
+
/**
* Build the delegation mapping.
@@ -149,38 +179,56 @@
buildAvailableMappingList();
// Dependency closure is OK, now look for method delegation
- Map/* <MethodMetadata, Mapping> */availableMethods = new HashMap();
+ Map/* <MethodMetadata, Mapping> */availableSvcMethods = new HashMap();
+ Map/* <MethodMetadata, Mapping> */availableInstMethods = new HashMap();
for (int i = 0; i < m_mappings.size(); i++) {
Mapping map = (Mapping) m_mappings.get(i);
SpecificationMetadata spec = map.getSpecification();
for (int j = 0; j < spec.getMethods().size(); j++) {
MethodMetadata method = (MethodMetadata) spec.getMethods().get(j);
- availableMethods.put(method, map);
+ if (spec.isInterface()) {
+ availableSvcMethods.put(method, map);
+ } else {
+ availableInstMethods.put(method, map);
+ }
}
}
- // For each needed method search if available and store the mapping
+ // For each needed method, search if available and store the mapping
for (int j = 0; j < m_specification.getMethods().size(); j++) {
MethodMetadata method = (MethodMetadata) m_specification.getMethods().get(j);
- Set keys = availableMethods.keySet();
+ Set keys = availableInstMethods.keySet(); // Look first in methods contained in the glue code.
Iterator it = keys.iterator();
boolean found = false;
while (it.hasNext() & !found) {
MethodMetadata met = (MethodMetadata) it.next();
if (met.equals(method)) {
found = true;
- FieldMetadata field = ((Mapping) availableMethods.get(met)).getField();
+ FieldMetadata field = ((Mapping) availableInstMethods.get(met)).getField();
field.setUseful(true);
method.setDelegation(field);
- // Test optionality
- if (field.isOptional() && !method.getExceptions().contains("java/lang/UnsupportedOperationException")) {
- m_handler.getManager().getFactory().getLogger().log(Logger.WARNING, "The method " + method.getMethodName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");
+ }
+ }
+ if (!found) { // If not found looks inside method contained in services.
+ keys = availableSvcMethods.keySet(); // Look first in methods contained in the glue code
+ it = keys.iterator();
+ while (it.hasNext() & !found) {
+ MethodMetadata met = (MethodMetadata) it.next();
+ if (met.equals(method)) {
+ found = true;
+ FieldMetadata field = ((Mapping) availableSvcMethods.get(met)).getField();
+ field.setUseful(true);
+ method.setDelegation(field);
+ // Test optionality
+ if (field.isOptional() && !method.getExceptions().contains("java/lang/UnsupportedOperationException")) {
+ m_handler.getManager().getFactory().getLogger().log(Logger.WARNING, "The method " + method.getMethodName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");
+ }
}
}
}
if (!found) {
- throw new CompositionException("Composition non consistent : " + method.getMethodName() + " could not be delegated");
+ throw new CompositionException("Unconsistent composition - the method " + method.getMethodName() + " could not be delegated");
}
}
}
@@ -226,7 +274,7 @@
List fields = getFieldList();
for (int i = 0; i < fields.size(); i++) {
FieldMetadata field = (FieldMetadata) fields.get(i);
- if (field.isUseful()) {
+ if (field.isUseful() && field.getSpecification().isInterface()) {
Element dep = new Element("Dependency", "");
dep.addAttribute(new Attribute("field", field.getName()));
if (field.getSpecification().isOptional()) {
@@ -236,6 +284,19 @@
elem.addElement(dep);
}
}
+
+ Element properties = new Element("properties", "");
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata field = (FieldMetadata) fields.get(i);
+ if (field.isUseful() && ! field.getSpecification().isInterface()) {
+ Element prop = new Element("Property", "");
+ prop.addAttribute(new Attribute("field", field.getName()));
+ properties.addElement(prop);
+ }
+ }
+ if (properties.getElements().length != 0) {
+ elem.addElement(properties);
+ }
// Insert information to metadata
Element manip = new Element("Manipulation", "");
@@ -268,7 +329,7 @@
* Get the field list to use for the delegation.
* @return the field list.
*/
- private List getFieldList() {
+ public List getFieldList() {
List list = new ArrayList();
for (int i = 0; i < m_mappings.size(); i++) {
Mapping map = (Mapping) m_mappings.get(i);
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
index 633bf24..be77541 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.ipojo.composite.service.provides;
+import java.util.List;
import java.util.Properties;
import org.apache.felix.ipojo.ComponentFactory;
@@ -25,7 +26,9 @@
import org.apache.felix.ipojo.CompositeManager;
import org.apache.felix.ipojo.ServiceContext;
import org.apache.felix.ipojo.UnacceptableConfiguration;
+import org.apache.felix.ipojo.composite.instance.InstanceHandler;
import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -79,6 +82,11 @@
* Exporter.
*/
private ServiceExporter m_exports;
+
+ /**
+ * Created instance name.
+ */
+ private String m_instanceName;
/**
* Constructor.
@@ -92,36 +100,28 @@
m_scope = m_manager.getServiceContext();
m_context = m_manager.getContext();
m_composition = new CompositionMetadata(m_manager.getContext(), element, handler, name);
- try {
- m_composition.buildMapping();
- } catch (CompositionException e) {
- return;
- }
}
/**
* Start method.
* Build service implementation type, factory and instance.
+ * @throws CompositionException if a consistent mapping cannot be discovered.
*/
- public void start() {
- String name = m_composition.getSpecificationMetadata().getName() + "Provider";
+ public void start() throws CompositionException {
+ m_composition.buildMapping();
+
+ m_instanceName = m_composition.getSpecificationMetadata().getName() + "Provider";
m_clazz = m_composition.buildPOJO();
- m_metadata = m_composition.buildMetadata(name);
+ m_metadata = m_composition.buildMetadata(m_instanceName);
// Create the factory
m_factory = new ComponentFactory(m_context, m_clazz, m_metadata);
m_factory.start();
- Properties p = new Properties();
- p.put("name", name);
- try {
- m_instance = m_factory.createComponentInstance(p, m_scope);
- } catch (UnacceptableConfiguration e) {
- return;
- }
// Create the exports
- m_exports = new ServiceExporter(m_composition.getSpecificationMetadata().getName(), "(" + Constants.SERVICE_PID + "=" + name + ")", false, false,
+ m_exports = new ServiceExporter(m_composition.getSpecificationMetadata().getName(), "(" + Constants.SERVICE_PID + "=" + m_instanceName + ")", false, false,
m_scope, m_context, this);
+ m_exports.start();
}
/**
@@ -165,9 +165,9 @@
* Unregister published service.
*/
protected void unregister() {
- if (m_exports != null) {
- m_instance.stop();
- m_exports.stop();
+ if (m_instance != null) {
+ m_instance.dispose();
+ m_instance = null;
}
}
@@ -176,11 +176,42 @@
*/
protected void register() {
if (m_exports != null) {
- m_instance.start();
- m_exports.start();
+ if (m_instance != null) { m_instance.dispose(); }
+ Properties p = new Properties();
+ p.put("name", m_instanceName);
+ List fields = m_composition.getFieldList();
+ for (int i = 0; i < fields.size(); i++) {
+ FieldMetadata fm = (FieldMetadata) fields.get(i);
+ if (fm.isUseful() && !fm.getSpecification().isInterface()) {
+ String type = fm.getSpecification().getComponentType();
+ Object o = getObjectByType(type);
+ p.put(fm.getName(), o);
+ }
+ }
+ try {
+ m_instance = m_factory.createComponentInstance(p, m_scope);
+ } catch (UnacceptableConfiguration e) {
+ e.printStackTrace();
+ return;
+ }
}
}
+ /**
+ * Get an object from the given type.
+ * @param type : type
+ * @return an object from an instance of this type or null
+ */
+ private Object getObjectByType(String type) {
+ InstanceHandler h = (InstanceHandler) m_manager.getCompositeHandler("org.apache.felix.ipojo.composite.instance.InstanceHandler");
+ Object o = h.getObjectFromInstance(type);
+ if (o == null) {
+ m_manager.getFactory().getLogger().log(Logger.ERROR, "An instance object cannot be found for the type : " + type);
+ }
+ return o;
+
+ }
+
public String getSpecification() {
return m_composition.getSpecificationMetadata().getName();
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
index 9175f3a..e937b17 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
@@ -27,6 +27,7 @@
import org.apache.felix.ipojo.CompositeManager;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.BundleContext;
/**
@@ -56,6 +57,16 @@
private ArrayList m_managedServices = new ArrayList();
/**
+ * Handler validity. False if
+ */
+ private boolean m_valid = false;
+
+ /**
+ * List of component type.
+ */
+ private ArrayList m_types;
+
+ /**
* Configure the handler.
*
* @param im : the instance manager
@@ -76,6 +87,7 @@
// Compute imports and instances
computeAvailableServices(metadata);
+ computeAvailableTypes(metadata);
for (int i = 0; i < provides.length; i++) {
ProvidedService ps = new ProvidedService(this, provides[i], "" + i);
@@ -94,9 +106,24 @@
public void start() {
for (int i = 0; i < m_managedServices.size(); i++) {
ProvidedService ps = (ProvidedService) m_managedServices.get(i);
- ps.start();
+ try {
+ ps.start();
+ } catch (CompositionException e) {
+ m_manager.getFactory().getLogger().log(Logger.ERROR, "Cannot start the provided service handler", e);
+ m_valid = false;
+ return;
+ }
}
-
+ m_valid = true;
+ }
+
+ /**
+ * Check the handler validity.
+ * @return true if the handler is valid.
+ * @see org.apache.felix.ipojo.CompositeHandler#isValid()
+ */
+ public boolean isValid() {
+ return m_valid;
}
/**
@@ -188,5 +215,23 @@
public HandlerDescription getDescription() {
return new ProvidedServiceHandlerDescription(true, m_managedServices);
}
+
+ /**
+ * Build available instance type.
+ *
+ * @param metadata : composite metadata
+ */
+ private void computeAvailableTypes(Element metadata) {
+ m_types = new ArrayList();
+ Element[] instances = metadata.getElements("instance", "");
+ for (int i = 0; i < instances.length; i++) {
+ String itf = instances[i].getAttribute("component");
+ m_types.add(itf);
+ }
+ }
+
+ public List getInstanceType() {
+ return m_types;
+ }
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
index b007a87..d45c862 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
@@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
@@ -55,6 +56,16 @@
* Is the specification optional?
*/
private boolean m_isOptional = false;
+
+ /**
+ * Is the specification an interface?
+ */
+ private boolean m_isInterface = true;
+
+ /**
+ * Componenet Type.
+ */
+ private String m_componentType = null;
/**
* Reference on the handler.
@@ -141,6 +152,36 @@
m_isAggregate = isAggregate;
m_isOptional = isOptional;
}
+
+ /**
+ * Constructor.
+ * @param c : class
+ * @param type : componenet type
+ * @param psd : the parent handler
+ */
+ public SpecificationMetadata(Class c, String type, ProvidedServiceHandler psd) {
+ m_handler = psd;
+ m_isAggregate = false;
+ m_isOptional = false;
+ m_componentType = type;
+ m_name = c.getName();
+ Method[] methods = c.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ String desc = Type.getMethodDescriptor(methods[i]);
+ MethodMetadata method = new MethodMetadata(methods[i].getName(), desc);
+ Type[] args = Type.getArgumentTypes(desc);
+ Class[] exceptionClasses = methods[i].getExceptionTypes();
+ for (int j = 0; j < args.length; j++) {
+ method.addArgument(args[j].getClassName());
+ }
+ for (int j = 0; j < exceptionClasses.length; j++) {
+ method.addException(exceptionClasses[j].getName());
+ }
+
+ addMethod(method);
+ }
+ m_isInterface = false;
+ }
public boolean isAggregate() {
return m_isAggregate;
@@ -149,9 +190,17 @@
public boolean isOptional() {
return m_isOptional;
}
+
+ public boolean isInterface() {
+ return m_isInterface;
+ }
public void setIsOptional(boolean optional) {
m_isOptional = optional;
}
+
+ public String getComponentType() {
+ return m_componentType;
+ }
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/manipulation/POJOWriter.java b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/manipulation/POJOWriter.java
index 2dc57e1..36ae9bc 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/manipulation/POJOWriter.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/composite/service/provides/manipulation/POJOWriter.java
@@ -196,7 +196,11 @@
}
// Invoke
- mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+ if (delegator.getSpecification().isInterface()) {
+ mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+ } else {
+ mv.visitMethodInsn(INVOKEVIRTUAL, delegator.getSpecification().getName().replace('.', '/'), name, desc);
+ }
// Return
writeReturn(Type.getReturnType(desc), mv);
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 4e0b298..b98131b 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -613,8 +613,10 @@
* Stop the dependency.
*/
public void stop() {
+ m_handler.getInstanceManager().getContext().removeServiceListener(this);
+
m_handler.getInstanceManager().getFactory().getLogger().log(Logger.INFO,
- "[" + m_handler.getInstanceManager().getClassName() + "] Stop a dependency on : " + m_specification + " with " + m_strFilter);
+ "[" + m_handler.getInstanceManager().getInstanceName() + "] Stop a dependency on : " + m_specification + " with " + m_strFilter + " (" + m_handler.getInstanceManager() + ")");
m_state = UNRESOLVED;
// Unget all services references
@@ -623,7 +625,6 @@
}
m_ref = new ServiceReference[0];
- m_handler.getInstanceManager().getContext().removeServiceListener(this);
m_clazz = null;
m_services = new Object[0];
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index 9a4c05d..b850a72 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -123,11 +123,7 @@
* Check the validity of the dependencies.
*/
protected void checkContext() {
-
synchronized (this) {
-
- m_manager.getFactory().getLogger().log(Logger.INFO, "[DependencyHandler on " + m_manager.getClassName() + "] Check Context ...");
-
// Store the initial state
int initialState = m_state;
@@ -451,12 +447,9 @@
Dependency dep = m_dependencies[i];
valide = valide & dep.isSatisfied();
if (!valide) {
- m_manager.getFactory().getLogger().log(Logger.INFO,
- "[DependencyHandler on " + m_manager.getClassName() + "] Component Dependencies are not valid : " + dep.getSpecification());
return false;
}
}
- m_manager.getFactory().getLogger().log(Logger.INFO, "[DependencyHandler on " + m_manager.getClassName() + "] Component Dependencies are valid");
return valide;
}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/util/Logger.java b/ipojo/src/main/java/org/apache/felix/ipojo/util/Logger.java
index a04a59c..364212a 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/util/Logger.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/util/Logger.java
@@ -32,8 +32,6 @@
*/
public class Logger implements ServiceListener {
- // TODO how to stop the logging (remove listener ...)
-
/**
* Log Level ERROR.
*/