Ported servicebinder code:
o  package updates to org.apache.felix.servicebinder
o  non-invasive IDE warning fixes
o  author tag to felix dev list
o  M2 POM to provide initial install support
o  license update to ASL 2.0
o  kxml update to 1.21
o  svn ignores

git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@388786 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.servicebinder/pom.xml b/org.apache.felix.servicebinder/pom.xml
new file mode 100644
index 0000000..a21263f
--- /dev/null
+++ b/org.apache.felix.servicebinder/pom.xml
@@ -0,0 +1,60 @@
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>osgi-bundle</packaging>
+  <name>Apache Felix Service Binder</name>
+  <artifactId>org.apache.felix.servicebinder</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
+      <artifactId>org.osgi</artifactId>
+      <version>${pom.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>kxml</groupId>
+      <artifactId>kxml</artifactId>
+      <version>1.21</version>
+      <scope>required</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix.plugins</groupId>
+        <artifactId>maven-osgi-plugin</artifactId>
+        <version>${pom.version}</version>
+        <extensions>true</extensions>
+        <configuration>
+          <osgiManifest>
+            <entries>
+              <property>
+                <name>Metadata-Location</name>
+                <value>metadata.xml</value>
+              </property>
+            </entries>
+            <bundleName>Service Binder</bundleName>
+            <bundleVendor>Apache Software Foundation</bundleVendor>
+            <!--<bundleVersion>1.1.2</bundleVersion>-->
+            <bundleDescription>
+              This bundle provides a mechanism to automate service dependency management.
+            </bundleDescription>
+            <bundleActivator>
+              org.apache.felix.servicebinder.impl.Activator
+            </bundleActivator>
+            <exportPackage>
+              org.apache.felix.servicebinder; specification-version="1.1.0",org.apache.felix.servicebinder.architecture; specification-version="1.1.0"
+            </exportPackage>
+            <metadataLocation>
+              metadata.xml
+            </metadataLocation>
+          </osgiManifest>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/DependencyMetadata.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/DependencyMetadata.java
new file mode 100644
index 0000000..8ce80d1
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/DependencyMetadata.java
@@ -0,0 +1,167 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * Metadata of a dependency
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class DependencyMetadata
+{
+    private String m_serviceName = "";
+    private String m_filter = "";
+    private String m_bindMethod = "";
+    private String m_unbindMethod = "";
+    private String m_cardinality = "";
+    private String m_policy = "";
+
+    private boolean m_isStatic = true;
+    private boolean m_isOptional = false;
+    private boolean m_isMultiple = false;
+
+    /**
+     * Constructor
+     *
+    **/
+    DependencyMetadata(String servicename,String cardinality,String policy,String filter,String bindmethod,String unbindmethod)
+    {
+        m_serviceName = servicename;
+
+        String classnamefilter = "(objectClass="+servicename+")";
+
+        if(filter.equals("") == false)
+        {
+            m_filter = "(&"+classnamefilter+filter+")";
+        }
+        else
+        {
+            m_filter = classnamefilter;
+        }
+
+        m_bindMethod = bindmethod;
+        m_unbindMethod = unbindmethod;
+        m_cardinality = cardinality;
+        m_policy = policy;
+
+        if(policy.equals("static") == false)
+        {
+            m_isStatic = false;
+        }
+
+        if(cardinality.equals("0..1") || cardinality.equals("0..n"))
+        {
+            m_isOptional = true;
+        }
+
+        if(cardinality.equals("0..n") || cardinality.equals("1..n"))
+        {
+            m_isMultiple = true;
+        }
+    }
+
+    /**
+     * Returns the name of the required service
+     *
+     * @return the name of the required service
+    **/
+    public String getServiceName()
+    {
+        return m_serviceName;
+    }
+
+    /**
+     * Returns the filter
+     *
+     * @return A string with the filter
+    **/
+    public String getFilter()
+    {
+        return m_filter;
+    }
+
+    /**
+     * Get the name of the Bind method
+     *
+     * @return a String with the name of the BindMethod
+    **/
+    public String getBindMethodName()
+    {
+        return m_bindMethod;
+    }
+
+    /**
+     * Get the name of the Unbind method
+     *
+     * @return a String with the name of the Unbind method
+    **/
+    public String getUnbindMethodName()
+    {
+        return m_unbindMethod;
+    }
+
+
+    /**
+     * Test if dependency's binding policy is static
+     *
+     * @return true if static
+    **/
+    public boolean isStatic()
+    {
+        return m_isStatic;
+    }
+
+    /**
+     * Test if dependency is optional (0..1 or 0..n)
+     *
+     * @return true if the dependency is optional
+    **/
+    public boolean isOptional()
+    {
+        return m_isOptional;
+    }
+
+    /**
+     * Test if dependency is multiple (0..n or 1..n)
+     *
+     * @return true if the dependency is multiple
+    **/
+    public boolean isMultiple()
+    {
+        return m_isMultiple;
+    }
+
+    /**
+     * Get the cardinality as a string
+     *
+     * @return the cardinality
+    **/
+    public String getCardinality()
+    {
+        return m_cardinality;
+    }
+
+    /**
+     * Get the policy as a string
+     *
+     * @return the policy
+    **/
+    public String getPolicy()
+    {
+        return m_policy;
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/GenericActivator.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/GenericActivator.java
new file mode 100644
index 0000000..32c17a7
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/GenericActivator.java
@@ -0,0 +1,328 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import java.io.InputStream;
+
+import org.apache.felix.servicebinder.architecture.DependencyChangeEvent;
+import org.apache.felix.servicebinder.architecture.InstanceChangeEvent;
+import org.apache.felix.servicebinder.impl.ArchitectureServiceImpl;
+import org.apache.felix.servicebinder.parser.KxmlParser;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * The GenericActivator, it will read information from the metadata.xml file
+ * and will create the corresponding instance managers
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+abstract public class GenericActivator implements BundleActivator
+{
+    private BundleContext m_context = null;
+    private List m_instanceManagers = new ArrayList();
+
+    private static boolean m_trace = false;
+    private static boolean m_error = true;
+
+    private static String m_version = "1.1.1 (17062004)";
+
+    // Static initializations based on system properties
+    static {
+        // Get system properties to see if traces or errors need to be displayed
+        String result = System.getProperty("servicebinder.showtrace");
+        if(result != null && result.equals("true"))
+        {
+            m_trace = true;
+        }
+        result = System.getProperty("servicebinder.showerrors");
+        if(result != null && result.equals("false"))
+        {
+            m_error = false;
+        }
+        result = System.getProperty("servicebinder.showversion");
+        if(result != null && result.equals("true"))
+        {
+            System.out.println("[ ServiceBinder version = "+m_version+" ]\n");
+        }        
+    }
+
+    public GenericActivator()
+    {
+    }
+
+    /**
+    * Called upon starting of the bundle. This method invokes initialize() which
+    * parses the meta data and creates the instance managers
+    *
+    * @param   context  The bundle context passed by the framework
+    * @exception   Exception any exception thrown from initialize
+    */
+    public void start(BundleContext context) throws Exception
+    {
+        m_context = context;
+        try
+        {
+            initialize();
+        }
+        catch (Exception e)
+        {
+            GenericActivator.error("GenericActivator : in bundle ["
+                + context.getBundle().getBundleId() + "] : " + e);
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+    /**
+    * Gets the MetaData location, parses the meta data and requests the processing
+    * of binder instances
+    *
+    * @throws java.io.FileNotFoundException if the metadata file is not found
+    * @throws javax.xml.parsers.ParserConfigurationException
+    * @throws org.xml.sax.SAXException
+    * @throws java.io.IOException
+    * @throws java.lang.ClassNotFoundException it the instance class is not found
+    * @throws java.lang.NoSuchMethodException if binder methods are not found
+    * @throws org.osgi.framework.InvalidSyntaxException if the filter has an incorrect syntax
+    * @throws Exception if any exception is thrown during the validation of the InstanceManagers
+    */
+    private void initialize() throws Exception
+    {
+        // Get the Metadata-Location value from the manifest
+
+        String metadataLocation = "";
+        //Dictionary dict = m_context.getBundle().getHeaders();
+        
+        metadataLocation = (String) m_context.getBundle().getHeaders().get("Metadata-Location");
+
+        if (metadataLocation == null)
+        {
+            throw new java.io.FileNotFoundException("Metadata-Location entry not found in the manifest");
+        }
+
+        if (metadataLocation.startsWith("/") == false)
+        {
+            metadataLocation="/"+metadataLocation;
+        }
+
+        InputStream stream = getClass().getResourceAsStream(metadataLocation);
+
+        if (stream == null)
+        {
+            throw new java.io.FileNotFoundException("MetaData file not found at:"+metadataLocation);
+        }
+
+        // Create the parser
+
+        XmlHandler handler = new XmlHandler();
+        BufferedReader in = new BufferedReader(new InputStreamReader(stream));
+        KxmlParser parser = new KxmlParser(in);
+
+        parser.parseXML(handler);
+
+        // Create An instance manager for every entry
+
+        Iterator i = handler.getInstanceMetadatas().iterator();
+
+        while (i.hasNext())
+        {
+            InstanceMetadata descriptor = (InstanceMetadata) i.next();
+                        
+            if(descriptor.isFactory()) 
+            {
+                // NOT YET SUPPORTED IN THIS VERSION
+            }
+            else // deployment instance
+            {
+                // create the instance manager
+                InstanceManager currentinstance = new InstanceManager(this,descriptor);
+                // start managing lifecycle
+                currentinstance.validate();
+            }
+        }
+    }
+
+    /**
+    * Stop method that destroys all the instance managers
+    *
+    * @param   context The Bundle Context passed by the framework
+    * @exception Exception any exception thrown during destruction of the instance managers
+    */
+    public void stop(BundleContext context) throws java.lang.Exception
+    {
+        GenericActivator.trace("GenericActivator : Bundle ["+context.getBundle().getBundleId()+"] will destroy "+m_instanceManagers.size()+" instances");
+
+        while (m_instanceManagers.size() !=0 )
+        {
+            InstanceManager current = (InstanceManager)m_instanceManagers.get(0);
+            try
+            {
+                current.destroy();
+            }
+            catch(Exception e)
+            {
+                GenericActivator.error("GenericActivator : Exception during invalidate : "+e);
+                e.printStackTrace();
+            }
+        }
+
+        m_context = null;
+
+        GenericActivator.trace("GenericActivator : Bundle ["+context.getBundle().getBundleId()+"] STOPPED");
+    }
+
+    /**
+    * Returns the list of instance references currently associated to this activator
+    *
+    * @return the list of instance references
+    */
+    protected List getInstanceReferences()
+    {
+        return m_instanceManagers;
+    }
+
+    /**
+    * Returns the BundleContext
+    *
+    * @return the BundleContext
+    */
+    protected BundleContext getBundleContext()
+    {
+        return m_context;
+    }
+
+    /**
+    * Add an instance manager to the list
+    *
+    * @param instance an instance manager
+    */
+    synchronized void addInstanceManager(InstanceManager instance)
+    {
+        ArchitectureServiceImpl.addInstanceReference(instance);
+
+        m_instanceManagers.add(instance);
+    }
+
+    /**
+    * Removes a binder instance from the list
+    *
+    * @param instance an instance manager
+    */
+    synchronized void removeInstanceManager(InstanceManager instance)
+    {
+        ArchitectureServiceImpl.removeInstanceReference(instance);
+
+        m_instanceManagers.remove(instance);
+    }
+
+    /**
+     * Method to display traces
+     *
+     * @param s a string to be displayed
+    **/
+    static void trace(String s)
+    {
+        if(m_trace)
+        {
+            System.out.println("--- "+s);
+        }
+    }
+
+    /**
+     * Method to display errors
+     *
+     * @param s a string to be displayed
+    **/
+    static void error(String s)
+    {
+        if(m_error)
+        {
+            System.err.println("### "+s);
+        }
+    }
+
+    /**
+     * Method called before an object implementing services is registered
+     * in the OSGi framework. This method is provided so that subclasses of
+     * the generic activator may proxy the object. The default implementation
+     * returns the passed in object.
+     *
+     * @param obj the instance object
+     * @param descriptor the instance descriptor that provides information relevant to
+     *          the instance object
+    **/
+    protected Object proxyProvidedServiceObject(Object obj, InstanceMetadata descriptor)
+    {
+        return obj;
+    }
+
+    /**
+     * Method called before the binding of the service object occurs.
+     * This method is provided so that subclasses of the generic activator
+     * may proxy the object. The default implementation returns the passed in object.
+     *
+     * @param obj the instance object
+     * @param descriptor the dependency descriptor that provides information relevant to
+     *          the service object
+    **/
+    protected Object proxyRequiredServiceObject(Object obj, DependencyMetadata descriptor)
+    {
+        return obj;
+    }
+
+    /**
+     * Fires an event when an instance has changed
+     * The generic activator always requests a reference of EvtGeneratorImpl
+     * since this class can be instantiated at anytime since it is
+     * the service implementation.
+     *
+     * @evt The InstanceChangeEvent
+    **/
+    void fireInstanceChangeEvent(InstanceChangeEvent evt)
+    {
+        ArchitectureServiceImpl evtGenerator = ArchitectureServiceImpl.getReference();
+
+        if(evtGenerator != null)
+        {
+            evtGenerator.fireInstanceChangeEvent(evt);
+        }
+    }
+
+    /**
+     * Fires an event when a dependency has changed
+     *
+     * @evt The InstanceChangeEvent
+     **/
+    void fireDependencyChangeEvent(DependencyChangeEvent evt)
+    {
+        ArchitectureServiceImpl evtGenerator = ArchitectureServiceImpl.getReference();
+
+        if(evtGenerator != null)
+        {
+            evtGenerator.fireDependencyChangeEvent(evt);
+        }
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceManager.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceManager.java
new file mode 100644
index 0000000..8bd7eba
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceManager.java
@@ -0,0 +1,1278 @@
+/*

+ *   Copyright 2006 The Apache Software Foundation

+ *

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

+

+import java.util.Properties;

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Map;

+import java.util.HashMap;

+

+import org.apache.felix.servicebinder.architecture.Dependency;

+import org.apache.felix.servicebinder.architecture.DependencyChangeEvent;

+import org.apache.felix.servicebinder.architecture.Instance;

+import org.apache.felix.servicebinder.architecture.InstanceChangeEvent;

+import org.apache.felix.servicebinder.impl.ArchitectureServiceImpl;

+import org.osgi.framework.ServiceRegistration;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.InvalidSyntaxException;

+import org.osgi.framework.ServiceListener;

+import org.osgi.framework.ServiceEvent;

+import org.osgi.framework.ServiceReference;

+import org.osgi.framework.Bundle;

+

+import java.lang.reflect.Constructor;

+import java.lang.reflect.Method;

+import java.lang.reflect.InvocationTargetException;

+
+/**
+ * A InstanceManager is created for every component instance.
 * 
 * When the InstanceManager is instantiated, a collection of DependencyManagers is
 * created. Each dependency manager corresponds to a required service
 * 
 * A InstanceManager follows a sequence of clearly defined steps.
 * 
 * 1.- Creation : the binder instance is created, its state becomes CREATED. This step is further divided
 *                in the following substeps:
 *                  - The binder instance checks if all of the dependencies are valid, if this
 *                    is false, it returns.
 *                  - If the dependendencies are valid, its state becomes executing. The object from
 *                    the instance class is created (if this object receives a ServiceBinderContext as
 *                    a parameter in its constructor, the context is passed to it.
 *                  - The validate() method is called on the dependency managers, this will cause
 *                    calls on the binding methods to occur
 *                  - The binder instance adds itself to the list of binder instances in the activator
 *                  - The binder instance registers the services implemented by the instance object.
 * 
 * 2.- Disposal :
 * 
 * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+

+public class InstanceManager implements InstanceReference, Instance

+{

+    // The values ranging from 0 to 3 are public and are defined in InstanceReference

+    static final int INSTANCE_CREATING = 4;

+    static final int INSTANCE_VALIDATING = 5;

+    static final int INSTANCE_INVALIDATING = 6;

+    static final int INSTANCE_DESTROYING = 7;

+

+    static final String m_states[]={"CREATED","VALID","INVALID",

+                                    "DESTROYED","CREATING","VALIDATING",

+                                    "INVALIDATING","DESTROYING"};

+

+    // The state of this instance manager

+    private int m_state = INSTANCE_CREATING;
+
+    /**
+     * 
+     * @uml.property name="m_instanceMetadata"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    // The metadata
+    private InstanceMetadata m_instanceMetadata;
+

+

+    // The object that implements the service and that is bound to other services

+    private Object m_implementorObject;

+

+    // The dependency managers that manage every dependency

+    private List m_dependencyManagers;

+

+    // The ServiceRegistration

+    private ServiceRegistration m_serviceRegistration;
+
+    /**
+     * 
+     * @uml.property name="m_activator"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    // A reference to the GenericActivator
+    private GenericActivator m_activator;
+
+    /**
+     * 
+     * @uml.property name="m_sbcontext"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    // The context that will be passed to the objects
+    private ServiceBinderContextImpl m_sbcontext;
+
+    /**
+     * 
+     * @uml.property name="m_instanceListener"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    // Listeners to validation events
+    private InstanceReferenceListener m_instanceListener = null;
+
+    // Properties that can be attached to te InstanceManager

+    private Properties m_localProperties = new Properties();

+    

+    // Flag that indicates that activate was called

+    private boolean m_activateCalled = false;

+

+    /**

+    * Constructor that creates a collection of dependency managers that will be in

+    * charge of the different dependencies for a particular instance.

+    *

+    * @param   activator A reference to the generic activator

+    * @param   descriptor an InstanceMetadata that contains information found in the descriptor file

+    * @throws  java.lang.ClassNotFoundException if the instance class (declared in the descriptor file) is not found

+    * @throws  java.lang.NoSuchMethodException if the bind or unbind methods are not found on the instance class

+    * @throws  org.osgi.framework.InvalidSyntaxException if the filter declared in the requires entry has an invalid syntax

+    **/

+    InstanceManager(GenericActivator activator,InstanceMetadata descriptor)

+        throws ClassNotFoundException, NoSuchMethodException, InvalidSyntaxException

+    {

+        m_activator = activator;

+

+        m_instanceMetadata = descriptor;

+

+        m_dependencyManagers = new ArrayList();

+

+        if (m_instanceMetadata.getDependencies().size() != 0)

+        {

+            Iterator dependencyit = m_instanceMetadata.getDependencies().iterator();

+

+            while(dependencyit.hasNext())

+            {

+                DependencyMetadata currentdependency = (DependencyMetadata)dependencyit.next();

+

+                DependencyManager depmanager = new DependencyManager(currentdependency);

+

+                m_dependencyManagers.add(depmanager);

+

+                // Register the dependency managers as listeners to service events so that they begin

+                // to manage the dependency autonomously

+

+                m_activator.getBundleContext().addServiceListener(depmanager,depmanager.getDependencyMetadata().getFilter());

+            }

+        }

+

+        m_sbcontext = new ServiceBinderContextImpl(this);

+

+        // Add this instance manager to the Generic activator list

+        m_activator.addInstanceManager(this);

+

+        setState(INSTANCE_CREATED);

+    }

+

+    /**

+    * Validate this Instance manager.

+    *

+    * CONCURRENCY NOTE: This method can be called either after an instance manager is created

+    * or after the instance is validated again after by the instance manager itself

+    */

+    synchronized void validate()

+    {

+        if (m_state == INSTANCE_VALID)

+        {

+            return;

+        }

+        else if (m_state != INSTANCE_INVALID && m_state !=INSTANCE_CREATED)

+        {

+            GenericActivator.error("InstanceManager : create() called for a non INVALID or CREATED InstanceManager ("+m_states[m_state]+")");

+            return;

+        }

+

+        setState(INSTANCE_VALIDATING);

+

+        // Test if all dependency managers are valid

+

+        Iterator it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

+            // It is not possible to call the isValid method yet in the DependencyManager

+            // since they have not been initialized yet, but we can't call initialize

+            // since the object where bindings will be done has not been created.

+            // This test is necessary, because we don't want to instantiate

+            // the object if the dependency managers won't be valid.

+            DependencyManager dm = (DependencyManager)it.next();

+            if (dm.getRequiredServiceRefs() == null && dm.getDependencyMetadata().isOptional() == false)

+            {

+                setState(INSTANCE_INVALID);

+                return;

+            }

+        }

+

+        // everything ok to go...

+

+        try

+        {

+            Class c = m_activator.getClass().getClassLoader().loadClass(m_instanceMetadata.getImplementorName());

+            try

+            {

+                Constructor cons = c.getConstructor(new Class[] {ServiceBinderContext.class});

+                m_implementorObject = cons.newInstance(new Object[] {m_sbcontext});

+            }

+            catch(NoSuchMethodException ex)

+            {

+                // Aparently he doesn't want a ServiceBinderContext...

+            }

+

+            // Create from no-param constructor

+            if (m_implementorObject == null)

+            {

+                m_implementorObject = c.newInstance();

+            }

+

+            /* is it a factory?

+            if (m_implementorObject instanceof GenericFactory)

+            {

+                ((GenericFactory) m_implementorObject).setActivator(m_activator, this);

+            }

+            */

+

+            // Allow somebody to proxy the object through the proxyProvidedServiceObject method

+            // in the activator

+            Object proxy = m_activator.proxyProvidedServiceObject(m_implementorObject, this.getInstanceMetadata());

+            if (proxy != null)

+            {

+                m_implementorObject = proxy;

+            }

+            else

+            {

+                GenericActivator.error("InstanceManager : Proxy method returned a null value");

+            }

+        }

+        catch (Throwable t)

+        {

+            // failure at creation

+            GenericActivator.error("InstanceManager : Error during instantiation : "+t);

+            t.printStackTrace();

+            _invalidate();

+            return;

+        }

+        

+        // initial bindings

+

+        it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

+            DependencyManager dm = (DependencyManager)it.next();

+            if (dm.initialize() == false)

+            {

+                _invalidate();

+                return;

+            }

+        }

+        

+        // We need to check if we are still validating because it is possible that when we

+        // registered the service above our thread causes an instance to become valid which

+        // then registered a service that then generated an event that we needed that

+        // caused validate() to be called again, thus if we are not still VALIDATING, it

+        // means we are already VALID.

+        if (m_state == INSTANCE_VALIDATING)

+        {

+            // activate

+

+            if (m_implementorObject instanceof Lifecycle)

+            {

+                try

+                {

+                    ((Lifecycle)m_implementorObject).activate();

+                    this.m_activateCalled=true;

+                }

+                catch(Exception e)

+                {

+                    GenericActivator.error("InstanceManager : exception during activate:"+e);

+                    e.printStackTrace();

+                    _invalidate();

+                    return;

+                }

+            }

+

+            // validated!

+

+            fireInstanceReferenceValidated();

+            setState(INSTANCE_VALID);

+        }

+        

+

+        // register services

+

+        boolean reg = requestRegistration();

+

+        if (!reg)

+        {

+            GenericActivator.error("InstanceManager : registration of the services failed...");

+            _invalidate();

+            return;

+        }

+        

+        // Configuration ended successfuly.

+

+    }

+

+    /**

+     * This method invalidates the InstanceManager

+     *

+     * CONCURRENCY NOTE: This method may be called either from application code or event thread.

+    **/

+    synchronized void invalidate()

+    {

+        if (m_state == INSTANCE_INVALID)

+        {

+            return;

+        }

+        else if (m_state != INSTANCE_VALID && m_state != INSTANCE_DESTROYING)

+        {

+            GenericActivator.error("InstanceManager : invalidate() called for a non VALID InstanceManager ("+m_states[m_state]+")");

+            return;

+        }

+

+        if (m_state != INSTANCE_DESTROYING)

+        {

+            setState(INSTANCE_INVALIDATING);

+        }

+

+        // Fire invalidating events

+        fireInstanceReferenceInvalidating();

+

+        _invalidate();

+

+

+    }

+

+    /**

+     * this method invalidates the InstanceManager without performing any of the callbacks

+     * associated with the Lifecycle interface or the InstanceReference event listeners.

+    **/

+    private void _invalidate()

+    {

+        // Unregister services

+

+        requestUnregistration();

+        

+        if(m_activateCalled==true)

+        {        

+            // Call deactivate on the Lifecycle

+

+            if (m_implementorObject instanceof Lifecycle)

+            {

+                try

+                {

+                    ((Lifecycle)m_implementorObject).deactivate();

+                }

+                catch(Exception e)

+                {

+                    GenericActivator.error("InstanceManager : exception during call to deactivate():"+e);

+                }

+            }

+

+        }

+

+        // Unbind all services

+

+        Iterator it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

+            DependencyManager dm = (DependencyManager)it.next();

+            dm.unbindAll();

+        }

+

+        //m_activator.removeInstanceManager(this);

+

+        // remove all instances from a factory

+

+        /*

+        if (m_implementorObject instanceof GenericFactory)

+        {

+            ((GenericFactory)m_implementorObject).invalidateInstances();

+        }

+        */

+

+        // Release the object reference

+

+        m_implementorObject = null;

+

+        GenericActivator.trace("InstanceManager from bundle ["

+           + m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");

+

+        if (m_state != INSTANCE_DESTROYING)

+        {

+            setState(INSTANCE_INVALID);

+        }

+    }

+

+    /**

+     * This method should be called to completely remove the InstanceManager from the system.

+     * This means that the dependency managers will stop listening to events.

+     *

+     * CONCURRENCY NOTE: This method is only called from the GenericActivator, which is

+     *                   essentially application code and not via events.

+    **/

+    synchronized void destroy()

+    {

+        if (m_state == INSTANCE_DESTROYED)

+        {

+            return;

+        }

+

+        // Theoretically this should never be in any state other than VALID or INVALID,

+        // because validate is called right after creation.

+        boolean invalidatefirst = (m_state == INSTANCE_VALID);

+

+        setState(INSTANCE_DESTROYING);

+

+        // Stop the dependency managers to listen to events...

+        Iterator it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

+            DependencyManager dm = (DependencyManager)it.next();

+            m_activator.getBundleContext().removeServiceListener(dm);

+        }

+

+        if (invalidatefirst)

+        {

+            invalidate();

+        }

+

+        m_dependencyManagers.clear();

+

+        m_instanceListener = null;

+

+        GenericActivator.trace("InstanceManager from bundle ["

+           + m_activator.getBundleContext().getBundle().getBundleId() + "] was destroyed.");

+

+        m_activator.removeInstanceManager(this);

+        setState(INSTANCE_DESTROYED);

+

+        m_activator = null;

+    }

+

+    /**

+    * Returns the InstanceMetadata

+    */

+    public InstanceMetadata getInstanceMetadata()

+    {

+        return m_instanceMetadata;

+    }

+

+    /**

+    * Get the object that is implementing this descriptor

+    *

+    * @return the object that implements

+    */

+    public Object getObject()

+    {

+        return m_implementorObject;

+    }

+

+    /**

+    * Request the registration of the service provided by this binder instance

+    *

+    * @return returns false if registration was not successful,

+    *                returns true if registration was successful

+    **/

+    boolean requestRegistration()

+    {

+        if (!m_instanceMetadata.instanceRegistersServices())

+        {

+            return true;

+        }

+        else if (m_implementorObject == null)

+        {

+            GenericActivator.error("GenericActivator : Cannot register, implementor object not created!");

+            return false;

+        }

+        else if (m_serviceRegistration != null)

+        {

+            GenericActivator.error("GenericActivator : Cannot register, binder instance already registered :"

+                + m_instanceMetadata.getImplementorName());

+            return true;

+        }

+

+        // Check validity of dependencies before registering !

+        Iterator it = m_dependencyManagers.iterator();

+        while (it.hasNext())

+        {

+            DependencyManager dm = (DependencyManager)it.next();

+            if (dm.isValid() == false)

+                return false;

+        }

+

+        // When registering a factory, add an instanceClass property which is an array

+        // of service interfaces implemented by the objects created by the factory.

+

+        if (m_instanceMetadata.isFactory())

+        {

+            if(m_instanceMetadata.getProperties().get("instanceClass") == null)

+            {

+                m_instanceMetadata.getProperties().put("instanceClass",m_instanceMetadata.getInstantiates().getInterfaces());

+            }

+        }

+

+        m_serviceRegistration = m_activator.getBundleContext().registerService(

+            m_instanceMetadata.getInterfaces(), m_implementorObject, m_instanceMetadata.getProperties());

+

+        GenericActivator.trace("Generic Activator : InstanceManager inside bundle ["

+            + m_activator.getBundleContext().getBundle().getBundleId()

+            + "] successfully registered its services !");

+

+        return true;

+    }

+

+

+    /**

+    *

+    * Request the unfegistration of the service provided by this binder instance

+    *

+    **/

+    void requestUnregistration()

+    {

+        if (m_serviceRegistration != null)

+        {

+            m_serviceRegistration.unregister();

+            m_serviceRegistration = null;

+

+            GenericActivator.trace("Generic Activator : InstanceManager inside bundle ["

+                + m_activator.getBundleContext().getBundle().getBundleId()

+                + "] unregistered its services !");

+

+         }

+    }

+

+    /**

+    * Get the state

+    */

+    public int getState()

+    {

+        return m_state;

+    }

+

+    /**

+    * Get the state

+    */

+    public long getBundleId()

+    {

+        return m_activator.getBundleContext().getBundle().getBundleId();

+    }

+

+    /**

+     * Get a property associated with this instance. For classes

+     * implementing this method, special care must be taken for

+     * values implementing <tt>InstanceReference.ValueHolder</tt>.

+     * In such cases, the value itself should not be returned, but

+     * the value of <tt>InstanceReference.ValueHolder.get()</tt>

+     * should be returned instead. This may be used to defer

+     * creating value objects in cases where creating the value

+     * object is expensive.

+     * @param name the name of the property to retrieve.

+     * @return the value of the associated property or <tt>null</tt>.

+    **/

+    public Object get(String name)

+    {

+        GenericActivator.trace("InstanceManager.get("+name+")");

+

+        if(name.equals(InstanceReference.INSTANCE_STATE))

+        {

+            return new Integer(m_state);

+        }

+        else if(name.equals(InstanceReference.INSTANCE_METADATA))

+        {

+            return getInstanceMetadata();

+        }

+        else if(name.equals(InstanceReference.INSTANCE_BUNDLE))

+        {

+            return new Integer((int) getBundleId());

+        }

+        else if(name.equals(InstanceReference.INSTANCE_DEPENDENCIES))

+        {

+            return getDependencies();

+        }

+        else

+        {

+            Object ret = m_localProperties.get(name);

+

+            if (ret != null)

+            {

+                if (ret instanceof ValueHolder)

+                {

+                    return ((ValueHolder)ret).get(this);

+                }

+                return ret;

+            }

+

+            return m_instanceMetadata.getProperties().get(name);

+        }

+

+    }

+

+    /**

+     * Associate a property with this instance. For classes

+     * implementing this method, special care must be taken for

+     * values implementing <tt>InstanceReference.ValueHolder</tt>.

+     * In such cases, the value itself should not be returned, but

+     * the value of <tt>InstanceReference.ValueHolder.get()</tt>

+     * should be returned instead. This may be used to defer

+     * creating value objects in cases where creating the value

+     * object is expensive.

+     * @param name the name of the property to add.

+     * @param obj the value of the property.

+    **/

+    public void put(String name, Object obj)

+    {

+        m_localProperties.put(name,obj);

+    }

+

+    /**

+     * Adds an instance reference listener to listen for changes to

+     * the availability of the underlying object associated with this

+     * instance reference.

+     * @param l the listener to add.

+    **/

+    public void addInstanceReferenceListener(InstanceReferenceListener l)

+    {

+        m_instanceListener = StateChangeMulticaster.add(m_instanceListener, l);

+    }

+

+    /**

+     * Removes an instance reference listener.

+     * @param l the listener to remove.

+    **/

+    public void removeInstanceReferenceListener(InstanceReferenceListener l)

+    {

+        m_instanceListener = StateChangeMulticaster.remove(m_instanceListener, l);

+    }

+

+    /**

+     * Fires an event when the instance reference has been validated

+    **/

+    protected void fireInstanceReferenceValidated()

+    {

+        try

+        {

+            if (m_instanceListener != null)

+            {

+                m_instanceListener.validated(new InstanceReferenceEvent(this));

+            }

+        }

+        catch(Exception ex)

+        {

+            // Ignore any exception

+        }

+    }

+

+    /**

+     * Fires an event when the instance reference is invalidating

+    **/

+    protected void fireInstanceReferenceInvalidating()

+    {

+        try

+        {

+            if (m_instanceListener != null)

+            {

+                m_instanceListener.invalidating(new InstanceReferenceEvent(this));

+            }

+        }

+        catch(Exception ex)

+        {

+            // Ignore any exception

+        }

+    }

+

+    /**

+     * sets the state of the instanceManager

+    **/

+    synchronized void setState(int newState)

+    {

+        m_state = newState;

+

+        if(m_state == INSTANCE_CREATED || m_state == INSTANCE_VALID || m_state == INSTANCE_INVALID || m_state == INSTANCE_DESTROYED)

+        {

+            m_activator.fireInstanceChangeEvent(new InstanceChangeEvent(this,m_instanceMetadata,m_state));

+        }

+    }

+

+    /**

+     * Get an array of dependencies for this instance. This method is declared

+     * in the Instance interface

+     *

+     * @return an array of Dependencies

+    **/

+    public Dependency [] getDependencies()

+    {

+        Dependency deps [] = new Dependency[m_dependencyManagers.size()];

+        return (Dependency[]) m_dependencyManagers.toArray(deps);

+    }

+

+    /**

+     * Get a list of child instances in case this is a factory

+     *

+     * @return an array of Instances

+    **/

+     public Instance[] getChildInstances()

+    {

+        /*

+        if(m_implementorObject != null && m_implementorObject instanceof GenericFactory)

+        {

+            List instanceRefs = ((GenericFactory)m_implementorObject).getInstanceReferences();

+            Instance [] instances = new Instance[instanceRefs.size()];

+            instances = (Instance [])instanceRefs.toArray(instances);

+            return instances;

+        }

+        */

+        return null;

+    }
+
+/**
+ * This class implements the ServiceBinderContext, which cannot be directly
 * implemented by the activator because of the getInstanceReference() method
+ */
+

+    class ServiceBinderContextImpl implements ServiceBinderContext

+    {
+
+        /**
+         * 
+         * @uml.property name="m_parent"
+         * @uml.associationEnd multiplicity="(0 1)"
+         */
+        private InstanceReference m_parent;
+
+        ServiceBinderContextImpl(InstanceReference parent)

+        {

+            m_parent = parent;

+        }

+

+        /**

+         * Get the bundle context

+        **/

+        public BundleContext getBundleContext()

+        {

+            return m_activator.getBundleContext();

+        }

+

+        /**

+         * Return all of the InstanceReferences created in the same bundle

+        **/

+        public List getInstanceReferences()

+        {

+            return m_activator.getInstanceReferences();

+        }

+

+        /**

+         * Get the parent InstanceReference

+        **/

+        public InstanceReference getInstanceReference()

+        {

+            return m_parent;

+        }

+    }
+
+/**
+ * The DependencyManager task is to listen to service events and to call the
 * bind/unbind methods on a given object. It is also responsible for requesting
 * the unregistration of a service in case a dependency is broken.
+ */
+

+    class DependencyManager implements ServiceListener, Dependency

+    {
+
+        /**
+         * 
+         * @uml.property name="m_dependencyMetadata"
+         * @uml.associationEnd multiplicity="(0 1)"
+         */
+        private DependencyMetadata m_dependencyMetadata;
+
+        private Map m_boundServices = new HashMap();

+        private Method m_bindMethod;

+        private Method m_unbindMethod;

+        private boolean m_isValid;

+        private int m_depState;

+        private boolean m_receivesRef = false;

+

+        /**

+         * Constructor that receives several parameters.

+         *

+         * @param   dependency  An object that contains data about the dependency

+        **/

+        DependencyManager(DependencyMetadata dependency) throws ClassNotFoundException, NoSuchMethodException

+        {

+            m_dependencyMetadata = dependency;

+            m_isValid = false;

+

+            m_bindMethod = getTargetMethod(m_dependencyMetadata.getBindMethodName(),InstanceManager.this.getInstanceMetadata().getImplementorName(),m_dependencyMetadata.getServiceName());

+            m_unbindMethod = getTargetMethod(m_dependencyMetadata.getUnbindMethodName(),InstanceManager.this.getInstanceMetadata().getImplementorName(),m_dependencyMetadata.getServiceName());

+

+            setStateDependency(DependencyChangeEvent.DEPENDENCY_CREATED);

+        }

+

+        /**

+         * initializes a dependency. This method binds all of the service occurrences to the instance object

+         *

+         * @return true if the operation was successful, false otherwise

+        **/

+        boolean initialize()

+        {

+            if(getObject() == null)

+            {

+                return false;

+            }

+

+            ServiceReference refs[] = getRequiredServiceRefs();

+

+            if (refs == null && m_dependencyMetadata.isOptional() == false)

+            {

+                m_isValid = false;

+                setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);

+                return m_isValid;

+            }

+

+            m_isValid = true;

+            setStateDependency(DependencyChangeEvent.DEPENDENCY_VALID);

+

+            if (refs != null)

+            {

+                int max = 1;

+                boolean retval = true;

+

+                if (m_dependencyMetadata.isMultiple() == true)

+                {

+                    max = refs.length;

+                }

+

+                for (int index = 0; index < max; index++)

+                {

+                    retval = callBindMethod(refs[index]);

+                    if(retval == false && (max == 1))

+                    {

+                        // There was an exception when calling the bind method

+                        GenericActivator.error("Dependency Manager: Possible exception in the bind method during initialize()");

+                        m_isValid = false;

+                        setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);

+                        return m_isValid;

+                    }

+                }

+            }

+

+            return m_isValid;

+        }

+

+        /**

+         * Called upon a service event. This method is responsible for calling the

+         * binding and unbinding methods and also to request the eventual unregistering

+         * of a service when a dependency breaks

+         *

+         * @param evt  The ServiceEvent

+        **/

+        public void serviceChanged(ServiceEvent evt)

+        {

+            synchronized (InstanceManager.this)

+            {

+                // If the object is being created or destroyed, we can safely ignore events.

+                if (m_state == INSTANCE_DESTROYING || m_state == INSTANCE_DESTROYED || m_state == INSTANCE_CREATING || m_state == INSTANCE_CREATED)

+                {

+                    return;

+                }

+

+                // If we are in the process of invalidating, it is not necessary to pass

+                // unregistration events, since we are unbinding everything anyway.

+                else if (m_state == INSTANCE_INVALIDATING && evt.getType() == ServiceEvent.UNREGISTERING)

+                {

+                    return;

+                }

+

+                // We do not have an entry for VALIDATING because it is reentrant.

+

+                // A service is unregistering

+                if (evt.getType() == ServiceEvent.UNREGISTERING)

+                {

+                    if (m_boundServices.keySet().contains(evt.getServiceReference()) == true)

+                    {

+                        // A static dependency is broken the instance manager will be invalidated

+                        if (m_dependencyMetadata.isStatic())

+                        {

+                            m_isValid = false;

+                            setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);

+                            try

+                            {

+                                GenericActivator.trace("Dependency Manager: Static dependency is broken");

+                                invalidate();

+                                GenericActivator.trace("Dependency Manager: RECREATING");

+                                validate();

+                            }

+                            catch(Exception e)

+                            {

+                                e.printStackTrace();

+                            }

+                        }

+                        // dynamic dependency

+                        else

+                        {

+                            // Release references to the service, call unbinder method

+                            // and eventually request service unregistration

+

+                            callUnbindMethod(evt.getServiceReference());

+

+                            // The only thing we need to do here is check if we can reinitialize

+                            // once the bound services becomes zero. This tries to repair dynamic

+                            // 1..1 or rebind 0..1, since replacement services may be available.

+                            // In the case of aggregates, this will only invalidate them since they

+                            // can't be repaired.

+                            if (m_boundServices.size() == 0)

+                            {

+                                // try to reinitialize

+                                if (!initialize())

+                                {

+                                    if (!m_dependencyMetadata.isOptional())

+                                    {

+                                        GenericActivator.trace("Dependency Manager: Mandatory dependency not fullfilled and no replacements available... unregistering service...");

+                                        invalidate();

+                                        GenericActivator.trace("Dependency Manager: RECREATING");

+                                        validate();

+                                    }

+                                }

+                            }

+                        }

+                    }

+                }

+                // A service is registering.

+                else if (evt.getType() == ServiceEvent.REGISTERED)

+                {

+                    if (m_boundServices.keySet().contains(evt.getServiceReference()) == true)

+                    {

+                        // This is a duplicate

+                        GenericActivator.trace("DependencyManager : ignoring REGISTERED ServiceEvent (already bound)");

+                    }

+                    else

+                    {

+                        m_isValid = true;

+                        setStateDependency(DependencyChangeEvent.DEPENDENCY_VALID);

+

+                        // If the InstanceManager is invalid, a call to validate is made

+                        // which will fix everything.

+                        if (InstanceManager.this.getState() != INSTANCE_VALID)

+                        {

+                            validate();

+                        }

+                        // Otherwise, this checks for dynamic 0..1, 0..N, and 1..N it never

+                        // checks for 1..1 dynamic which is done above by the validate()

+                        else if (!m_dependencyMetadata.isStatic())

+                        {

+                            // For dependency that are aggregates, always bind the service

+                            // Otherwise only bind if bind services is zero, which captures the 0..1 case

+                            if (m_dependencyMetadata.isMultiple() || m_boundServices.size() == 0)

+                            {

+                                callBindMethod(evt.getServiceReference());

+                            }

+                        }

+                    }

+                }

+            }

+        }

+

+        /**

+         * Revoke all bindings. This method cannot throw an exception since it must try

+         * to complete all that it can

+         *

+        **/

+        void unbindAll()

+        {

+            Object []allrefs = m_boundServices.keySet().toArray();

+

+            if (allrefs == null)

+                return;

+

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

+            {

+                callUnbindMethod((ServiceReference)allrefs[i]);

+            }

+        }

+

+        /**

+         * Test if this dependency managed by this object is valid

+        **/

+        boolean isValid()

+        {

+            return m_isValid;

+        }

+

+        /**

+         *

+         * Returns an array containing the service references that are pertinent to the

+         * dependency managed by this object. This method filters out services that

+         * belong to bundles that are being (or are actually) shutdown. This is an issue

+         * since is not clearly specified in the OSGi specification if a getServiceReference

+         * call should return the services that belong to bundles that are stopping.

+         *

+         * @return an array of ServiceReferences valid in the context of this dependency

+        **/

+        ServiceReference [] getRequiredServiceRefs()

+        {

+            try

+            {

+                ArrayList list=new ArrayList();

+                ServiceReference temprefs[] =

+                    m_activator.getBundleContext().getServiceReferences(m_dependencyMetadata.getServiceName(), m_dependencyMetadata.getFilter());

+

+                if (temprefs == null)

+                {

+                    return null;

+                }

+

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

+                {

+                     if (temprefs[i].getBundle().getState() == Bundle.ACTIVE

+                            || temprefs[i].getBundle().getState() == Bundle.STARTING)

+                     {

+                         list.add(temprefs[i]);

+                     }

+                }

+

+                return (ServiceReference []) list.toArray(new ServiceReference [temprefs.length]);

+

+            }

+            catch (Exception e)

+            {

+                GenericActivator.error("DependencyManager: exception while getting references :"+e);

+                return null;

+            }

+        }

+

+        /**

+         * Gets a target method based on a set of parameters

+         *

+         * @param methodname The name of the method

+         * @param targetClass the class to which the method belongs to

+         * @param paramClass the class of the parameter that is passed to the method

+         * @throws java.lang.ClassNotFoundException if the class was not found

+         * @throws java.lang.NoSuchMethodException if the method was not found

+        **/

+        private Method getTargetMethod(String methodname, String targetClass, String paramClass)

+            throws ClassNotFoundException, NoSuchMethodException

+        {

+            Class targetclass = m_activator.getClass().getClassLoader().loadClass(targetClass);

+

+            Method method = null;

+            

+            try

+            {

+                method = targetclass.getMethod(methodname, 

+                    new Class[]{m_activator.getClass().getClassLoader().loadClass(paramClass)});

+               

+            }

+            catch(NoSuchMethodException ex)

+            {

+                // Test if the bind method receives a ServiceReference as the first parameter

+                

+                method = targetclass.getMethod(methodname, 

+                    new Class[]{ServiceReference.class, m_activator.getClass().getClassLoader().loadClass(paramClass)});

+               

+                m_receivesRef = true;

+            }

+            

+            return method;

+        }

+

+        /**

+         * Call the bind method. In case there is an exception while calling the bind method, the service

+         * is not considered to be bound to the instance object

+         *

+         * @param ref A ServiceReference with the service that will be bound to the instance object

+         * @return true if the call was successful, false otherwise

+        **/

+        boolean callBindMethod(ServiceReference ref)

+        {

+            try

+            {

+                Object requiredService = m_activator.getBundleContext().getService(ref);

+                Object proxy = m_activator.proxyRequiredServiceObject(requiredService,m_dependencyMetadata);

+                

+                if(proxy == null)

+                {

+                    // ignore a null return value from the proxy method

+                    proxy = requiredService;

+                }

+                if(m_receivesRef == false)

+                {

+                    m_bindMethod.invoke(getObject(),new Object[] {proxy});

+                }

+                else

+                {

+                    m_bindMethod.invoke(getObject(),new Object[] {ref,proxy});

+                }

+                m_boundServices.put(ref,proxy);

+                

+                return true;

+            }

+            catch(Exception e)

+            {

+                if(e instanceof InvocationTargetException)

+                {

+                    InvocationTargetException ite = (InvocationTargetException) e;

+                    GenericActivator.error("DependencyManager : exception while invoking "+m_dependencyMetadata.getBindMethodName()+" :"+ite.getTargetException());

+                }

+                else

+                {

+                    GenericActivator.error("DependencyManager : exception while invoking "+m_dependencyMetadata.getBindMethodName()+" :"+e);

+                }

+                e.printStackTrace();

+                return false;

+            }

+        }

+

+        /**

+         * Call the unbind method

+         *

+         * @param ref A service reference corresponding to the service that will be unbound

+        **/

+        void callUnbindMethod(ServiceReference ref)

+        {

+            Object requiredService = m_boundServices.get(ref);

+            if (requiredService == null)

+            {

+                GenericActivator.error("DependencyManager : callUnbindMethod UNBINDING UNKNOWN SERVICE !!!!");

+                return;

+            }

+

+            try

+            {

+                if(m_receivesRef == false)

+                {

+                    m_unbindMethod.invoke(getObject(),new Object [] {requiredService});

+                }

+                else

+                {

+                    m_unbindMethod.invoke(getObject(),new Object [] {ref, requiredService});

+                }

+                

+                m_boundServices.remove(ref);

+                m_activator.getBundleContext().ungetService(ref);

+            }

+            catch(Exception e)

+            {

+                if(e instanceof InvocationTargetException)

+                {

+                    InvocationTargetException ite = (InvocationTargetException) e;

+                    GenericActivator.error("DependencyManager : exception while invoking "+m_dependencyMetadata.getUnbindMethodName()+" :"+ite.getTargetException());

+                }

+                else

+                {

+                    GenericActivator.error("DependencyManager : exception while invoking "+m_dependencyMetadata.getUnbindMethodName()+" :"+e);

+                }

+                e.printStackTrace();

+            }

+        }

+

+        /**

+         * Return the dependency descriptor

+         *

+         * @return the corresponding dependency descriptor

+        **/

+        public DependencyMetadata getDependencyMetadata()

+        {

+            return m_dependencyMetadata;

+        }

+

+        /**

+         * Fire a state change event.

+         *

+         * @param state the state of the dependency manager

+        **/

+        void setStateDependency(int state)

+        {

+            m_depState = state;

+            m_activator.fireDependencyChangeEvent(new DependencyChangeEvent(this,m_dependencyMetadata,state));

+        }

+

+        /**

+         * Get the state of the dependency.

+         *

+         * @return the state of the dependency manager

+        **/

+        public int getDependencyState()

+        {

+            return m_depState;

+        }

+

+        /**

+         * Get the bound service objects. This method is declared in the Dependency interface

+         * and is used for to get a model.

+         *

+         * @return an array containing the bound service objects

+        **/

+        public Instance[] getBoundInstances()

+        {

+            Object bound[] = m_boundServices.values().toArray();

+

+            ArrayList tempArray = new ArrayList();

+

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

+            {

+                InstanceReference ref = ArchitectureServiceImpl.findInstanceReference(bound[i]);

+                if(ref != null)

+                {

+                    tempArray.add(ref);

+                }

+            }

+

+            Instance instances[]= new Instance[tempArray.size()];

+            instances = (Instance [])tempArray.toArray(instances);

+

+            return instances;

+

+

+        }

+    }
+
+/**
+ * @version X.XX Feb 3, 2004 
 * @author Humberto Cervantes
+ */
+

+    static public class StateChangeMulticaster implements InstanceReferenceListener

+    {
+
+        /**
+         * 
+         * @uml.property name="a"
+         * @uml.associationEnd multiplicity="(0 1)"
+         */
+        protected InstanceReferenceListener a;
+
+        /**
+         * 
+         * @uml.property name="b"
+         * @uml.associationEnd multiplicity="(0 1)"
+         */
+        protected InstanceReferenceListener b;
+
+        protected StateChangeMulticaster(InstanceReferenceListener a, InstanceReferenceListener b)    

+        {        

+            this.a = a;        

+            this.b = b;    

+        }    

+    

+    

+        public void validated(InstanceReferenceEvent e)    

+        {

+            a.validated(e);        

+            b.validated(e);

+        }

+    

+        public void invalidating(InstanceReferenceEvent e)    

+        {

+            a.invalidating(e);        

+            b.invalidating(e);

+        }

+    

+        public static InstanceReferenceListener add(InstanceReferenceListener a, InstanceReferenceListener b)

+        {

+            if (a == null)

+                return b;

+            else if (b == null)

+                return a;

+            else

+                return new StateChangeMulticaster(a, b);

+        }

+    

+        public static InstanceReferenceListener remove(InstanceReferenceListener a, InstanceReferenceListener b)

+        {

+            if ((a == null) || (a == b))            

+                return null;        

+            else if (a instanceof StateChangeMulticaster)            

+                return add (remove (((StateChangeMulticaster) a).a, b),remove (((StateChangeMulticaster) a).b, b));        

+            else            

+                return a;    

+        }

+    }

+}

diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceMetadata.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceMetadata.java
new file mode 100644
index 0000000..6585796
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceMetadata.java
@@ -0,0 +1,204 @@
+/*

+ *   Copyright 2006 The Apache Software Foundation

+ *

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

+

+import java.util.Properties;

+import java.util.Collection;

+import java.util.ArrayList;

+import java.util.Iterator;
+
+/**
+ * Description of an instance entry in the descriptor file
 * 
 * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class InstanceMetadata

+{

+    // These properties will be filled by the parser

+    private String m_implementorName;

+    private Collection m_interfaces = null;

+    private Properties m_properties = new Properties();

+    private Collection m_dependencies = null;
+
+    /**
+     * 
+     * @uml.property name="m_instantiates"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private InstanceMetadata m_instantiates = null;
+
+    /**
+     * 
+     * @uml.property name="m_parent"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private InstanceMetadata m_parent = null;
+
+    private boolean m_isFactory = false;

+    private boolean m_registersService = false;

+    private boolean m_isInstance = false;

+

+    /**

+     * Constructor

+     *

+     * @param   implementorName name of the class of the implementation object

+     * @param   parent the parent to this service descriptor

+     */

+    InstanceMetadata(String implementorName,InstanceMetadata parent)

+    {

+        m_interfaces = new ArrayList();

+        m_dependencies = new ArrayList();

+

+        m_implementorName = implementorName;

+

+        // The parent will be != null if this descriptor corresponds to an

+        // instantiate entry

+

+        if(parent != null)

+        {

+            m_parent = parent;

+            m_parent.m_instantiates = this;

+            m_parent.m_isFactory = true;

+            m_isInstance = true;

+        }

+    }

+

+    /**

+     * Returns the name of the implementor

+     *

+     * @return the name of the implementor

+     */

+    public String getImplementorName()

+    {

+        return m_implementorName;

+    }

+

+

+    /**

+     * Used to add an interface to the service descriptor

+     *

+     * @param   newInterface name of the interface implemented by the implementation object

+     */

+    void addInterface(String newInterface)

+    {

+        // As soon as there is one interface provided, it cannot be a bundle-to-service.

+        m_registersService = true;

+        m_interfaces.add(newInterface);

+    }

+

+    /**

+     * Returns the implemented interfaces

+     *

+     * @return the implemented interfaces as a string array

+     */

+    public String [] getInterfaces()

+    {

+        String interfaces[] = new String[m_interfaces.size()];

+        Iterator it = m_interfaces.iterator();

+        int count = 0;

+        while (it.hasNext())

+        {

+            interfaces[count++] = it.next().toString();

+        }

+        return interfaces;

+    }

+

+    /**

+     * Used to add a property to the instance

+     *

+     * @param   newProperty a property descriptor

+     */

+    void addProperty(PropertyMetadata newProperty)

+    {

+        String key = newProperty.getName();

+        Object value = newProperty.getValue();

+        if(key != null && value != null)

+        {

+            m_properties.put(key,value);

+        }

+    }

+

+    /**

+     * Returns the property descriptors

+     *

+     * @return the property descriptors as a Collection

+     */

+    public Properties getProperties()

+    {

+        return m_properties;

+    }

+

+    /**

+     * Used to add a dependency descriptor to the service descriptor

+     *

+     * @param newDependency a new dependency to be added

+     */

+    void addDependency(DependencyMetadata newDependency)

+    {

+        m_dependencies.add(newDependency);

+    }

+

+

+    /**

+     * Returns the dependency descriptors

+     *

+     * @return a Collection of dependency descriptors

+     */

+    public Collection getDependencies()

+    {

+        return m_dependencies;

+    }

+

+    /**

+     * Test to see if this service is a factory

+     *

+     * @return true if it is a factory, false otherwise

+     */

+    public boolean isFactory()

+    {

+        return m_isFactory;

+    }

+

+     /**

+     * Get the meta data of the instances

+     *

+     * @return the instance metadata

+     */

+    public InstanceMetadata getInstantiates()

+    {

+        return m_instantiates;

+    }

+

+     /**

+     * Test to see if this descriptor describes a bundle-to-service dependency

+     * that means that the instance does not register any services.

+     *

+     * @return true if the dependency is bundle-to-service

+     */

+    public boolean instanceRegistersServices()

+    {

+        return m_registersService;

+    }

+

+     /**

+     * Test to see if this descriptor is registered from an instance from a factory.

+     *

+     * @return true if this descriptor is registered from an instance from a factory.

+     */

+    public boolean isInstance()

+    {

+        return m_isInstance;

+    }

+}

diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReference.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReference.java
new file mode 100644
index 0000000..c4366b2
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReference.java
@@ -0,0 +1,99 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * This interface creates a level of indirection for the objects
+ * created by a factory. This is necessary because it might not
+ * be possible for a factory to create the actual object instance
+ * at the time of the call to <tt>Factory.createInstance()</tt>
+ * due to unfulfilled dependencies. In such a scenario, this
+ * interface can be used to listen for the object instance to
+ * become available.
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a> 
+ */
+public interface InstanceReference
+{
+    public static final String INSTANCE_STATE = "INSTANCE_STATE";
+    public static final String INSTANCE_METADATA = "INSTANCE_METADATA";
+    public static final String INSTANCE_BUNDLE = "INSTANCE_BUNDLE";
+    public static final String INSTANCE_DEPENDENCIES ="INSTANCE_DEPENDENCIES";
+
+    /**
+     * Get a property associated with this instance. For classes
+     * implementing this method, special care must be taken for
+     * values implementing <tt>InstanceReference.ValueHolder</tt>.
+     * In such cases, the value itself should not be returned, but
+     * the value of <tt>InstanceReference.ValueHolder.get()</tt>
+     * should be returned instead. This may be used to defer
+     * creating value objects in cases where creating the value
+     * object is expensive.
+     * @param name the name of the property to retrieve.
+     * @return the value of the associated property or <tt>null</tt>.
+    **/
+    public Object get(String name);
+
+    /**
+     * Associate a property with this instance. For classes
+     * implementing this method, special care must be taken for
+     * values implementing <tt>InstanceReference.ValueHolder</tt>.
+     * In such cases, the value itself should not be returned, but
+     * the value of <tt>InstanceReference.ValueHolder.get()</tt>
+     * should be returned instead. This may be used to defer
+     * creating value objects in cases where creating the value
+     * object is expensive.
+     * @param name the name of the property to add.
+     * @param value the value of the property.
+    **/
+    public void put(String name, Object value);
+
+    /**
+     * Gets the actual object associated with this instance refernce.
+     * @return the object associated with this reference or <tt>null</tt>
+     *         if the reference is not currently valid.
+    **/
+    public Object getObject();
+
+    /**
+     * Adds an instance reference listener to listen for changes to
+     * the availability of the underlying object associated with this
+     * instance reference.
+     * @param l the listener to add.
+    **/
+    public void addInstanceReferenceListener(InstanceReferenceListener l);
+
+    /**
+     * Removes an instance reference listener.
+     * @param l the listener to remove.
+    **/
+    public void removeInstanceReferenceListener(InstanceReferenceListener l);
+
+    /**
+     * A simple interface that enabled deferred value creation for
+     * the <tt>InstanceReference.get()</tt> and <tt>InstanceReference.put()</tt>
+     * methods.
+    **/
+    public static interface ValueHolder
+    {
+        /**
+         * Returns the associated value.
+         * @return the associated value or <tt>null</tt>.
+        **/
+        public Object get(InstanceReference ir);
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceEvent.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceEvent.java
new file mode 100644
index 0000000..2df4c47
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceEvent.java
@@ -0,0 +1,40 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * This class is the event generated when the availability of the
+ * underlying object associated with an <tt>InstanceReference</tt>
+ * changes. Use the <tt>InstanceReferenceListener</tt> interface
+ * to listen for this event. The <tt>getSource()</tt> method
+ * returns the <tt>InstanceReference</tt> that generated the event.
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+**/
+public class InstanceReferenceEvent extends java.util.EventObject
+{
+    private static final long serialVersionUID = 189791898139565080L;
+
+    /**
+     * Construct an event with the specified source instance reference.
+     * @param ir the instance reference that generated the event.
+    **/
+    public InstanceReferenceEvent(InstanceReference ir)
+    {
+        super(ir);
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceListener.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceListener.java
new file mode 100644
index 0000000..d616ff7
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/InstanceReferenceListener.java
@@ -0,0 +1,71 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * This is an event listener for listening to changes in
+ * the availability of the underlying object associated
+ * with an <tt>InstanceReference</tt>. For the precise
+ * details of when this event is fired, refer to the
+ * methods below.
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+**/
+public interface InstanceReferenceListener extends java.util.EventListener
+{
+    /**
+     * This method is called when an <tt>InstanceReference</tt>'s
+     * underlying object becomes valid, i.e., the instance is
+     * available for use. This event is fired during the following
+     * sequence of steps:
+     * <p>
+     * <ol>
+     *   <li>Instance created.</li>
+     *   <li>Dependencies bound, if any.</li>
+     *   <li>Services registered, if any.</li>
+     *   <li><tt>Lifecycle.activate()</tt> is called, if the instance
+     *       implements the <tt>Lifecycle</tt> interface.</li>
+     *   <li>Fire <tt>InstanceReferenceListener.validated()</tt>.
+     * </ol>
+     * @param event the associated instance reference event.
+    **/
+    public void validated(InstanceReferenceEvent event);
+
+    /**
+     * This method is called when an <tt>InstanceReference</tt>'s
+     * underlying object is going to be invalidated. This event
+     * is fired during the following sequence of steps:
+     * <p>
+     * <ol>
+     *   <li>Fire <tt>InstanceReferenceListener.invalidating()</tt>.
+     *   <li>Call <tt>Lifecycle.deactivate()</tt>, if the instance
+     *       implements the <tt>Lifecycle</tt> interface.</li>
+     *   <li>Unregister services, if any.</li>
+     *   <li>Unbind dependencies, if any.</li>
+     *   <li>Dispose instance.</li>
+     * </ol>
+     * <p>
+     * Note: Care must be taken during this callback, because the
+     * underlying object associated with the instance reference may
+     * not be fully functioning. For example, this event might be
+     * fired in direct response to a dependent service shutting down,
+     * which then instigates the invalidation of the underlying object
+     * instance.
+     * @param event the associated instance reference event.
+    **/
+    public void invalidating(InstanceReferenceEvent event);
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/Lifecycle.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/Lifecycle.java
new file mode 100644
index 0000000..7d5b40f
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/Lifecycle.java
@@ -0,0 +1,44 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * Instances created by the service binder, either via the
+ * <tt>GenericActivator</tt> or the <tt>GenericFactory</tt>,
+ * may implement this interface to receive notification of
+ * object life cycle events. See each interface method for
+ * a precise description of when the method is invoked.
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+**/
+public interface Lifecycle
+{
+    /**
+     * This method is called after the instance is created, all of its
+     * dependencies are valid, and all implemented services are registered.
+    **/
+    public void activate();
+
+    /**
+     * This method is called prior to instance disposal. At the time
+     * of invocation, all dependencies are still valid and all services
+     * are still registered. Be aware that at this point some dependent
+     * services may have been shutdown and using them may result in
+     * error conditions.
+    **/
+    public void deactivate();
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/PropertyMetadata.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/PropertyMetadata.java
new file mode 100644
index 0000000..e89892f
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/PropertyMetadata.java
@@ -0,0 +1,115 @@
+/*

+ *   Copyright 2006 The Apache Software Foundation

+ *

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

+

+/**

+ * A property descriptor that contains the information for properties

+ * defined in the meta-data file.

+ *

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

+ */

+public class PropertyMetadata

+{

+	String name;

+	String type;

+	Object value;

+

+	/**

+	 * Create a PropertyMetadata object

+	 *

+	 * @param   name the name of the property

+	 * @param   type the type of the property (string, boolean, byte, char, short, int, long, float or double)

+	 * @param   val the value of the property

+	 */

+	public PropertyMetadata(String name, String type, String val)

+	{

+		this.name = name;

+		type.toLowerCase();

+		this.type = type;

+		value = null;

+

+		if(type.equals("string") || type.equals("String"))

+        {

+			value = new String(val);

+        }

+		else if(type.equals("boolean"))

+        {

+			value = new Boolean(val);

+        }

+		else if(type.equals("byte"))

+        {

+			value = new Byte(val);

+        }

+		else if(type.equals("char"))

+        {

+			value = new Byte(val);

+        }

+		else if(type.equals("short"))

+        {

+			value = new Short(val);

+        }

+		else if(type.equals("int"))

+        {

+			value = new Integer(val);

+        }

+		else if(type.equals("long"))

+        {

+			value = new Long(val);

+        }

+		else if(type.equals("float"))

+        {

+			value = new Float(val);

+        }

+		else if(type.equals("double"))

+        {

+			value = new Double(val);

+        }

+	}
+
+    /**
+     * Get the name of the property
+     * 
+     * @return the name of the property
+     * 
+     * @uml.property name="name"
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Get the type of the property
+     * 
+     * @return the type of the property
+     * 
+     * @uml.property name="type"
+     */
+    public String getType() {
+        return type;
+    }
+
+    /**
+     * Get the value of the property
+     * 
+     * @return the value of the property as an Object
+     * 
+     * @uml.property name="value"
+     */
+    public Object getValue() {
+        return value;
+    }
+}

diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderContext.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderContext.java
new file mode 100644
index 0000000..bcadab5
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderContext.java
@@ -0,0 +1,50 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+import org.osgi.framework.BundleContext;
+
+import java.util.List;
+
+/**
+ * The ServiceBinderContext is passed to the objects that implement the services
+ * if they implement a constructor that receives a reference of this type. Through
+ * this interface, they can access the BundleContext along with the list ob
+ * binder instances located on the same bundle.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface ServiceBinderContext
+{
+    /**
+     *
+     *@return the Bundle Context of the bundle where the receiver of the context is located
+    **/
+    BundleContext getBundleContext();
+
+    /**
+     *
+     *
+    **/
+    List getInstanceReferences();
+
+    /**
+     *
+     *
+    **/
+    InstanceReference getInstanceReference();
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderException.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderException.java
new file mode 100644
index 0000000..9713430
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/ServiceBinderException.java
@@ -0,0 +1,32 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+/**
+ * Exceptions thrown by the ServiceBinder.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class ServiceBinderException extends Exception
+{
+    private static final long serialVersionUID = 2819108687170297942L;
+
+    public ServiceBinderException(String msg)
+    {
+        super(msg);
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/XmlHandler.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/XmlHandler.java
new file mode 100644
index 0000000..c3e5f6b
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/XmlHandler.java
@@ -0,0 +1,143 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder;
+
+import java.util.Properties;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.servicebinder.parser.ParseException;
+
+/**
+ * Simple content handler that builds a list of service descriptors
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class XmlHandler
+{
+    /**
+     * 
+     * @uml.property name="parentDescriptor"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private InstanceMetadata parentDescriptor = null;
+
+    /**
+     * 
+     * @uml.property name="currentDescriptor"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private InstanceMetadata currentDescriptor = null;
+
+    private List descriptors = new ArrayList();
+
+    XmlHandler()
+    {
+    }
+
+    /**
+     * Method called when a tag opens
+     *
+     * @param   uri
+     * @param   localName
+     * @param   qName
+     * @param   attrib
+     * @exception   ParseException
+    **/
+    public void startElement(String uri,String localName,String qName,Properties attrib) throws ParseException
+    {
+        if (qName.equals("instance") || qName.equals("component"))
+        {
+            currentDescriptor = new InstanceMetadata(attrib.getProperty("class"),parentDescriptor);
+            descriptors.add(currentDescriptor);
+        }
+        if (qName.equals("service")) // will be deprecated
+        {
+            if(currentDescriptor == null)
+            {
+                return;
+            }
+            currentDescriptor.addInterface(attrib.getProperty("interface"));
+        }
+        if (qName.equals("provides"))
+        {
+            if(currentDescriptor == null)
+            {
+                return;
+            }
+            currentDescriptor.addInterface(attrib.getProperty("service"));
+        }
+        if (qName.equals("property"))
+        {
+
+            if(currentDescriptor == null)
+            {
+                return;
+            }
+            PropertyMetadata prop = new PropertyMetadata(attrib.getProperty("name"),
+                attrib.getProperty("type"),
+                attrib.getProperty("value"));
+            currentDescriptor.addProperty(prop);
+        }
+        if (qName.equals("requires"))
+        {
+            if(currentDescriptor == null)
+            {
+                return;
+            }
+
+            DependencyMetadata dd=new DependencyMetadata(attrib.getProperty("service"),
+                attrib.getProperty("cardinality"),attrib.getProperty("policy"),attrib.getProperty("filter"),
+                attrib.getProperty("bind-method"),attrib.getProperty("unbind-method"));
+
+            currentDescriptor.addDependency(dd);
+        }
+        
+        if (qName.equals("instantiates"))
+        {
+            GenericActivator.error("ERROR: Version 1.1 does not support factories");
+        }
+
+    }
+
+    /**
+    * Method called when a tag closes
+    *
+    * @param   uri
+    * @param   localName
+    * @param   qName
+    * @exception   ParseException
+    */
+    public void endElement(java.lang.String uri,java.lang.String localName,java.lang.String qName) throws ParseException
+    {
+        if (qName.equals("instantiates") || qName.equals("component"))
+        {
+            currentDescriptor = parentDescriptor;
+            parentDescriptor = null;
+        }
+    }
+
+    /**
+    * Called to retrieve the service descriptors
+    *
+    * @return   A list of service descriptors
+    */
+    List getInstanceMetadatas()
+    {
+        return descriptors;
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ArchitectureService.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ArchitectureService.java
new file mode 100644
index 0000000..d72789d
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ArchitectureService.java
@@ -0,0 +1,48 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+/**
+ *
+ * A service to provide an architectural vision of the instances created by the
+ * service binder
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface ArchitectureService
+{
+    /**
+     * Get a list of all the available instance references
+     *
+     * @return a List containing all of the instance references
+    **/
+    public Instance [] getInstances();
+
+    /**
+     * Add a service binder listener
+     *
+     * @param listener a ServiceBinderListener to add to the Architecture service
+    **/
+    public void addServiceBinderListener(ServiceBinderListener listener);
+
+    /**
+     * Remove a service binder listener
+     *
+     * @param listener the listener to be removed
+    **/
+    public void removeServiceBinderListener(ServiceBinderListener listener);
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Dependency.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Dependency.java
new file mode 100644
index 0000000..3ef0a27
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Dependency.java
@@ -0,0 +1,48 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+import org.apache.felix.servicebinder.DependencyMetadata;
+
+/**
+ * Interface for a dependency
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface Dependency
+{
+    /**
+     * get the dependency state
+     *
+     * @return the state of the dependency
+    **/
+    public int getDependencyState();
+
+    /**
+     * get the dependency metadata
+     *
+     * @return the metadata of the dependency
+    **/
+    public DependencyMetadata getDependencyMetadata();
+
+    /**
+     * get the bound service objects
+     *
+     * @return the bound Instances
+    **/
+    public Instance []getBoundInstances();
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/DependencyChangeEvent.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/DependencyChangeEvent.java
new file mode 100644
index 0000000..603d97d
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/DependencyChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+import org.apache.felix.servicebinder.DependencyMetadata;
+
+/**
+ * An event thrown when a dependency changes
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class DependencyChangeEvent
+{
+    public static final int DEPENDENCY_CREATED = 0;
+    public static final int DEPENDENCY_VALID = 1;
+    public static final int DEPENDENCY_INVALID = 2;
+    public static final int DEPENDENCY_DESTROYED = 3;
+
+    /**
+     * 
+     * @uml.property name="m_dep"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private Dependency m_dep;
+
+    /**
+     * 
+     * @uml.property name="m_meta"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private DependencyMetadata m_meta;
+
+    private int m_state;
+
+    public DependencyChangeEvent(Dependency dep, DependencyMetadata meta,int newState)
+    {
+        m_dep = dep;
+        m_meta = meta;
+        m_state = newState;
+    }
+
+    public Dependency getDependency()
+    {
+        return m_dep;
+    }
+
+    public DependencyMetadata getDependencyMetadata()
+    {
+        return m_meta;
+    }
+
+    public int getState()
+    {
+        return m_state;
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Instance.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Instance.java
new file mode 100644
index 0000000..21aa209
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/Instance.java
@@ -0,0 +1,66 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+import org.apache.felix.servicebinder.InstanceMetadata;
+
+/**
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface Instance
+{
+    public static final int INSTANCE_CREATED = 0;
+    public static final int INSTANCE_VALID = 1;
+    public static final int INSTANCE_INVALID = 2;
+    public static final int INSTANCE_DESTROYED = 3;
+
+    /**
+     * Get the state of the instance
+     *
+     * @return an integer representing the state of the instance
+    **/
+    public int getState();
+
+    /**
+     * Get the bundle
+     *
+     * @return an integer with the bundle id
+    **/
+     public long getBundleId();
+
+    /**
+     * Get a list of depenencies
+     *
+     * @return a List containing all of the dependencies
+    **/
+    public Dependency[] getDependencies();
+
+    /**
+     * Get a list of child instances in case this instance is a factory
+     *
+     * @return a List containing all of the child instances
+    **/
+    public Instance[] getChildInstances();
+
+    /**
+     * Get the instance metadata
+     *
+     * @return the isntance metadata
+    **/
+    public InstanceMetadata getInstanceMetadata();
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/InstanceChangeEvent.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/InstanceChangeEvent.java
new file mode 100644
index 0000000..deba479
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/InstanceChangeEvent.java
@@ -0,0 +1,64 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+import org.apache.felix.servicebinder.InstanceMetadata;
+
+/**
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class InstanceChangeEvent
+{
+    /**
+     * 
+     * @uml.property name="m_ref"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private Instance m_ref;
+
+    /**
+     * 
+     * @uml.property name="m_meta"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private InstanceMetadata m_meta;
+
+    private int m_state;
+
+    public InstanceChangeEvent(Instance ref,InstanceMetadata meta,int state)
+    {
+        m_ref = ref;
+        m_meta = meta;
+        m_state = state;
+    }
+
+    public Instance getInstance()
+    {
+        return m_ref;
+    }
+
+    public InstanceMetadata getInstanceMetadata()
+    {
+        return m_meta;
+    }
+
+    public int getState()
+    {
+        return m_state;
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ServiceBinderListener.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ServiceBinderListener.java
new file mode 100644
index 0000000..dec4b4e
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/architecture/ServiceBinderListener.java
@@ -0,0 +1,38 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.architecture;
+
+/**
+ * The ServiceBinderListener interface must be implemented by any subclass
+ * of the GenericActivator if it wishes to receive notifications about
+ * changes in the architecture
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public interface ServiceBinderListener extends java.util.EventListener
+{
+    /*
+    * Method called when an instance changes its state
+    */
+    void instanceReferenceChanged(InstanceChangeEvent evt);
+
+    /*
+    * Method called when a dependency changes its state
+    */
+    void dependencyChanged(DependencyChangeEvent evt);
+
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/Activator.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/Activator.java
new file mode 100644
index 0000000..578a064
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/Activator.java
@@ -0,0 +1,27 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.impl;
+
+import org.apache.felix.servicebinder.GenericActivator;
+
+/**
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class Activator extends GenericActivator
+{
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureEventMulticaster.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureEventMulticaster.java
new file mode 100644
index 0000000..ecbeba0
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureEventMulticaster.java
@@ -0,0 +1,80 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.impl;
+
+import org.apache.felix.servicebinder.architecture.DependencyChangeEvent;
+import org.apache.felix.servicebinder.architecture.InstanceChangeEvent;
+import org.apache.felix.servicebinder.architecture.ServiceBinderListener;
+
+/**
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class ArchitectureEventMulticaster implements ServiceBinderListener
+{
+    /**
+     * 
+     * @uml.property name="a"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    protected ServiceBinderListener a;
+
+    /**
+     * 
+     * @uml.property name="b"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    protected ServiceBinderListener b;
+
+    protected ArchitectureEventMulticaster(ServiceBinderListener a, ServiceBinderListener b)    
+    {        
+        this.a = a;        
+        this.b = b;    
+    }    
+    
+    public void dependencyChanged(DependencyChangeEvent e)    
+    {
+        a.dependencyChanged(e);        
+        b.dependencyChanged(e);
+    }
+    
+    public void instanceReferenceChanged(InstanceChangeEvent e)    
+    {
+        a.instanceReferenceChanged(e);        
+        b.instanceReferenceChanged(e);
+    }
+    
+    public static ServiceBinderListener add(ServiceBinderListener a, ServiceBinderListener b)
+    {
+        if (a == null)
+            return b;
+        else if (b == null)
+            return a;
+        else
+            return new ArchitectureEventMulticaster(a, b);
+    }
+    
+    public static ServiceBinderListener remove(ServiceBinderListener a, ServiceBinderListener b)
+    {
+        if ((a == null) || (a == b))            
+            return null;        
+        else if (a instanceof ArchitectureEventMulticaster)            
+            return add (remove (((ArchitectureEventMulticaster) a).a, b),remove (((ArchitectureEventMulticaster) a).b, b));        
+        else            
+            return a;    
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureServiceImpl.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureServiceImpl.java
new file mode 100644
index 0000000..c7518a1
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/impl/ArchitectureServiceImpl.java
@@ -0,0 +1,171 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.impl;
+
+import org.apache.felix.servicebinder.InstanceReference;
+import org.apache.felix.servicebinder.Lifecycle;
+import org.apache.felix.servicebinder.architecture.ArchitectureService;
+import org.apache.felix.servicebinder.architecture.DependencyChangeEvent;
+import org.apache.felix.servicebinder.architecture.Instance;
+import org.apache.felix.servicebinder.architecture.InstanceChangeEvent;
+import org.apache.felix.servicebinder.architecture.ServiceBinderListener;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Class that implements the architecture service
+ * an object of this class is created when the
+ * service binder bundle is activated
+ * 
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class ArchitectureServiceImpl implements ArchitectureService, Lifecycle
+{
+    /**
+     * 
+     * @uml.property name="m_listeners"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private ServiceBinderListener m_listeners = null;
+
+    /**
+     * 
+     * @uml.property name="m_ref"
+     * @uml.associationEnd multiplicity="(0 1)"
+     */
+    private static ArchitectureServiceImpl m_ref = null;
+
+    private static List m_instanceReferences = new ArrayList();
+
+    public ArchitectureServiceImpl() throws Exception
+    {
+        if(m_ref == null)
+        {
+            m_ref = this;
+        }
+    }
+
+    public static InstanceReference findInstanceReference(Object obj)
+    {
+        Object[] refs=m_instanceReferences.toArray();
+
+        for(int i=0; i<refs.length ;i++)
+        {
+            InstanceReference current = (InstanceReference) refs [i];
+            if(current.getObject( )== obj)
+            {
+                return current;
+            }
+        }
+
+        return null;
+    }
+
+    public static void addInstanceReference(InstanceReference ref)
+    {
+        m_instanceReferences.add(ref);
+    }
+
+    public static void removeInstanceReference(InstanceReference ref)
+    {
+        m_instanceReferences.remove(ref);
+    }
+
+    public Instance[] getInstances()
+    {
+        Instance instances[]=new Instance[m_instanceReferences.size()];
+        instances = (Instance [])m_instanceReferences.toArray(instances);
+
+        return instances;
+    }
+
+    public static ArchitectureServiceImpl getReference()
+    {
+        return m_ref;
+    }
+
+    public void activate()
+    {
+    }
+
+    synchronized public void deactivate()
+    {
+        m_ref = null;
+        m_listeners = null; //new EventListenerList();
+    }
+
+    /**
+     * Add a service binder listener
+    **/
+    public void addServiceBinderListener(ServiceBinderListener listener)
+    {
+        //m_listeners.add(ServiceBinderListener.class, listener);
+        m_listeners = ArchitectureEventMulticaster.add(m_listeners, listener);
+    }
+
+    /**
+     * Remove a service binder listener
+    **/
+    public void removeServiceBinderListener(ServiceBinderListener listener)
+    {
+        //m_listeners.remove(ServiceBinderListener.class, listener);
+        m_listeners = ArchitectureEventMulticaster.remove(m_listeners, listener);
+    }
+
+    /**
+     * Fires an event when an instance has changed
+    **/
+    public void fireInstanceChangeEvent(InstanceChangeEvent evt)
+    {
+        try
+        {
+            if (m_listeners != null)
+            {
+                m_listeners.instanceReferenceChanged(evt);
+            }
+        }
+        catch(Exception ex)
+        {
+            // Ignore any exception
+        }
+    }
+
+    /**
+     * Fires an event when a dependency has changed
+    **/
+    public void fireDependencyChangeEvent(DependencyChangeEvent evt)
+    {
+        try
+        {
+            if (m_listeners != null)
+            {
+                m_listeners.dependencyChanged(evt);
+            }
+        }
+        catch(Exception ex)
+        {
+            // Ignore any exception
+        }
+    }
+    
+
+
+}
+
+
+
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/KxmlParser.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/KxmlParser.java
new file mode 100644
index 0000000..4a553ff
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/KxmlParser.java
@@ -0,0 +1,77 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.parser;
+
+import org.apache.felix.servicebinder.XmlHandler;
+import org.kxml.parser.XmlParser;
+import org.kxml.parser.ParseEvent;
+import org.kxml.Xml;
+import org.kxml.Attribute;
+
+import java.io.Reader;
+
+import java.util.Properties;
+
+/**
+ * The KxmlParser extends the XmlParser from kxml. This is a very
+ * simple parser that does not take into account the DTD
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class KxmlParser extends XmlParser
+{
+    /**
+    * The constructor for a parser, it receives a java.io.Reader.
+    *
+    * @param   r  The reader
+    * @exception   java.io.IOException thrown by the superclass
+    */
+    public KxmlParser(Reader r) throws java.io.IOException
+    {
+        super(r);
+    }
+
+    /**
+    * Parser from the reader provided in the constructor, and call
+    * the startElement and endElement in a KxmlHandler
+    *
+    * @param   handler The handler
+    * @exception   java.io.IOException thrown by the superclass
+    */
+    public void parseXML(XmlHandler handler) throws java.io.IOException, ParseException
+    {
+        ParseEvent evt=null;
+        do
+        {
+            evt = read();
+            if (evt.getType() == Xml.START_TAG)
+            {
+                Properties props = new Properties();
+                for (int i=0; i<evt.getAttributeCount();i++)
+                {
+                    Attribute attr = evt.getAttribute(i);
+                    props.put(attr.getName(),attr.getValue());
+                }
+                handler.startElement("uri",evt.getName(),evt.getName(),props);
+            }
+            if (evt.getType() == Xml.END_TAG)
+            {
+                handler.endElement("uri",evt.getName(),evt.getName());
+            }
+        }while(evt.getType()!=Xml.END_DOCUMENT);
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/ParseException.java b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/ParseException.java
new file mode 100644
index 0000000..071ecbf
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/java/org/apache/felix/servicebinder/parser/ParseException.java
@@ -0,0 +1,32 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.servicebinder.parser;
+
+/**
+ * Exceptions thrown by the ServiceBinder.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class ParseException extends Exception
+{
+    private static final long serialVersionUID = -2658823754557277056L;
+
+    public ParseException(String msg)
+    {
+        super(msg);
+    }
+}
diff --git a/org.apache.felix.servicebinder/src/main/resources/metadata.dtd b/org.apache.felix.servicebinder/src/main/resources/metadata.dtd
new file mode 100644
index 0000000..6917216
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/resources/metadata.dtd
@@ -0,0 +1,29 @@
+<!--
+  DTD for org.apache.felix.servicebinder descriptor DTD
+  Version: 1.1
+-->
+
+<!ELEMENT bundle (component*)>
+<!ELEMENT component (property*,provides*,requires*)>
+  <!ATTLIST  component
+    class CDATA #REQUIRED
+  >
+<!ELEMENT provides EMPTY>
+  <!ATTLIST  provides
+    service CDATA #REQUIRED
+  >
+<!ELEMENT property EMPTY>
+  <!ATTLIST  property
+    name CDATA #REQUIRED
+    type CDATA #REQUIRED
+    value CDATA #REQUIRED
+  >
+<!ELEMENT requires EMPTY>
+  <!ATTLIST  requires
+    service CDATA #REQUIRED
+    filter CDATA #REQUIRED
+    cardinality (0..1|0..n|1..1|1..n) #REQUIRED
+    policy (static|dynamic) #REQUIRED
+    bind-method CDATA #REQUIRED
+    unbind-method CDATA #REQUIRED
+>
diff --git a/org.apache.felix.servicebinder/src/main/resources/metadata.xml b/org.apache.felix.servicebinder/src/main/resources/metadata.xml
new file mode 100644
index 0000000..18f0797
--- /dev/null
+++ b/org.apache.felix.servicebinder/src/main/resources/metadata.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--<!DOCTYPE bundle SYSTEM "metadata.dtd">-->
+<bundle>
+  <component class="org.apache.felix.servicebinder.impl.ArchitectureServiceImpl">
+    <provides service="org.apache.felix.servicebinder.architecture.ArchitectureService"/>
+  </component>
+</bundle>