Initial upload

git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@395940 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.scr/changelog.txt b/org.apache.felix.scr/changelog.txt
new file mode 100644
index 0000000..c4c3f89
--- /dev/null
+++ b/org.apache.felix.scr/changelog.txt
@@ -0,0 +1,5 @@
+04/21/2006

+

+This version of the declarative services is derived from the service binder's original source.

+At this point, it supports the declaration of components that provide services and references.

+The components may be immediate or delayed.
\ No newline at end of file
diff --git a/org.apache.felix.scr/pom.xml b/org.apache.felix.scr/pom.xml
new file mode 100644
index 0000000..67b40b6
--- /dev/null
+++ b/org.apache.felix.scr/pom.xml
@@ -0,0 +1,58 @@
+<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 Declarative Services</name>

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

+  <dependencies>

+    <dependency>

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

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

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

+      <scope>provided</scope>

+    </dependency>

+    <dependency>

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

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

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

+      <scope>provided</scope>

+    </dependency>

+    <dependency>

+      <groupId>kxml2</groupId>

+      <artifactId>kxml2</artifactId>

+      <version>2.2.2</version>

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

+            <bundleName>Service Component Runtime</bundleName>

+            <bundleVendor>Apache Software Foundation</bundleVendor>

+            <bundleDescription>

+              Implementation of the Declarative Services specification.

+            </bundleDescription>

+            <bundleActivator>

+              org.apache.felix.scr.Activator

+            </bundleActivator>

+            <bundleSymbolicName>org.apache.felix.scr</bundleSymbolicName>

+            <exportPackage>

+			  org.apache.felix.scr

+			</exportPackage>

+			<importPackage>

+              org.osgi.service.component, org.osgi.framework

+            </importPackage>			

+          </osgiManifest>

+        </configuration>

+      </plugin>

+    </plugins>

+  </build>

+</project>

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXHandler.java b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXHandler.java
new file mode 100644
index 0000000..6d32e75
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXHandler.java
@@ -0,0 +1,74 @@
+/*

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

+

+import java.util.Properties;

+

+/**

+ * Interface for SAX handler with kXML

+ *

+ * @author Didier Donsez (didier.donsez@imag.fr)

+ */

+public interface KXml2SAXHandler {

+

+	/**

+	* Method called when parsing text

+	*

+	* @param   ch

+	* @param   offset

+	* @param   length

+	* @exception   SAXException

+	*/

+	public void characters(char[] ch, int offset, int length) throws Exception;

+

+	/**

+	* Method called when a tag opens

+	*

+	* @param   uri

+	* @param   localName

+	* @param   qName

+	* @param   attrib

+	* @exception   SAXException

+	**/

+	public void startElement(

+		String uri,

+		String localName,

+		String qName,

+		Properties attrib)

+		throws Exception;

+	/**

+	* Method called when a tag closes

+	*

+	* @param   uri

+	* @param   localName

+	* @param   qName

+	* @exception   SAXException

+	*/

+	public void endElement(

+		java.lang.String uri,

+		java.lang.String localName,

+		java.lang.String qName)

+		throws Exception;

+

+	public void processingInstruction(String target,

+									  String data)

+							   throws Exception;

+		

+	public void setLineNumber(int lineNumber);

+

+	public void setColumnNumber(int columnNumber);

+}
\ No newline at end of file
diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXParser.java b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXParser.java
new file mode 100644
index 0000000..99a6ea3
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/KXml2SAXParser.java
@@ -0,0 +1,84 @@
+/*

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

+

+import java.io.Reader;

+import java.util.Properties;

+

+import org.kxml2.io.KXmlParser;

+import org.xmlpull.v1.XmlPullParser;

+import org.xmlpull.v1.XmlPullParserException;

+

+/**

+ * The KXml2SAXParser extends the XmlParser from kxml. This is a very

+ * simple parser that does not take into account the DTD

+ *

+ */

+public class KXml2SAXParser extends KXmlParser {

+	

+	public String uri="uri";

+

+	private Reader reader;

+	

+	/**

+	* The constructor for a parser, it receives a java.io.Reader.

+	*

+	* @param   reader  The reader

+	* @throws XmlPullParserException 

+	*/

+	public KXml2SAXParser(Reader reader) throws XmlPullParserException {

+		super();

+		this.reader=reader;

+	    setInput(reader);

+	}

+	

+	/**

+	* Parser from the reader provided in the constructor, and call

+	* the startElement and endElement in a KxmlHandler

+	*

+	* @param   reader  The reader

+	* @exception   Exception thrown by the superclass

+	*/

+	public void parseXML(KXml2SAXHandler handler) throws Exception {

+

+		while (next() != XmlPullParser.END_DOCUMENT) {

+			handler.setLineNumber(getLineNumber());

+			handler.setColumnNumber(getColumnNumber());

+			if (getEventType() == XmlPullParser.START_TAG) {

+				Properties props = new Properties();

+				for (int i = 0; i < getAttributeCount(); i++) {

+					props.put(getAttributeName(i), getAttributeValue(i));

+				}

+				handler.startElement(

+					getNamespace(),

+					getName(),

+					getName(),

+					props);

+			} else if (getEventType() == XmlPullParser.END_TAG) {

+				handler.endElement(getNamespace(), getName(), getName());

+			} else if (getEventType() == XmlPullParser.TEXT) {

+				String text = getText();

+				handler.characters(text.toCharArray(),0,text.length());

+			} else if (getEventType() == XmlPullParser.PROCESSING_INSTRUCTION) {

+				// TODO extract the target from the evt.getText()

+				handler.processingInstruction(null,getText()); 

+			} else {

+				// do nothing

+			}

+		}

+	}	

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/ParseException.java b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/ParseException.java
new file mode 100644
index 0000000..41a8a85
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/declarativeservices/scr/ParseException.java
@@ -0,0 +1,31 @@
+/*
+ *   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.declarativeservices.scr;
+
+public class ParseException extends Exception
+{
+	Exception m_originalException;
+	
+    public ParseException(String msg, Exception originalException) {
+        super(msg);
+        m_originalException = originalException;
+    }
+    
+    public Exception getException() {
+    	return m_originalException;
+    }
+}
diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/Activator.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/Activator.java
new file mode 100644
index 0000000..112f376
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/Activator.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.scr;

+

+import org.osgi.framework.BundleActivator;

+import org.osgi.framework.BundleContext;

+

+/**

+ * This activator is used to cover requirement described in section 112.8.1

+ * When SCR is implemented as a bundle, any component configurations

+ * activated by SCR must be deactivated when the SCR bundle is stopped. When

+ * the SCR bundle is started, it must process any components that are declared

+ * in active bundles. 

+ *

+ */

+public class Activator implements BundleActivator {

+

+	public void start(BundleContext arg0) throws Exception {

+		//TODO: pending

+	}

+

+	public void stop(BundleContext arg0) throws Exception {

+		// TODO: pending

+	}

+

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManager.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManager.java
new file mode 100644
index 0000000..e7696a6
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManager.java
@@ -0,0 +1,45 @@
+/*

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

+

+/**

+ * This interface is provided so that there can be multiple implementations of 

+ * managers that are responsible for managing component's lifecycle.  

+ * 

+ */

+public interface ComponentManager {

+	

+	/**

+	 * Enable the component

+	 * 

+	 * @return true if it was succesfully enabled, false otherwise

+	 */

+	public boolean enable();

+	

+	/**

+	 * Dispose the component

+	 * 

+	 */

+	public void dispose();

+

+	/**

+	 * Get the component information

+	 * 

+	 * @return a ComponentMetadata object

+	 */

+	public ComponentMetadata getComponentMetadata();

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java
new file mode 100644
index 0000000..a8779bb
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java
@@ -0,0 +1,1041 @@
+/*

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

+

+import java.util.Dictionary;

+import java.util.ArrayList;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Set;

+

+import org.osgi.framework.ServiceFactory;

+import org.osgi.framework.ServiceRegistration;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.ServiceListener;

+import org.osgi.framework.ServiceEvent;

+import org.osgi.framework.ServiceReference;

+import org.osgi.framework.Bundle;

+import org.osgi.service.component.ComponentContext;

+import org.osgi.service.component.ComponentInstance;

+

+import java.lang.reflect.Method;

+import java.lang.reflect.InvocationTargetException;

+

+
+/**

+ * The default ComponentManager. Objects of this class are responsible for managing

+ * implementation object's lifecycle.  

+ *

+ */

+public class ComponentManagerImpl implements ComponentManager, ComponentInstance

+{

+	// States of the instance manager

+	static final int INSTANCE_CREATING = 0;

+	static final int INSTANCE_CREATED = 1;

+	static final int INSTANCE_VALIDATING = 2;

+	static final int INSTANCE_VALID = 3;

+	static final int INSTANCE_INVALIDATING = 4;

+	static final int INSTANCE_INVALID = 5;

+	static final int INSTANCE_DESTROYING = 6;

+	static final int INSTANCE_DESTROYED = 7;

+		

+

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

+    								"VALIDATING","VALID",

+    								"INVALIDATING","INVALID",

+    								"DESTROYING","DESTROYED"

+                                    };

+

+    // The state of this instance manager

+    private int m_state = INSTANCE_CREATING;
+
+    // The metadata
+    private ComponentMetadata m_componentMetadata;

+

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

+    private Object m_implementationObject = null;

+

+    // The dependency managers that manage every dependency

+    private List m_dependencyManagers = new ArrayList();

+

+    // The ServiceRegistration

+    private ServiceRegistration m_serviceRegistration = null;
+
+    // A reference to the GenericActivator
+    private GenericActivator m_activator = null;
+
+    // The context that will be passed to the implementationObject

+    private ComponentContext m_componentContext = null;
+    

+    // In case of a delayed component, this holds a reference to the factory

+    private DelayedComponentServiceFactory m_delayedComponentServiceFactory;

+    

+    /**

+     * The constructor receives both the activator and the metadata

+     * 

+     * @param activator

+     * @param metadata

+     */

+    ComponentManagerImpl(GenericActivator activator,ComponentMetadata metadata)

+    {

+    	// Store the activator reference

+        m_activator = activator;

+

+        // Store the metadata reference

+        m_componentMetadata = metadata;

+    }

+    

+    /**

+     * Enable this component

+     * 

+     * @return true if enabling was successful

+     */

+    public boolean enable() {

+    	

+    	GenericActivator.trace("Enabling component", m_componentMetadata);

+    	

+    	try

+    	{

+	        // If this component has got dependencies, create dependency managers for each one of them.

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

+	        {

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

+	

+	            while(dependencyit.hasNext())

+	            {

+	                ReferenceMetadata currentdependency = (ReferenceMetadata)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.m_dependencyMetadata.getTarget());

+	            }

+	        }

+	

+	        // TODO: create the context

+	        //m_sbcontext = new ServiceBinderContextImpl(this);

+	

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

+	        //m_activator.addInstanceManager(this);

+	        

+	

+	        setState(INSTANCE_CREATED);

+	        

+	        activate();

+	        

+	        return true;

+    	}

+    	catch(Exception ex)

+    	{

+    		// TODO: Log this error

+    		return false;

+    	}

+    }

+

+    /**

+    * Activate this Instance manager.

+    * 

+    * 112.5.6 Activating a component configuration consists of the following steps

+    *   1. Load the component implementation class

+    *   2. Create the component instance and component context

+    *   3. Bind the target services

+    *   4. Call the activate method, if present

+    *   [5. Register provided services]

+    */

+    synchronized private void activate()

+    {

+        // CONCURRENCY NOTE: This method is called either by the enable() method or by the dependency

+    	// managers.    	

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

+    		// This state can only be entered from the CREATED or INVALID states

+    		return;

+    	}

+

+        setState(INSTANCE_VALIDATING);

+

+        // Before creating the implementation object, we are going to

+        // test if all the mandatory dependencies are satisfied

+        Iterator it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

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

+            // since they have not been initialized yet, but they can't be initialized yet

+            // because the implementationObject has not been created yet.

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

+            // the implementationObject if the dependency managers aren't valid.

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

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

+            {

+                setState(INSTANCE_INVALID);

+                return;

+            }

+        }

+        

+        // 1. Load the component implementation class

+        // 2. Create the component instance and component context

+        // If the component is not immediate, this is not done at this moment

+        if( m_componentMetadata.isImmediate() == true )

+        {

+        	//GenericActivator.trace("Loading implementation class and creating instance for component '"+m_componentMetadata.getName()+"'");

+        	try

+	        {

+	        	// 112.4.4 The class is retrieved with the loadClass method of the component's bundle

+	            Class c = m_activator.getBundleContext().getBundle().loadClass(m_componentMetadata.getImplementationClassName());

+	            

+	            // 112.4.4 The class must be public and have a public constructor without arguments so component instances

+	            // may be created by the SCR with the newInstance method on Class

+	            m_componentContext = new ComponentContextImpl();

+	            m_implementationObject = c.newInstance();

+	        }

+	        catch (Exception ex)

+	        {

+	            // TODO: manage this exception when implementation object cannot be created

+	            GenericActivator.exception("Error during instantiation", m_componentMetadata, ex);

+	            deactivate();

+	            //invalidate();

+	            return;

+	        }

+        } else {

+        	m_delayedComponentServiceFactory = new DelayedComponentServiceFactory();

+        }

+        

+        // 3. Bind the target services

+        it = m_dependencyManagers.iterator();

+

+        //GenericActivator.trace("Binding target services for component '"+m_componentMetadata.getName()+"'");

+        

+        while (it.hasNext())

+        {

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

+            

+            // if any of the dependency managers is unable to bind (it is invalid), the component is deactivated

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

+            {

+            	deactivate();

+                return;

+            }

+        }

+        

+        //GenericActivator.trace("Calling activate for component '"+m_componentMetadata.getName()+"'");

+        

+        // 4. Call the activate method, if present

+	        // 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_componentMetadata.isImmediate() == true && m_state == INSTANCE_VALIDATING)

+        {

+            // Search for the activate method

+        	try {

+        		Method activateMethod = m_implementationObject.getClass().getMethod("activate", new Class[]{ComponentContext.class});

+        		activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});

+        	}

+        	catch(NoSuchMethodException ex) {        		

+        		// We can safely ignore this one

+        		GenericActivator.trace("activate() method not implemented", m_componentMetadata);

+        	}

+        	catch(IllegalAccessException ex) {

+        		// TODO: Log this exception?

+        		GenericActivator.trace("activate() method cannot be called", m_componentMetadata);

+        	}

+        	catch(InvocationTargetException ex) {

+        		// TODO: 112.5.8 If the activate method throws an exception, SCR must log an error message

+        		// containing the exception with the Log Service

+        		GenericActivator.exception("The activate method has thrown an exception", m_componentMetadata, ex.getTargetException());

+        	}

+        }

+        

+        // Validation occurs before the services are provided, otherwhise the service provider's service may be called

+        // by a service requester while it is still VALIDATING

+        setState(INSTANCE_VALID);

+        

+        // 5. Register provided services

+        if(m_componentMetadata.getServiceMetadata() != null)

+        {

+            GenericActivator.trace("registering services", m_componentMetadata);

+

+        	if( m_componentMetadata.isImmediate() == true ) {

+	        	// In the case the component is immediate, the implementation object is registered

+	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_implementationObject, m_componentMetadata.getProperties());

+	        }else {

+	        	// In the case the component is delayed, a factory is registered

+	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_delayedComponentServiceFactory, m_componentMetadata.getProperties());

+	        }

+        }

+    }

+    

+    /**

+     * This method deactivates the manager, performing the following steps

+     * 

+     * [0. Remove published services from the registry]

+     * 1. Call the deactivate() method, if present

+     * 2. Unbind any bound services

+     * 3. Release references to the component instance and component context 

+    **/

+    synchronized private void deactivate()

+    {

+    	// CONCURRENCY NOTE: This method may be called either from application code or by the dependency managers

+    	if (m_state != INSTANCE_VALID && m_state != INSTANCE_VALIDATING && m_state != INSTANCE_DESTROYING) {

+    		return;

+    	}

+

+    	// In case the instance is valid when this is called, the manager is set to an invalidating state

+        if (m_state != INSTANCE_DESTROYING)

+        {

+            setState(INSTANCE_INVALIDATING);

+        }

+    	

+        // 0.- Remove published services from the registry

+        if(m_serviceRegistration != null)

+        {

+	        m_serviceRegistration.unregister();

+	        m_serviceRegistration = null;

+

+	        GenericActivator.trace("unregistering the services", m_componentMetadata);

+	    }

+

+        // 1.- Call the deactivate method, if present	    

+        // Search the deactivate method

+		try {

+			// It is necessary to check that the implementation Object is not null. This may happen if the component

+			// is delayed and its service was never requested.

+			if(m_implementationObject != null)

+			{

+				Method activateMethod = m_implementationObject.getClass().getMethod("deactivate", new Class[]{ComponentContext.class});

+				activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});				

+			}

+		}

+		catch(NoSuchMethodException ex) {

+			// We can safely ignore this one

+			GenericActivator.trace("deactivate() method is not implemented", m_componentMetadata);

+		}

+		catch(IllegalAccessException ex) {

+			// Ignored, but should it be logged?

+			GenericActivator.trace("deactivate() method cannot be called", m_componentMetadata);

+		}

+		catch(InvocationTargetException ex) {

+			// TODO: 112.5.12 If the deactivate method throws an exception, SCR must log an error message

+			// containing the exception with the Log Service

+			GenericActivator.exception("The deactivate method has thrown and exception", m_componentMetadata, ex);

+		}

+

+        // 2. Unbind any bound services

+        Iterator it = m_dependencyManagers.iterator();

+

+        while (it.hasNext())

+        {

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

+            dm.unbind();

+        }

+

+        // 3. Release references to the component instance and component context

+        m_implementationObject = null;

+        m_componentContext = null;

+        m_delayedComponentServiceFactory = null;

+

+        //GenericActivator.trace("InstanceManager from bundle ["+ m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");

+

+        if (m_state != INSTANCE_DESTROYING)

+        {

+            setState(INSTANCE_INVALID);

+        }

+    }

+

+    /**

+     * 

+     */

+    public synchronized void dispose()

+    {

+        // CONCURRENCY NOTE: This method is only called from the GenericActivator or by application logic

+    	// but not by the dependency managers

+

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

+        // because validate is called right after creation.

+        if (m_state != INSTANCE_VALID && m_state != INSTANCE_INVALID)

+        {

+            return;

+        }

+

+        boolean deactivationRequired = (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);

+        }

+

+        // in case the component is disposed when it was VALID, it is necessary to deactivate it first.

+        if (deactivationRequired)

+        {

+            deactivate();

+        }

+

+        m_dependencyManagers.clear();

+

+        setState(INSTANCE_DESTROYED);

+

+        m_activator = null;

+    }

+

+    //**********************************************************************************************************

+    

+    /**

+    * Get the object that is implementing this descriptor

+    *

+    * @return the object that implements the services

+    */

+    public Object getInstance() {

+        return m_implementationObject;

+    }

+

+    /**

+     * 

+     */

+    public ComponentMetadata getComponentMetadata() {

+    	return m_componentMetadata;

+    }

+    

+    /**

+     * sets the state of the manager

+    **/

+    private synchronized void setState(int newState) {

+    	GenericActivator.trace("State transition : "+m_states[m_state]+" -> "+m_states[newState], m_componentMetadata);

+    	

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

+        }

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

+    {

+    	// Reference to the metadata
+        private ReferenceMetadata m_dependencyMetadata;
+

+        // The bound services <ServiceReference> 
+        private Set m_boundServicesRefs = new HashSet();

+        

+        // A flag that denotes if the dependency is satisfied at any given moment

+        private boolean m_isValid;

+        

+        // A flag that defines if the bind method receives a ServiceReference

+        private boolean m_bindUsesServiceReference = false;

+

+        /**

+         * Constructor that receives several parameters.

+         *

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

+        **/

+        private DependencyManager(ReferenceMetadata dependency) throws ClassNotFoundException, NoSuchMethodException

+        {

+            m_dependencyMetadata = dependency;

+            m_isValid = false;

+

+            //m_bindMethod = getTargetMethod(m_dependencyMetadata.getBind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());

+            //m_unbindMethod = getTargetMethod(m_dependencyMetadata.getUnbind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());

+        }

+

+        /**

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

+         *

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

+        **/

+        private boolean bind()

+        {

+        	/* 

+            if(getInstance() == null)

+            {

+                return false;

+            }*/

+

+            // Get service references

+            ServiceReference refs[] = getRequiredServiceRefs();

+

+            // If no references were received, we have to check if the dependency

+            // is optional, if it is not then the dependency is invalid

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

+            {

+                m_isValid = false;

+                return m_isValid;

+            }

+

+            m_isValid = true;

+

+            // refs can be null if the dependency is optional

+            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 = invokeBindMethod(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;

+        }

+

+        /**

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

+         * to complete all that it can

+         *

+        **/

+        private void unbind()

+        {

+            Object []allrefs = m_boundServicesRefs.toArray();

+

+            if (allrefs == null)

+                return;

+

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

+            {

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

+            }

+        }

+

+        /**

+         *

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

+        **/

+        private ServiceReference [] getRequiredServiceRefs()

+        {

+            try

+            {

+                ArrayList list=new ArrayList();

+                

+                ServiceReference temprefs[] = m_activator.getBundleContext().getServiceReferences(m_dependencyMetadata.getInterface(), m_dependencyMetadata.getTarget());

+

+                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 bind or unbind method according to the policies described in the specification

+         *

+         * @param methodname The name of the method

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

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

+         * @return the method or null

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

+        **/

+        private Method getBindingMethod(String methodname, Class targetClass, String parameterClassName)

+        {

+            Method method = null;

+            

+            Class parameterClass = null;

+            

+            // 112.3.1 The method is searched for using the following priority

+            // 1. The method's parameter type is org.osgi.framework.ServiceReference

+            // 2. The method's parameter type is the type specified by the reference's interface attribute

+            // 3. The method's parameter type is assignable from the type specified by the reference's interface attribute

+            try{

+            	// Case 1

+            	

+                method = targetClass.getMethod(methodname, new Class[]{ServiceReference.class});

+               

+                m_bindUsesServiceReference = true;                

+            }

+            catch(NoSuchMethodException ex){

+            	

+            	try {

+            		// Case2

+            		

+            		m_bindUsesServiceReference = false;

+            		

+            		parameterClass = m_activator.getBundleContext().getBundle().loadClass(parameterClassName);

+            		

+	                method = targetClass.getMethod(methodname, new Class[]{parameterClass});

+            	}

+            	catch(NoSuchMethodException ex2) {

+            		

+            		// Case 3

+            		method = null;

+            		

+            		// Get all potential bind methods

+            		Method candidateBindMethods[]  = targetClass.getMethods();

+            		

+            		// Iterate over them

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

+            			Method currentMethod = candidateBindMethods[i];

+            			

+            			// Get the parameters for the current method

+            			Class[] parameters = currentMethod.getParameterTypes();

+            			

+            			// Select only the methods that receive a single parameter 

+            			if(parameters.length == 1) {

+            				

+            				// Get the parameter type

+            				Class theParameter = parameters[0];

+            				

+            				// Check if the parameter type is assignable from the type specified by the reference's interface attribute

+            				if(theParameter.isAssignableFrom(parameterClass)) {

+            					method = currentMethod;

+            				}

+            			}            				

+            		}

+            	} 

+            	catch(ClassNotFoundException ex2) {

+            		GenericActivator.exception("Cannot load class used as parameter "+parameterClassName,m_componentMetadata,ex2);

+            	}

+

+            }

+                        

+            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

+         * @param storeRef A boolean that indicates if the reference must be stored (this is used for the delayed components)

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

+        **/

+        private boolean invokeBindMethod(ServiceReference ref) {

+        	// The bind method is only invoked if the implementation object is not null. This is valid

+        	// for both immediate and delayed components

+        	if(m_implementationObject != null) {

+        		

+		        try {

+		        	// Get the bind method

+		            Method bindMethod = getBindingMethod(m_dependencyMetadata.getBind(),  getInstance().getClass(), m_dependencyMetadata.getInterface());

+		            

+		            if(bindMethod == null){

+		            	// 112.3.1 If the method is not found , SCR must log an error

+		            	// message with the log service, if present, and ignore the method

+		            	// TODO: log error message

+		            	GenericActivator.trace("bind() method not found", m_componentMetadata);

+		            	return false;

+		            }

+		            

+		            // Get the parameter

+		            Object parameter;

+		            

+		            if(m_bindUsesServiceReference == false) {		            	 

+		            	parameter = m_activator.getBundleContext().getService(ref);

+		            }

+		            else {

+		            	parameter = ref;

+		            }

+		            	

+		            // Invoke the method

+		            bindMethod.invoke(getInstance(),new Object[] {parameter});

+		            

+		            // Store the reference

+		        	m_boundServicesRefs.add(ref);                

+		            

+		            return true;

+		        }

+		        catch(IllegalAccessException ex)

+		        {

+		        	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error

+		        	// message with the log service, if present, and ignore the method

+		        	// TODO: log error message

+		        	return false;

+		        }

+		        catch(InvocationTargetException ex)

+		        {

+		        	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getBind()+"()", m_componentMetadata, ex);

+		            return false;

+		        }

+        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {

+        		// In the case the implementation object is null and the component is delayed

+        		// then we still have to store the object that is passed to the bind methods

+        		// so that it can be used once the implementation object is created.

+        		m_boundServicesRefs.add(ref);

+        		return true;

+        	} else {

+        		// TODO: assert false : this theoretically never happens...

+        		return false;

+        	}        	

+        }

+

+        /**

+         * Call the unbind method

+         *

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

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

+        **/

+        private boolean invokeUnbindMethod(ServiceReference ref) {

+        	// TODO: assert m_boundServices.contains(ref) == true : "DependencyManager : callUnbindMethod UNBINDING UNKNOWN SERVICE !!!!";	

+        	

+        	// The unbind method is only invoked if the implementation object is not null. This is valid

+        	// for both immediate and delayed components

+        	if ( m_implementationObject != null ) {

+	            try

+	            {

+	            	// TODO: me quede aqui por que el unbind method no funciona

+	            	GenericActivator.trace("getting unbind: "+m_dependencyMetadata.getUnbind(), m_componentMetadata);

+	            	Method unbindMethod = getBindingMethod(m_dependencyMetadata.getUnbind(), getInstance().getClass(), m_dependencyMetadata.getInterface());

+	            	

+		        	// Recover the object that is bound from the map.

+		            //Object parameter = m_boundServices.get(ref);

+	        		Object parameter = null;

+	        		

+	        		if(m_bindUsesServiceReference == true) {

+	        			parameter = ref;

+	        		} else {

+	        			parameter = m_activator.getBundleContext().getService(ref);

+	        		}

+		            

+	            	if(unbindMethod == null){

+	                	// 112.3.1 If the method is not found , SCR must log an error

+	                	// message with the log service, if present, and ignore the method

+	                	// TODO: log error message

+	                	GenericActivator.trace("unbind() method not found", m_componentMetadata);

+	                	return false;

+	                }

+	

+	            	unbindMethod.invoke(getInstance(),new Object [] {parameter});

+	            	                

+	                m_boundServicesRefs.remove(ref);

+	                

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

+	                

+	                return true;

+	            }

+	            catch (IllegalAccessException ex) {

+	            	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error

+	            	// message with the log service, if present, and ignore the method

+	            	// TODO: log error message

+	            	return false;

+	            }

+	            catch (InvocationTargetException ex) {

+	            	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getUnbind()+"()", m_componentMetadata, ex);

+	            	return false;

+	            }

+	            

+        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {

+        		// In the case the implementation object is null and the component is delayed

+        		// then we still have to store the object that is passed to the bind methods

+        		// so that it can be used once the implementation object is created.

+        		m_boundServicesRefs.remove(ref);

+        		return true;

+        	} else {

+        		// TODO: assert false : this theoretically never happens...

+        		return false;

+        	}

+        }

+        

+        /**

+         * 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 (ComponentManagerImpl.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_boundServicesRefs.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", m_componentMetadata);

+                                deactivate();

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

+                                activate();

+                            }

+                            catch(Exception ex)

+                            {

+                            	GenericActivator.exception("Exception while recreating dependency ",m_componentMetadata, ex);

+                            }

+                        }

+                        // dynamic dependency

+                        else

+                        {

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

+                            // and eventually request service unregistration

+

+                            invokeUnbindMethod(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_boundServicesRefs.size() == 0)

+                            {

+                                // try to reinitialize

+                                if (!bind())

+                                {

+                                    if (!m_dependencyMetadata.isOptional())

+                                    {

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

+                                        deactivate();

+                                        GenericActivator.trace("Dependency Manager: Recreating", m_componentMetadata);

+                                        activate();

+                                    }

+                                }

+                            }

+                        }

+                    }

+                }

+                // A service is registering.

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

+                {

+                    if (m_boundServicesRefs.contains(evt.getServiceReference()) == true)

+                    {

+                        // This is a duplicate

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

+                    }

+                    else

+                    {

+                        m_isValid = true;

+                        //setStateDependency(DependencyChangeEvent.DEPENDENCY_VALID);

+

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

+                        // which will fix everything.

+                        if (ComponentManagerImpl.this.m_state != INSTANCE_VALID)

+                        {

+                            activate();

+                        }

+                        // 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_boundServicesRefs.size() == 0)

+                            {

+                                invokeBindMethod(evt.getServiceReference());

+                            }

+                        }

+                    }

+                }

+            }

+        }

+    }

+

+    /**

+     * Implementation for the ComponentContext interface

+     *

+     */
+    class ComponentContextImpl implements ComponentContext {

+

+    	public Dictionary getProperties() {

+    		//TODO: 112.11.3.5 The Dictionary is read-only and cannot be modified

+    		return m_componentMetadata.getProperties();

+    	}

+

+    	public Object locateService(String arg0) {

+    		// TODO implement this method

+    		return null;

+    	}

+

+    	public Object locateService(String arg0, ServiceReference arg1) {

+    		// TODO implement this method

+    		return null;

+    	}

+

+    	public Object[] locateServices(String arg0) {

+    		// TODO implement this method

+    		return null;

+    	}

+

+    	public BundleContext getBundleContext() {

+    		return m_activator.getBundleContext();

+    	}

+

+    	public Bundle getUsingBundle() {

+    		// TODO implement this method

+    		return null;

+    	}

+

+    	public ComponentInstance getComponentInstance() {

+    		return ComponentManagerImpl.this;

+    	}

+

+    	public void enableComponent(String arg0) {

+    		// TODO implement this method

+    		

+    	}

+

+    	public void disableComponent(String arg0) {

+    		// TODO implement this method

+    		

+    	}

+

+    	public ServiceReference getServiceReference() {

+    		if(m_serviceRegistration != null) {

+    			return m_serviceRegistration.getReference();

+    		}

+    		else {

+    			return null;

+    		}

+    	}

+    }

+    

+    /**

+     * This class is a ServiceFactory that is used when a delayed component is created

+     *

+     */

+    class DelayedComponentServiceFactory implements ServiceFactory {

+    	

+    	public Object getService(Bundle arg0, ServiceRegistration arg1) {

+    		

+    		GenericActivator.trace("DelayedComponentServiceFactory.getService()", m_componentMetadata);

+    		// When the getServiceMethod is called, the implementation object must be created

+    		

+            // 1. Load the component implementation class

+            // 2. Create the component instance and component context

+            // If the component is not immediate, this is not done at this moment

+        	try

+	        {

+	        	// 112.4.4 The class is retrieved with the loadClass method of the component's bundle

+	            Class c = m_activator.getBundleContext().getBundle().loadClass(m_componentMetadata.getImplementationClassName());

+	            

+	            // 112.4.4 The class must be public and have a public constructor without arguments so component instances

+	            // may be created by the SCR with the newInstance method on Class

+	            m_componentContext = new ComponentContextImpl();

+	            m_implementationObject = c.newInstance();

+	        }

+	        catch (Exception ex)

+	        {

+	            // TODO: manage this exception when implementation object cannot be created

+	            GenericActivator.exception("Error during instantiation of the implementation object",m_componentMetadata,ex);

+	            deactivate();

+	            //invalidate();

+	            return null;

+	        }

+	        

+	        

+	        // 3. Bind the target services

+	        Iterator it = m_dependencyManagers.iterator();

+

+	        while ( it.hasNext() )

+	        {

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

+	            Iterator bound = dm.m_boundServicesRefs.iterator();

+	            while ( bound.hasNext() ) {

+	            	ServiceReference nextRef = (ServiceReference) bound.next();	            	

+	            	dm.invokeBindMethod(nextRef);

+	            }

+	        }

+	        

+	        // 4. Call the activate method, if present

+            // Search for the activate method

+        	try {

+        		Method activateMethod = m_implementationObject.getClass().getMethod("activate", new Class[]{ComponentContext.class});

+        		activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});

+        	}

+        	catch(NoSuchMethodException ex) {

+        		// We can safely ignore this one

+        	}

+        	catch(IllegalAccessException ex) {

+        		// TODO: Log this exception?

+        		

+        	}

+        	catch(InvocationTargetException ex) {

+        		// TODO: 112.5.8 If the activate method throws an exception, SCR must log an error message

+        		// containing the exception with the Log Service

+        	}

+    		

+    		return m_implementationObject;

+    	}

+

+    	public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2) {

+    		// TODO Auto-generated method stub

+

+    	}

+    }

+

+

+    

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentMetadata.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentMetadata.java
new file mode 100644
index 0000000..e8c010b
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ComponentMetadata.java
@@ -0,0 +1,297 @@
+/*

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

+

+import java.util.Iterator;

+import java.util.Properties;

+import java.util.List;

+import java.util.ArrayList;

+

+import org.osgi.service.component.ComponentException;

+
+/**
+ * This class holds the information associated to a component in the descriptor
 * 
 */

+public class ComponentMetadata {

+	// 112.4.3: A Globally unique component name (required)

+	private String m_name;

+	

+	// 112.4.3: Controls whether the component is enabled when the bundle is started. (optional, default is true).

+	private boolean m_enabled = true;

+	

+	// 112.4.3: Factory identified. If set to a non empty string, it indicates that the component is a factory component (optional).

+	private String m_factory = null;

+	

+	// 112.4.3: Controls whether component configurations must be immediately activated after becoming 

+	// satisfied or whether activation should be delayed. (optional, default value is false).

+	private boolean m_immediate = false;

+	

+    // 112.4.4 Implementation Element (required)

+    private String m_implementationClassName = null;

+    

+    // Associated properties (0..*)

+    private Properties m_properties = new Properties();

+    

+    // Provided services (0..1)

+    private ServiceMetadata m_service = null;

+    

+    // List of service references, (required services 0..*)

+    private List m_references = new ArrayList();

+    

+    // Flag that is set once the component is verified (its properties cannot be changed)

+    private boolean m_validated = false;

+        

+       

+    /////////////////////////////////////////// SETTERS //////////////////////////////////////

+    

+    /**

+     * Setter for the name

+     * 

+     * @param name

+     */

+    public void setName(String name) {

+    	if(m_validated) {

+    		return;

+    	}

+    	m_name = name;

+    }

+    

+    /**

+     * Setter for the enabled property

+     * 

+     * @param enabled

+     */

+    public void setEnabled(boolean enabled) {

+    	if(m_validated) {

+    		return;

+    	}

+    	m_enabled = enabled;

+    }

+    

+    /**

+     * 

+     * @param factoryIdentifier

+     */

+    public void setFactoryIdentifier(String factoryIdentifier) {

+    	if(m_validated) {

+    		return;

+    	}

+    	m_factory = factoryIdentifier;

+    }

+    

+    /**

+     * Setter for the immediate property

+     * 

+     * @param immediate

+     */

+    public void setImmediate(boolean immediate) {

+    	if(m_validated) {

+    		return;

+    	}

+    	m_immediate = immediate;

+    }   

+    

+    /**

+     * Sets the name of the implementation class

+     * 

+     * @param implementationClassName a class name

+     */

+    public void setImplementationClassName(String implementationClassName) {

+    	if(m_validated) {

+    		return;

+    	}

+        m_implementationClassName = implementationClassName;

+    }

+

+    /**

+     * Used to add a property to the instance

+     *

+     * @param newProperty a property metadata object

+     */

+    public void addProperty(PropertyMetadata newProperty) {

+    	if(m_validated) {

+    		return;

+    	}

+    	if(newProperty == null) {

+    		throw new IllegalArgumentException ("Cannot add a null property");

+    	}

+        String key = newProperty.getName();

+        Object value = newProperty.getValue();

+        m_properties.put(key,value);

+    }

+

+    /**

+     * Used to set a ServiceMetadata object.

+     *

+     * @param service a ServiceMetadata

+     */

+    public void setService(ServiceMetadata service) {

+    	if(m_validated) {

+    		return;

+    	}

+        m_service = service;

+    }

+

+    /**

+     * Used to add a reference metadata to the component

+     *

+     * @param newReference a new ReferenceMetadata to be added

+     */

+    public void addDependency(ReferenceMetadata newReference) {

+    	if(newReference == null) {

+    		throw new IllegalArgumentException ("Cannot add a null ReferenceMetadata");

+    	}

+        m_references.add(newReference);

+    }

+

+    

+    /////////////////////////////////////////// GETTERS //////////////////////////////////////

+    

+    /**

+     * Returns the name of the component

+     * 

+     * @return A string containing the name of the component 

+     */

+    public String getName() {

+    	return m_name;

+    }

+    

+    /**

+     * Returns the value of the enabled flag 

+     * 

+     * @return a boolean containing the value of the enabled flag

+     */

+    public boolean isEnabled() {

+    	return m_enabled;

+    }

+

+    /**

+     * Returns the factory identifier

+     * 

+     * @return A string containing a factory identifier or null

+     */

+    public String getFactoryIdentifier() {

+    	return m_factory;

+    }

+    

+    /**

+     * Returns the flag that defines the activation policy for the component

+     * 

+     * @return a boolean that defines the activation policy

+     */

+    public boolean isImmediate() {

+    	return m_immediate;

+    }

+    

+    /**

+     * Returns the name of the implementation class

+     *

+     * @return the name of the implementation class

+     */

+    public String getImplementationClassName() {

+        return m_implementationClassName;

+    }

+

+    /**

+     * Returns the associated ServiceMetadata

+     * 

+     * @return a ServiceMetadata object or null if the Component does not provide any service

+     */

+    public ServiceMetadata getServiceMetadata() {

+    	return m_service;

+    }

+

+    /**

+     * Returns the property descriptors

+     *

+     * @return the property descriptors as a Collection

+     */

+    public Properties getProperties() {

+        return m_properties;

+    }

+

+    /**

+     * Returns the dependency descriptors

+     *

+     * @return a Collection of dependency descriptors

+     */

+    public List getDependencies() {

+        return m_references;

+    }

+

+    /**

+     * Test to see if this service is a factory

+     *

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

+     */

+    public boolean isFactory() {

+        return m_factory != null;

+    }

+    

+    /**

+     * Method used to verify if the semantics of this metadata are correct

+     */

+    void validate() {

+    	

+    	// First check if the properties are valid

+    	Iterator propertyIterator = m_properties.keySet().iterator();

+    	while ( propertyIterator.hasNext() ) {

+    		((PropertyMetadata)propertyIterator.next()).validate();

+    	}

+    	

+    	// Check that the provided services are valid too

+    	if(m_service != null) {

+    		m_service.validate();

+    	}

+    	

+    	// Check that the references are ok

+    	Iterator referenceIterator = m_references.iterator();

+    	while ( referenceIterator.hasNext() ) {

+    		((ReferenceMetadata)referenceIterator.next()).validate();

+    	}

+    	    	

+    	// 112.10 The name of the component is required

+    	if( m_name == null ) {

+    		throw new ComponentException("The component name has not been set");

+    	}

+    	

+    	// 112.10 There must be one implementation element and the class atribute is required

+    	if ( m_implementationClassName == null ) {

+    		throw new ComponentException("The implementation class name has not been set for this component");

+    	}

+    	

+    	// 112.2.3 A delayed component specifies a service, is not specified to be a factory component

+    	// and does not have the immediate attribute of the component element set to true.

+    	if(m_immediate == false && m_service == null) {

+    		throw new ComponentException("Component '"+m_name+"' is specified as being delayed but does not provide any service.");

+    	}    	

+    	

+    	if ( m_factory != null && m_immediate == false) {

+    		throw new ComponentException("A factory cannot be a delayed component");

+    	}

+    	

+    	// TODO: 112.4.6 The serviceFactory attribute (of a provided service) must not be true if 

+    	// the component is a factory component or an immediate component

+

+    	

+    	m_validated = true;

+    	// TODO: put a similar flag on the references and the services

+    }

+

+}

+

+

+

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/GenericActivator.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/GenericActivator.java
new file mode 100644
index 0000000..2c22574
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/GenericActivator.java
@@ -0,0 +1,306 @@
+/*

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

+

+import java.util.ArrayList;

+import java.util.HashSet;

+import java.util.Iterator;

+import java.util.List;

+import java.util.Set;

+import java.util.StringTokenizer;

+

+import java.io.InputStream;

+

+import org.apache.felix.declarativeservices.scr.KXml2SAXParser;

+import org.apache.felix.declarativeservices.scr.ParseException;

+import org.osgi.framework.BundleActivator;

+import org.osgi.framework.BundleContext;

+import org.osgi.service.component.ComponentException;

+

+import java.io.BufferedReader;

+import java.io.FileNotFoundException;

+import java.io.IOException;

+import java.io.InputStreamReader;

+

+/**

+ * The GenericActivator is the main startup class. It will read information from the metadata.xml file

+ * descriptors and create the corresponding managers.

+ *

+ */

+public class GenericActivator implements BundleActivator

+{	

+	// The bundle context

+    private BundleContext m_context = null;

+    

+    // This is a list of component instance managers that belong to a particular bundle

+    private List m_managers = new ArrayList();

+

+    // Flag that sets tracing messages

+    private static boolean m_trace = true;

+    

+    // Flag that sets error messages

+    private static boolean m_error = true;

+

+    // A string containing the version number

+    private static String m_version = "1.0.0 (12012006)";

+

+    // Registry of component names

+    static Set m_componentNames = new HashSet();

+

+    // Static initializations based on system properties

+    static {

+        // Get system properties to see if traces or errors need to be displayed

+        String result = System.getProperty("ds.showtrace");

+        if(result != null && result.equals("true"))

+        {

+            m_trace = true;

+        }

+        result = System.getProperty("ds.showerrors");

+        if(result != null && result.equals("false"))

+        {

+            m_error = false;

+        }

+        result = System.getProperty("ds.showversion");

+        if(result != null && result.equals("true"))

+        {

+            System.out.println("[ Version = "+m_version+" ]\n");

+        }        

+    }

+

+    /**

+    * Called upon starting of the bundle. This method invokes initialize() which

+    * parses the metadata 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

+    {

+    	// Stores the context

+        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 FileNotFoundException if the metadata file is not found

+    * @throws ParseException if the metadata file is not found

+    */

+    private void initialize() throws ParseException {

+        // Get the Metadata-Location value from the manifest

+        String descriptorLocations = (String) m_context.getBundle().getHeaders().get("Service-Component");

+

+        if (descriptorLocations == null)

+        {

+            throw new ComponentException("Service-Component entry not found in the manifest");

+        }

+

+        // 112.4.1: The value of the the header is a comma separated list of XML entries within the Bundle 

+		StringTokenizer st = new StringTokenizer(descriptorLocations, ", ");

+        

+		while (st.hasMoreTokens()) {

+			String descriptorLocation = st.nextToken();

+			

+			try {

+				InputStream stream = m_context.getBundle().getResource(descriptorLocation).openStream();

+

+				BufferedReader in = new BufferedReader(new InputStreamReader(stream)); 

+	            XmlHandler handler = new XmlHandler(); 

+	            KXml2SAXParser parser;

+

+	            parser = new KXml2SAXParser(in); 

+

+		        parser.parseXML(handler);

+

+		        // 112.4.2 Component descriptors may contain a single, root component element

+		        // or one or more component elements embedded in a larger document

+		        Iterator i = handler.getComponentMetadataList().iterator();

+		        while (i.hasNext()) {

+                	try {

+    		            ComponentMetadata metadata = (ComponentMetadata) i.next();

+    		            

+    		            validate(metadata);

+    		        	

+    	                // Request creation of the component manager

+    	                ComponentManager manager = ManagerFactory.createManager(this,metadata);

+                		

+                		if(metadata.isFactory()) {

+                			// 112.2.4 SCR must register a Component Factory service on behalf ot the component

+                			// as soon as the component factory is satisfied

+                		}

+                		else if(metadata.isEnabled()) {

+		                	// enable the component

+		                	manager.enable();

+		                	m_managers.add(manager);

+		                }

+	                } catch (Exception e) {

+						// There is a problem with this particular component, we'll log the error

+	                	// and proceed to the next one

+	                	// TODO: log the error

+						e.printStackTrace();

+					} 

+		        }

+		        

+		        stream.close();

+

+			}

+			catch ( IOException ex ) {

+				// 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached

+				// fragments, SCR must log an error message with the Log Service, if present, and continue.

+				

+				error("Component descriptor entry '" + descriptorLocation	+ "' not found");

+			}

+			catch (Exception ex) {

+				ex.printStackTrace();

+			}

+		}

+    }

+

+    /**

+    * 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_managers.size()+" instances");

+

+        while (m_managers.size() !=0 )

+        {

+            ComponentManager manager = (ComponentManager)m_managers.get(0);

+            try {

+                manager.dispose();

+                m_managers.remove(manager);

+            }

+            catch(Exception e) {

+                GenericActivator.error("GenericActivator : Exception during invalidate : "+e);

+                e.printStackTrace();

+            }

+            finally {

+            	m_componentNames.remove(manager.getComponentMetadata().getName());

+            }

+            

+        }

+

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

+    }

+

+    /**

+    * Returns the BundleContext

+    *

+    * @return the BundleContext

+    */

+    protected BundleContext getBundleContext()

+    {

+        return m_context;

+    }

+

+    /**

+     * Method to display traces

+     *

+     * @param message a string to be displayed

+     * @param metadata ComponentMetadata associated to the message (can be null)

+    **/

+    static void trace(String message, ComponentMetadata metadata)

+    {

+        if(m_trace)

+        {

+            System.out.print("--- ");

+            if(metadata != null) {

+            	System.out.print("[");

+            	System.out.print(metadata.getName());

+            	System.out.print("] ");

+            	System.out.println(message);

+            }

+        }

+    }

+

+    /**

+     * Method to display errors

+     *

+     * @param s a string to be displayed

+    **/

+    static void error(String s) {

+        if(m_error) {

+            System.err.println("### "+s);

+        }

+    }

+

+    /**

+     * Method to display exceptions

+     *

+     * @param ex an exception

+    **/   

+    static void exception(String message, ComponentMetadata metadata, Throwable ex) {

+    	 if(m_error) {

+    		 System.out.println("--- Exception in component "+metadata.getName()+" : "+message+" ---");

+             ex.printStackTrace();

+         }   	

+    }

+

+    /**

+     * This method is used to validate that the component. This method verifies multiple things:

+     * 

+     * 1.- That the name attribute is set and is globally unique

+     * 2.- That an implementation class name has been set 

+     * 3.- That a delayed component provides a service and is not specified to be a factory

+     * - That the serviceFactory attribute for the provided service is not true if the component is a factory or immediate

+     * 

+     * If the component is valid, its name is registered

+     * 

+     * @throws A ComponentException if something is not right

+     */

+    void validate(ComponentMetadata component) throws ComponentException {

+

+    	if(m_componentNames.contains(component.getName()))

+    	{

+    		throw new ComponentException("The component name '"+component.getName()+"' has already been registered.");

+    	}

+    	

+    	m_componentNames.add(component.getName());

+    

+    	component.validate();

+    	

+    	trace("Validated and registered component",component);

+    }

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ManagerFactory.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ManagerFactory.java
new file mode 100644
index 0000000..6ca71b6
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ManagerFactory.java
@@ -0,0 +1,30 @@
+/*

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

+

+/**

+ * This factory allows other types of ComponentManagers to be provided.

+ * 

+ * 

+ */

+public class ManagerFactory {

+	

+	static ComponentManager createManager(GenericActivator activator, ComponentMetadata metadata) {

+		GenericActivator.trace("ManagerFactory.createManager", metadata);

+		return new ComponentManagerImpl(activator,metadata);

+	}

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/PropertyMetadata.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/PropertyMetadata.java
new file mode 100644
index 0000000..28d028a
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/PropertyMetadata.java
@@ -0,0 +1,147 @@
+/*

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

+

+import org.osgi.service.component.ComponentException;

+

+/**

+ * A property descriptor that contains the information for properties

+ * defined in the descriptor

+ *

+ */

+public class PropertyMetadata {

+	

+	// Name of the property (required)

+	private String m_name;

+	

+	// Type of the property (optional)

+	private String m_type = "String";

+	

+	// Value of the type (optional)

+	private Object m_value;

+	

+	// Flag that indicates if this PropertyMetadata has been validated and thus has become immutable

+	private boolean m_validated = false;

+

+	/**

+	 * Set the name

+	 * 

+	 * @param name

+	 */

+	public void setName(String name) {

+		if (m_validated == true) {

+			return;

+		}

+		

+		m_name = name;

+	}

+	

+

+	/**

+	 * Set the type

+	 * 

+	 * @param type

+	 */

+	public void setType(String type) {

+		if (m_validated == true) {

+			return;

+		}

+		m_type = type;

+	}

+		

+	/**

+	 * Set the value

+	 * 

+	 * @param value

+	 */

+	public void setValue(String value) {

+		if (m_validated == true) {

+			return;

+		}

+		

+		// 112.4.5 Parsing of the value is done by the valueOf(String) method (P. 291)

+		// Should the type accept lowercase too?

+		if(m_type.equals("String")) {

+			m_value = String.valueOf(value);

+        }

+		else if(m_type.equals("Long")) {

+			m_value = Long.valueOf(value);

+        }

+		else if(m_type.equals("Double")) {

+			m_value = Double.valueOf(value);

+        }

+		else if(m_type.equals("Float")) {

+			m_value = Float.valueOf(value);

+        }

+		else if(m_type.equals("Integer")) {

+			m_value = Integer.valueOf(value);

+        }

+		else if(m_type.equals("Byte")) {

+			m_value = Byte.valueOf(value);

+        }

+		else if(m_type.equals("Char")) {

+			//TODO: verify if this is adequate for Characters

+			m_value = Byte.valueOf(value);

+        }

+		else if(m_type.equals("Boolean")) {

+			m_value = Boolean.valueOf(value);

+        }

+		else if(m_type.equals("Short")) {

+			m_value = Short.valueOf(value);

+        }

+		else {

+			throw new IllegalArgumentException("Undefined property type '"+m_type+"'");

+		}

+	}
+
+    /**
+     * Get the name of the property
+     * 
+     * @return the name of the property
+     */
+    public String getName() {
+        return m_name;
+    }
+
+    /**
+     * Get the type of the property
+     * 
+     * @return the type of the property
+     */
+    public String getType() {
+        return m_type;
+    }
+
+    /**
+     * Get the value of the property
+     * 
+     * @return the value of the property as an Object
+     */
+    public Object getValue() {
+        return m_value;
+    }
+

+    /**

+     * Method used to verify if the semantics of this metadata are correct

+     */

+    public void validate(){

+    	if(m_name == null)

+    	{

+    		throw new ComponentException("Property name attribute is mandatory");

+    	}

+    }
+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ReferenceMetadata.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ReferenceMetadata.java
new file mode 100644
index 0000000..8b61eca
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ReferenceMetadata.java
@@ -0,0 +1,285 @@
+/*
+ *   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.scr;
+
+import org.osgi.service.component.ComponentException;
+
+/**
+ * Information associated to a dependency
+ *
+ */
+public class ReferenceMetadata {
+	// Name for the reference (required)
+	private String m_name = null;
+	
+	// Interface name (required)
+    private String m_interface = null;
+    
+    // Cardinality (optional, default="1..1")
+    private String m_cardinality = "1..1";
+    
+    // Target (optional)
+    private String m_target;
+    
+    // Name of the bind method (optional)
+    private String m_bind = null;
+    
+    // Name of the unbind method (optional)
+    private String m_unbind = null;
+    
+    // Policy attribute (optional, default = static)
+    private String m_policy = "static";
+
+    // Flag that is set once the component is verified (its properties cannot be changed)
+    private boolean m_validated = false;
+    
+    // Flags that store the values passed as strings
+    private boolean m_isStatic = true;
+    private boolean m_isOptional = false;
+    private boolean m_isMultiple = false;
+
+    /////////////////////////////////////////////// setters ///////////////////////////////////
+    
+    /**
+     * Setter for the name attribute
+     * 
+     * @param name
+     */
+    public void setName(String name) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	m_name = name;
+    }
+    
+    /**
+     * Setter for the interfaceName attribute
+     * 
+     * @param interfaceName
+     */
+    public void setInterface(String interfaceName) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	m_interface = interfaceName;
+    	
+    }
+    
+    /**
+     * Setter for the cardinality attribute
+     * 
+     * @param cardinality
+     */
+    public void setCardinality(String cardinality) {
+    	if(m_validated) {
+    		return;
+    	}
+    		  	
+    	if(!m_cardinality.equals("0..1") && !m_cardinality.equals("0..n") && !m_cardinality.equals("1..1") && !m_cardinality.equals("1..n")) {
+    		throw new IllegalArgumentException ("Cardinality should take one of the following values: 0..1, 0..n, 1..1, 1..n");
+    	}    	
+    	if(m_cardinality.equals("0..1") || m_cardinality.equals("0..n")) {
+            m_isOptional = true;
+        }
+        if(m_cardinality.equals("0..n") || m_cardinality.equals("1..n")) {
+            m_isMultiple = true;
+        }
+    
+    	m_cardinality = cardinality;
+    }
+    
+    /** 
+     *	Setter for the policy attribute
+     *
+     * @param policy
+     */
+    public void setPolicy(String policy) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	if(!m_policy.equals("static") && !m_policy.equals("dynamic")) {
+    		throw new IllegalArgumentException ("Policy must be either 'static' or 'dynamic'");
+    	}    	
+    	if(policy.equals("static") == false) {
+            m_isStatic = false;
+        }
+
+       	m_policy = policy;
+    }
+    
+    /**
+     * Setter for the target attribute (filter)
+     * 
+     * @param target
+     */
+    public void setTarget(String target) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	//TODO: check if we really need to extend the filter to limit seaches to a particular interface
+        String classnamefilter = "(objectClass="+m_interface+")";
+        if(target != null) {
+            m_target = "(&"+classnamefilter+target+")";
+        }
+        else {
+            m_target = classnamefilter;
+        }    	
+    }
+    
+    /**
+     * Setter for the bind method attribute
+     * 
+     * @param bind
+     */    
+    public void setBind(String bind) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	m_bind = bind;
+    }
+    
+    /**
+     * Setter for the unbind method attribute
+     * 
+     * @param bind
+     */    
+    public void setUnbind(String unbind) {
+    	if(m_validated) {
+    		return;
+    	}
+    		
+    	m_unbind = unbind;
+    }
+    
+    
+    /////////////////////////////////////////////// getters ///////////////////////////////////
+
+    /**
+     * Returns the name of the reference
+     *
+     * @return A string containing the reference's name
+    **/
+    public String getName() {
+        return m_name;
+    }
+
+    /**
+     * Returns the fully qualified name of the class that is used by the component to access the service
+     *
+     * @return A string containing a fully qualified name
+    **/
+    public String getInterface() {
+        return m_interface;
+    }
+
+    /**
+     * Get the cardinality as a string
+     *
+     * @return A string with the cardinality
+    **/
+    public String getCardinality() {
+        return m_cardinality;
+    }
+
+    /**
+     * Get the policy as a string
+     *
+     * @return A string with the policy
+    **/
+    public String getPolicy() {
+        return m_policy;
+    }
+
+    /**
+     * Returns the filter expression that further constrains the set of target services
+     *
+     * @return A string with a filter
+    **/
+    public String getTarget() {
+        return m_target;
+    }
+
+    /**
+     * Get the name of a method in the component implementation class that is used to notify that
+     * a service is bound to the component configuration
+     *
+     * @return a String with the name of the bind method
+    **/
+    public String getBind() {
+        return m_bind;
+    }
+
+    /**
+     * Get the name of a method in the component implementation class that is used to notify that
+     * a service is unbound from the component configuration
+     *
+     * @return a String with the name of the unbind method
+    **/
+    public String getUnbind() {
+        return m_unbind;
+    }
+
+    // Getters for boolean values that determine both policy and cardinality
+
+    /**
+     * 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;
+    }
+    
+    /**
+     *  Method used to verify if the semantics of this metadata are correct
+     *
+     */
+    void validate() {
+    	if (m_name == null) {
+    		throw new ComponentException("the name for the reference must be set");
+    	}
+    	
+    	if (m_interface == null) {
+    		throw new ComponentException("the interface for the reference must be set");
+    	}
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ServiceMetadata.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ServiceMetadata.java
new file mode 100644
index 0000000..9b20d4e
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/ServiceMetadata.java
@@ -0,0 +1,101 @@
+/*

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

+

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+

+import org.osgi.service.component.ComponentException;

+

+/**

+ * This class contains the metadata associated to a service that is provided

+ * by a component

+ *

+ */

+public class ServiceMetadata {

+	

+	// 112.4.6 Flag that indicates if the service is a ServiceFactory 

+	private boolean m_serviceFactory = false;

+	

+	// List of provided interfaces

+	private List m_provides = new ArrayList();

+	

+	// Flag that indicates if this metadata has been validated and has become immutable

+	private boolean m_validated = false;

+	

+	/**

+	 * Setter for the servicefactory attribute of the service element

+	 * 

+	 * @param serviceFactory

+	 */

+	public void setServiceFactory(boolean serviceFactory) {

+		if(m_validated) {

+			return;

+		}			

+		

+		m_serviceFactory = serviceFactory;

+	}

+	

+	/**

+	 * Add a provided interface to this service

+	 * 

+	 * @param provide a String containing the name of the provided interface

+	 */

+	public void addProvide(String provide) {

+		if(m_validated) {

+			return;

+		}			

+

+		m_provides.add(provide);

+	}

+	

+	/**

+	 * Return the flag that defines if it is a service factory or not

+	 * 

+	 * @return a boolean flag

+	 */

+	public boolean isServiceFactory() {

+		return m_serviceFactory; 

+	}

+	

+	/**

+     * Returns the implemented interfaces

+     *

+     * @return the implemented interfaces as a string array

+     */

+    public String [] getProvides() {

+        String provides[] = new String[m_provides.size()];

+        Iterator it = m_provides.iterator();

+        int count = 0;

+        while (it.hasNext())

+        {

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

+        }

+        return provides;

+    }

+    

+    /**

+     * Verify if the semantics of this metadata are correct

+     *

+     */

+    void validate() {

+    	if(m_provides.size() == 0) {

+    		throw new ComponentException("At least one provided interface must be given");

+    	}

+    }

+}

diff --git a/org.apache.felix.scr/src/main/java/org/apache/felix/scr/XmlHandler.java b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/XmlHandler.java
new file mode 100644
index 0000000..0f0b81f
--- /dev/null
+++ b/org.apache.felix.scr/src/main/java/org/apache/felix/scr/XmlHandler.java
@@ -0,0 +1,209 @@
+/*
+ *   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.scr;
+
+import java.util.Properties;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.declarativeservices.scr.KXml2SAXHandler;
+import org.apache.felix.declarativeservices.scr.ParseException;
+
+/**
+ * 
+ * 
+ */
+public class XmlHandler implements KXml2SAXHandler {
+
+    // A reference to the current component
+    private ComponentMetadata m_currentComponent = null;
+
+    // The current service
+    private ServiceMetadata m_currentService = null;
+    
+    // A list of component descriptors contained in the file
+    private List m_components = new ArrayList();
+
+    /**
+     * 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
+    {
+    	try {
+    		
+	    	// 112.4.3 Component Element
+	        if (qName.equals("component")) {
+
+	        	// Create a new ComponentMetadata
+	        	m_currentComponent = new ComponentMetadata();
+
+	        	// name attribute is mandatory
+	        	m_currentComponent.setName(attrib.getProperty("name"));
+	        	
+	        	// enabled attribute is optional
+	        	if(attrib.getProperty("enabled") != null) {
+	        		m_currentComponent.setEnabled(attrib.getProperty("enabled").equals("true"));
+	        	}
+
+	        	// immediate attribute is optional
+	        	if(attrib.getProperty("immediate") != null) {
+	        		m_currentComponent.setImmediate(attrib.getProperty("immediate").equals("true"));
+	        	}
+	        	
+	        	// factory attribute is optional
+	        	if(attrib.getProperty("factory") != null) {
+	        		m_currentComponent.setFactoryIdentifier(attrib.getProperty("factory"));
+	        	}
+		        	
+	        	// Add this component to the list
+	            m_components.add(m_currentComponent);
+	        }
+	        
+	        // 112.4.4 Implementation
+	        else if (qName.equals("implementation"))
+	        {
+	        	// Set the implementation class name (mandatory)
+	        	m_currentComponent.setImplementationClassName(attrib.getProperty("class"));
+	        }
+	        // 112.4.5 Properties and Property Elements
+	        else if (qName.equals("property")) {
+	        	// 112.4.5: If the value attribute is specified, the body of the element is ignored.
+	        	if( attrib.getProperty("value") != null) {
+	        		PropertyMetadata prop = new PropertyMetadata();
+	        		
+	        		// name attribute is mandatory
+	        		prop.setName(attrib.getProperty("name"));
+	        		
+	        		// type attribute is optional
+	        		if(attrib.getProperty("type") != null) {
+	        			prop.setType(attrib.getProperty("type"));
+	        		}
+	        		
+	        		// value attribute is optional
+	        		if(attrib.getProperty("value") != null) {
+	        			prop.setValue(attrib.getProperty("value"));
+	        		}
+	            	m_currentComponent.addProperty(prop);
+	        	}
+	        	else {
+	        		// TODO: treat the case where property value is not specified (p. 291)
+	        	}
+	        	// TODO: treat the case where a properties file name is provided (p. 292)
+	        }
+	        else if(qName.equals("properties")) {
+	        	// TODO: implement the properties tag
+	        }
+	        // 112.4.6 Service Element
+	        else if (qName.equals("service")) {
+	        	
+	        	m_currentService = new ServiceMetadata();
+	        	
+	        	// servicefactory attribute is optional
+	        	if(attrib.getProperty("servicefactory") != null) {
+	        		m_currentService.setServiceFactory(attrib.getProperty("servicefactory").equals("true"));
+	        	}      	
+	        	
+	            m_currentComponent.setService(m_currentService);
+	        }
+	        else if (qName.equals("provide")) {
+	            m_currentService.addProvide(attrib.getProperty("interface"));
+	        }
+	        
+	        // 112.4.7 Reference element
+	        else if (qName.equals("reference")) {
+	            ReferenceMetadata ref=new ReferenceMetadata ();
+	            ref.setName(attrib.getProperty("name"));
+	            ref.setInterface(attrib.getProperty("interface"));
+	            
+	            // Cardinality 
+	            if(attrib.getProperty("cardinality")!= null) {
+	            	ref.setCardinality(attrib.getProperty("cardinality"));
+	            }
+	            
+	            if(attrib.getProperty("policy") != null) {
+	            	ref.setPolicy(attrib.getProperty("policy"));
+	            }
+	            
+	            //if
+	            ref.setTarget(attrib.getProperty("target"));
+	            ref.setBind(attrib.getProperty("bind"));
+	            ref.setUnbind(attrib.getProperty("unbind"));
+	
+	            m_currentComponent.addDependency(ref);
+	        }
+    	}
+    	catch(Exception ex) {
+    		ex.printStackTrace();
+    		throw new ParseException("Exception during parsing",ex);
+    	}
+    }
+
+    /**
+    * 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("component"))
+        {
+        	// When the closing tag for a component is found, the component is validated to check if 
+        	// the implementation class has been set
+        	m_currentComponent.validate();
+        }
+    }
+
+    /**
+    * Called to retrieve the service descriptors
+    *
+    * @return   A list of service descriptors
+    */
+    List getComponentMetadataList()
+    {
+        return m_components;
+    }
+
+	public void characters(char[] ch, int offset, int length) throws Exception {
+		// Not used
+		
+	}
+
+	public void processingInstruction(String target, String data) throws Exception {
+		// Not used
+		
+	}
+
+	public void setLineNumber(int lineNumber) {
+		// Not used
+		
+	}
+
+	public void setColumnNumber(int columnNumber) {
+		// Not used
+		
+	}
+}
+
diff --git a/org.apache.felix.scr/todolist.txt b/org.apache.felix.scr/todolist.txt
new file mode 100644
index 0000000..90935b5
--- /dev/null
+++ b/org.apache.felix.scr/todolist.txt
@@ -0,0 +1,66 @@
+Component Description

+

+112.4.1 Service Component Header 

+[    ] Process multi-entry (comma separated) header

+[    ] Support fragments

+[    ] Log error with log service in case header cannot be located

+

+112.4.2 XML Document

+[    ] Use document namespace

+

+112.4.3 Component Element

+[    ] Verify that the name of a component is globally unique

+[ OK ] Enabled set to true when not present

+[ OK ] Support null factory attribute

+[ OK ] Immediate set to false by default

+

+112.4.4 Implementation Element

+[ OK ] Check that the implementation element is present

+

+112.4.5 Properties and Property Elements

+[ OK ] Support property

+[    ] Support Configuration Admin's service

+[    ] Element body with multiple lines

+[    ] Support properties (file)

+

+112.4.6 Service Element

+[ OK ] Support for optional declaration

+[ OK ] Support for provides

+

+112.4.7 Reference Element

+[ OK ] Name of the reference

+[ OK ] Interface

+[ OK ] Cardinality

+[ OK ] Policy

+[ OK ] Target

+[ OK ] bind

+[ OK ] unbind

+

+Component Lifecycle

+

+[ OK ] 112.5.1 Enabled

+[ OK ] 112.5.2 Satisfied

+[ OK ] 112.5.3 Immediate

+[ OK ] 112.5.4 Delayed

+[    ] 112.5.5 Factory

+[ OK ] 112.5.6 Activation

+[ OK ] 112.5.7 Binding Services

+[ OK ] 112.5.8 Activate Method

+[    ] 112.5.9 Component Context

+[    ] 112.5.10 Bound Service Replacement

+[    ] 112.5.11 Deactivation

+[ OK ] 112.5.12 Deactivate Method

+[ OK ] 112.5.13 Unbinding

+

+[    ] 112.6 Component Properties

+[    ] 112.7 Deployment

+

+Service Component Runtime

+

+[    ] 112.8.1 Relationship to OSGi Framework

+[    ] 112.8.2 Starting and Stopping SCR

+

+Security

+

+[    ] 112.9.1 Service Permissions

+[    ] 112.9.2 Using hasPermission

diff --git a/pom.xml b/pom.xml
index 95b71d9..85decaa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
     <module>org.apache.felix.upnp.tester</module>      

     <module>org.apache.felix.upnp.sample.tv</module>

     <module>org.apache.felix.http.jetty</module>

+	<module>org.apache.felix.scr</module>

   </modules>

 

   <repositories>