Commit the new iPOJO version (0.7.6).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@642265 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/composite/pom.xml b/ipojo/composite/pom.xml
new file mode 100644
index 0000000..222dc6d
--- /dev/null
+++ b/ipojo/composite/pom.xml
@@ -0,0 +1,120 @@
+<!--

+	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.

+-->

+<project>

+	<parent>

+		<artifactId>iPOJO</artifactId>

+		<groupId>org.apache.felix</groupId>

+		<version>0.7.6-SNAPSHOT</version>

+		<relativePath>../pom.xml</relativePath>

+	</parent>

+	<modelVersion>4.0.0</modelVersion>

+	<packaging>bundle</packaging>

+	<name>Apache Felix iPOJO Composite</name>

+	<artifactId>org.apache.felix.ipojo.composite</artifactId>

+	<dependencies>

+		<dependency>

+			<groupId>${pom.groupId}</groupId>

+			<artifactId>org.osgi.core</artifactId>

+			<version>1.0.0</version>

+		</dependency>

+		<dependency>

+			<groupId>${pom.groupId}</groupId>

+			<artifactId>org.osgi.compendium</artifactId>

+			<version>1.0.0</version>

+		</dependency>

+		<dependency>

+			<groupId>${pom.groupId}</groupId>

+			<artifactId>org.apache.felix.ipojo.metadata</artifactId>

+			<version>${pom.version}</version>

+		</dependency>

+		<dependency>

+			<groupId>${pom.groupId}</groupId>

+			<artifactId>org.apache.felix.ipojo.manipulator</artifactId>

+			<version>${pom.version}</version>

+		</dependency>

+		<dependency>

+			<groupId>${pom.groupId}</groupId>

+			<artifactId>org.apache.felix.ipojo</artifactId>

+			<version>${pom.version}</version>

+		</dependency>

+	</dependencies>

+	<build>

+		<plugins>

+			<plugin>

+				<groupId>org.apache.felix</groupId>

+				<artifactId>maven-bundle-plugin</artifactId>

+				<version>1.4.0</version>

+				<extensions>true</extensions>

+				<configuration>

+					<instructions>

+						<Bundle-Name>iPOJO Composite</Bundle-Name>

+						<Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>

+						<Bundle-Description>

+							iPOJO Composititon Framework

+						</Bundle-Description>

+						<Import-Package>

+							org.apache.felix.ipojo,

+							org.apache.felix.ipojo.architecture,

+							org.apache.felix.ipojo.context,

+							org.apache.felix.ipojo.metadata,

+							org.apache.felix.ipojo.parser,

+							org.apache.felix.ipojo.util,

+							org.osgi.framework

+						</Import-Package>

+						<Private-Package>

+							org.apache.felix.ipojo.manipulation,

+							org.apache.felix.ipojo.composite.architecture,

+							org.apache.felix.ipojo.composite.service*,

+							org.apache.felix.ipojo.composite.instance,

+							org.apache.felix.ipojo.composite.util,

+							!org.objectweb.asm.xml*,

+							org.objectweb.asm*;-split-package:=merge-first

+						</Private-Package>

+						<Export-Package>

+							org.apache.felix.ipojo.composite;

+							version="0.7.6"

+						</Export-Package>

+						<IPOJO-Extension>

+							composite:org.apache.felix.ipojo.composite.CompositeFactory

+						</IPOJO-Extension>

+						<_donotcopy>

+							(CVS|.svn|.+.bak|~.+|metadata.xml)

+						</_donotcopy>

+					</instructions>

+				</configuration>

+			</plugin>

+			<plugin>

+				<groupId>org.apache.felix</groupId>

+				<artifactId>maven-ipojo-plugin</artifactId>

+				<version>${pom.version}</version>

+				<executions>

+					<execution>

+						<goals>

+							<goal>ipojo-bundle</goal>

+						</goals>

+						<configuration>

+							<metadata>metadata.xml</metadata>

+							<ignoreAnnotations>true</ignoreAnnotations>

+						</configuration>

+					</execution>

+				</executions>

+			</plugin>

+		</plugins>

+	</build>

+</project>

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeFactory.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeFactory.java
new file mode 100644
index 0000000..9c980a1
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeFactory.java
@@ -0,0 +1,178 @@
+/* 

+ * 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;

+

+import java.util.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+

+import org.apache.felix.ipojo.ComponentFactory;

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.Handler;

+import org.apache.felix.ipojo.HandlerManager;

+import org.apache.felix.ipojo.IPojoContext;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.util.Logger;

+import org.apache.felix.ipojo.util.Tracker;

+import org.apache.felix.ipojo.util.TrackerCustomizer;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Constants;

+import org.osgi.framework.InvalidSyntaxException;

+

+/**

+ * The component factory manages component instance objects. This management

+ * consist in creating and managing component instance build with the component

+ * factory. This class could export Factory and ManagedServiceFactory services.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class CompositeFactory extends ComponentFactory implements TrackerCustomizer {

+

+    /**

+     * Tracker used to track required handler factories.

+     */

+    protected Tracker m_tracker;

+

+    /**

+     * Create a composite factory.

+     * @param context : bundle context

+     * @param metadata : metadata of the component to create

+     * @throws ConfigurationException occurs when the element describing the factory is malformed.

+     */

+    public CompositeFactory(BundleContext context, Element metadata) throws ConfigurationException {

+        super(context, metadata);

+    }

+    

+    /**

+     * Check if the metadata are well formed.

+     * @param metadata : metadata

+     * @throws ConfigurationException occurs when the element describing the factory is malformed.

+     * @see org.apache.felix.ipojo.ComponentFactory#check(org.apache.felix.ipojo.metadata.Element)

+     */

+    public void check(Element metadata) throws ConfigurationException {

+        String name = metadata.getAttribute("name");

+        if (name == null) {

+            throw new ConfigurationException("A composite needs a name : " + metadata);

+        }

+    }

+    

+    public String getClassName() { return "composite"; }

+        

+    

+    /**

+     * Compute required handlers.

+     * @return the list of required handler.

+     */

+    public List getRequiredHandlerList() {

+        List list = new ArrayList();

+        Element[] elems = m_componentMetadata.getElements();

+        for (int i = 0; i < elems.length; i++) {

+            Element current = elems[i]; 

+            RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace());

+            if (! list.contains(req)) { list.add(req); }

+        }

+        

+        // Add architecture if architecture != 'false'

+        String arch = m_componentMetadata.getAttribute("architecture");

+        if (arch == null || arch.equalsIgnoreCase("true")) {

+            RequiredHandler req = new RequiredHandler("architecture", null);

+            if (! list.contains(req)) { list.add(req); }

+        }

+        

+        return list;

+    }

+    

+    /**

+     * Stop all the instance managers.

+     */

+    public synchronized void stopping() {

+        if (m_tracker != null) {

+            m_tracker.close();

+        }

+        m_tracker = null;

+    }

+

+    /**

+     * Start all the instance managers.

+     */

+    public synchronized void starting() {

+        if (m_requiredHandlers.size() != 0) {

+            try {

+                String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"

+                    + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + CompositeHandler.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;

+            }

+        }

+    }

+    

+    /**

+     * Create an instance from the current factory.

+     * @param configuration : instance configuration

+     * @param context : bundle context to inject in the instance manager

+     * @param handlers : array of handler object to attached on the instance 

+     * @return the created instance

+     * @throws ConfigurationException either the instance configuration or the instance starting has failed 

+     * @see org.apache.felix.ipojo.ComponentFactory#createInstance(java.util.Dictionary, org.apache.felix.ipojo.IPojoContext, org.apache.felix.ipojo.HandlerManager[])

+     */

+    public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException {

+        CompositeManager inst = new CompositeManager(this, context, handlers);

+        inst.configure(m_componentMetadata, configuration);

+        inst.start();

+        return inst;

+    }

+

+    /**

+     * Reconfigure an existing instance.

+     * @param properties : the new configuration to push.

+     * @throws UnacceptableConfiguration : occurs if the new configuration is

+     * not consistent with the component type.

+     * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.

+     * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)

+     */

+    public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {

+        if (properties == null || properties.get("name") == null) {

+            throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");

+        }

+        String name = (String) properties.get("name");

+        

+        ComponentInstance instance = (CompositeManager) m_componentInstances.get(name);

+        

+        if (instance == null) {

+            return; // The instance does not exist.

+        }

+        

+        instance.reconfigure(properties); // re-configure the component

+    }

+

+    public String getFactoryName() {

+        return m_componentMetadata.getAttribute("name");

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeHandler.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeHandler.java
new file mode 100644
index 0000000..4194fed
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeHandler.java
@@ -0,0 +1,83 @@
+/* 

+ * 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;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.Handler;

+import org.apache.felix.ipojo.util.Logger;

+

+

+/**

+ * Composite Handler Abstract Class. An composite handler need implements these

+ * method to be notified of lifecycle change...

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public abstract class CompositeHandler extends Handler {

+    

+    /**

+     * Composite Handler type.

+     */

+    public static final String HANDLER_TYPE = "composite";

+    

+    /**

+     * Reference on the composite manager.

+     */

+    private CompositeManager m_manager;

+    

+    /**

+     * Composite Factory.

+     */

+    private CompositeFactory m_factory;

+    

+    /**

+     * Set the manager.

+     * This method me be called only once time.

+     * @param instance : the composite manager.

+     */

+    protected final void attach(ComponentInstance instance) {

+        m_manager = (CompositeManager) instance;

+    }

+    

+    public final void setFactory(Factory factory) {

+        m_factory = (CompositeFactory) factory;

+    }

+    

+    public final Logger getLogger() {

+        return m_factory.getLogger();

+    }

+    

+    public final CompositeManager getCompositeManager() {

+        return m_manager;

+    }

+    

+    /**

+     * Get a plugged handler of the same container.

+     * This method must be call only in the start method (or after).

+     * In the configure method, this method can not return a consistent

+     * result as all handlers are not plugged. 

+     * @param name : name of the handler to find (class name). 

+     * @return the composite handler object or null if the handler is not found.

+     */

+    public final Handler getHandler(String name) {

+        return m_manager.getCompositeHandler(name);

+    }

+    

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeManager.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeManager.java
new file mode 100644
index 0000000..00537ea
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeManager.java
@@ -0,0 +1,442 @@
+/* 

+ * 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;

+

+import java.util.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+

+import org.apache.felix.ipojo.ComponentFactory;

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.HandlerFactory;

+import org.apache.felix.ipojo.HandlerManager;

+import org.apache.felix.ipojo.IPojoContext;

+import org.apache.felix.ipojo.InstanceStateListener;

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.architecture.Architecture;

+import org.apache.felix.ipojo.architecture.InstanceDescription;

+import org.apache.felix.ipojo.metadata.Element;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * iPOJO Composite manager. The composite manager class manages one instance of

+ * a component type which is a composition. It manages component lifecycle, and

+ * handlers...

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class CompositeManager implements ComponentInstance, InstanceStateListener {

+

+    /**

+     * The context of the component.

+     */

+    private BundleContext m_context;

+

+    /**

+     * Parent factory (ComponentFactory).

+     */

+    private CompositeFactory m_factory;

+

+    /**

+     * Composite Handler list.

+     */

+    private HandlerManager[] m_handlers = new HandlerManager[0];

+

+    /**

+     * Instance State Listener List.

+     */

+    private List m_listeners = new ArrayList();

+

+    /**

+     * Internal service context of the composition.

+     */

+    private CompositeServiceContext m_internalContext;

+    

+    /**

+     * Name of the component instance.

+     */

+    private String m_name;

+

+    /**

+     * Component state (STOPPED at the beginning).

+     */

+    private int m_state = STOPPED;

+

+    /**

+     * Construct a new Component Manager.

+     * @param factory : the factory managing the instance manager

+     * @param context : the bundle context to give to the instance

+     * @param handlers : the handlers to plug

+     */

+    public CompositeManager(CompositeFactory factory, BundleContext context, HandlerManager[] handlers) {

+        m_factory = factory;

+        m_context = context;

+        // Initialize the service context.

+        m_internalContext = new CompositeServiceContext(m_context, this);

+        m_handlers = handlers;

+    }

+

+    /**

+     * Plug the given handler to the current container.

+     * @param handler : the handler to plug.

+     */

+    public synchronized void addCompositeHandler(HandlerManager handler) {

+        if (m_handlers.length > 0) {

+            HandlerManager[] newInstances = new HandlerManager[m_handlers.length + 1];

+            System.arraycopy(m_handlers, 0, newInstances, 0, m_handlers.length);

+            newInstances[m_handlers.length] = handler;

+            m_handlers = newInstances;

+        } else {

+            m_handlers = new HandlerManager[] { handler };

+        }

+    }

+

+    /**

+     * 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) {

+        synchronized (m_listeners) {

+            m_listeners.add(listener);

+        }

+    }

+

+    /**

+     * Configure the instance manager. Stop the existing handler, clear the

+     * handler list, change the metadata, recreate the handler

+     * 

+     * @param metadata : the component type metadata

+     * @param configuration : the configuration of the instance

+     * @throws ConfigurationException : occurs when the component type are incorrect.

+     */

+    public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {        

+        // 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 < m_handlers.length; i++) {

+            m_handlers[i].init(this, metadata, configuration);

+        }

+    }

+    

+    /** 

+     * Dispose the instance.

+     * @see org.apache.felix.ipojo.ComponentInstance#dispose()

+     */

+    public void dispose() {

+        if (m_state > STOPPED) { stop(); }

+        

+        for (int i = 0; i < m_listeners.size(); i++) {

+            ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, DISPOSED);

+        }

+        

+        m_factory.disposed(this);

+

+        // Cleaning

+        m_state = DISPOSED;

+        for (int i = m_handlers.length - 1; i > -1; i--) {

+            m_handlers[i].dispose();

+        }

+        m_handlers = new HandlerManager[0];

+        m_listeners.clear();

+    }

+

+    /**

+     * Return a specified handler.

+     * @param name : class name of the handler to find

+     * @return : the handler, or null if not found

+     */

+    public CompositeHandler getCompositeHandler(String name) {

+        for (int i = 0; i < m_handlers.length; i++) {

+            HandlerFactory fact = (HandlerFactory) m_handlers[i].getFactory();

+            if (fact.getHandlerName().equals(name) || fact.getComponentDescription().getClassName().equals(name)) {

+                return (CompositeHandler) m_handlers[i].getHandler();

+            }

+        }

+        return null;

+    }

+

+    /**

+     * Get the bundle context used by this instance.

+     * @return the parent context of the instance.

+     * @see org.apache.felix.ipojo.ComponentInstance#getContext()

+     */

+    public BundleContext getContext() {

+        return m_context;

+    }

+

+    /**

+     * Get the factory which create this instance.

+     * @return the factory of the component

+     * @see org.apache.felix.ipojo.ComponentInstance#getFactory()

+     */

+    public ComponentFactory getFactory() {

+        return m_factory;

+    }

+    

+    /**

+     * Get the global bundle context.

+     * @return the global bundle context.

+     */

+    public BundleContext getGlobalContext() {

+        IPojoContext context = (IPojoContext) m_context;

+        return context.getGlobalContext();

+    }

+    

+    /**

+     * Return the instance description of this instance.

+     * @return the instance description.

+     * @see org.apache.felix.ipojo.ComponentInstance#getInstanceDescription()

+     */

+    public InstanceDescription getInstanceDescription() {

+        InstanceDescription desc = new InstanceDescription(m_name, m_state, getContext().getBundle().getBundleId(), m_factory.getComponentDescription());

+        CompositeHandler[] handlers = getRegistredCompositeHandlers();

+        for (int i = 0; i < handlers.length; i++) {

+            desc.addHandler(handlers[i].getDescription());

+        }

+

+        // Get instances description of internal instance

+        ServiceReference[] refs;

+        try {

+            refs = m_internalContext.getServiceReferences(Architecture.class.getName(), null);

+            if (refs != null) {

+                for (int i = 0; i < refs.length; i++) {

+                    Architecture arch = (Architecture) m_internalContext.getService(refs[i]);

+                    desc.addInstance(arch.getInstanceDescription());

+                    m_internalContext.ungetService(refs[i]);

+                }

+            }

+        } catch (InvalidSyntaxException e) {

+            // Cannot happen

+        }

+        return desc;

+    }

+

+    /**

+     * Get the instance name.

+     * @return the instance name

+     * @see org.apache.felix.ipojo.ComponentInstance#getInstanceName()

+     */

+    public String getInstanceName() {

+        return m_name;

+    }

+

+    /**

+     * Get the parent service context.

+     * @return the parent service context.

+     */

+    public ServiceContext getParentServiceContext() {

+        IPojoContext context = (IPojoContext) m_context;

+        return context.getServiceContext();

+    }

+

+    /**

+     * REturn the list of handlers plugged on this instance.

+     * @return the list of the registered handlers.

+     */

+    public CompositeHandler[] getRegistredCompositeHandlers() {

+        CompositeHandler[] handler = new CompositeHandler[m_handlers.length];

+        for (int i = 0; i < m_handlers.length; i++) {

+            handler[i] = (CompositeHandler) m_handlers[i].getHandler();

+        }

+        return handler;

+    }

+    

+    /**

+     * Get the internal service context of this instance.

+     * @return the internal service context.

+     */

+    public ServiceContext getServiceContext() {

+        return m_internalContext;

+    }

+    

+    /**

+     * Get the actual state of the instance.

+     * @return the actual state of the instance

+     * @see org.apache.felix.ipojo.ComponentInstance#getState()

+     */

+    public int getState() {

+        return m_state;

+    }

+    

+    /**

+     * Check if the instance is started.

+     * @return true if the instance is started.

+     * @see org.apache.felix.ipojo.ComponentInstance#isStarted()

+     */

+    public boolean isStarted() {

+        return m_state > STOPPED;

+    }

+

+    /**

+     * Reconfigure the current instance.

+     * @param configuration : the new instance configuration.

+     * @see org.apache.felix.ipojo.ComponentInstance#reconfigure(java.util.Dictionary)

+     */

+    public void reconfigure(Dictionary configuration) {

+        for (int i = 0; i < m_handlers.length; i++) {

+            m_handlers[i].reconfigure(configuration);

+        }

+    }

+

+    /**

+     * 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) {

+        synchronized (m_listeners) {

+            m_listeners.remove(listener);

+        }

+    }

+

+    /**

+     * Set the state of the component. 

+     * if the state changed call the stateChanged(int) method on the handlers.

+     * @param state : new state

+     */

+    public void setState(int state) {

+        if (m_state != state) {

+            if (state > m_state) {

+                // The state increases (Stopped = > IV, IV => V) => invoke handlers from the higher priority to the lower

+                m_state = state;

+                for (int i = 0; i < m_handlers.length; i++) {

+                    m_handlers[i].getHandler().stateChanged(state);

+                }

+            } else {

+                // The state decreases (V => IV, IV = > Stopped, Stopped => Disposed)

+                m_state = state;

+                for (int i = m_handlers.length - 1; i > -1; i--) {

+                    m_handlers[i].getHandler().stateChanged(state);

+                }

+            }

+            

+            for (int i = 0; i < m_listeners.size(); i++) {

+                ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, state);

+            }

+        }

+    }

+

+    /**

+     * Start the instance manager.

+     */

+    public synchronized void start() {

+        if (m_state > STOPPED) {

+            return;

+        } // Instance already started

+

+

+        // The new state of the component is UNRESOLVED

+        m_state = INVALID;

+

+        m_internalContext.start(); // Turn on the factory tracking

+

+        for (int i = 0; i < m_handlers.length; i++) {

+            m_handlers[i].start();

+            m_handlers[i].addInstanceStateListener(this);

+        }

+        

+        for (int i = 0; i < m_handlers.length; i++) {

+            if (m_handlers[i].getState() != VALID) {

+                setState(INVALID);

+                return;

+            }

+        }

+        setState(VALID);

+        

+    }

+

+    /**

+     * 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

+            boolean isValid = true;

+            for (int i = 0; i < m_handlers.length; i++) {

+                isValid = isValid && m_handlers[i].getState() == VALID;

+            }

+            

+            if (isValid) { setState(VALID); }

+        }

+        if (newState == DISPOSED) {

+            kill();

+        }

+    }

+

+    /**

+     * Stop the instance manager.

+     */

+    public synchronized void stop() {

+        if (m_state <= STOPPED) {

+            return;

+        } // Instance already stopped

+

+        setState(INVALID);

+        // Stop all the handlers

+        for (int i = m_handlers.length - 1; i > -1; i--) {

+            m_handlers[i].removeInstanceStateListener(this);

+            m_handlers[i].stop();

+        }

+

+        m_internalContext.stop(); // Turn off the factory tracking

+        m_state = STOPPED;

+        

+        for (int i = 0; i < m_listeners.size(); i++) {

+            ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, STOPPED);

+        }

+    }

+    

+    /**

+     * Kill the current instance.

+     * Only the factory of this instance can call this method.

+     */

+    protected synchronized void kill() {

+        if (m_state > STOPPED) { stop(); }

+        

+        for (int i = 0; i < m_listeners.size(); i++) {

+            ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, DISPOSED);

+        }

+

+        // Cleaning

+        m_state = DISPOSED;

+        

+        for (int i = m_handlers.length - 1; i > -1; i--) {

+            m_handlers[i].dispose();

+        }

+        m_handlers = new HandlerManager[0];

+        m_listeners.clear();

+    }

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
new file mode 100644
index 0000000..1b0ebfc
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
@@ -0,0 +1,482 @@
+/* 

+ * 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;

+

+import java.io.File;

+import java.io.InputStream;

+import java.util.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.IPojoContext;

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.context.ServiceRegistry;

+import org.apache.felix.ipojo.util.Tracker;

+import org.apache.felix.ipojo.util.TrackerCustomizer;

+import org.osgi.framework.Bundle;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.BundleException;

+import org.osgi.framework.BundleListener;

+import org.osgi.framework.Filter;

+import org.osgi.framework.FrameworkListener;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceListener;

+import org.osgi.framework.ServiceReference;

+import org.osgi.framework.ServiceRegistration;

+

+/**

+ * CompositeServiceContext Class. This class provides an implementation of the

+ * service context for composite.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class CompositeServiceContext implements ServiceContext, TrackerCustomizer {

+

+    /**

+     * Structure storing the reference, the factory and the registration.

+     */

+    private class Record {

+        /**

+         * Reference of the represented factory from the external context.

+         */

+        private ServiceReference m_ref;

+        /**

+         * Registration of the factory in the internal context.

+         */

+        private ServiceRegistration m_reg;

+        /**

+         * Represented Factory. 

+         */

+        private FactoryProxy m_fact;

+    }

+

+    /**

+     * List of imported factories.

+     */

+    private List m_factories = new ArrayList();

+    /**

+     * Internal service registry.

+     */

+    private ServiceRegistry m_registry;

+

+    /**

+     * Component Instance who creates this registry.

+     */

+    private ComponentInstance m_instance;

+    

+    /**

+     * Global service context.

+     */

+    private BundleContext m_global;

+    

+    /**

+     * Tracker tracking Factories to import.

+     */

+    private Tracker m_tracker;

+

+    /**

+     * Constructor. This constructor instantiate a service registry with the

+     * given bundle context.

+     * 

+     * @param context : the bundle context

+     */

+    public CompositeServiceContext(BundleContext context) {

+        m_registry = new ServiceRegistry(context);

+        if (context instanceof IPojoContext) {

+            m_global = ((IPojoContext) context).getGlobalContext();

+        } else {

+            m_global = context; // the parent context is the global context

+        }

+    }

+

+    /**

+     * Constructor.

+     * 

+     * @param context : the bundle context

+     * @param instance : the component instance owning this context

+     */

+    public CompositeServiceContext(BundleContext context, ComponentInstance instance) {

+        this(context);

+        m_instance = instance;

+    }

+

+    /**

+     * Add a service listener.

+     * @param arg0 : The service listener to add

+     * @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener)

+     */

+    public void addServiceListener(ServiceListener arg0) {

+        m_registry.addServiceListener(arg0);

+    }

+

+    /**

+     * Add a filtered service listener.

+     * @param arg0 : the service listener object to add

+     * @param arg1 : the LDAP filter for this listener

+     * @throws InvalidSyntaxException : occurs if the LDAP filter is malformed

+     * @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener,

+     * java.lang.String)

+     */

+    public void addServiceListener(ServiceListener arg0, String arg1) throws InvalidSyntaxException {

+        m_registry.addServiceListener(arg0, arg1);

+    }

+

+    /**

+     * Get all service references.

+     * @param arg0 : The required service interface.

+     * @param arg1 : LDAP filter

+     * @return the list of all service reference matching with the query

+     * @throws InvalidSyntaxException : occurs when the given filter is malformed

+     * @see org.apache.felix.ipojo.ServiceContext#getAllServiceReferences(java.lang.String,

+     * java.lang.String)

+     */

+    public ServiceReference[] getAllServiceReferences(String arg0, String arg1) throws InvalidSyntaxException {

+        return m_registry.getAllServiceReferences(arg0, arg1);

+    }

+

+    /**

+     * Get a service object for the given service reference.

+     * @param arg0 : the service reference

+     * @return the service object or null if the reference is no more valid or if the object is not accessible

+     * @see org.apache.felix.ipojo.ServiceContext#getService(org.osgi.framework.ServiceReference)

+     */

+    public Object getService(ServiceReference arg0) {

+        return m_registry.getService(m_instance, arg0);

+    }

+

+    

+    /**

+     * Get a service reference for the required interface.

+     * @param arg0 : the required interface name

+     * @return the service reference or null if no available provider

+     * @see org.apache.felix.ipojo.ServiceContext#getServiceReference(java.lang.String)

+     */

+    public ServiceReference getServiceReference(String arg0) {

+        return m_registry.getServiceReference(arg0);

+    }

+

+    /**

+     * Get all accessible service reference for the given query.

+     * @param clazz : required interface

+     * @param filter : LDAP filter

+     * @return the list (array) of service reference matching with the query.

+     * @throws InvalidSyntaxException : occurs when the LDAP filter is malformed

+     * @see org.apache.felix.ipojo.ServiceContext#getServiceReferences(java.lang.String, java.lang.String)

+     */

+    public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {

+        return m_registry.getServiceReferences(clazz, filter);

+    }

+

+

+    /**

+     * Register a service inside the composite context.

+     * @param arg0 : list of interfaces to register.

+     * @param arg1 : service object

+     * @param arg2 : properties list

+     * @return the service registration

+     * @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)

+     */

+    public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2) {

+        return m_registry.registerService(m_instance, arg0, arg1, arg2);

+    }

+

+    /**

+     * Register a service inside the composite context.

+     * @param arg0 : interface to register.

+     * @param arg1 : service object

+     * @param arg2 : properties list

+     * @return the service registration

+     * @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String, java.lang.Object, java.util.Dictionary)

+     */

+    public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2) {

+        return m_registry.registerService(m_instance, arg0, arg1, arg2);

+    }

+

+    /**

+     * Remove a service listener.

+     * @param arg0 : the service listener to remove

+     * @see org.apache.felix.ipojo.ServiceContext#removeServiceListener(org.osgi.framework.ServiceListener)

+     */

+    public void removeServiceListener(ServiceListener arg0) {

+        m_registry.removeServiceListener(arg0);

+    }

+

+    /**

+     * Unget a service.

+     * @param arg0 the service reference to unget

+     * @return true

+     * @see org.apache.felix.ipojo.ServiceContext#ungetService(org.osgi.framework.ServiceReference)

+     */

+    public boolean ungetService(ServiceReference arg0) {

+        return m_registry.ungetService(m_instance, arg0);

+    }

+

+    /**

+     * Import a factory form the parent to the internal registry.

+     * 

+     * @param ref : the reference of the factory to import.

+     */

+    private void importFactory(ServiceReference ref) {        

+        Record rec = new Record();

+        m_factories.add(rec);

+        Dictionary dict = new Properties();

+        for (int j = 0; j < ref.getPropertyKeys().length; j++) {

+            dict.put(ref.getPropertyKeys()[j], ref.getProperty(ref.getPropertyKeys()[j]));

+        }

+        rec.m_fact = new FactoryProxy((Factory) m_tracker.getService(ref), this);

+        rec.m_reg = registerService(Factory.class.getName(), rec.m_fact, dict);

+        rec.m_ref = ref;

+    }

+

+    /**

+     * Remove a factory of the available factory list.

+     * 

+     * @param ref : the reference on the factory to remove.

+     */

+    private void removeFactory(ServiceReference ref) {

+        for (int i = 0; i < m_factories.size(); i++) {

+            Record rec = (Record) m_factories.get(i);

+            if (rec.m_ref == ref) {

+                if (rec.m_reg != null) {

+                    rec.m_reg.unregister();

+                    rec.m_fact = null;

+                }

+                m_tracker.ungetService(rec.m_ref);

+                m_factories.remove(rec);

+                return;

+            }

+        }

+    }

+

+    /**

+     * Start the registry management.

+     */

+    public void start() {

+        m_tracker = new Tracker(m_global, Factory.class.getName(), this);

+        m_tracker.open();

+    }

+

+    /**

+     * Stop the registry management.

+     */

+    public synchronized void stop() {

+        m_tracker.close();

+        m_registry.reset();

+        for (int i = 0; i < m_factories.size(); i++) {

+            Record rec = (Record) m_factories.get(i);

+            removeFactory(rec.m_ref);

+        }

+        m_tracker = null;

+    }

+

+    /**

+     * Check if the factory list contain the given reference.

+     * 

+     * @param ref : the reference to find.

+     * @return true if the list contains the given reference.

+     */

+    private boolean containsRef(ServiceReference ref) {

+        for (int i = 0; i < m_factories.size(); i++) {

+            Record rec = (Record) m_factories.get(i);

+            if (rec.m_ref == ref) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+    /**

+     * Add a bundle listener.

+     * Delegate on the global bundle context.

+     * @param arg0 : bundle listener to add

+     * @see org.osgi.framework.BundleContext#addBundleListener(org.osgi.framework.BundleListener)

+     */

+    public void addBundleListener(BundleListener arg0) {

+        m_global.addBundleListener(arg0);

+    }

+

+    /**

+     * Add a framework listener.

+     * Delegate on the global bundle context.

+     * @param arg0 : framework listener to add.

+     * @see org.osgi.framework.BundleContext#addFrameworkListener(org.osgi.framework.FrameworkListener)

+     */

+    public void addFrameworkListener(FrameworkListener arg0) {

+        m_global.addFrameworkListener(arg0);

+    }

+

+    /**

+     * Create a LDAP filter.

+     * @param arg0 : String-form of the filter

+     * @return the created filter object

+     * @throws InvalidSyntaxException : if the given argument is not a valid against the LDAP grammar.

+     * @see org.osgi.framework.BundleContext#createFilter(java.lang.String)

+     */

+    public Filter createFilter(String arg0) throws InvalidSyntaxException {

+        return m_global.createFilter(arg0);

+    }

+

+    /**

+     * Get the current bundle.

+     * @return the current bundle

+     * @see org.osgi.framework.BundleContext#getBundle()

+     */

+    public Bundle getBundle() {

+        return m_global.getBundle();

+    }

+

+    /**

+     * Get the bundle object with the given id.

+     * @param bundleId : bundle id

+     * @return the bundle object

+     * @see org.osgi.framework.BundleContext#getBundle(long)

+     */

+    public Bundle getBundle(long bundleId) {

+        return m_global.getBundle(bundleId);

+    }

+

+    /**

+     * Get installed bundles.

+     * @return the list of installed bundles

+     * @see org.osgi.framework.BundleContext#getBundles()

+     */

+    public Bundle[] getBundles() {

+        return m_global.getBundles();

+    }

+

+

+    /**

+     * Get a data file.

+     * @param filename : File name.

+     * @return the File object

+     * @see org.osgi.framework.BundleContext#getDataFile(java.lang.String)

+     */

+    public File getDataFile(String filename) {

+        return m_global.getDataFile(filename);

+    }

+

+    /**

+     * Get a property value.

+     * @param key : key of the asked property

+     * @return the property value (object) or null if no property are associated with the given key

+     * @see org.osgi.framework.BundleContext#getProperty(java.lang.String)

+     */

+    public String getProperty(String key) {

+        return m_global.getProperty(key);

+    }

+

+    /**

+     * Install a bundle.

+     * @param location : URL of the bundle to install

+     * @return the installed bundle

+     * @throws BundleException : if the bundle cannot be installed correctly

+     * @see org.osgi.framework.BundleContext#installBundle(java.lang.String)

+     */

+    public Bundle installBundle(String location) throws BundleException {

+        return m_global.installBundle(location);

+    }

+

+    /**

+     * Install a bundle.

+     * @param location : URL of the bundle to install

+     * @param input : 

+     * @return the installed bundle

+     * @throws BundleException : if the bundle cannot be installed correctly

+     * @see org.osgi.framework.BundleContext#installBundle(java.lang.String, java.io.InputStream)

+     */

+    public Bundle installBundle(String location, InputStream input) throws BundleException {

+        return m_global.installBundle(location, input);

+    }

+

+    /**

+     * Remove a bundle listener.

+     * @param listener : the listener to remove

+     * @see org.osgi.framework.BundleContext#removeBundleListener(org.osgi.framework.BundleListener)

+     */

+    public void removeBundleListener(BundleListener listener) {

+        m_global.removeBundleListener(listener);

+    }

+

+    /**

+     * Remove a framework listener.

+     * @param listener : the listener to remove

+     * @see org.osgi.framework.BundleContext#removeFrameworkListener(org.osgi.framework.FrameworkListener)

+     */

+    public void removeFrameworkListener(FrameworkListener listener) {

+        m_global.removeFrameworkListener(listener);

+    }

+

+    /**

+     * A new factory is detected.

+     * @param reference : service reference

+     * @return true if not already imported.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)

+     */

+    public boolean addingService(ServiceReference reference) {

+        if (!containsRef(reference)) {

+            return true;

+        }

+        return false;

+    }

+    

+    /**

+     * A matching reference has been added. The import factory can now be imported.

+     * @param reference : the added reference.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)

+     */

+    public void addedService(ServiceReference reference) {

+        importFactory(reference);

+    }

+

+    /**

+     * An imported factory is modified.

+     * @param reference : modified reference

+     * @param service : factory object.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)

+     */

+    public void modifiedService(ServiceReference reference, Object service) {

+        for (int i = 0; i < m_factories.size(); i++) {

+            Record rec = (Record) m_factories.get(i);

+            if (rec.m_ref == reference) {

+                Dictionary dict = new Properties();

+                for (int j = 0; j < reference.getPropertyKeys().length; j++) {

+                    dict.put(reference.getPropertyKeys()[j], reference.getProperty(reference.getPropertyKeys()[j]));

+                }

+                rec.m_reg.setProperties(dict);

+                return;

+            }

+        }

+    }

+

+    /**

+     * An imported factory disappears.

+     * @param reference : reference

+     * @param service : factory object.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)

+     */

+    public void removedService(ServiceReference reference, Object service) {

+        if (containsRef(reference)) {

+            removeFactory(reference);

+        }

+        

+    }

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
new file mode 100644
index 0000000..a2a67ba
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
@@ -0,0 +1,173 @@
+/* 

+ * 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;

+

+import java.util.Dictionary;

+import java.util.List;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.FactoryStateListener;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;

+import org.apache.felix.ipojo.metadata.Element;

+import org.osgi.framework.BundleContext;

+

+/**

+ * Bridge representing a Factory inside a composition.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class FactoryProxy implements Factory {

+

+    /**

+     * Delegated factory.

+     */

+    private Factory m_delegate;

+

+    /**

+     * Destination context.

+     */

+    private ServiceContext m_context;

+

+    /**

+     * Constructor.

+     * @param fact : the targeted factory.

+     * @param svcContext : the service context to target.

+     */

+    public FactoryProxy(Factory fact, ServiceContext svcContext) {

+        m_delegate = fact;

+        m_context = svcContext;

+    }

+

+    /**

+     * Create an instance manager (i.e. component type instance).

+     * @param configuration : the configuration properties for this component.

+     * @return the created instance manager.

+     * @throws UnacceptableConfiguration : when a given configuration is not valid.

+     * @throws MissingHandlerException : occurs when the creation failed due to a missing handler (the factory should be invalid)

+     * @throws ConfigurationException : occurs when the creation failed due to a configuration issue

+     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)

+     */

+    public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException,

+            ConfigurationException {

+        return m_delegate.createComponentInstance(configuration, m_context);

+    }

+

+    /**

+     * Create an instance manager (i.e. component type instance). This has these service interaction in the scope given in argument.

+     * @param configuration : the configuration properties for this component.

+     * @param serviceContext : the service context of the component.

+     * @return the created instance manager.

+     * @throws UnacceptableConfiguration : when the given configuration is not valid.

+     * @throws MissingHandlerException : when at least one handler is missing.

+     * @throws ConfigurationException : when an issue occurs during the oconfiguration of the instance.

+     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary, org.apache.felix.ipojo.ServiceContext)

+     */

+    public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration,

+            MissingHandlerException, ConfigurationException {

+        return m_delegate.createComponentInstance(configuration, serviceContext);

+    }

+

+    /**

+     * Get the component type information containing provided service, configuration properties ...

+     * @return the component type information.

+     * @see org.apache.felix.ipojo.Factory#getDescription()

+     */

+    public Element getDescription() {

+        return m_delegate.getDescription();

+    }

+

+    /**

+     * Return the factory name.

+     * @return the name of the factory.

+     * @see org.apache.felix.ipojo.Factory#getName()

+     */

+    public String getName() {

+        return m_delegate.getName();

+    }

+

+    /**

+     * Check if the given configuration is acceptable as a configuration of a component instance.

+     * @param conf : the configuration to test

+     * @return true if the configuration is acceptable

+     * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)

+     */

+    public boolean isAcceptable(Dictionary conf) {

+        return m_delegate.isAcceptable(conf);

+    }

+

+    /**

+     * Reconfigure an instance already created. This configuration need to have the name property to identify the instance.

+     * @param conf : the configuration to reconfigure the instance.

+     * @throws UnacceptableConfiguration : if the given configuration is not consistent for the targeted instance.

+     * @throws MissingHandlerException : when at least one handler is missing

+     * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)

+     */

+    public void reconfigure(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {

+        m_delegate.reconfigure(conf);

+    }

+

+    /**

+     * Add a factory listener.

+     * @param listener : the listener to add.

+     * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)

+     */

+    public void addFactoryStateListener(FactoryStateListener listener) {

+        m_delegate.addFactoryStateListener(listener);

+

+    }

+

+    public List getMissingHandlers() {

+        return m_delegate.getMissingHandlers();

+    }

+

+    public List getRequiredHandlers() {

+        return m_delegate.getRequiredHandlers();

+    }

+

+    /**

+     * Remove a service listener.

+     * @param listener : the listener to remove

+     * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)

+     */

+    public void removeFactoryStateListener(FactoryStateListener listener) {

+        m_delegate.removeFactoryStateListener(listener);

+

+    }

+

+    public ComponentTypeDescription getComponentDescription() {

+        return m_delegate.getComponentDescription();

+    }

+

+    public String getClassName() {

+        return m_delegate.getClassName();

+    }

+

+    public int getState() {

+        return m_delegate.getState();

+    }

+

+    public BundleContext getBundleContext() {

+        return m_delegate.getBundleContext();

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java
new file mode 100644
index 0000000..e5554b1
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/architecture/ArchitectureHandler.java
@@ -0,0 +1,77 @@
+/* 

+ * 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.architecture;

+

+import java.util.Dictionary;

+

+import org.apache.felix.ipojo.architecture.Architecture;

+import org.apache.felix.ipojo.architecture.InstanceDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.metadata.Element;

+

+/**

+ * Composite Architecture Handler.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ArchitectureHandler extends CompositeHandler implements Architecture {

+

+    /**

+     * Name of the component.

+     */

+    private String m_name;

+

+    /**

+     * Configure the handler.

+     * 

+     * @param metadata : the metadata of the component

+     * @param configuration : the 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(Element metadata, Dictionary configuration) {

+        m_name = (String) configuration.get("name");

+    }

+

+    /**

+     * Stop the handler.

+     * @see org.apache.felix.ipojo.Handler#stop()

+     */

+    public void stop() {

+        // Nothing to do.

+    }

+

+    /**

+     * Start the handler.

+     * @see org.apache.felix.ipojo.Handler#start()

+     */

+    public void start() { 

+        info("Start composite architecture handler with " + m_name + " name");

+    }

+

+    /**

+     * Get the instance description.

+     * @return the instance description

+     * @see org.apache.felix.ipojo.architecture.Architecture#getDescription()

+     */

+    public InstanceDescription getInstanceDescription() {

+        return getCompositeManager().getInstanceDescription();

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
new file mode 100644
index 0000000..3443073
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandler.java
@@ -0,0 +1,402 @@
+/* 

+ * 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.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.InstanceManager;

+import org.apache.felix.ipojo.InstanceStateListener;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.parser.ParseException;

+

+/**

+ * Composite Instance Handler.

+ * This handler allows creating an instance inside a composite.

+ * This instance is determine by its type and a configuration.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class InstanceHandler extends CompositeHandler implements InstanceStateListener {

+

+    /**

+     * Internal context.

+     */

+    private ServiceContext m_scope;

+    

+    /**

+     * Available factories.

+     */

+    private Factory[] m_factories;

+    

+

+    /**

+     * This structure aims to manage a configuration. It stores all necessary

+     * information to create an instance and to track the factory.

+     */

+    class ManagedConfiguration {

+        /**

+         * Configuration of the instance to create.

+         */

+        private Dictionary m_configuration;

+

+        /**

+         * Factory name.

+         */

+        private String m_factoryName;

+

+        /**

+         * Created instance.

+         */

+        private ComponentInstance m_instance;

+        

+        /**

+         * Desired Factory (can be the classname).

+         */

+        private String m_desiredFactory;

+

+        /**

+         * Constructor.

+         * 

+         * @param conf : the configuration to create.

+         */

+        ManagedConfiguration(Dictionary conf) {

+            m_configuration = conf;

+            m_desiredFactory = (String) conf.get("component");

+        }

+

+        /**

+         * Return the managed configuration.

+         * @return the configuration.

+         */

+        protected Dictionary getConfiguration() {

+            return m_configuration;

+        }

+

+        /**

+         * Return the used factory name.

+         * @return the factory name

+         */

+        protected String getFactory() {

+            return m_factoryName;

+        }

+        

+        protected String getNeededFactoryName() {

+            return m_desiredFactory;

+        }

+

+        /**

+         * Return the created instance.

+         * @return the instance (or null if no instance are created).

+         */

+        protected ComponentInstance getInstance() {

+            return m_instance;

+        }

+

+        /**

+         * Set the factory name.

+         * 

+         * @param name : the factory name.

+         */

+        protected void setFactory(String name) {

+            m_factoryName = name;

+        }

+

+        /**

+         * Set the instance object.

+         * 

+         * @param instance : the instance

+         */

+        protected 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 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, m_scope));

+            config.setFactory(fact.getName());

+            config.getInstance().addInstanceStateListener(this);

+        } catch (UnacceptableConfiguration e) {

+            error("A factory is available for the configuration but the configuration is not acceptable", e);

+        } catch (MissingHandlerException e) {

+            error("The instance creation has failed, at least one handler is missing", e);

+        } catch (ConfigurationException e) {

+            error("The instance creation has failed, an error during the configuration has occured", e);

+        }

+    }

+    

+    /**

+     * A new valid factory appears.

+     * @param factory : factory.

+     */

+    public void bindFactory(Factory factory) {

+        boolean implicated = false;

+        String factName = factory.getName();

+        String className = factory.getComponentDescription().getClassName();

+        for (int i = 0; i < m_configurations.length; i++) {

+            if (m_configurations[i].getInstance() == null && (m_configurations[i].getNeededFactoryName().equals(factName) || m_configurations[i].getNeededFactoryName().equals(className))) {

+                createInstance(factory, m_configurations[i]);

+                implicated = true;

+            }

+        }

+        if (implicated && ! getValidity()) {

+            checkValidity();

+        }

+    }

+    

+    /**

+     * An existing factory disappears or becomes invalid.

+     * @param factory : factory

+     */

+    public void unbindFactory(Factory factory) {

+        boolean implicated = false;

+        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);

+                implicated = true;

+            }

+        }

+        if (implicated && getValidity()) {

+            checkValidity();

+        }

+    }

+

+    /**

+     * Stop all created instances.

+     */

+    public synchronized void stop() {

+        for (int i = 0; i < m_configurations.length; i++) {

+            if (m_configurations[i].getInstance() != null) {

+                m_configurations[i].getInstance().removeInstanceStateListener(this);

+                if (m_configurations[i].getInstance().getState() != ComponentInstance.DISPOSED) {

+                    m_configurations[i].getInstance().dispose();

+                }

+            }

+            m_configurations[i].setInstance(null);

+            m_configurations[i].setFactory(null);

+        }

+        m_configurations = new ManagedConfiguration[0];

+    }

+

+    /**

+     * Configure method.

+     * @param metadata : component type metadata.

+     * @param configuration : instance configuration.

+     * @throws ConfigurationException : occurs an instance cannot be parsed correctly. 

+     * @see org.apache.felix.ipojo.CompositeHandler#configure(org.apache.felix.ipojo.CompositeManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)

+     */

+    public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {

+        m_scope = getCompositeManager().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) {

+                error("An instance cannot be parsed correctly", e);

+                throw new ConfigurationException("An instance cannot be parsed correctly : " + e.getMessage());

+            }

+            m_configurations[i] = new ManagedConfiguration(conf);

+        }

+    }

+

+    /**

+     * 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.

+     */

+    public static Dictionary parseInstance(Element instance) throws ParseException {

+        Dictionary dict = new Properties();

+        String name = instance.getAttribute("name");

+        if (name != null) {

+            dict.put("name", name);

+        }

+        

+        String comp = instance.getAttribute("component");

+        if (comp == null) { 

+            throw new ParseException("An instance does not have the 'component' attribute"); 

+        } else {

+            dict.put("component", comp);

+        }

+

+        Element[] props = instance.getElements("property");

+        for (int i = 0; props != null && i < props.length; i++) {

+            parseProperty(props[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 property cannot be parsed correctly

+     */

+    public static void parseProperty(Element prop, Dictionary dict) throws ParseException {

+        // Check that the property has a name

+        String name = prop.getAttribute("name");

+        String value = prop.getAttribute("value");

+        if (name == null) { throw new ParseException("A property does not have the 'name' attribute"); }

+        // Final case : the property element has a 'value' attribute

+        if (value == null) {

+            // Recursive case

+            // Check if there is 'property' element

+            Element[] subProps = prop.getElements("property");

+            if (subProps == null) { 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);

+            }

+        } else {

+            dict.put(name, value);

+        }

+    }

+

+    /**

+     * Start method.

+     * @see org.apache.felix.ipojo.CompositeHandler#start()

+     */

+    public void start() { 

+        for (int j = 0; j < m_factories.length; j++) {

+            String factName = m_factories[j].getName();

+            String className = m_factories[j].getClassName(); 

+            for (int i = 0; i < m_configurations.length; i++) {

+                if (m_configurations[i].getInstance() == null && (m_configurations[i].getNeededFactoryName().equals(factName) || m_configurations[i].getNeededFactoryName().equals(className))) {

+                    createInstance(m_factories[j], m_configurations[i]);

+                }

+            }

+        }

+        checkValidity();

+    }

+

+    /**

+     * Check handler validity.

+     * The method update the validaity of the handler.

+     */

+    private void checkValidity() {

+        for (int i = 0; i < m_configurations.length; i++) {

+            if (m_configurations[i].getInstance() == null || m_configurations[i].getInstance().getState() != ComponentInstance.VALID) {

+                setValidity(false);

+                return;

+            }

+        }

+        setValidity(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 (!getValidity()) {

+                    checkValidity();

+                }

+                break;

+            case ComponentInstance.INVALID:

+                if (getValidity()) {

+                    checkValidity();

+                }

+                break;

+            default:

+                break;

+

+        }

+    }

+

+    /**

+     * Method returning an instance object of the given component type.

+     * This method must be called 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())) {

+                if (m_configurations[i].getInstance().getState() == ComponentInstance.VALID) {

+                    return ((InstanceManager) m_configurations[i].getInstance()).getPojoObject();

+                } else {

+                    error("An object cannot be get from the instance of the type " + type + ": invalid instance" + m_configurations[i].getInstance().getInstanceDescription().getDescription());

+                    return null;

+                }

+            }

+        }

+        return null;

+    }

+

+    /**

+     * Return the handler description, i.e. the state of created instances.

+     * @return the handler description.

+     * @see org.apache.felix.ipojo.CompositeHandler#getDescription()

+     */

+    public HandlerDescription getDescription() {

+        List list = new ArrayList();

+        for (int i = 0; i < m_configurations.length; i++) {

+            list.add(m_configurations[i]);

+        }

+        return new InstanceHandlerDescription(this, list);

+    }

+

+    /**

+     * Get the list of used component type.

+     * @return the list containing the used component type

+     */

+    public List getUsedType() {

+        List result = new ArrayList();

+        for (int i = 0; i < m_configurations.length; i++) {

+            result.add(m_configurations[i].getConfiguration().get("component"));

+        }

+        return result;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
new file mode 100644
index 0000000..2be1122
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/instance/InstanceHandlerDescription.java
@@ -0,0 +1,90 @@
+/* 

+ * 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.composite.CompositeHandler;

+import org.apache.felix.ipojo.composite.instance.InstanceHandler.ManagedConfiguration;

+import org.apache.felix.ipojo.metadata.Attribute;

+import org.apache.felix.ipojo.metadata.Element;

+

+/**

+ * Description of the Instance Handler.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class InstanceHandlerDescription extends HandlerDescription {

+

+    /**

+     * List of managed instances.

+     */

+    private List m_instances;

+

+    /**

+     * Constructor.

+     * 

+     * @param handler : handler

+     * @param insts : list of component instances

+     */

+    public InstanceHandlerDescription(CompositeHandler handler, List insts) {

+        super(handler);

+        m_instances = insts;

+    }

+

+    /**

+     * Build 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++) {

+            ManagedConfiguration inst = (ManagedConfiguration) m_instances.get(i);

+            Element instance = new Element("Instance", "");

+            if (inst.getInstance() == null) { 

+                instance.addAttribute(new Attribute("Factory", inst.getConfiguration().get("component").toString()));

+                instance.addAttribute(new Attribute("State", "Not Available"));

+            } else {

+                instance.addAttribute(new Attribute("Factory", inst.getFactory()));

+                instance.addAttribute(new Attribute("Name", inst.getInstance().getInstanceName()));

+                String state = null;

+                switch(inst.getInstance().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;

+                    default :

+                        break;

+                }

+                instance.addAttribute(new Attribute("State", state));

+                instance.addElement(inst.getInstance().getInstanceDescription().getDescription());

+            }

+            instances.addElement(instance);

+        }

+        return instances;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceDependencyHandler.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceDependencyHandler.java
new file mode 100644
index 0000000..76f912c
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceDependencyHandler.java
@@ -0,0 +1,371 @@
+/* 

+ * 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.service.instantiator;

+

+import java.util.ArrayList;

+import java.util.Comparator;

+import java.util.Dictionary;

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.PolicyServiceContext;

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.composite.instance.InstanceHandler;

+import org.apache.felix.ipojo.composite.util.SourceManager;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.parser.ParseException;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.apache.felix.ipojo.util.DependencyStateListener;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.InvalidSyntaxException;

+

+/**

+ * Service Instantiator Class. This handler allows to instantiate service

+ * instance inside the composition.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ServiceDependencyHandler extends CompositeHandler implements DependencyStateListener {

+

+    /**

+     * List of instances to manage.

+     */

+    private List/* <SvcInstance> */m_instances = new ArrayList();

+    

+    /**

+     * List of importers.

+     */

+    private List/* <ServiceImporter> */ m_importers = new ArrayList();

+    

+    /**

+     * Flag indicating if the handler has already finished the start method.

+     */

+    private boolean m_isStarted;

+

+    /**

+     * Source Managers.

+     */

+    private List m_sources;

+    

+    

+    /**

+     * Create a Service instance object form the given Element.

+     * This method parse the given element and configure the service instance object.

+     * @param service : the Element describing the service instance

+     * @throws ConfigurationException : the service instance cannot be created correctly

+     */

+    private void createServiceInstance(Element service) throws ConfigurationException {

+        String spec = service.getAttribute("specification");

+        if (spec == null) {

+            throw new ConfigurationException("Malformed service : the specification attribute is mandatory");

+        }

+        String filter = "(&(!(factory.name=" + getCompositeManager().getFactory().getComponentDescription().getName() + "))(factory.state=1))"; // Cannot reinstantiate yourself

+        String givenFilter = service.getAttribute("filter");

+        if (givenFilter != null) {

+            filter = "(&" + filter + givenFilter + ")"; //NOPMD

+        }

+        

+        Filter fil;

+        try {

+            fil = getCompositeManager().getGlobalContext().createFilter(filter);

+        } catch (InvalidSyntaxException e) {

+            throw new ConfigurationException("Malformed filter " + filter + " : " + e.getMessage());

+        }

+        

+        Properties prop = new Properties();

+        Element[] props = service.getElements("property");

+        for (int k = 0; props != null && k < props.length; k++) {

+            try {

+                InstanceHandler.parseProperty(props[k], prop);

+            } catch (ParseException e) {

+                throw new ConfigurationException("An instance configuration is invalid : " + e.getMessage());

+            }

+        }

+        

+        String aggregate = service.getAttribute("aggregate");

+        boolean agg = aggregate != null && aggregate.equalsIgnoreCase("true");

+        

+        String optional = service.getAttribute("optional");

+        boolean opt = optional != null && optional.equalsIgnoreCase("true");

+        

+        int policy = DependencyModel.getPolicy(service);

+        

+        Comparator cmp = DependencyModel.getComparator(service, getCompositeManager().getGlobalContext());

+        

+        SvcInstance inst = new SvcInstance(this, spec, prop, agg, opt, fil, cmp, policy);

+        m_instances.add(inst);

+        

+        String sources = service.getAttribute("context-source");

+        if (sources != null) {

+            SourceManager source = new SourceManager(sources, filter, inst, getCompositeManager());

+            if (m_sources == null) {

+                m_sources = new ArrayList(1);

+            }

+            m_sources.add(source);

+        }

+    }

+    

+    /**

+     * Create a Service importer object from the given Element.

+     * This method parse the given element and configure the service importer object.

+     * @param imp : Element describing the import

+     * @param confFilter : instance filter customization

+     * @throws ConfigurationException : the service importer cannot be created correctly

+     */

+    private void createServiceImport(Element imp, Dictionary confFilter) throws ConfigurationException {

+        boolean optional = false;

+        boolean aggregate = false;

+        String specification = imp.getAttribute("specification");

+

+        if (specification == null) { 

+            // Malformed import

+            error("Malformed imports : the specification attribute is mandatory");

+            throw new ConfigurationException("Malformed imports : the specification attribute is mandatory");

+        } else {

+            String opt = imp.getAttribute("optional");

+            optional = opt != null && opt.equalsIgnoreCase("true");

+

+            String agg = imp.getAttribute("aggregate");

+            aggregate = agg != null && agg.equalsIgnoreCase("true");

+

+            String original = "(&(objectClass=" + specification + ")(!(instance.name=" + getCompositeManager().getInstanceName() + ")))"; // Cannot import yourself

+            String filter = original;

+            String givenFilter = imp.getAttribute("filter");

+            if (givenFilter != null) {

+                filter = "(&" + filter + givenFilter + ")"; //NOPMD

+            }

+

+            String identitity = imp.getAttribute("id");

+

+            String scope = imp.getAttribute("scope");

+            BundleContext context = getCompositeManager().getGlobalContext(); // Get the default bundle context.

+            if (scope != null) {

+                if (scope.equalsIgnoreCase("global")) {

+                    context = new PolicyServiceContext(getCompositeManager().getGlobalContext(), getCompositeManager().getParentServiceContext(), PolicyServiceContext.GLOBAL);

+                } else if (scope.equalsIgnoreCase("composite")) {

+                    context = new PolicyServiceContext(getCompositeManager().getGlobalContext(), getCompositeManager().getParentServiceContext(), PolicyServiceContext.LOCAL);

+                } else if (scope.equalsIgnoreCase("composite+global")) {

+                    context = new PolicyServiceContext(getCompositeManager().getGlobalContext(), getCompositeManager().getParentServiceContext(), PolicyServiceContext.LOCAL_AND_GLOBAL);

+                }

+            }

+

+            // Configure instance filter if available

+            if (confFilter != null && identitity != null && confFilter.get(identitity) != null) {

+                filter = "(&" + original + (String) confFilter.get(identitity) + ")";

+            }

+

+            Filter fil = null;

+            if (filter != null) {

+                try {

+                    fil = getCompositeManager().getGlobalContext().createFilter(filter);

+                } catch (InvalidSyntaxException e) {

+                    throw new ConfigurationException("A required filter " + filter + " is malformed : " + e.getMessage());

+                }

+            }

+

+            Comparator cmp = DependencyModel.getComparator(imp, getCompositeManager().getGlobalContext());

+            Class spec = DependencyModel.loadSpecification(specification, getCompositeManager().getGlobalContext());

+            int policy = DependencyModel.getPolicy(imp);

+

+            ServiceImporter importer = new ServiceImporter(spec, fil, aggregate, optional, cmp, policy, context, identitity, this);

+            m_importers.add(importer);

+            

+            String sources = imp.getAttribute("context-source");

+            if (sources != null) {

+                SourceManager source = new SourceManager(sources, filter, importer, getCompositeManager());

+                if (m_sources == null) {

+                    m_sources = new ArrayList(1);

+                }

+                m_sources.add(source);

+            }

+            

+        }

+    }

+

+    /**

+     * Configure the handler.

+     * @param metadata : the metadata of the component

+     * @param conf : the instance configuration

+     * @throws ConfigurationException : the specification attribute is missing

+     * @see org.apache.felix.ipojo.CompositeHandler#configure(org.apache.felix.ipojo.CompositeManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)

+     */

+    public void configure(Element metadata, Dictionary conf) throws ConfigurationException {

+        Element[] services = metadata.getElements("subservice");

+        // Get instance filters

+        Dictionary confFilter = null;

+        if (conf.get("requires.filters") != null) {

+            confFilter = (Dictionary) conf.get("requires.filters");

+        }

+        

+        for (int i = 0; i < services.length; i++) {

+            String action = services[i].getAttribute("action");

+            if (action == null) {

+                throw new ConfigurationException("The action attribute must be set to 'instantiate' or 'import'");

+            } else if ("instantiate".equalsIgnoreCase(action)) {

+                createServiceInstance(services[i]);

+            } else if ("import".equalsIgnoreCase(action)) {

+                createServiceImport(services[i], confFilter);

+            } else {

+                throw new ConfigurationException("Unknown action : " + action);

+            }

+            

+            

+

+        }

+    }

+

+    /**

+     * Start the service instantiator handler.

+     * Start all created service instance.

+     * @see org.apache.felix.ipojo.CompositeHandler#start()

+     */

+    public void start() {

+        for (int i = 0; m_sources != null && i < m_sources.size(); i++) {

+            SourceManager source = (SourceManager) m_sources.get(i);

+            source.start();

+        }

+        

+        for (int i = 0; i < m_importers.size(); i++) {

+            ServiceImporter imp = (ServiceImporter) m_importers.get(i);

+            imp.start();

+        }

+        

+        for (int i = 0; i < m_instances.size(); i++) {

+            SvcInstance inst = (SvcInstance) m_instances.get(i);

+            inst.start();

+        }

+

+        isHandlerValid();

+        m_isStarted = true;

+    }

+

+    /**

+     * Check the handler validity.

+     * @see org.apache.felix.ipojo.CompositeHandler#isValid()

+     */

+    private void isHandlerValid() {

+        for (int i = 0; i < m_importers.size(); i++) {

+            ServiceImporter imp = (ServiceImporter) m_importers.get(i);

+            if (imp.getState() != DependencyModel.RESOLVED) {

+                setValidity(false);

+                return;

+            }

+        }

+        

+        for (int i = 0; i < m_instances.size(); i++) {

+            SvcInstance inst = (SvcInstance) m_instances.get(i);

+            if (inst.getState() != DependencyModel.RESOLVED) {

+                setValidity(false);

+                return;

+            }

+        }

+        

+        setValidity(true);

+    }

+

+    /**

+     * Handler stop method.

+     * Stop all created service instance.

+     * @see org.apache.felix.ipojo.CompositeHandler#stop()

+     */

+    public void stop() {

+        for (int i = 0; m_sources != null && i < m_sources.size(); i++) {

+            SourceManager source = (SourceManager) m_sources.get(i);

+            source.stop();

+        }

+        

+        for (int i = 0; i < m_instances.size(); i++) {

+            SvcInstance inst = (SvcInstance) m_instances.get(i);

+            inst.stop();

+        }

+        

+        for (int i = 0; i < m_importers.size(); i++) {

+            ServiceImporter imp = (ServiceImporter) m_importers.get(i);

+            imp.stop();

+        }

+

+        m_isStarted = false;

+    }

+    

+    /**

+     * State change callback.

+     * This method is used to freeze the set of used provider if the static binding policy is used.

+     * @param newState : the new state of the underlying instance

+     * @see org.apache.felix.ipojo.Handler#stateChanged(int)

+     */

+    public void stateChanged(int newState) {

+        // If we are becoming valid and started, check if we need to freeze importers.

+        if (m_isStarted && newState == ComponentInstance.VALID) { 

+            for (int i = 0; i < m_importers.size(); i++) {

+                ServiceImporter imp = (ServiceImporter) m_importers.get(i);

+                if (imp.getBindingPolicy() == DependencyModel.STATIC_BINDING_POLICY) {

+                    imp.freeze();

+                }

+            }

+            

+            for (int i = 0; i < m_instances.size(); i++) {

+                SvcInstance imp = (SvcInstance) m_instances.get(i);

+                if (imp.getBindingPolicy() == DependencyModel.STATIC_BINDING_POLICY) {

+                    imp.freeze();

+                }

+            }

+        }

+    }

+

+    /**

+     * An service instance becomes valid.

+     * @param dep : dependency becoming valid.

+     */

+    public void validate(DependencyModel dep) {

+        if (!getValidity()) {

+            isHandlerValid();

+        }

+    }

+

+    /**

+     * A service instance becomes invalid.

+     * @param dep : dependency becoming valid.

+     */

+    public void invalidate(DependencyModel dep) {

+        if (getValidity()) {

+            isHandlerValid();

+        }

+    }

+

+    /**

+     * Get the service instantiator handler description.

+     * @return the description

+     * @see org.apache.felix.ipojo.CompositeHandler#getDescription()

+     */

+    public HandlerDescription getDescription() {

+        return new ServiceInstantiatorDescription(this, m_instances, m_importers);

+    }

+    

+    public List getInstances() {

+        return m_instances;

+    }

+    

+    public List getRequirements() {

+        return m_importers;

+    }

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceImporter.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceImporter.java
new file mode 100644
index 0000000..019ebb0
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceImporter.java
@@ -0,0 +1,319 @@
+/* 

+ * 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.service.instantiator;

+

+import java.util.ArrayList;

+import java.util.Comparator;

+import java.util.Dictionary;

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.PolicyServiceContext;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.ServiceReference;

+import org.osgi.framework.ServiceRegistration;

+

+/**

+ * Import a service form the parent to the internal service registry.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ServiceImporter extends DependencyModel {

+

+    /**

+     * Reference on the handler.

+     */

+    private ServiceDependencyHandler m_handler;

+

+    private final class Record {

+        /**

+         * External Reference.

+         */

+        private ServiceReference m_ref;

+

+        /**

+         * Internal Registration.

+         */

+        private ServiceRegistration m_reg;

+

+        /**

+         * Exposed Object.

+         */

+        private Object m_svcObject;

+

+        /**

+         * Constructor.

+         * @param ref : service reference.

+         */

+        protected Record(ServiceReference ref) {

+            m_ref = ref;

+        }

+

+        /**

+         * Register the current import.

+         */

+        private void register() {

+            if (m_reg != null) {

+                m_reg.unregister();

+            }

+            m_svcObject = getService(m_ref);

+            m_reg = m_handler.getCompositeManager().getServiceContext().registerService(getSpecification().getName(), m_svcObject, getProps(m_ref));

+        }

+

+        /**

+         * Update the current import.

+         */

+        private void update() {

+            if (m_reg != null) {

+                m_reg.setProperties(getProps(m_ref));

+            }

+        }

+

+        /**

+         * Unregister and release the current import.

+         */

+        private void dispose() {

+            if (m_reg != null) {

+                m_reg.unregister();

+                m_svcObject = null;

+                m_reg = null;

+            }

+            m_ref = null;

+        }

+

+        /**

+         * Test object equality.

+         * @param object : object to confront against the current object.

+         * @return true if the two objects are equals (same service reference).

+         * @see java.lang.Object#equals(java.lang.Object)

+         */

+        public boolean equals(Object object) {

+            if (object instanceof Record) {

+                Record rec = (Record) object;

+                return rec.m_ref == m_ref;

+            }

+            return false;

+        }

+        

+        /**

+         * Hash code method.

+         * @return the hash code by calling the parent method.

+         */

+        public int hashCode() {

+            return super.hashCode();

+        }

+    }

+

+    /**

+     * List of managed records.

+     */

+    private List/*<Record>*/m_records = new ArrayList()/* <Record> */;

+

+    /**

+     * Requirement Id.

+     */

+    private String m_id;

+

+    /**

+     * Is this requirement attached to a service-level requirement.

+     */

+    private boolean m_specLevelReq;

+

+    /**

+     * Is the set of used provider frozen ?

+     */

+    private boolean m_isFrozen;

+

+    /**

+     * Constructor.

+     * 

+     * @param specification : targeted specification

+     * @param filter : LDAP filter

+     * @param multiple : should the importer imports several services ?

+     * @param optional : is the import optional ?

+     * @param cmp : comparator to use for the tracking 

+     * @param policy : resolving policy

+     * @param context : bundle context to use for the tracking (can be a servie context)

+     * @param identitity : requirement id (may be null)

+     * @param handler : handler

+     */

+    public ServiceImporter(Class specification, Filter filter, boolean multiple, boolean optional, Comparator cmp, int policy, BundleContext context, String identitity

+            , ServiceDependencyHandler handler) {

+        super(specification, multiple, optional, filter, cmp, policy, context, handler);

+

+        this.m_handler = handler;

+

+        if (m_id == null) {

+            m_id = super.getSpecification().getName();

+        } else {

+            m_id = identitity;

+        }

+

+    }

+

+    /**

+     * Get the properties for the exposed service from the given reference.

+     * 

+     * @param ref : the reference.

+     * @return the property dictionary

+     */

+    private static Dictionary getProps(ServiceReference ref) {

+        Properties prop = new Properties();

+        String[] keys = ref.getPropertyKeys();

+        for (int i = 0; i < keys.length; i++) {

+            prop.put(keys[i], ref.getProperty(keys[i]));

+        }

+        return prop;

+    }

+

+    /**

+     * Freeze the set of used provider.

+     * This method allow to fix the set of provider when the static binding policy is used.

+     */

+    public void freeze() {

+        m_isFrozen = true;

+    }

+

+    public boolean isFrozen() {

+        return m_isFrozen;

+    }

+

+    /**

+     * Stop the management of the import.

+     */

+    public void stop() {

+

+        super.stop();

+

+        for (int i = 0; i < m_records.size(); i++) {

+            Record rec = (Record) m_records.get(i);

+            rec.dispose();

+        }

+

+        m_records.clear();

+

+    }

+

+    /**

+     * Get the record list using the given reference.

+     * 

+     * @param ref : the reference

+     * @return the list containing all record using the given reference

+     */

+    private List/* <Record> */getRecordsByRef(ServiceReference ref) {

+        List list = new ArrayList();

+        for (int i = 0; i < m_records.size(); i++) {

+            Record rec = (Record) m_records.get(i);

+            if (rec.m_ref == ref) {

+                list.add(rec);

+            }

+        }

+        return list;

+    }

+

+    /**

+     * Build the list of imported service provider.

+     * @return the list of all imported services.

+     */

+    public List getProviders() {

+        List list = new ArrayList();

+        for (int i = 0; i < m_records.size(); i++) {

+            list.add((((Record) m_records.get(i)).m_ref).getProperty("instance.name"));

+        }

+        return list;

+    }

+

+    /**

+     * Set that this dependency is a service level dependency.

+     * This forces the scoping policy to be STRICT. 

+     * @param b

+     */

+    public void setServiceLevelDependency() {

+        m_specLevelReq = true;

+        PolicyServiceContext context = new PolicyServiceContext(m_handler.getCompositeManager().getGlobalContext(), m_handler.getCompositeManager().getParentServiceContext(), PolicyServiceContext.LOCAL);

+        setBundleContext(context);

+    }

+

+    public String getId() {

+        return m_id;

+    }

+

+    public boolean isServiceLevelRequirement() {

+        return m_specLevelReq;

+    }

+

+    /**

+     * On Dependency Reconfiguration notification method.

+     * @param departs : leaving service references.

+     * @param arrivals : new injected service references.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])

+     */

+    public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) {

+        for (int i = 0; departs != null && i < departs.length; i++) {

+            onServiceDeparture(departs[i]);

+        }

+        

+        for (int i = 0; arrivals != null && i < arrivals.length; i++) {

+            onServiceArrival(arrivals[i]);

+        }

+    }

+

+    /**

+     * A new service is injected by the tracker.

+     * This method create a 'Record' and register it.

+     * @param ref : new service reference.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceArrival(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceArrival(ServiceReference ref) {

+        Record rec = new Record(ref);

+        m_records.add(rec);

+        // Always register the reference, as the method is call only when needed. 

+        rec.register();

+    }

+

+    /**

+     * A used service disappears.

+     * This method find the implicated 'Record', dispose it and remove it from the list.

+     * @param ref : leaving service reference.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceDeparture(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceDeparture(ServiceReference ref) {

+        List list = getRecordsByRef(ref);

+        for (int i = 0; i < list.size(); i++) { // Stop the implied record

+            Record rec = (Record) list.get(i);

+            rec.dispose();

+        }

+        m_records.removeAll(list);

+    }

+

+    /**

+     * A used service is modified.

+     * @param ref : modified service reference.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceModification(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceModification(ServiceReference ref) {

+        List list = getRecordsByRef(ref);

+        for (int i = 0; i < list.size(); i++) { // Stop the implied record

+            Record rec = (Record) list.get(i);

+            rec.update();

+        }

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java
new file mode 100644
index 0000000..2125153
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/ServiceInstantiatorDescription.java
@@ -0,0 +1,117 @@
+/* 

+ * 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.service.instantiator;

+

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.metadata.Attribute;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * Description of the Service Creator Handler.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ServiceInstantiatorDescription extends HandlerDescription {

+

+    /**

+     * List of managed service instances.

+     */

+    private List m_instances;

+

+    /**

+     * List of exports.

+     */

+    private List m_imports;

+

+    /**

+     * Constructor.

+     * 

+     * @param handler : composite handler

+     * @param insts : list of service instances

+     * @param imps : list of service importers

+     */

+    public ServiceInstantiatorDescription(CompositeHandler handler, List insts, List imps) {

+        super(handler);

+        m_instances = insts;

+        m_imports = imps;

+    }

+

+    /**

+     * Build service instantiator handler description.

+     * @return the handler description

+     * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()

+     */

+    public Element getHandlerInfo() {

+        Element services = super.getHandlerInfo();

+        for (int i = 0; i < m_imports.size(); i++) {

+            ServiceImporter imp = (ServiceImporter) m_imports.get(i);

+            Element impo = new Element("Requires", "");

+            impo.addAttribute(new Attribute("Specification", imp.getSpecification().getName()));

+            if (imp.getFilter() != null) {

+                impo.addAttribute(new Attribute("Filter", imp.getFilter()));

+            }

+            if (imp.getState() == DependencyModel.RESOLVED) {

+                impo.addAttribute(new Attribute("State", "resolved"));

+                for (int j = 0; j < imp.getProviders().size(); j++) {

+                    Element prov = new Element("Provider", "");

+                    prov.addAttribute(new Attribute("name", (String) imp.getProviders().get(j)));

+                    impo.addElement(prov);

+                }

+            } else {

+                impo.addAttribute(new Attribute("State", "unresolved"));

+            }

+            services.addElement(impo);

+        }

+        

+        for (int i = 0; i < m_instances.size(); i++) {

+            SvcInstance inst = (SvcInstance) m_instances.get(i);

+            Element service = new Element("Service", "");

+            service.addAttribute(new Attribute("Specification", inst.getServiceSpecification()));

+            String state = "unresolved";

+            if (inst.getState() == DependencyModel.RESOLVED) {

+                state = "resolved";

+            }

+            service.addAttribute(new Attribute("State", state));

+            Map map = inst.getMatchingFactories();

+            Set keys = map.keySet();

+            Iterator iterator = keys.iterator();

+            while (iterator.hasNext()) {

+                ServiceReference ref = (ServiceReference) iterator.next();

+                Object object = map.get(ref);

+                if (object != null) {

+                    Element fact = new Element("Factory", "");

+                    fact.addAttribute(new Attribute("Name", ((ComponentInstance) object).getFactory().getName()));

+                    service.addElement(fact);

+                }

+            }

+            services.addElement(service);

+        }

+        return services;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
new file mode 100644
index 0000000..94c0a09
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
@@ -0,0 +1,267 @@
+/* 

+ * 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.service.instantiator;

+

+import java.util.Comparator;

+import java.util.Dictionary;

+import java.util.Enumeration;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Properties;

+import java.util.Set;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;

+import org.apache.felix.ipojo.architecture.PropertyDescription;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.osgi.framework.Filter;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * Manage a service instantiation. This service create component instance providing the required service specification.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class SvcInstance extends DependencyModel {

+

+    /**

+     * Configuration to push to the instance.

+     */

+    private Dictionary m_configuration;

+

+    /**

+     * Handler creating the service instance.

+     */

+    private ServiceDependencyHandler m_handler;

+

+    /**

+     * Map of matching factories Service Reference => instance or null (null if the service reference is not actually used).

+     */

+    private Map /* <ServiceReference, Instance> */m_factories = new HashMap();

+

+    /**

+     * Required specification.

+     */

+    private String m_specification;

+

+    /**

+     * Is the service provider frozen ? (Is used for static biding policy)

+     */

+    private boolean m_isFrozen;

+

+    /**

+     * Constructor.

+     * @param handler : the handler.

+     * @param spec : required specification.

+     * @param conf : instance configuration.

+     * @param isAgg : is the service instance an aggregate service ?

+     * @param isOpt : is the service instance optional ?

+     * @param filt : LDAP filter

+     * @param cmp : comparator to use for the tracking

+     * @param policy : binding policy

+     * @throws ConfigurationException : an attribute cannot be parsed correctly, or is incorrect.

+     */

+    public SvcInstance(ServiceDependencyHandler handler, String spec, Dictionary conf, boolean isAgg, boolean isOpt, Filter filt, Comparator cmp, int policy) throws ConfigurationException {

+        super(Factory.class, isAgg, isOpt, filt, cmp, policy, null, handler);

+

+        m_specification = spec;

+

+        m_handler = handler;

+        setBundleContext(m_handler.getCompositeManager().getServiceContext());

+

+        m_configuration = conf;

+    }

+

+    /**

+     * Stop the service instance.

+     */

+    public void stop() {

+        super.stop();

+

+        Set keys = m_factories.keySet();

+        Iterator iterator = keys.iterator();

+        while (iterator.hasNext()) {

+            ServiceReference ref = (ServiceReference) iterator.next();

+            Object object = m_factories.get(ref);

+            if (object != null) {

+                ((ComponentInstance) object).dispose();

+            }

+        }

+

+        m_factories.clear();

+

+    }

+

+    public boolean isFrozen() {

+        return m_isFrozen;

+    }

+

+    /**

+     * Freeze the set of used provider.

+     * This method is when the static binding policy is applied.

+     */

+    public void freeze() {

+        m_isFrozen = true;

+    }

+

+    /**

+     * Create an instance for the given reference. The instance is not added inside the map.

+     * @param factory : the factory from which we need to create the instance.

+     * @return the created component instance.

+     * @throws ConfigurationException : the instance cannot be configured correctly.

+     * @throws MissingHandlerException : the factory is invalid.

+     * @throws UnacceptableConfiguration : the given configuration is invalid for the given factory.

+     */

+    private ComponentInstance createInstance(Factory factory) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {

+        // Recreate the configuration to avoid sharing.

+        Properties props = new Properties();

+        Enumeration keys = m_configuration.keys();

+        while (keys.hasMoreElements()) {

+            String key = (String) keys.nextElement();

+            props.put(key, m_configuration.get(key));

+        }

+        ComponentInstance instance = null;

+        instance = factory.createComponentInstance(props);

+        return instance;

+    }

+

+    /**

+     * Does the service instance match with the given factory ?

+     * @param fact : the factory to test.

+     * @return true if the factory match, false otherwise.

+     */

+    public boolean match(ServiceReference fact) {

+        // Check if the factory can provide the specification

+        ComponentTypeDescription desc = (ComponentTypeDescription) fact.getProperty("component.description");

+        if (desc == null) { 

+            return false; // No component type description.

+        }

+

+        String[] provides = desc.getprovidedServiceSpecification();

+        for (int i = 0; provides != null && i < provides.length; i++) {

+            if (provides[i].equals(m_specification)) {

+                // Check that the factory needs every properties contained in

+                // the configuration

+                PropertyDescription[] props = desc.getProperties();

+                Properties conf = new Properties();

+                Enumeration keys = m_configuration.keys();

+                while (keys.hasMoreElements()) {

+                    String key = (String) keys.nextElement();

+                    if (!containsProperty(key, props)) { return false; }

+                    conf.put(key, m_configuration.get(key));

+                }

+

+                Factory factory = (Factory) getService(fact);

+                return factory.isAcceptable(conf);

+            }

+        }

+        return false;

+    }

+

+    /**

+     * Does the factory support the given property ? This method check if the property is contained in the given property description array.

+     * @param name : name of the property

+     * @param props : list of property description

+     * @return true if the factory support this property

+     */

+    private boolean containsProperty(String name, org.apache.felix.ipojo.architecture.PropertyDescription[] props) {

+        for (int i = 0; props != null && i < props.length; i++) {

+            if (props[i].getName().equalsIgnoreCase(name)) { return true; }

+        }

+        if (name.equalsIgnoreCase("name")) { return true; } // Skip the name property

+        return false;

+    }

+

+    /**

+     * Get the required specification.

+     * @return the required specification.

+     */

+    public String getServiceSpecification() {

+        return m_specification;

+    }

+

+    /**

+     * Get the map of used references [reference, component instance].

+     * @return the map of used references.

+     */

+    protected Map getMatchingFactories() {

+        return m_factories;

+    }

+

+    /**

+     * On Dependency Reconfiguration notification method.

+     * @param departs : leaving service references.

+     * @param arrivals : new injected service references.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])

+     */

+    public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) {

+        for (int i = 0; departs != null && i < departs.length; i++) {

+            onServiceDeparture(departs[i]);

+        }

+        

+        for (int i = 0; arrivals != null && i < arrivals.length; i++) {

+            onServiceArrival(arrivals[i]);

+        }

+    }

+

+    /**

+     * A new service is injected.

+     * This method create the sub-service instance in the composite.

+     * @param ref : service reference.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceArrival(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceArrival(ServiceReference ref) {

+        // The given factory matches.

+        try {

+            Factory fact = (Factory) getService(ref);

+            ComponentInstance instance = createInstance(fact);

+            m_factories.put(ref, instance);

+        } catch (UnacceptableConfiguration e) {

+            m_handler.error("A matching factory refuse the actual configuration : " + e.getMessage());

+            m_handler.getCompositeManager().stop();

+        } catch (MissingHandlerException e) {

+            m_handler.error("A matching factory is no more valid : " + e.getMessage());

+            m_handler.getCompositeManager().stop();

+        } catch (ConfigurationException e) {

+            m_handler.error("A matching configuration is refuse by the instance : " + e.getMessage());

+            m_handler.getCompositeManager().stop();

+        }

+

+    }

+

+    

+    /**

+     * A used service is leaving.

+     * This method dispose the created instance.

+     * @param ref : leaving service reference.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceDeparture(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceDeparture(ServiceReference ref) {

+        // Remove the reference is contained

+        Object instance = m_factories.remove(ref);

+        if (instance != null) {

+            ((ComponentInstance) instance).dispose();

+        }

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java
new file mode 100644
index 0000000..9423d3c
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionException.java
@@ -0,0 +1,41 @@
+/* 

+ * 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.service.provides;

+

+/**

+ * Exception occurs when a composition error occurs.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class CompositionException extends Exception {

+    //TODO consider removing this class to use configuration exception.

+    /**

+     * serialVersionUID.

+     */

+    private static final long serialVersionUID = -3063353267573738105L;

+

+    /**

+     * Constructor.

+     * @param message : a message.

+     */

+    public CompositionException(String message) {

+        super(message);

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
new file mode 100644
index 0000000..8ccf749
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
@@ -0,0 +1,359 @@
+/* 

+ * 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.service.provides;

+

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.manipulation.Manipulator;

+import org.apache.felix.ipojo.metadata.Attribute;

+import org.apache.felix.ipojo.metadata.Element;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * Check and build a composition, i.e. a POJO containing the composition.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class CompositionMetadata {

+

+    /**

+     * Implemented composition.

+     */

+    private SpecificationMetadata m_specification;

+

+    /**

+     * Name of the composition.

+     */

+    private String m_name;

+

+    /**

+     * Bundle Context.

+     */

+    private BundleContext m_context;

+

+    /**

+     * Manipulation Metadata.

+     */

+    private Element m_manipulation;

+

+    /**

+     * Reference on the handler.

+     */

+    private ProvidedServiceHandler m_handler;

+

+    /**

+     * List of Mappings.

+     */

+    private List m_mappings = new ArrayList();

+

+    /**

+     * Constructor.

+     * @param context : bundle context

+     * @param description : 'provides' element

+     * @param psh : parent handler 

+     * @param name : name of the composition.

+     */

+    public CompositionMetadata(BundleContext context, Element description, ProvidedServiceHandler psh, String name) {

+        m_context = context;

+        m_handler = psh;

+        // Get the composition name

+        m_name = description.getAttribute("specification") + name;

+

+        // Get implemented service specification

+        String spec = description.getAttribute("specification");

+        m_specification = new SpecificationMetadata(spec, m_context, false, false, m_handler);

+

+        Element[] mappings = description.getElements("delegation");

+        for (int i = 0; mappings != null && i < mappings.length; i++) {

+            String methodName = mappings[i].getAttribute("method");

+            MethodMetadata method = m_specification.getMethodByName(methodName);

+            if (method == null) {

+                m_handler.error("The method " + methodName + " does not exist in the specicifation " + spec);

+                return;

+            }

+

+            if (mappings[i].getAttribute("policy").equalsIgnoreCase("All")) {

+                method.setAllPolicy();

+            }

+        }

+    }

+

+    protected BundleContext getBundleContext() {

+        return m_context;

+    }

+

+    public String getName() {

+        return m_name;

+    }

+

+    public SpecificationMetadata getSpecificationMetadata() {

+        return m_specification;

+    }

+

+    /**

+     * Build Available Mappings.

+     * @throws CompositionException : a factory is not available, the composition cannot be checked.

+     */

+    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(), "(factory.name=" + type + ")");

+                if (refs == null) {

+                    m_handler.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.error("A LDAP filter is not valid : " + e.getMessage());

+            } catch (ClassNotFoundException e) {

+                m_handler.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);

+            FieldMetadata field = new FieldMetadata(spec);

+            field.setName("_field" + index);

+            if (spec.isOptional()) {

+                field.setOptional(true);

+            }

+            if (spec.isAggregate()) {

+                field.setAggregate(true);

+            }

+            Mapping map = new Mapping(spec, field);

+            m_mappings.add(map);

+            index++;

+        }

+    }

+

+    /**

+     * Build the delegation mapping.

+     * @throws CompositionException : occurs when the mapping cannot be inferred correctly

+     */

+    protected void buildMapping() throws CompositionException {

+        buildAvailableMappingList();

+

+        // Dependency closure is OK, now look for method delegation

+        Map/* <MethodMetadata, Mapping> */svcMethods = new HashMap();

+        Map/* <MethodMetadata, Mapping> */instMethods = 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);

+                if (spec.isInterface()) {

+                    svcMethods.put(method, map);

+                } else {

+                    instMethods.put(method, map);

+                }

+            }

+        }

+

+        // 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 = instMethods.keySet(); // Look first in methods contained in the glue code.

+            Iterator iterator = keys.iterator();

+            boolean found = false;

+            while (iterator.hasNext() & !found) {

+                MethodMetadata met = (MethodMetadata) iterator.next();

+                if (met.equals(method)) {

+                    found = true;

+                    FieldMetadata field = ((Mapping) instMethods.get(met)).getField();

+                    field.setUseful(true);

+                    method.setDelegation(field);

+                }

+            }

+            if (!found) { // If not found looks inside method contained in services.

+                keys = svcMethods.keySet(); // Look first in methods contained in the glue code

+                iterator = keys.iterator();

+                while (!found && iterator.hasNext()) {

+                    MethodMetadata met = (MethodMetadata) iterator.next();

+                    if (met.equals(method)) {

+                        found = true;

+                        FieldMetadata field = ((Mapping) svcMethods.get(met)).getField();

+                        field.setUseful(true);

+                        method.setDelegation(field);

+                        // Test optional

+                        if (field.isOptional() && !method.throwsUnsupportedOperationException()) {

+                            m_handler.warn("The method " + method.getMethod().getName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");

+                        }

+                    }

+                }

+            }

+            if (!found) { throw new CompositionException("Inconsistent composition - the method " + method.getMethod() + " could not be delegated"); }

+        }

+    }

+

+    /**

+     * Build a service implementation.

+     * @return the byte[] of the POJO.

+     */

+    protected byte[] buildPOJO() {

+        Class clazz = null;

+        try {

+            clazz = getBundleContext().getBundle().loadClass(m_specification.getName());

+        } catch (ClassNotFoundException e1) {

+            // The class has already be loaded.

+            return null;

+        }

+        byte[] pojo = POJOWriter.dump(clazz, m_name, getFieldList(), getMethodList());

+        Manipulator manipulator = new Manipulator();

+        try {

+            byte[] newclazz = manipulator.manipulate(pojo);

+            m_manipulation = manipulator.getManipulationMetadata();

+            return newclazz;

+        } catch (IOException e) {

+            m_handler.error("An error occurs during the composite implementation creation : " + e.getMessage(), e);

+        }

+        return null;

+    }

+

+    /**

+     * Build service implementation metadata.

+     * @param name : name of the future instance (used to avoid cycle)

+     * @return Component Type metadata. 

+     */

+    protected Element buildMetadata(String name) {

+        Element elem = new Element("component", "");

+        Attribute className = new Attribute("className", m_name);

+        Attribute factory = new Attribute("factory", "false");

+        elem.addAttribute(className);

+        elem.addAttribute(factory);

+

+        // Add architecture for debug

+        elem.addAttribute(new Attribute("architecture", "true"));

+

+        // Provides

+        Element provides = new Element("provides", "");

+        provides.addAttribute(new Attribute("specification", m_specification.getName()));

+        elem.addElement(provides);

+

+        // Dependencies

+        List fields = getFieldList();

+        for (int i = 0; i < fields.size(); i++) {

+            FieldMetadata field = (FieldMetadata) fields.get(i);

+            if (field.isUseful() && field.getSpecification().isInterface()) {

+                Element dep = new Element("requires", "");

+                dep.addAttribute(new Attribute("field", field.getName()));

+                dep.addAttribute(new Attribute("scope", "composite"));

+                if (field.getSpecification().isOptional()) {

+                    dep.addAttribute(new Attribute("optional", "true"));

+                }

+                dep.addAttribute(new Attribute("filter", "(!(instance.name=" + name + "))"));

+                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

+        elem.addElement(m_manipulation);

+

+        return elem;

+    }

+

+    /**

+     * Get the field list to use for the delegation.

+     * @return the field list.

+     */

+    public List getFieldList() {

+        List list = new ArrayList();

+        for (int i = 0; i < m_mappings.size(); i++) {

+            Mapping map = (Mapping) m_mappings.get(i);

+            list.add(map.getField());

+        }

+        return list;

+    }

+

+    /**

+     * Get the method list contained in the implemented specification.

+     * @return the List of implemented method.

+     */

+    private List getMethodList() {

+        return m_specification.getMethods();

+    }

+

+    /**

+     * Store links between Field and pointed Specification.

+     */

+    private class Mapping {

+

+        /**

+         * Specification.

+         */

+        private SpecificationMetadata m_spec;

+

+        /**

+         * Field.

+         */

+        private FieldMetadata m_field;

+

+        /**

+         * Constructor.

+         * @param spec : specification metadata.

+         * @param field : the field.

+         */

+        public Mapping(SpecificationMetadata spec, FieldMetadata field) {

+            m_spec = spec;

+            m_field = field;

+        }

+

+        public SpecificationMetadata getSpecification() {

+            return m_spec;

+        }

+

+        public FieldMetadata getField() {

+            return m_field;

+        }

+

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java
new file mode 100644
index 0000000..4df41a8
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/FieldMetadata.java
@@ -0,0 +1,105 @@
+/* 

+ * 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.service.provides;

+

+/**

+ * Field used inside a composition.

+ * This class contains all information useful for the generation.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class FieldMetadata {

+

+    /**

+     * Name of the field.

+     */

+    private String m_name;

+

+    /**

+     * Is the field an array?

+     */

+    private boolean m_isAggregate = false;

+

+    /**

+     * Interface of the field.

+     */

+    private SpecificationMetadata m_specification;

+

+    /**

+     * Is the field useful in this composition.

+     */

+    private boolean m_isUseful;

+

+    /**

+     * Is the dependency for this field optional.

+     */

+    private boolean m_isOptional = false;

+

+    /**

+     * Constructor.

+     * @param specification : interface of the field.

+     */

+    public FieldMetadata(SpecificationMetadata specification) {

+        super();

+        this.m_specification = specification;

+        if (m_specification.isAggregate()) {

+            m_isAggregate = true;

+        }

+    }

+

+    public boolean isAggregate() {

+        return m_isAggregate;

+    }

+

+    public void setAggregate(boolean aggregate) {

+        m_isAggregate = aggregate;

+    }

+

+    public String getName() {

+        return m_name;

+    }

+

+    public void setName(String name) {

+        this.m_name = name;

+    }

+

+    public SpecificationMetadata getSpecification() {

+        return m_specification;

+    }

+

+    public void setSpecification(SpecificationMetadata specification) {

+        this.m_specification = specification;

+    }

+

+    public boolean isUseful() {

+        return m_isUseful;

+    }

+

+    public void setUseful(boolean useful) {

+        m_isUseful = useful;

+    }

+

+    public boolean isOptional() {

+        return m_isOptional;

+    }

+

+    public void setOptional(boolean opt) {

+        m_isOptional = opt;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
new file mode 100644
index 0000000..510514e
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
@@ -0,0 +1,138 @@
+/* 

+ * 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.service.provides;

+

+import java.lang.reflect.Method;

+

+/**

+ * Information on Method for the composition.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class MethodMetadata {

+

+    /**

+     * ONE POLICY.

+     */

+    public static final int ONE_POLICY = 1;

+

+    /**

+     * ALL POLICY. 

+     */

+    public static final int ALL_POLICY = 2;

+

+    /**

+     * Method Object.

+     */

+    private Method m_method;

+    

+    /**

+     * Delegation field.

+     */

+    private FieldMetadata m_delegation;

+

+    /**

+     * Delegation policy (default = ONE).

+     */

+    private int m_policy = ONE_POLICY;

+

+    /**

+     * Constructor.

+     * @param method : method object.

+     */

+    public MethodMetadata(Method method) {

+        m_method = method;

+    }

+

+    public Method getMethod() {

+        return m_method;

+    }

+

+    public void setDelegation(FieldMetadata field) {

+        m_delegation = field;

+    }

+

+    public FieldMetadata getDelegation() {

+        return m_delegation;

+    }

+    

+    /**

+     * Equals method.

+     * This method check if two MethodMetadata are equals or if the current MemethodMetadata is equals with a Method object. 

+     * @param object : object.

+     * @return true if the current object and the given object are equals.

+     * @see java.lang.Object#equals(java.lang.Object)

+     */

+    public boolean equals(Object object) {

+        if (object instanceof MethodMetadata) {

+            Method met = ((MethodMetadata) object).getMethod();

+            return equals(met);

+        }

+        

+        if (object instanceof Method) {

+            Method met = (Method) object;

+            if (! met.getName().equals(m_method.getName()) || met.getParameterTypes().length != m_method.getParameterTypes().length) {

+                return false;

+            }

+

+            for (int i = 0; i < m_method.getParameterTypes().length; i++) {

+                if (!m_method.getParameterTypes()[i].getName().equals(met.getParameterTypes()[i].getName())) {

+                    return false;

+                }

+            }

+

+            return true;

+        }

+        

+        return false;

+    }

+    

+    /**

+     * Hash code method.

+     * @return the parent hash code.

+     * @see java.lang.Object#hashCode()

+     */

+    public int hashCode() {

+        return super.hashCode();

+    }

+

+    public int getPolicy() {

+        return m_policy;

+    }

+

+    /**

+     * Activate the all policy for this method.

+     */

+    public void setAllPolicy() {

+        m_policy = ALL_POLICY;

+    }

+    

+    /**

+     * Check if the method can throw UnsupportedOperationException.

+     * @return true if the method has declared the UnsupportedOperationException.

+     */

+    protected boolean throwsUnsupportedOperationException() {

+        for (int i = 0; i < m_method.getExceptionTypes().length; i++) {

+            if (m_method.getExceptionTypes()[i].getName().equals(UnsupportedOperationException.class.getName())) {

+                return true;

+            }

+        }

+        return false;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
new file mode 100644
index 0000000..91ed8cc
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
@@ -0,0 +1,377 @@
+/* 

+ * 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.service.provides;

+

+import java.lang.reflect.Method;

+import java.util.List;

+

+import org.objectweb.asm.ClassWriter;

+import org.objectweb.asm.Label;

+import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

+import org.objectweb.asm.Type;

+

+/**

+ * Create the Proxy class.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class POJOWriter implements Opcodes {

+    

+    //TODO : consider using getOpCode

+    //TODO : fix bug on double-space

+    //TODO : use a logger

+    //TODO : merge this class with another class only static method.

+

+    /**

+     * Create a class.

+     * @param cw : class writer

+     * @param className : class name

+     * @param spec : implemented specification

+     */

+    private static void createClass(ClassWriter cw, String className, String spec) {

+        // Create the class

+        cw.visit(V1_2, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[] { spec.replace('.', '/') });

+    }

+

+    /**

+     * Inject field in the current class.

+     * @param cw : class writer.

+     * @param fields : list of field to inject.

+     */

+    private static void injectFields(ClassWriter cw, List fields) {

+        // Inject fields

+        for (int i = 0; i < fields.size(); i++) {

+            FieldMetadata field = (FieldMetadata) fields.get(i);

+            if (field.isUseful()) {

+                SpecificationMetadata spec = field.getSpecification();

+                String fieldName = field.getName();

+                String desc = "";

+                if (field.isAggregate()) {

+                    desc = "[L" + spec.getName().replace('.', '/') + ";";

+                } else {

+                    desc = "L" + spec.getName().replace('.', '/') + ";";

+                }

+

+                cw.visitField(Opcodes.ACC_PRIVATE, fieldName, desc, null, null);

+            }

+        }

+    }

+

+    /**

+     * Return the proxy 'classname' for the contract 'contractname' by delegating on available service.

+     * @param clazz : Specification class

+     * @param className : The class name to create

+     * @param fields : the list of fields on which delegate

+     * @param methods : the list of method on which delegate

+     * @return byte[] : the build class

+     */

+    public static byte[] dump(Class clazz, String className, List fields, List methods) {

+        Method[] itfmethods = clazz.getMethods();

+

+        // Create the class

+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

+        className = className.replace('.', '/');

+        createClass(cw, className, clazz.getName());

+

+        // Inject fields inside the POJO

+        injectFields(cw, fields);

+

+        // Inject a constructor <INIT>()V

+        MethodVisitor cst = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);

+        cst.visitVarInsn(ALOAD, 0);

+        cst.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");

+        cst.visitInsn(RETURN);

+        cst.visitMaxs(0, 0);

+        cst.visitEnd();

+

+        for (int i = 0; i < itfmethods.length; ++i) {

+            Method method = itfmethods[i];

+

+            // Get the field for this method

+            // 1) find the MethodMetadata

+            FieldMetadata delegator = null; // field to delegate

+            MethodMetadata methodDelegator = null; // field to delegate

+            for (int j = 0; j < methods.size(); j++) {

+                MethodMetadata methodMeta = (MethodMetadata) methods.get(j);

+                if (methodMeta.equals(method)) {

+                    delegator = methodMeta.getDelegation();

+                    methodDelegator = methodMeta;

+                }

+            }

+

+            generateOneMethod(cw, className, methodDelegator, method, delegator);

+

+        }

+

+        // End process

+        cw.visitEnd();

+        return cw.toByteArray();

+    }

+

+    /**

+     * Generate on method.

+     * @param cw : class writer

+     * @param className : the current class name

+     * @param method : the method to generate

+     * @param sign : method signature to generate

+     * @param delegator : the field on which delegate

+     */

+    private static void generateOneMethod(ClassWriter cw, String className, MethodMetadata method, Method sign, FieldMetadata delegator) {

+        String desc = Type.getMethodDescriptor(sign);

+        String name = sign.getName();

+        String[] exc = new String[sign.getExceptionTypes().length];

+        for (int i = 0; i < sign.getExceptionTypes().length; i++) {

+            exc[i] = Type.getType(sign.getExceptionTypes()[i]).getInternalName();

+        }

+

+        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, null, exc);

+

+        if (delegator.isOptional()) {

+            if (!delegator.isAggregate()) {

+                generateOptionalCase(mv, delegator, className);

+            }

+            if (delegator.isAggregate() /*&& method.getPolicy() == MethodMetadata.ONE_POLICY*/) {

+                generateOptionalAggregateCase(mv, delegator, className);

+            }

+        }

+

+        if (delegator.isAggregate()) {

+            if (method.getPolicy() == MethodMetadata.ONE_POLICY) {

+                // Aggregate and One Policy

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+                mv.visitInsn(ICONST_0); // Take the first one

+                mv.visitInsn(AALOAD);

+

+                // Loads args

+                Type[] args = Type.getArgumentTypes(desc);

+                for (int i = 0; i < args.length; i++) {

+                    writeLoad(args[i], i + 1, mv);

+                }

+

+                // Invoke

+                mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);

+

+                // Return

+                writeReturn(Type.getReturnType(desc), mv);

+            } else { // All policy

+                if (Type.getReturnType(desc).getSort() != Type.VOID) {

+                    //TODO use logger.

+                    System.err.println("All policy cannot be used on method which does not return void");

+                }

+

+                Type[] args = Type.getArgumentTypes(desc);

+                int index = args.length + 1;

+

+                // Init

+                mv.visitInsn(ICONST_0);

+                mv.visitVarInsn(ISTORE, index);

+                Label l1b = new Label();

+                mv.visitLabel(l1b);

+                Label l2b = new Label();

+                mv.visitJumpInsn(GOTO, l2b);

+

+                // Loop

+                Label l3b = new Label();

+                mv.visitLabel(l3b);

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+                mv.visitVarInsn(ILOAD, index);

+                mv.visitInsn(AALOAD);

+

+                // Loads args

+                for (int i = 0; i < args.length; i++) {

+                    writeLoad(args[i], i + 1, mv);

+                }

+

+                mv.visitMethodInsn(INVOKEINTERFACE, delegator.getSpecification().getName().replace('.', '/'), name, desc);

+

+                Label l4b = new Label();

+                mv.visitLabel(l4b);

+                mv.visitIincInsn(index, 1); // i++;

+

+                // Condition

+                mv.visitLabel(l2b);

+                mv.visitVarInsn(ILOAD, index);

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+                mv.visitInsn(ARRAYLENGTH);

+                mv.visitJumpInsn(IF_ICMPLT, l3b);

+

+                Label l5b = new Label();

+                mv.visitLabel(l5b);

+                mv.visitInsn(RETURN);

+            }

+        } else {

+            mv.visitVarInsn(ALOAD, 0);

+            mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+

+            // Loads args

+            Type[] args = Type.getArgumentTypes(desc);

+            for (int i = 0; i < args.length; i++) {

+                writeLoad(args[i], i + 1, mv);

+            }

+

+            // Invoke

+            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);

+        }

+

+        mv.visitMaxs(0, 0);

+        mv.visitEnd();

+    }

+

+    /**

+     * Generate Optional Case for aggregate field.

+     * @param mv : method visitor

+     * @param delegator : Field on which delegate

+     * @param className : current class name

+     */

+    private static void generateOptionalAggregateCase(MethodVisitor mv, FieldMetadata delegator, String className) {

+        mv.visitVarInsn(ALOAD, 0);

+        mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "[L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+        mv.visitInsn(ARRAYLENGTH);

+        Label l1a = new Label();

+        mv.visitJumpInsn(IFNE, l1a);

+        Label l2a = new Label();

+        mv.visitLabel(l2a);

+        mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException");

+        mv.visitInsn(DUP);

+        mv.visitLdcInsn("Operation not supported");

+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V");

+        mv.visitInsn(ATHROW);

+        mv.visitLabel(l1a);

+    }

+

+    /**

+     * Generate Optional case for non aggregate fields.

+     * 

+     * @param mv : the method visitor

+     * @param delegator : the field on which delegate.

+     * @param className : the name of the current class.

+     */

+    private static void generateOptionalCase(MethodVisitor mv, FieldMetadata delegator, String className) {

+        mv.visitVarInsn(ALOAD, 0);

+        mv.visitFieldInsn(GETFIELD, className, delegator.getName(), "L" + delegator.getSpecification().getName().replace('.', '/') + ";");

+        mv.visitTypeInsn(INSTANCEOF, "org/apache/felix/ipojo/Nullable");

+        Label end = new Label();

+        mv.visitJumpInsn(IFEQ, end);

+        Label begin = new Label();

+        mv.visitLabel(begin);

+        mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException");

+        mv.visitInsn(DUP);

+        mv.visitLdcInsn("Operation not supported");

+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "(Ljava/lang/String;)V");

+        mv.visitInsn(ATHROW);

+        mv.visitLabel(end);

+    }

+

+    /**

+     * Write a return instruction according to the given type.

+     * @param t : the type

+     * @param mv : the method visitor

+     */

+    private static void writeReturn(Type t, MethodVisitor mv) {

+        switch (t.getSort()) {

+            case Type.BOOLEAN:

+            case Type.INT:

+            case Type.BYTE:

+            case Type.CHAR:

+            case Type.SHORT:

+                // Integer or Boolean : return 0 ( false)

+                mv.visitInsn(IRETURN);

+                break;

+            case Type.LONG:

+                // mv.visitInsn(LCONST_0);

+                mv.visitInsn(LRETURN);

+                break;

+            case Type.DOUBLE:

+                // Double : return 0.0

+                // mv.visitInsn(DCONST_0);

+                mv.visitInsn(DRETURN);

+                break;

+            case Type.FLOAT:

+                // Double : return 0.0

+                // mv.visitInsn(DCONST_0);

+                mv.visitInsn(FRETURN);

+                break;

+            case Type.ARRAY:

+            case Type.OBJECT:

+                // Return always null for array and object

+                // mv.visitInsn(ACONST_NULL);

+                mv.visitInsn(ARETURN);

+                break;

+            case Type.VOID:

+                mv.visitInsn(RETURN);

+                break;

+            default:

+                System.err.println("Type not yet managed : " + t);

+                break;

+        }

+    }

+

+    /**

+     * Write a load instruction according to the given type.

+     * @param t : the type

+     * @param mv : the method visitor

+     * @param index : variable name (index)

+     */

+    private static void writeLoad(Type t, int index, MethodVisitor mv) {

+        switch (t.getSort()) {

+            case Type.BOOLEAN:

+            case Type.INT:

+            case Type.BYTE:

+            case Type.CHAR:

+            case Type.SHORT:

+                // Integer or Boolean : return 0 ( false)

+                mv.visitVarInsn(ILOAD, index);

+                break;

+            case Type.LONG:

+                // mv.visitInsn(LCONST_0);

+                mv.visitVarInsn(LLOAD, index);

+                break;

+            case Type.FLOAT:

+                // mv.visitInsn(LCONST_0);

+                mv.visitVarInsn(FLOAD, index);

+                break;

+            case Type.DOUBLE:

+                // Double : return 0.0

+                // mv.visitInsn(DCONST_0);

+                mv.visitVarInsn(DLOAD, index);

+                break;

+            case Type.ARRAY:

+            case Type.OBJECT:

+                // Return always null for array and object

+                // mv.visitInsn(ACONST_NULL);

+                mv.visitVarInsn(ALOAD, index);

+                break;

+            default:

+                System.err.println("Type not yet managed : " + t);

+                break;

+        }

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
new file mode 100644
index 0000000..f76aea1
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedService.java
@@ -0,0 +1,235 @@
+/* 

+ * 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.service.provides;

+

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentFactory;

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.composite.CompositeManager;

+import org.apache.felix.ipojo.composite.instance.InstanceHandler;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.apache.felix.ipojo.util.DependencyStateListener;

+import org.apache.felix.ipojo.util.Logger;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.InvalidSyntaxException;

+

+/**

+ * Composite Provided Service.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ProvidedService implements DependencyStateListener {

+

+    /**

+     * Composite Manager.

+     */

+    private CompositeManager m_manager;

+

+    /**

+     * Composition Model.

+     */

+    private CompositionMetadata m_composition;

+

+    /**

+     * Internal context.

+     */

+    private ServiceContext m_scope;

+

+    /**

+     * External context.

+     */

+    private BundleContext m_context;

+

+    /**

+     * Created Factory.

+     */

+    private ComponentFactory m_factory;

+

+    /**

+     * Created Instance.

+     */

+    private ComponentInstance m_instance;

+

+    /**

+     * Exporter.

+     */

+    private ServiceExporter m_exports;

+

+    /**

+     * Created instance name.

+     */

+    private String m_instanceName;

+

+    /**

+     * Constructor.

+     * The delegation mapping is infers in this method.

+     * @param handler : the handler.

+     * @param element : 'provides' element.

+     * @param name : name of this provided service.

+     */

+    public ProvidedService(ProvidedServiceHandler handler, Element element, String name) {

+        m_manager = handler.getCompositeManager();

+        m_scope = m_manager.getServiceContext();

+        m_context = m_manager.getContext();

+        m_composition = new CompositionMetadata(m_manager.getContext(), element, handler, name);

+    }

+

+    /**

+     * Start method.

+     * Build service implementation type, factory and instance.

+     * @throws CompositionException if a consistent mapping cannot be discovered.

+     */

+    public void start() throws CompositionException {

+        m_composition.buildMapping();

+

+        m_instanceName = m_composition.getSpecificationMetadata().getName() + "Provider-Gen";

+        byte[] clazz = m_composition.buildPOJO();

+        Element metadata = m_composition.buildMetadata(m_instanceName);

+

+        // Create the factory

+        try {

+            m_factory = new ComponentFactory(m_context, clazz, metadata);

+        } catch (ConfigurationException e) {

+            // Should not happen.

+        }

+        m_factory.start();

+

+        try {

+            Class spec = DependencyModel.loadSpecification(m_composition.getSpecificationMetadata().getName(), m_context);

+            Filter filter = m_context.createFilter("(instance.name=" + m_instanceName + ")");

+            // Create the exports

+            m_exports = new ServiceExporter(spec, filter, false, false, null, DependencyModel.DYNAMIC_BINDING_POLICY, m_scope, m_context, this, m_manager);

+        } catch (InvalidSyntaxException e) {

+            throw new CompositionException("A provided service filter is invalid : " + e.getMessage());

+        } catch (ConfigurationException e) {

+            throw new CompositionException("The class " + m_composition.getSpecificationMetadata().getName() + " cannot be loaded : " + e.getMessage());

+        }

+    }

+

+    /**

+     * Stop the provided service.

+     * Kill the exporter, the instance and the factory.

+     */

+    public void stop() {

+        if (m_exports != null) {

+            m_exports.stop();

+            m_exports = null;

+        }

+        if (m_instance != null) {

+            m_instance.dispose();

+            m_instance = null;

+        }

+        if (m_factory != null) {

+            m_factory.stop();

+            m_factory = null;

+        }

+    }

+

+    protected CompositeManager getManager() {

+        return m_manager;

+    }

+

+    /**

+     * The exporter becomes valid.

+     * @param exporter : the exporter

+     */

+    public void validate(DependencyModel exporter) {

+        // Nothing to do.

+    }

+

+    /**

+     * The exporter becomes invalid.

+     * @param exporter : the exporter

+     */

+    public void invalidate(DependencyModel exporter) {

+        // Nothing to do.

+    }

+

+    /**

+     * 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 handler = (InstanceHandler) m_manager.getCompositeHandler("org.apache.felix.ipojo.composite.instance.InstanceHandler");

+        Object pojo = handler.getObjectFromInstance(type);

+        if (pojo == null) {

+            m_manager.getFactory().getLogger().log(Logger.ERROR, "An instance object cannot be found for the type : " + type);

+        }

+        return pojo;

+    }

+

+    public String getSpecification() {

+        return m_composition.getSpecificationMetadata().getName();

+    }

+

+    /**

+     * Unregister the exposed service.

+     */

+    public void unregister() {

+        m_exports.stop();

+    }

+

+    /**

+     * Register the exposed service.

+     */

+    public void register() {

+        Properties props = new Properties();

+        props.put("name", m_instanceName);

+        List fields = m_composition.getFieldList();

+        for (int i = 0; i < fields.size(); i++) {

+            FieldMetadata field = (FieldMetadata) fields.get(i);

+            if (field.isUseful() && !field.getSpecification().isInterface()) {

+                String type = field.getSpecification().getComponentType();

+                Object pojo = getObjectByType(type);

+                props.put(field.getName(), pojo);

+            }

+        }

+

+        if (m_instance == null) {

+         // Else we have to create the instance 

+            try {

+                m_instance = m_factory.createComponentInstance(props, m_manager.getServiceContext());

+            } catch (UnacceptableConfiguration e) {

+                throw new IllegalStateException("Cannot create the service implementation : " + e.getMessage());

+            } catch (MissingHandlerException e) {

+                throw new IllegalStateException("Cannot create the service implementation : " + e.getMessage());

+            } catch (ConfigurationException e) {

+                throw new IllegalStateException("Cannot create the service implementation : " + e.getMessage());

+            }

+        } else {

+            // We have to reconfigure the instance in order to inject up to date glue component instance.

+            m_instance.reconfigure(props);

+        }

+        

+        m_exports.start();

+    }

+

+    public boolean isRegistered() {

+        return m_exports.getState() == DependencyModel.RESOLVED;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
new file mode 100644
index 0000000..fcbec3c
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
@@ -0,0 +1,496 @@
+/* 

+ * 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.service.provides;

+

+import java.lang.reflect.Field;

+import java.util.ArrayList;

+import java.util.Comparator;

+import java.util.Dictionary;

+import java.util.List;

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.Factory;

+import org.apache.felix.ipojo.HandlerFactory;

+import org.apache.felix.ipojo.HandlerManager;

+import org.apache.felix.ipojo.MissingHandlerException;

+import org.apache.felix.ipojo.PolicyServiceContext;

+import org.apache.felix.ipojo.UnacceptableConfiguration;

+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.composite.instance.InstanceHandler;

+import org.apache.felix.ipojo.composite.service.instantiator.ServiceDependencyHandler;

+import org.apache.felix.ipojo.composite.service.instantiator.ServiceImporter;

+import org.apache.felix.ipojo.composite.service.instantiator.SvcInstance;

+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.util.DependencyModel;

+import org.apache.felix.ipojo.util.DependencyStateListener;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * Composite Provided Service Handler.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ProvidedServiceHandler extends CompositeHandler implements DependencyStateListener {

+

+    /**

+     * External context.

+     */

+    private BundleContext m_context;

+

+    /**

+     * List of "available" services in the internal context.

+     */

+    private List m_services = new ArrayList();

+

+    /**

+     * List of exporters.

+     */

+    private List m_exporters = new ArrayList();

+

+    /**

+     * List of managed services.

+     */

+    private List m_managedServices = new ArrayList();

+

+    /**

+     * List of component type.

+     */

+    private List m_types;

+

+    /**

+     * Initialize the component type.

+     * @param desc : component type description to populate.

+     * @param metadata : component type metadata.

+     * @throws ConfigurationException : metadata are incorrect.

+     * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element)

+     */

+    public void initializeComponentFactory(ComponentTypeDescription desc, Element metadata) throws ConfigurationException {

+        Element[] provides = metadata.getElements("provides");

+        for (int i = 0; i < provides.length; i++) {

+            String action = provides[i].getAttribute("action");

+            if (action == null) {

+                throw new ConfigurationException("Invalid composition service providing : no specified action");

+            } else if (action.equalsIgnoreCase("implement")) {

+                String spec = provides[i].getAttribute("specification");

+                if (spec == null) {

+                    throw new ConfigurationException("Malformed provides : the specification attribute is mandatory");

+                } else {

+                    desc.addProvidedServiceSpecification(spec);

+                }

+            } else if (action.equalsIgnoreCase("export")) {

+                String spec = provides[i].getAttribute("specification");

+                if (spec == null) {

+                    throw new ConfigurationException("Malformed exports - Missing the specification attribute");

+                } else {

+                    desc.addProvidedServiceSpecification(spec);

+                }

+            } else {

+                throw new ConfigurationException("Invalid composition service providing : unknown action " + action);

+            }

+        }

+    }

+

+    /**

+     * Configure the handler.

+     * @param metadata : the metadata of the component

+     * @param configuration : the instance configuration

+     * @throws ConfigurationException  : the exporter cannot be created

+     * @see org.apache.felix.ipojo.CompositeHandler#configure(org.apache.felix.ipojo.CompositeManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)

+     */

+    public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {

+        m_context = getCompositeManager().getContext();

+

+        Element[] provides = metadata.getElements("provides", "");

+        for (int i = 0; i < provides.length; i++) {

+            String action = provides[i].getAttribute("action");

+            if (action.equalsIgnoreCase("implement")) {

+                ProvidedService svc = new ProvidedService(this, provides[i], Integer.toString(i));

+                m_managedServices.add(svc);

+            } else if (action.equalsIgnoreCase("export")) {

+                boolean optional = false;

+                boolean aggregate = false;

+                String specification = provides[i].getAttribute("specification");

+

+                String filter = "(objectClass=" + specification + ")";

+

+                String opt = provides[i].getAttribute("optional");

+                optional = opt != null && opt.equalsIgnoreCase("true");

+

+                String agg = provides[i].getAttribute("aggregate");

+                aggregate = agg != null && agg.equalsIgnoreCase("true");

+

+                String givenFilter = provides[i].getAttribute("filter");

+                if (givenFilter != null) {

+                    filter = "(&" + filter + givenFilter + ")"; //NOPMD

+                }

+

+                Filter fil = null;

+                try {

+                    fil = m_context.createFilter(filter);

+                } catch (InvalidSyntaxException e) {

+                    throw new ConfigurationException("An exporter filter is invalid " + filter + " : " + e.getMessage());

+                }

+

+                Comparator cmp = DependencyModel.getComparator(provides[i], m_context);

+                int policy = DependencyModel.getPolicy(provides[i]);

+                Class spec = DependencyModel.loadSpecification(specification, m_context);

+

+                ServiceExporter imp = new ServiceExporter(spec, fil, aggregate, optional, cmp, policy, getCompositeManager().getServiceContext(), m_context, this, getCompositeManager());

+                m_exporters.add(imp);

+            } // Others case cannot happen. The test was already made during the factory initialization.

+        }

+

+    }

+

+    /**

+     * Start method.

+     * Start all managed provided service.

+     * @see org.apache.felix.ipojo.CompositeHandler#start()

+     */

+    public void start() {

+        // Compute imports and instances

+        computeAvailableServices();

+        computeAvailableTypes();

+

+        for (int i = 0; i < m_managedServices.size(); i++) {

+            ProvidedService svc = (ProvidedService) m_managedServices.get(i);

+            try {

+                checkServiceSpecification(svc);

+                svc.start();

+            } catch (CompositionException e) {

+                error("Cannot start the provided service handler", e);

+                setValidity(false);

+                return;

+            }

+        }

+

+        for (int i = 0; i < m_exporters.size(); i++) {

+            ServiceExporter exp = (ServiceExporter) m_exporters.get(i);

+            exp.start();

+        }

+

+        isHandlerValid();

+    }

+

+    /**

+     * Stop method.

+     * Stop all managed provided service.

+     * @see org.apache.felix.ipojo.CompositeHandler#stop()

+     */

+    public void stop() {

+        for (int i = 0; i < m_managedServices.size(); i++) {

+            ProvidedService svc = (ProvidedService) m_managedServices.get(i);

+            svc.stop();

+        }

+

+        for (int i = 0; i < m_exporters.size(); i++) {

+            ServiceExporter exp = (ServiceExporter) m_exporters.get(i);

+            exp.stop();

+        }

+    }

+

+    /**

+     * Check the handler validity.

+     * @see org.apache.felix.ipojo.CompositeHandler#isValid()

+     */

+    private void isHandlerValid() {

+        for (int i = 0; i < m_exporters.size(); i++) {

+            ServiceExporter exp = (ServiceExporter) m_exporters.get(i);

+            if (exp.getState() != DependencyModel.RESOLVED) {

+                setValidity(false);

+                return;

+            }

+        }

+

+        setValidity(true);

+    }

+

+    /**

+     * Handler state changed.

+     * @param state : the new instance state.

+     * @see org.apache.felix.ipojo.CompositeHandler#stateChanged(int)

+     */

+    public void stateChanged(int state) {

+        if (state == ComponentInstance.INVALID) {

+            for (int i = 0; i < m_managedServices.size(); i++) {

+                ProvidedService svc = (ProvidedService) m_managedServices.get(i);

+                svc.unregister();

+            }

+            return;

+        }

+

+        // If the new state is VALID => register all the services

+        if (state == ComponentInstance.VALID) {

+            for (int i = 0; i < m_managedServices.size(); i++) {

+                ProvidedService svc = (ProvidedService) m_managedServices.get(i);

+                svc.register();

+            }

+            return;

+        }

+    }

+

+    /**

+     * Notify the handler that an exporter becomes invalid.

+     * 

+     * @param exporter : the implicated exporter.

+     */

+    public void invalidate(DependencyModel exporter) {

+        // An export is no more valid

+        if (getValidity()) {

+            setValidity(false);

+        }

+

+    }

+

+    /**

+     * Notify the handler that an exporter becomes valid.

+     * 

+     * @param exporter : the implicated exporter.

+     */

+    public void validate(DependencyModel exporter) {

+        // An import becomes valid

+        if (!getValidity()) {

+            isHandlerValid();

+        }

+    }

+

+    /**

+     * Build the list of available specification.

+     * @return the list of available specification.

+     */

+    protected List getSpecifications() {

+        return m_services;

+    }

+

+    /**

+     * Build the list of available specifications.

+     */

+    private void computeAvailableServices() {

+        // Get instantiated services :

+        ServiceDependencyHandler handler = (ServiceDependencyHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":subservice");

+

+        for (int i = 0; handler != null && i < handler.getInstances().size(); i++) {

+            SvcInstance svc = (SvcInstance) handler.getInstances().get(i);

+            String itf = svc.getServiceSpecification();

+            boolean agg = svc.isAggregate();

+            boolean opt = svc.isOptional();

+

+            SpecificationMetadata specMeta = new SpecificationMetadata(itf, m_context, agg, opt, this);

+            m_services.add(specMeta);

+        }

+

+        for (int i = 0; handler != null && i < handler.getRequirements().size(); i++) {

+            ServiceImporter imp = (ServiceImporter) handler.getRequirements().get(i);

+            String itf = imp.getSpecification().getName();

+            boolean agg = imp.isAggregate();

+            boolean opt = imp.isOptional();

+

+            SpecificationMetadata specMeta = new SpecificationMetadata(itf, m_context, agg, opt, this);

+            m_services.add(specMeta);

+        }

+    }

+

+    /**

+     * Check composite requirement against service specification requirement is available.

+     * @param svc : the provided service to check

+     * @throws CompositionException : occurs if the specification field of the service specification cannot be analyzed correctly.

+     */

+    private void checkServiceSpecification(ProvidedService svc) throws CompositionException {

+        try {

+            Class spec = m_context.getBundle().loadClass(svc.getSpecification());

+            Field specField = spec.getField("specification");

+            Object object = specField.get(null);

+            if (object instanceof String) {

+                Element specification = ManifestMetadataParser.parse((String) object);

+                Element[] reqs = specification.getElements("requires");

+                for (int j = 0; reqs != null && j < reqs.length; j++) {

+                    ServiceImporter imp = getAttachedRequirement(reqs[j]);

+                    if (imp != null) {

+                        // Fix service-level dependency flag

+                        imp.setServiceLevelDependency();

+                    }

+                    checkRequirement(imp, reqs[j]);

+                }

+            } else {

+                error("[" + getCompositeManager().getInstanceName() + "] The specification field of the service specification " + svc.getSpecification() + " need to be a String");

+                throw new CompositionException("Service Specification checking failed : The specification field of the service specification " + svc.getSpecification() + " need to be a String");

+            }

+        } catch (NoSuchFieldException e) {

+            return; // No specification field

+        } catch (ClassNotFoundException e) {

+            error("[" + getCompositeManager().getInstanceName() + "] The service specification " + svc.getSpecification() + " cannot be load");

+            throw new CompositionException("The service specification " + svc.getSpecification() + " cannot be load : " + e.getMessage());

+        } catch (IllegalArgumentException e) {

+            error("[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + svc.getSpecification() + " is not accessible : " + e.getMessage());

+            throw new CompositionException("The field 'specification' of the service specification " + svc.getSpecification() + " is not accessible : " + e.getMessage());

+        } catch (IllegalAccessException e) {

+            error("[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + svc.getSpecification() + " is not accessible : " + e.getMessage());

+            throw new CompositionException("The field 'specification' of the service specification " + svc.getSpecification() + " is not accessible : " + e.getMessage());

+        } catch (ParseException e) {

+            error("[" + getCompositeManager().getInstanceName() + "] The field 'specification' of the service specification " + svc.getSpecification() + " does not contain a valid String : " + e.getMessage());

+            throw new CompositionException("The field 'specification' of the service specification " + svc.getSpecification() + " does not contain a valid String : " + e.getMessage());

+        }

+    }

+

+    /**

+     * Look for the implementation (i.e. composite) requirement for the given service-level requirement metadata.

+     * @param element : the service-level requirement metadata

+     * @return the ServiceImporter object, null if not found or if the DependencyHandler is not plugged to the instance

+     */

+    private ServiceImporter getAttachedRequirement(Element element) {

+        ServiceDependencyHandler handler = (ServiceDependencyHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":subservice");

+        if (handler == null) { return null; }

+

+        String identity = element.getAttribute("id");

+        if (identity != null) {

+            // Look for dependency Id

+            for (int i = 0; i < handler.getRequirements().size(); i++) {

+                ServiceImporter imp = (ServiceImporter) handler.getRequirements().get(i);

+                if (imp.getId().equals(identity)) { return imp; }

+            }

+        }

+

+        // If not found or no id, look for a dependency with the same specification

+        String requirement = element.getAttribute("specification");

+        for (int i = 0; i < handler.getRequirements().size(); i++) {

+            ServiceImporter imp = (ServiceImporter) handler.getRequirements().get(i);

+            if (imp.getId().equals(requirement) || imp.getSpecification().getName().equals(requirement)) { return imp; }

+        }

+        return null;

+    }

+

+    /**

+     * Check the correctness of the composite requirement against the service level dependency.

+     * @param imp : requirement to check

+     * @param elem : service-level dependency metadata

+     * @throws CompositionException : occurs if the requirement does not match with service-level specification requirement

+     */

+    private void checkRequirement(ServiceImporter imp, Element elem) throws CompositionException {

+        String optional = elem.getAttribute("optional");

+        boolean opt = optional != null && optional.equalsIgnoreCase("true");

+

+        String aggregate = elem.getAttribute("aggregate");

+        boolean agg = aggregate != null && aggregate.equalsIgnoreCase("true");

+

+        if (imp == null) {

+            // Add the missing requirement

+            ServiceDependencyHandler handler = (ServiceDependencyHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":subservice");

+            if (handler == null) {

+                // Look for the ServiceDependencyHandler factory

+                HandlerManager handlerManager = null;

+                try {

+                    ServiceReference[] refs = m_context.getServiceReferences(Factory.class.getName(), "(&(handler.name=subservice)(handler.namespace=" + HandlerFactory.IPOJO_NAMESPACE + ")(handler.type=composite))");

+                    Factory factory = (Factory) m_context.getService(refs[0]);

+                    handlerManager = (HandlerManager) factory.createComponentInstance(null, getCompositeManager().getServiceContext());

+                } catch (InvalidSyntaxException e) {

+                    // Should not happen

+                } catch (UnacceptableConfiguration e) {

+                    // Should not happen

+                } catch (MissingHandlerException e) {

+                    // Should not happen

+                } catch (ConfigurationException e) {

+                    // Should not happen

+                }

+                

+                // Add the required handler 

+                try {

+                    handlerManager.init(getCompositeManager(), new Element("composite", ""), new Properties());

+                } catch (ConfigurationException e) {

+                    error("Internal error : cannot configure the Import Handler : " + e.getMessage());

+                    throw new CompositionException("Internal error : cannot configure the Import Handler : " + e.getMessage());

+                }

+                handler = (ServiceDependencyHandler) handlerManager.getHandler();

+                getCompositeManager().addCompositeHandler(handlerManager);

+            }

+

+            String spec = elem.getAttribute("specification");

+            String filter = "(&(objectClass=" + spec + ")(!(instance.name=" + getCompositeManager().getInstanceName() + ")))"; // Cannot import yourself

+            String givenFilter = elem.getAttribute("filter");

+            if (givenFilter != null) {

+                filter = "(&" + filter + givenFilter + ")"; //NOPMD

+            }

+

+            BundleContext context = new PolicyServiceContext(getCompositeManager().getGlobalContext(), getCompositeManager().getParentServiceContext(), PolicyServiceContext.GLOBAL);

+

+            Filter fil = null;

+            try {

+                fil = getCompositeManager().getGlobalContext().createFilter(filter);

+            } catch (InvalidSyntaxException e) {

+                throw new CompositionException("A required filter " + filter + " is malformed : " + e.getMessage());

+            }

+

+            Class specToImport = null;

+            try {

+                specToImport = getCompositeManager().getGlobalContext().getBundle().loadClass(spec);

+            } catch (ClassNotFoundException e) {

+                throw new CompositionException("A required specification cannot be loaded : " + spec);

+            }

+

+            ServiceImporter importer = new ServiceImporter(specToImport, fil, agg, opt, null, DependencyModel.DYNAMIC_BINDING_POLICY, context, null, handler);

+

+            handler.getRequirements().add(importer);

+            SpecificationMetadata specMeta = new SpecificationMetadata(spec, m_context, agg, opt, this);

+            m_services.add(specMeta); // Update the available types

+            return;

+        }

+

+        if (imp.isAggregate() && !agg) {

+            error("[" + getCompositeManager().getInstanceName() + "] The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");

+            throw new CompositionException("The requirement " + elem.getAttribute("specification") + " is aggregate in the implementation and is declared as a simple service-level requirement");

+        }

+

+        String filter = elem.getAttribute("filter");

+        if (filter != null) {

+            String filter2 = imp.getFilter();

+            if (filter2 == null || !filter2.equalsIgnoreCase(filter)) {

+                error("[" + getCompositeManager().getInstanceName() + "] The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");

+                throw new CompositionException("The specification requirement " + elem.getAttribute("specification") + " as not the same filter as declared in the service-level requirement");

+            }

+        }

+    }

+

+    public HandlerDescription getDescription() {

+        return new ProvidedServiceHandlerDescription(this, m_managedServices, m_exporters);

+    }

+

+    /**

+     * Build available instance types.

+     */

+    private void computeAvailableTypes() {

+        InstanceHandler handler = (InstanceHandler) getHandler(HandlerFactory.IPOJO_NAMESPACE + ":instance");

+        if (handler == null) {

+            m_types = new ArrayList();

+        } else {

+            m_types = handler.getUsedType();

+        }

+    }

+

+    public List getInstanceType() {

+        return m_types;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java
new file mode 100644
index 0000000..5c22246
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandlerDescription.java
@@ -0,0 +1,96 @@
+/* 

+ * 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.service.provides;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.apache.felix.ipojo.architecture.HandlerDescription;

+import org.apache.felix.ipojo.composite.CompositeHandler;

+import org.apache.felix.ipojo.metadata.Attribute;

+import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.util.DependencyModel;

+

+/**

+ * Provided Service Handler Description for composite.

+ * 

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ProvidedServiceHandlerDescription extends HandlerDescription {

+

+    /**

+     * Provided Service Description list.

+     */

+    private List m_services = new ArrayList();

+    

+    /**

+     * List of exports.

+     */

+    private List m_exports;

+

+    /**

+     * Constructor.

+     * 

+     * @param handler : composite handler.

+     * @param services : The list of Provided Service.

+     * @param exporters : list of managed exports

+     */

+    public ProvidedServiceHandlerDescription(CompositeHandler handler, List services, List exporters) {

+        super(handler);

+        m_services = services;

+        m_exports = exporters;

+    }

+

+    /**

+     * Get the handler description.

+     * @return the provided service handler description

+     * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()

+     */

+    public Element getHandlerInfo() {

+        Element services = super.getHandlerInfo();

+        for (int i = 0; i < m_services.size(); i++) {

+            ProvidedService svc = (ProvidedService) m_services.get(i);

+            Element service = new Element("service", "");

+            String state = "unregistered";

+            if (svc.isRegistered()) {

+                state = "registered";

+            }

+            String spec = "[" + svc.getSpecification() + "]";

+            service.addAttribute(new Attribute("Specification", spec));

+            service.addAttribute(new Attribute("State", state));

+            services.addElement(service);

+        }

+        

+        for (int i = 0; i < m_exports.size(); i++) {

+            ServiceExporter exp = (ServiceExporter) m_exports.get(i);

+            Element expo = new Element("Exports", "");

+            expo.addAttribute(new Attribute("Specification", exp.getSpecification().getName()));

+            expo.addAttribute(new Attribute("Filter", exp.getFilter()));

+            if (exp.getState() == DependencyModel.RESOLVED) {

+                expo.addAttribute(new Attribute("State", "resolved"));

+            } else {

+                expo.addAttribute(new Attribute("State", "unresolved"));

+            }

+            services.addElement(expo);

+        }

+        

+        return services;

+    }

+

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java
new file mode 100644
index 0000000..38a790f
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/ServiceExporter.java
@@ -0,0 +1,163 @@
+/* 

+ * 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.service.provides;

+

+import java.util.Comparator;

+import java.util.Dictionary;

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Properties;

+import java.util.Set;

+

+import org.apache.felix.ipojo.ServiceContext;

+import org.apache.felix.ipojo.composite.CompositeManager;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.apache.felix.ipojo.util.DependencyStateListener;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Filter;

+import org.osgi.framework.ServiceReference;

+import org.osgi.framework.ServiceRegistration;

+

+/**

+ * Export an service from the scope to the parent context.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class ServiceExporter extends DependencyModel {

+

+    /**

+     * Destination context.

+     */

+    private BundleContext m_destination;

+

+    /**

+     * Composite Manager.

+     */

+    private CompositeManager m_manager;

+

+    /**

+     * Map of service reference - service registration storing exported services.

+     */

+    private Map/*<ServiceReference, ServiceRegistration>*/m_registrations = new HashMap();

+

+    /**

+     * Constructor.

+     * 

+     * @param specification : exported service specification.

+     * @param filter : LDAP filter

+     * @param multiple : is the export an aggregate export?

+     * @param optional : is the export optional?

+     * @param cmp : comparator to use in the dependency

+     * @param policy : binding policy.

+     * @param from : internal service context

+     * @param dest : parent bundle context

+     * @param listener : dependency lifecycle listener to notify when the dependency state change. 

+     * @param manager : composite manager

+     */

+    public ServiceExporter(Class specification, Filter filter, boolean multiple, boolean optional, Comparator cmp, int policy, ServiceContext from, BundleContext dest, DependencyStateListener listener, CompositeManager manager) {

+        super(specification, multiple, optional, filter, cmp, policy, from, listener);

+

+        m_destination = dest;

+

+        m_manager = manager;

+

+    }

+

+    /**

+     * Transform service reference property in a dictionary.

+     * instance.name and factory.name are injected too.

+     * @param ref : the service reference.

+     * @return the dictionary containing all property of the given service reference.

+     */

+    private Dictionary getProps(ServiceReference ref) {

+        Properties prop = new Properties();

+        String[] keys = ref.getPropertyKeys();

+        for (int i = 0; i < keys.length; i++) {

+            prop.put(keys[i], ref.getProperty(keys[i]));

+        }

+

+        prop.put("instance.name", m_manager.getInstanceName());

+        prop.put("factory.name", m_manager.getFactory().getName());

+

+        return prop;

+    }

+

+    /**

+     * Stop an exporter.

+     * Remove the service listener

+     * Unregister all exported services.

+     */

+    public void stop() {

+        super.stop();

+        Set refs = m_registrations.keySet();

+        Iterator iterator = refs.iterator();

+        while (iterator.hasNext()) {

+            ServiceReference ref = (ServiceReference) iterator.next();

+            ServiceRegistration reg = (ServiceRegistration) m_registrations.get(ref);

+            reg.unregister();

+        }

+        m_registrations.clear();

+    }

+

+    /**

+     * A service has been injected. Register it.

+     * @param reference : the new reference.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)

+     */

+    public void onServiceArrival(ServiceReference reference) {

+        Object svc = getService(reference);

+        ServiceRegistration reg = m_destination.registerService(getSpecification().getName(), svc, getProps(reference));

+        m_registrations.put(reference, reg);

+    }

+

+    /**

+     * An exported service was modified.

+     * @param reference : modified reference

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)

+     */

+    public void onServiceModification(ServiceReference reference) {

+        ServiceRegistration reg = (ServiceRegistration) m_registrations.get(reference);

+        if (reg != null) {

+            reg.setProperties(getProps(reference));

+        }

+    }

+

+    /**

+     * An exported service disappears.

+     * @param reference : service reference

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)

+     */

+    public void onServiceDeparture(ServiceReference reference) {

+        ServiceRegistration reg = (ServiceRegistration) m_registrations.get(reference);

+        if (reg != null) {

+            reg.unregister();

+        }

+        m_registrations.remove(reference);

+    }

+

+    /**

+     * On Dependency Reconfiguration notification method.

+     * @param departs : leaving service references.

+     * @param arrivals : new injected service references.

+     * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])

+     */

+    public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) {

+        throw new UnsupportedOperationException("Dynamic dependency reconfiguration is not supported by service exporter");

+    }

+}

diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
new file mode 100644
index 0000000..392de87
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
@@ -0,0 +1,158 @@
+/* 

+ * 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.service.provides;

+

+import java.lang.reflect.Method;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.osgi.framework.BundleContext;

+

+/**

+ * Represent a service specification.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class SpecificationMetadata {

+

+    /**

+     * Name of the specification, i.e. name of the interface.

+     */

+    private String m_name;

+

+    /**

+     * List of the method contained in the specification.

+     */

+    private List/* <MethodMetadata> */m_methods = new ArrayList/* <MethodMetadata> */();

+

+    /**

+     * Is the specification an aggregate?

+     */

+    private boolean m_isAggregate;

+

+    /**

+     * Is the specification optional?

+     */

+    private boolean m_isOptional = false;

+

+    /**

+     * Is the specification an interface?

+     */

+    private boolean m_isInterface = true;

+

+    /**

+     * Component Type.

+     */

+    private String m_componentType = null;

+

+    /**

+     * Reference on the handler.

+     */

+    private ProvidedServiceHandler m_handler;

+

+    /**

+     * Constructor.

+     * @param name : specification name.

+     * @param context : bundle context.

+     * @param isAggregate : is the specification aggregate.

+     * @param isOptional : is the specification optional.

+     * @param psd : the handler.

+     */

+    public SpecificationMetadata(String name, BundleContext context, boolean isAggregate, boolean isOptional, ProvidedServiceHandler psd) {

+        m_name = name;

+        m_handler = psd;

+

+        // Populate methods :

+        try {

+            Class clazz = context.getBundle().loadClass(name);

+            Method[] methods = clazz.getMethods();

+            for (int i = 0; i < methods.length; i++) {

+                MethodMetadata method = new MethodMetadata(methods[i]);

+                m_methods.add(method);

+            }

+        } catch (ClassNotFoundException e) {

+            m_handler.error("Cannot open " + name + " : " + e.getMessage());

+            return;

+        }

+

+        m_isAggregate = isAggregate;

+        m_isOptional = isOptional;

+    }

+

+    /**

+     * Constructor.

+     * @param clazz : class

+     * @param type : component type

+     * @param psd : the parent handler

+     */

+    public SpecificationMetadata(Class clazz, String type, ProvidedServiceHandler psd) {

+        m_handler = psd;

+        m_isAggregate = false;

+        m_isOptional = false;

+        m_componentType = type;

+        m_name = clazz.getName();

+        Method[] methods = clazz.getMethods();

+        for (int i = 0; i < methods.length; i++) {

+            MethodMetadata method = new MethodMetadata(methods[i]);

+            m_methods.add(method);

+        }

+        m_isInterface = false;

+    }

+

+    public String getName() {

+        return m_name;

+    }

+

+    public List/* <MethodMetadata> */getMethods() {

+        return m_methods;

+    }

+

+    /**

+     * Get a method by its name.

+     * @param name : method name

+     * @return the method metadata contained in the current specification with the given name. Null if the method is not found.

+     */

+    public MethodMetadata getMethodByName(String name) {

+        for (int i = 0; i < m_methods.size(); i++) {

+            MethodMetadata met = (MethodMetadata) m_methods.get(i);

+            if (met.getMethod().getName().equals(name)) { return met; }

+        }

+        return null;

+    }

+

+    public boolean isAggregate() {

+        return m_isAggregate;

+    }

+

+    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/composite/src/main/java/org/apache/felix/ipojo/composite/util/SourceManager.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/util/SourceManager.java
new file mode 100644
index 0000000..d7f227a
--- /dev/null
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/util/SourceManager.java
@@ -0,0 +1,376 @@
+/* 

+ * 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.util;

+

+import java.util.ArrayList;

+import java.util.Dictionary;

+import java.util.List;

+

+import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.ContextListener;

+import org.apache.felix.ipojo.ContextSource;

+import org.apache.felix.ipojo.composite.CompositeManager;

+import org.apache.felix.ipojo.parser.ParseUtils;

+import org.apache.felix.ipojo.util.DependencyModel;

+import org.apache.felix.ipojo.util.Tracker;

+import org.apache.felix.ipojo.util.TrackerCustomizer;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.Constants;

+import org.osgi.framework.Filter;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceReference;

+

+/**

+ * This class manages context-source management.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class SourceManager implements ContextListener {

+

+    /**

+     * Source Name service property.

+     */

+    public static final String SOURCE_NAME = "source.name";

+

+    /**

+     * Managed dependency.

+     */

+    private DependencyModel m_dependency;

+

+    /**

+     * List of monitored context sources.

+     */

+    private List/* <ContextSource> */m_sources = new ArrayList(1);

+

+    /**

+     * PRoperties contained in the original filter.

+     */

+    private String[] m_properties;

+

+    /**

+     * Original filter (containing variables). 

+     */

+    private String m_filter;

+

+    /**

+     * Bundle context.

+     */

+    private BundleContext m_context;

+

+    /**

+     * Service Tracker List.

+     */

+    private List/*<SourceTracker>*/m_trackers = new ArrayList(1);

+

+    /**

+     * Constructor.

+     * @param sources : context-source attribute from the dependency metadata

+     * @param depfilter : original dependency filter

+     * @param dependency : dependency object

+     * @param manager : composite manager

+     * @throws ConfigurationException : the sources are incorrect.

+     */

+    public SourceManager(String sources, String depfilter, DependencyModel dependency, CompositeManager manager) throws ConfigurationException {

+        m_filter = depfilter;

+        m_properties = getProperties(depfilter);

+        m_dependency = dependency;

+        m_context = manager.getGlobalContext();

+        if (manager.getParentServiceContext() == null) {

+            // The parent is the global context

+            parseSources(sources, manager.getGlobalContext(), manager.getGlobalContext(), manager.getServiceContext());

+        } else {

+            parseSources(sources, manager.getGlobalContext(), manager.getParentServiceContext(), manager.getServiceContext());

+        }

+    }

+

+    /**

+     * Start the context management.

+     */

+    public void start() {

+        for (int i = 0; i < m_trackers.size(); i++) {

+            ((SourceTracker) m_trackers.get(i)).open();

+        }

+        computeFilter();

+    }

+

+    /**

+     * Stop the context management.

+     */

+    public void stop() {

+        for (int i = 0; i < m_trackers.size(); i++) {

+            ((SourceTracker) m_trackers.get(i)).close();

+        }

+        setFilter(m_filter);

+        m_sources.clear();

+    }

+

+    /**

+     * Get the state of this source manager.

+     * @return the state of this source manager.

+     */

+    public int getState() {

+        if (m_sources.isEmpty()) {

+            return DependencyModel.UNRESOLVED;

+        } else {

+            return DependencyModel.RESOLVED;

+        }

+    }

+

+    /**

+     * Set the filter of the managed dependency.

+     * @param filter : the new filter to apply

+     */

+    private void setFilter(String filter) {

+        if (!filter.equals(m_dependency.getFilter())) {

+            // Reconfigure

+            try {

+                m_dependency.setFilter(m_context.createFilter(filter));

+            } catch (InvalidSyntaxException e) {

+                throw new IllegalStateException("A context filter is invalid : " + filter);

+            }

+        }

+    }

+

+    /**

+     * Compute the new filter.

+     */

+    private void computeFilter() {

+        String fil = m_filter;

+        synchronized (this) {

+            for (int i = 0; i < m_sources.size(); i++) {

+                Dictionary props = ((ContextSource) m_sources.get(i)).getContext();

+                fil = substitute(fil, props); //NOPMD

+            }

+        }

+        if (!fil.equals(m_dependency.getFilter())) {

+            setFilter(fil);

+        }

+    }

+

+    /**

+     * This method substitute ${var} substring by values stored in a map.

+     * @param str : string with variables

+     * @param values : dictionary containing the variable name and the value.

+     * @return resulted string

+     */

+    public static String substitute(String str, Dictionary values) {       

+        int len = str.length();

+        StringBuffer buffer = new StringBuffer(len);

+

+        int prev = 0;

+        int start = str.indexOf("${");

+        int end = str.indexOf('}', start);

+        while (start != -1 && end != -1) {

+            String key = str.substring(start + 2, end);

+            Object value = values.get(key);

+            if (value == null) {

+                buffer.append(str.substring(prev, end + 1));

+            } else {

+                buffer.append(str.substring(prev, start));

+                buffer.append(value);

+            }

+            prev = end + 1;

+            if (prev >= str.length()) {

+                break;

+            }

+

+            start = str.indexOf("${", prev);

+            if (start != -1) {

+                end = str.indexOf('}', start);

+            }

+        }

+

+        buffer.append(str.substring(prev));

+

+        return buffer.toString();

+    }

+

+    /**

+     * Compute the properties (${name}) from the given filter.

+     * @param str : string form of the filter.

+     * @return the list of found properties.

+     */

+    public static String[] getProperties(String str) {

+        List list = new ArrayList();

+        int prev = 0;

+        int start = str.indexOf("${");

+        int end = str.indexOf('}', start);

+        while (start != -1 && end != -1) {

+            String key = str.substring(start + 2, end);

+            list.add(key);

+            prev = end + 1;

+            if (prev >= str.length()) {

+                break;

+            }

+

+            start = str.indexOf("${", prev);

+            if (start != -1) {

+                end = str.indexOf('}', start);

+            }

+        }

+

+        return (String[]) list.toArray(new String[list.size()]);

+    }

+

+    /**

+     * A context source has modified a monitored property. 

+     * @param source : source

+     * @param property : modified property

+     * @param value : new value.

+     * @see org.apache.felix.ipojo.ContextListener#update(org.apache.felix.ipojo.ContextSource, java.lang.String, java.lang.Object)

+     */

+    public synchronized void update(ContextSource source, String property, Object value) {

+        computeFilter();

+    }

+

+    /**

+     * Parse the context-source attribute in order to create source tracker object.

+     * @param sourceAtt : context-source attribute.

+     * @param global : global bundle context.

+     * @param parent : parent bundle context.

+     * @param local : local bundle context.

+     * @throws ConfigurationException : the context-source attribute is invalid.

+     */

+    private void parseSources(String sourceAtt, BundleContext global, BundleContext parent, BundleContext local) throws ConfigurationException {

+        String[] sources = ParseUtils.split(sourceAtt, ",");

+        for (int i = 0; i < sources.length; i++) {

+            String[] srcs = ParseUtils.split(sources[i], ":");

+            if (srcs.length == 1) {

+                // No prefix use local. //TODO choose default case.

+                SourceTracker tracker = new SourceTracker(srcs[0], local);

+                m_trackers.add(tracker);

+            } else if (srcs.length == 2) {

+                // According to prefix add the source in the good list.

+                if (srcs[0].equalsIgnoreCase("parent")) {

+                    SourceTracker tracker = new SourceTracker(srcs[1], parent);

+                    m_trackers.add(tracker);

+                } else if (srcs[0].equalsIgnoreCase("local")) {

+                    SourceTracker tracker = new SourceTracker(srcs[1], local);

+                    m_trackers.add(tracker);

+                } else if (srcs[0].equalsIgnoreCase("global")) {

+                    SourceTracker tracker = new SourceTracker(srcs[1], global);

+                    m_trackers.add(tracker);

+                } else {

+                    throw new ConfigurationException("Unknowns context scope : " + srcs[0]);

+                }

+            } else {

+                throw new ConfigurationException("Malformed context source : " + sources[i]);

+            }

+        }

+    }

+

+    /**

+     * A context source appears.

+     * @param source : new context source.

+     */

+    private void addContextSource(ContextSource source) {

+        m_sources.add(source);

+        computeFilter();

+        source.registerContextListener(this, m_properties);

+    }

+

+    /**

+     * A context source disappears.

+     * @param source : leaving context source.

+     */

+    private void removeContextSource(ContextSource source) {

+        m_sources.remove(source);

+        computeFilter();

+    }

+

+    private class SourceTracker implements TrackerCustomizer {

+

+        /**

+         * Service tracker.

+         */

+        private Tracker m_tracker;

+

+        /**

+         * Constructor.

+         * @param name : name of the required context-source.

+         * @param countext : bundle context to use.

+         * @throws ConfigurationException : the context-source name is invalid.

+         */

+        public SourceTracker(String name, BundleContext countext) throws ConfigurationException {

+            String fil = "(&(" + Constants.OBJECTCLASS + "=" + ContextSource.class.getName() + ")(" + SOURCE_NAME + "=" + name + "))";

+            try {

+                Filter filter = countext.createFilter(fil);

+                m_tracker = new Tracker(countext, filter, this);

+            } catch (InvalidSyntaxException e) {

+                throw new ConfigurationException("A Context source filter is invalid " + fil + " : " + e.getMessage());

+            }

+        }

+

+        /**

+         * Open the tracker.

+         */

+        public void open() {

+            m_tracker.open();

+        }

+

+        /**

+         * Close the tracker.

+         */

+        public void close() {

+            m_tracker.close();

+        }

+

+        /**

+         * A new context-source was added.

+         * This method inject the context-source object in the source manager.

+         * @param reference : service reference.

+         * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)

+         */

+        public void addedService(ServiceReference reference) {

+            addContextSource((ContextSource) m_tracker.getService(reference));

+        }

+

+        /**

+         * A new context-source is adding in the tracker.. 

+         * @param reference : service reference

+         * @return true.

+         * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)

+         */

+        public boolean addingService(ServiceReference reference) {

+            return true;

+        }

+

+        /**

+         * A used context-source is modified.

+         * @param reference : service reference.

+         * @param service : service object.

+         * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)

+         */

+        public void modifiedService(ServiceReference reference, Object service) {

+            // Nothing to do.

+        }

+

+        /**

+         * A used context-source disappears.

+         * This method notify the Source Manager in order to manage this departure. 

+         * @param reference : service reference.

+         * @param service : service object.

+         * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)

+         */

+        public void removedService(ServiceReference reference, Object service) {

+            removeContextSource((ContextSource) service);

+        }

+

+    }

+

+}

diff --git a/ipojo/composite/src/main/resources/metadata.xml b/ipojo/composite/src/main/resources/metadata.xml
new file mode 100644
index 0000000..cb71d71
--- /dev/null
+++ b/ipojo/composite/src/main/resources/metadata.xml
@@ -0,0 +1,27 @@
+<ipojo>

+	<!-- Composite Handler -->

+	<handler

+		classname="org.apache.felix.ipojo.composite.instance.InstanceHandler"

+		name="instance" type="composite" architecture="false" level="1">

+		<requires filter="(factory.state=1)" field="m_factories"

+			optional="true">

+			<callback type="bind" method="bindFactory" />

+			<callback type="unbind" method="unbindFactory" />

+		</requires>

+	</handler>

+	<handler

+		classname="org.apache.felix.ipojo.composite.service.instantiator.ServiceDependencyHandler"

+		name="subservice" type="composite" architecture="false">

+	</handler>

+	<handler

+		classname="org.apache.felix.ipojo.composite.service.provides.ProvidedServiceHandler"

+		name="provides" type="composite" architecture="false" level="3">

+	</handler>

+	<handler

+		classname="org.apache.felix.ipojo.composite.architecture.ArchitectureHandler"

+		name="architecture" type="composite" architecture="false">

+		<provides>

+			<property field="m_name" name="instance.name" value="" />

+		</provides>

+	</handler>

+</ipojo>
\ No newline at end of file