moved new dm4 from sandbox to trunk.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1663056 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/.classpath b/dependencymanager/org.apache.felix.dependencymanager.runtime/.classpath
new file mode 100644
index 0000000..f89ae43
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="bin" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.runtime/.gitignore
new file mode 100644
index 0000000..90dde36
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/.gitignore
@@ -0,0 +1,3 @@
+/bin/
+/bin_test/
+/generated/
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/.project b/dependencymanager/org.apache.felix.dependencymanager.runtime/.project
new file mode 100644
index 0000000..56b71cc
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.felix.dependencymanager.runtime</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/.settings/org.eclipse.jdt.core.prefs b/dependencymanager/org.apache.felix.dependencymanager.runtime/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..7341ab1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd
new file mode 100644
index 0000000..087aae0
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd
@@ -0,0 +1,44 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+Bundle-Version: 4.0.0
+-buildpath: \
+	osgi.core;version=4.2,\
+	osgi.cmpn;version=4.2,\
+	org.apache.felix.dependencymanager;version=latest,\
+	de.twentyeleven.skysail.org.json-osgi;version=20080701.0
+Bundle-Activator:org.apache.felix.dm.runtime.Activator
+Private-Package: \
+	org.apache.felix.dm.runtime,\
+	org.json
+Export-Package:  \
+	org.apache.felix.dm.runtime.api
+Provide-Capability: osgi.extender; osgi.extender="org.apache.felix.dependencymanager.runtime";\
+	uses:="org.apache.felix.dm";version:Version="4.0.0"
+Include-Resource: META-INF/=resources/LICENSE,\
+	META-INF/=resources/NOTICE,\
+	META-INF/=resources/DEPENDENCIES,\
+	META-INF/=resources/changelog.txt
+
+Bundle-Name: Apache Felix Dependency Manager Runtime
+Bundle-Description: Loads Apache Felix Dependency Manager component descriptors from active \
+	annoted bundles
+Bundle-Category: osgi
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Vendor: The Apache Software Foundation
+Bundle-ContactAddress: http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager.html
+# Work around used to make sure DM api is imported using proper version range (can be removed with bndtools 3)
+Import-Package: org.apache.felix.dm;org.apache.felix.dm.context;version="[4, 5)", *
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/DEPENDENCIES b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/DEPENDENCIES
new file mode 100644
index 0000000..3fdced9
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/DEPENDENCIES
@@ -0,0 +1,24 @@
+Apache Felix Dependency Manager Runtime
+Copyright 2011-2015 The Apache Software Foundation
+
+This software was developed at the Apache Software Foundation
+(http://www.apache.org) and may have dependencies on other
+Apache software licensed under Apache License 2.0.
+
+I. Included Third-Party Software
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+Licensed under the JSON License
+
+II. Used Third-Party Software
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2014).
+Licensed under the Apache License 2.0.
+
+III. Overall License Summary
+
+- Apache License 2.0
+- JSON License
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/LICENSE b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/LICENSE
new file mode 100644
index 0000000..eedfc8a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/LICENSE
@@ -0,0 +1,228 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+=========================================================================
+==  JSON License                                                       ==
+=========================================================================
+
+Copyright (c) 2002 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/NOTICE b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/NOTICE
new file mode 100644
index 0000000..5fa750e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/NOTICE
@@ -0,0 +1,10 @@
+Apache Felix Dependency Manager Runtime
+Copyright 2011-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+Licensed under the JSON License
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/changelog.txt b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/changelog.txt
new file mode 100644
index 0000000..3c75cff
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/resources/changelog.txt
@@ -0,0 +1,8 @@
+Release 4.0.0:
+-------------
+
+FELIX-4777: Dynamic initialization time configuration of @ConfigurationDependency
+FELIX-4676: Add Provide-Capability for DependencyManager Runtime bundle
+FELIX-4600: Cherrypicking of propagated properties
+FELIX-4684: Replace DependencyManager Runtime "factorySet" by a cleaner API
+FELIX-4709: Incorrect Named Dependencies are binded to the Service Instance
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/.gitignore
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AbstractBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AbstractBuilder.java
new file mode 100644
index 0000000..2e58f1c
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AbstractBuilder.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentState;
+import org.apache.felix.dm.ComponentStateListener;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Base class for all kind of DM component builders (for Component, Aspect, Adapters ...).
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class AbstractBuilder
+{
+    /**
+     * Returns the service component type.
+     */
+    abstract String getType();
+
+    /**
+     * Builds the service component.
+     * @param serviceMetaData the service component metadata parsed from the descriptor file.
+     * @param serviceDependencies the service component dependencies metadata parsed from the descriptor file.
+     */
+    abstract void build(MetaData serviceMetaData, List<MetaData> serviceDependencies, Bundle b, DependencyManager dm)
+        throws Exception;
+
+    /**
+     * Sets common Service parameters, if provided from our Component descriptor
+     */
+    protected void setCommonServiceParams(Component c, MetaData srvMeta) throws Exception
+    {
+        // Set auto configured component fields.
+        DependencyManager dm = c.getDependencyManager();
+        boolean autoConfigureComponents = "true".equals(dm.getBundleContext().getProperty(
+            Activator.CONF_ENABLE_AUTOCONFIG));
+
+        if (!autoConfigureComponents)
+        {
+            c.setAutoConfig(BundleContext.class, Boolean.FALSE);
+            c.setAutoConfig(ServiceRegistration.class, Boolean.FALSE);
+            c.setAutoConfig(DependencyManager.class, Boolean.FALSE);
+            c.setAutoConfig(Component.class, Boolean.FALSE);
+        }
+
+        // See if BundleContext must be auto configured.
+        String bundleContextField = srvMeta.getString(Params.bundleContextField, null);
+        if (bundleContextField != null)
+        {
+            c.setAutoConfig(BundleContext.class, bundleContextField);
+        }
+
+        // See if DependencyManager must be auto configured.
+        String dependencyManagerField = srvMeta.getString(Params.dependencyManagerField, null);
+        if (dependencyManagerField != null)
+        {
+            c.setAutoConfig(DependencyManager.class, dependencyManagerField);
+        }
+
+        // See if Component must be auto configured.
+        String componentField = srvMeta.getString(Params.componentField, null);
+        if (componentField != null)
+        {
+            c.setAutoConfig(Component.class, componentField);
+        }
+
+        // Now, if the component has a @Started annotation, then add our component state listener,
+        // which will callback the corresponding annotated method, once the component is started.
+        String registered = srvMeta.getString(Params.registered, null);
+        String unregistered = srvMeta.getString(Params.unregistered, null);
+
+        if (registered != null || unregistered != null)
+        {
+            c.add(new RegistrationListener(registered, unregistered));
+        }
+    }
+
+    /**
+     * Registers all unnamed dependencies into a given service. Named dependencies are
+     * handled differently, and are managed by the ServiceLifecycleHandler class.
+     * @throws Exception 
+     */
+    protected static void addUnamedDependencies(Bundle b, DependencyManager dm, Component s, MetaData srvMeta,
+        List<MetaData> depsMeta) throws Exception
+    {
+        for (MetaData dependency : depsMeta)
+        {
+            String name = dependency.getString(Params.name, null);
+            if (name == null)
+            {
+                DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                Log.instance().info("adding dependency %s into service %s", dependency, srvMeta);
+                Dependency d = depBuilder.build(b, dm);
+                s.add(d);
+            }
+        }
+    }
+
+    static class RegistrationListener implements ComponentStateListener
+    {
+        private final String m_registered;
+        private final String m_unregistered;
+        private volatile boolean m_isRegistered;
+
+        RegistrationListener(String registered, String unregistered)
+        {
+            m_registered = registered;
+            m_unregistered = unregistered;
+        }
+
+        public void changed(Component c, ComponentState state)
+        {
+            boolean wasRegistered = m_isRegistered;
+            switch (state)
+            {
+                case TRACKING_OPTIONAL:
+                    // Started
+                    m_isRegistered = true;
+                    if (!wasRegistered && m_registered != null)
+                    {
+                        // The component has registered a service: notify all component instances
+                        Object[] componentInstances = c.getInstances();
+                        for (Object instance : componentInstances)
+                        {
+                            try
+                            {
+                                Class<?>[][] signatures = new Class<?>[][] { { ServiceRegistration.class }, {} };
+                                Object[][] params = new Object[][] { { c.getServiceRegistration() }, {} };
+                                InvocationUtil.invokeCallbackMethod(instance, m_registered, signatures, params);
+                            }
+                            catch (Throwable t)
+                            {
+                                Log.instance().error("Exception caught while invoking method %s on component %s", t,
+                                    m_registered, instance);
+                            }
+                        }
+                    }
+                    break;
+
+                case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+                    // Stopped
+                    m_isRegistered = false;
+                    if (wasRegistered && m_unregistered != null)
+                    {
+                        Object[] componentInstances = c.getInstances();
+                        for (Object instance : componentInstances)
+                        {
+                            try
+                            {
+                                InvocationUtil.invokeCallbackMethod(instance, m_unregistered, new Class[][] { {} },
+                                    new Object[][] { {} });
+                            }
+                            catch (Throwable t)
+                            {
+                                Log.instance().error("Exception caught while invoking method %s on component %s", t,
+                                    m_registered, instance);
+                            }
+                        }
+                    }
+                    break;
+                
+                default:
+                    break;
+            }
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Activator.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Activator.java
new file mode 100644
index 0000000..91d702a
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Activator.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/*
+ * This is the Activator for our DependencyManager Component Runtime.
+ * Here, we'll track started/stopped bundles which have some DependencyManager
+ * descriptors (META-INF/dependencymanager/*.dm). Such descriptors are generated 
+ * by the Bnd plugin which parses DependencyManager annotations at compile time.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Activator extends DependencyActivatorBase
+{
+    /**
+     * Name of bundle context property telling if log service is required or not.
+     * (default = false)
+     */
+    final static String CONF_LOG = "org.apache.felix.dependencymanager.runtime.log";
+        
+    /**
+     * Name of bundle context property telling if Components must be auto configured
+     * with BundleContext/ServiceRegistration etc .. (default = false) 
+     */
+    final static String CONF_ENABLE_AUTOCONFIG = "org.apache.felix.dependencymanager.runtime.autoconfig";
+    
+    /**
+     * Initialize our DependencyManager Runtime service.
+     * 
+     * We depend on the OSGi LogService, and we track all started bundles which do have a 
+     * "DependencyManager-Component" Manifest header.
+     * If the "dm.runtime.log=true" or "dm.runtime.packageAdmin=true" parameter is configured in the Felix config.properties
+     * then we'll use a required/temporal service dependency over the respective service.
+     * These temporal dependencies avoid us to be restarted if the respective service is temporarily
+     * unavailable (that is: when the service is updating).
+     * if the "dm.runtime.log" or "dm.runtime.packageAdmin" is not configured or it it is set to false, then we'll use
+     * an optional dependency over the respective service, in order to use a NullObject in case
+     * the service is not available.  
+     */
+    @Override
+    public void init(BundleContext context, DependencyManager dm) throws Exception
+    {
+		Component component = createComponent()
+				.setImplementation(DependencyManagerRuntime.class)
+				.setComposition("getComposition")
+				.add(createBundleDependency()
+						.setRequired(false)
+						.setStateMask(Bundle.ACTIVE)
+						.setFilter("(DependencyManager-Component=*)")
+						.setCallbacks("bundleStarted", "bundleStopped"))
+				.add(createServiceDependency()
+						.setRequired(true)
+						.setService(PackageAdmin.class))
+				.add(createServiceDependency()
+						.setRequired("true".equalsIgnoreCase(context.getProperty(CONF_LOG)))
+						.setService(LogService.class));
+				                
+        dm.add(component);
+    }
+
+    /**
+     * Our bundle is stopping: shutdown our Dependency Manager Runtime service.
+     */
+    @Override
+    public void destroy(BundleContext context, DependencyManager dm) throws Exception
+    {
+    }    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AdapterServiceBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
new file mode 100644
index 0000000..6acd109
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Builded called when the JSON parser find an adapter service descriptor.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AdapterServiceBuilder extends AbstractBuilder
+{
+    /** The type attribute specified in the JSON descriptor */
+    private final static String TYPE = "AdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+        throws Exception
+    {
+        Class<?> adapterImplClass = b.loadClass(srvMeta.getString(Params.impl));
+        String[] provides = srvMeta.getStrings(Params.provides, null);
+        Dictionary<String, Object> adapterProperties = srvMeta.getDictionary(Params.properties, null);
+        Class<?> adapteeService = b.loadClass(srvMeta.getString(Params.adapteeService));
+        String adapteeFilter = srvMeta.getString(Params.adapteeFilter, null);   
+        String field = srvMeta.getString(Params.field, null);
+        String added = srvMeta.getString(Params.added, null);
+        String changed = srvMeta.getString(Params.changed, null);
+        String removed = srvMeta.getString(Params.removed, null);
+        String swap = srvMeta.getString(Params.swap, null);
+        boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "true"));
+        
+        if (field != null && (added != null || changed != null || removed != null || swap != null))
+        {
+            throw new IllegalArgumentException("autoconfig field " + field + " can't be defined with both added/changed/removed/swap calllbacks");
+        }
+        
+        Component c;
+        
+        if (field != null)
+        {
+            c = dm.createAdapterService(adapteeService, adapteeFilter, field, null, null, null, null, null, propagate);
+        }
+        else
+        {
+            if (added != null || changed != null || removed != null || swap != null)
+            {
+                c = dm.createAdapterService(adapteeService, adapteeFilter, null, null, added, changed, removed, swap, propagate);
+
+            }
+            else
+            {
+                c = dm.createAdapterService(adapteeService, adapteeFilter, null, null, null, null, null, null, propagate);
+            }
+        }
+        
+        setCommonServiceParams(c, srvMeta);
+        c.setInterface(provides, adapterProperties);
+        
+        String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+        if (factoryMethod == null)
+        {
+            c.setImplementation(adapterImplClass);
+        } 
+        else
+        {
+            c.setFactory(adapterImplClass, factoryMethod);
+        }
+        c.setComposition(srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+        dm.add(c);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AspectServiceBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AspectServiceBuilder.java
new file mode 100644
index 0000000..46273ef
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/AspectServiceBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build an aspect service using metadata found from DependencyManager runtime
+ * meta-inf descriptor.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class AspectServiceBuilder extends AbstractBuilder
+{
+    private final static String TYPE = "AspectService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+        throws Exception
+    {
+        Log.instance().info("AspectServiceBuilder: building aspect service: %s with dependencies %s",
+                            srvMeta,
+                            depsMeta);
+
+        Class<?> serviceInterface = b.loadClass(srvMeta.getString(Params.service));
+        String serviceFilter = srvMeta.getString(Params.filter, null);
+        Dictionary<String, Object> aspectProperties = srvMeta.getDictionary(Params.properties, null);
+        int ranking = srvMeta.getInt(Params.ranking, 1);
+        String implClassName = srvMeta.getString(Params.impl);
+        Object implClass = b.loadClass(implClassName);
+        String field = srvMeta.getString(Params.field, null);
+        String added = srvMeta.getString(Params.added, null);
+        String changed = srvMeta.getString(Params.changed, null);
+        String removed = srvMeta.getString(Params.removed, null);
+        String swap = srvMeta.getString(Params.swap, null);
+
+        if (field != null && (added != null || changed != null || removed != null || swap != null))
+        {
+            throw new IllegalArgumentException("autoconfig field " + field + " can't be defined with both added/changed/removed/swap calllbacks");
+        }
+
+        Component c;
+        if (field != null)
+        {
+            c = dm.createAspectService(serviceInterface, serviceFilter, ranking, field)
+                  .setServiceProperties(aspectProperties);
+        } 
+        else
+        {
+            if (added != null || changed != null || removed != null || swap != null)
+            {
+                c = dm.createAspectService(serviceInterface, serviceFilter, ranking, added, changed, removed, swap)
+                      .setServiceProperties(aspectProperties);
+            } 
+            else
+            {
+                c = dm.createAspectService(serviceInterface, serviceFilter, ranking)
+                      .setServiceProperties(aspectProperties);
+            }
+ 
+        }
+        
+        setCommonServiceParams(c, srvMeta);
+        String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+        if (factoryMethod == null)
+        {
+            c.setImplementation(implClass);
+        }
+        else
+        {
+            c.setFactory(implClass, factoryMethod);
+        }
+
+        c.setComposition(srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle
+        // handler).
+        addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+        dm.add(c);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
new file mode 100644
index 0000000..94f8e62
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build a bundle adapter service using metadata found from DependencyManager runtime
+ * meta-inf descriptor.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BundleAdapterServiceBuilder extends AbstractBuilder
+{
+    private final static String TYPE = "BundleAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm) 
+        throws Exception
+    {
+        int stateMask = srvMeta.getInt(Params.stateMask, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE);
+        String filter = srvMeta.getString(Params.filter, null);
+        Class<?> adapterImplClass = b.loadClass(srvMeta.getString(Params.impl));
+        String[] provides = srvMeta.getStrings(Params.provides, null);
+        Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
+        Component c = dm.createBundleAdapterService(stateMask, filter, propagate);
+        c.setInterface(provides, properties);
+        String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+        if (factoryMethod == null)
+        {
+            c.setImplementation(adapterImplClass);
+        } 
+        else
+        {
+            c.setFactory(adapterImplClass, factoryMethod);
+        }
+
+        setCommonServiceParams(c, srvMeta);
+        c.setComposition(srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+        dm.add(c);
+    }    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java
new file mode 100644
index 0000000..b9ec8be
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+import org.osgi.framework.Bundle;
+
+/**
+ * Builds a DependencyManager Component.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentBuilder extends AbstractBuilder
+{
+    private final static String TYPE = "Component";
+    public final static String FACTORY_NAME = "dm.factory.name";
+    public final static String FACTORY_INSTANCE = "dm.factory.instance";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+        throws Exception
+    {
+        Component c = dm.createComponent();
+        String factory = srvMeta.getString(Params.factorySet, null);
+        String factoryName = srvMeta.getString(Params.factoryName, null);
+
+        // Setup Component auto config fields
+        setCommonServiceParams(c, srvMeta);
+        
+        // Check if we must provide a Component factory set (deprecated), or a ComponentFactory.
+        if (factory == null && factoryName == null)
+        {
+            Log.instance().info("ComponentBuilder: building service %s with dependencies %s",
+                                srvMeta,
+                                depsMeta);
+
+            String impl = srvMeta.getString(Params.impl);
+            String composition = srvMeta.getString(Params.composition, null);
+            String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+            if (factoryMethod == null)
+            {
+                c.setImplementation(b.loadClass(impl));
+            }
+            else
+            {
+                c.setFactory(b.loadClass(impl), factoryMethod);
+            }
+            c.setComposition(composition);
+
+            // Adds dependencies (except named dependencies, which are managed by the lifecycle
+            // handler).
+            addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+            // Creates a ServiceHandler, which will filter all service lifecycle callbacks.
+            ServiceLifecycleHandler lfcleHandler =
+                    new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+            c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+
+            // Set the provided services
+            Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
+            String[] services = srvMeta.getStrings(Params.provides, null);
+            c.setInterface(services, properties);
+        }
+        else if (factory != null) /* deprecated */ 
+        {
+            Log.instance()
+                    .info("ComponentBuilder: providing factory set for service %s with dependencies %s",
+                          srvMeta,
+                          depsMeta);
+
+            // We don't instantiate the service, but instead we provide a Set in the registry.
+            // This Set will act as a factory and another component may registers some
+            // service configurations into it in order to fire some service instantiations.
+            FactorySet factorySet = new FactorySet(b, srvMeta, depsMeta);
+            c.setImplementation(factorySet);
+            c.setCallbacks(null, "start", "stop", null);
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put(ComponentBuilder.FACTORY_NAME, factory);
+            c.setInterface(Set.class.getName(), props);
+        } 
+        else if (factoryName != null) {
+            Log.instance()
+            .info("ComponentBuilder: providing component factory for service %s with dependencies %s",
+                  srvMeta,
+                  depsMeta);
+
+            // We don't instantiate the service, but instead we provide a ComponentFactory in the registry.
+            // (similar to DS ComponentFactory).
+            ComponentFactoryImpl compFactory = new ComponentFactoryImpl(b, srvMeta, depsMeta);
+            c.setImplementation(compFactory);
+            c.setCallbacks(null, "start", "stop", null);
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put(ComponentBuilder.FACTORY_NAME, factoryName);
+            c.setInterface(ComponentFactory.class.getName(), props);
+        }
+
+        dm.add(c);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java
new file mode 100644
index 0000000..3a15ded
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentException;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+import org.apache.felix.dm.runtime.api.ComponentInstance;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class implements a DM Component factory service.
+ * When a <code>Component</annotation> contains a <code>factoryName</code> attribute, this class is provided
+ * into the OSGi registry with a <code>org.apache.felix.dependencymanager.factory.name</code> service property. 
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentFactoryImpl implements ComponentFactory {
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private MetaData m_srvMeta;
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private List<MetaData> m_depsMeta;
+
+    /**
+     * The DependencyManager which is used to create Service instances.
+     */
+    private DependencyManager m_dm;
+
+    /**
+     * Flag used to check if our service is Active.
+     */
+    private volatile boolean m_active;
+
+    /**
+     * The bundle containing the Service annotated with the factory attribute.
+     */
+    private final Bundle m_bundle;
+
+    /**
+     * Sole constructor.
+     * @param b the bundle containing the Service annotated with the factory attribute
+     * @param srvMeta the component service metadata
+     * @param depsMeta teh component dependencies metadata
+     */
+    public ComponentFactoryImpl(Bundle b, MetaData srvMeta, List<MetaData> depsMeta) {
+        m_bundle = b;
+        m_srvMeta = srvMeta;
+        m_depsMeta = depsMeta;
+    }
+
+    /**
+     * Our Service is starting. 
+     */
+    public void start(Component c) {
+        m_active = true;
+        m_dm = c.getDependencyManager();
+    }
+
+    /**
+     * Our Service is stopping.
+     */
+    public void stop() {
+        m_active = false;
+    }
+
+    /**
+     * Create or Update a Service.
+     */
+    public ComponentInstance newInstance(Dictionary<String, ?> conf) {
+        // Check parameter validity
+        if (conf == null) {
+            throw new NullPointerException("configuration parameter can't be null");
+        }
+
+        // Check if our service is running.
+        checkServiceAvailable();
+
+        try {
+            ComponentInstanceImpl instance = new ComponentInstanceImpl(m_dm,m_bundle, m_srvMeta, m_depsMeta, conf);
+            return instance;
+            
+        } catch (Throwable t) {
+            Log.instance().error("ServiceFactory: could not instantiate service %s", t, m_srvMeta);
+            throw new ComponentException("could not instantiate factory component", t);
+        }   
+    }
+
+    /**
+     * Checks if our Service is available (we are not stopped").
+     */
+    private void checkServiceAvailable() {
+        if (!m_active) {
+            throw new IllegalStateException("Service not available");
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java
new file mode 100644
index 0000000..90c0b1f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.Method;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentInstance;
+import org.osgi.framework.Bundle;
+
+/**
+ * Implementation for our DM Runtime ComponentInstance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentInstanceImpl implements ComponentInstance {
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final MetaData m_srvMeta;
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final List<MetaData> m_depsMeta;
+
+    /**
+     * The DependencyManager which is used to create Service instances.
+     */
+    private final DependencyManager m_dm;
+
+    /**
+     * The bundle containing the Service annotated with the factory attribute.
+     */
+    private final Bundle m_bundle;
+    
+    /**
+     * The component 
+     */
+    private final Object m_impl;
+    
+    /**
+     * The DM Component used to define the component
+     */
+    private final Component m_component;
+
+    public ComponentInstanceImpl(DependencyManager dm, Bundle b, MetaData srvMeta, List<MetaData> depsMeta, Dictionary<String, ?> conf) throws Exception
+    {
+        m_bundle = b;
+        m_dm = dm;
+        m_srvMeta = srvMeta;
+        m_depsMeta = depsMeta;
+        m_component = m_dm.createComponent();
+        
+        Class<?> implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
+        Object impl = conf.get(ComponentBuilder.FACTORY_INSTANCE);
+        if (impl == null) {
+            String factoryMethod = m_srvMeta.getString(Params.factoryMethod, null);
+            if (factoryMethod == null) {
+                impl = implClass.newInstance();
+            } else {
+                Method m = implClass.getDeclaredMethod(factoryMethod);
+                m.setAccessible(true);
+                impl = m.invoke(null);
+            }
+        }
+        m_impl = impl;
+
+        // Invoke "configure" callback
+        String configure = m_srvMeta.getString(Params.factoryConfigure, null);
+
+        if (configure != null) {
+            invokeConfigure(impl, configure, conf);
+        }
+
+        // Create Service
+        m_component.setImplementation(impl);
+        String[] provides = m_srvMeta.getStrings(Params.provides, null);
+        if (provides != null) {
+            // Merge service properties with the configuration provided by the factory.
+            Dictionary<String, ?> serviceProperties = m_srvMeta.getDictionary(Params.properties, null);
+            serviceProperties = mergeSettings(serviceProperties, conf);
+            m_component.setInterface(provides, serviceProperties);
+        }
+
+        m_component.setComposition(m_srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(m_component, m_bundle, m_dm, m_srvMeta, m_depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        m_component.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        for (MetaData dependency : m_depsMeta) {
+            String name = dependency.getString(Params.name, null);
+            if (name == null) {
+                DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s", dependency,
+                    m_srvMeta);
+                Dependency d = depBuilder.build(m_bundle, m_dm);
+                m_component.add(d);
+            }
+        }
+
+        // Register the Service instance, and keep track of it.
+        Log.instance().info("ServiceFactory: created service %s", m_srvMeta);
+        m_dm.add(m_component);
+    }
+
+    @Override
+    public void dispose() {
+        m_dm.remove(m_component);
+    }
+
+    @Override
+    public void update(Dictionary<String, ?> conf) {
+        // Reconfigure an already existing Service.
+        String configure = m_srvMeta.getString(Params.factoryConfigure, null);
+        if (configure != null) {
+            Log.instance().info("ServiceFactory: updating service %s", m_impl);
+            invokeConfigure(m_impl, configure, conf);
+        }
+
+        // Update service properties
+        String[] provides = m_srvMeta.getStrings(Params.provides, null);
+        if (provides != null) {
+            Dictionary<String, ?> serviceProperties = m_srvMeta.getDictionary(Params.properties, null);
+            serviceProperties = mergeSettings(serviceProperties, conf);
+            m_component.setServiceProperties(serviceProperties);
+        }
+    }
+
+    /**
+     * Invokes the configure callback method on the service instance implemenatation.
+     * @param impl
+     * @param configure
+     * @param config
+     */
+    private void invokeConfigure(Object impl, String configure, Dictionary<String, ?> config) {
+        try {
+            InvocationUtil.invokeCallbackMethod(impl, configure, new Class[][] { { Dictionary.class } },
+                new Object[][] { { config } });
+        }
+
+        catch (Throwable t) {
+            if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
+            } else {
+                throw new RuntimeException("Could not invoke method " + configure + " on object " + impl, t);
+            }
+        }
+    }
+
+    /**
+     * Merge factory configuration settings with the service properties. The private factory configuration 
+     * settings are ignored. A factory configuration property is private if its name starts with a dot (".").
+     * 
+     * @param serviceProperties
+     * @param factoryConfiguration
+     * @return
+     */
+    private Dictionary<String, Object> mergeSettings(Dictionary<String, ?> serviceProperties,
+        Dictionary<String, ?> factoryConfiguration)
+    {
+        Dictionary<String, Object> props = new Hashtable<>();
+
+        if (serviceProperties != null) {
+            Enumeration<String> keys = serviceProperties.keys();
+            while (keys.hasMoreElements()) {
+                String key = keys.nextElement();
+                Object val = serviceProperties.get(key);
+                props.put(key, val);
+            }
+        }
+
+        Enumeration<String> keys = factoryConfiguration.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            if (!key.toString().startsWith(".")) {
+                // public properties are propagated
+                Object val = factoryConfiguration.get(key);
+                props.put(key, val);
+            }
+        }
+        return props;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyBuilder.java
new file mode 100644
index 0000000..e25d441
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyBuilder.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import org.apache.felix.dm.BundleDependency;
+import org.apache.felix.dm.ConfigurationDependency;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ResourceDependency;
+import org.apache.felix.dm.ServiceDependency;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build a concrete dependency from meta data.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DependencyBuilder
+{
+    public enum DependencyType
+    {
+        ServiceDependency,
+        TemporalServiceDependency,
+        ConfigurationDependency,
+        BundleDependency,
+        ResourceDependency
+    }
+
+    private MetaData m_metaData;
+
+    public DependencyBuilder(MetaData dependencyMetaData)
+    {
+        m_metaData = dependencyMetaData;
+    }
+
+    public Dependency build(Bundle b, DependencyManager dm)
+        throws Exception
+    {
+        Dependency dp = null;
+        DependencyType type;
+
+        try
+        {
+            type = DependencyType.valueOf(m_metaData.getString(Params.type));
+        }
+        catch (IllegalArgumentException e)
+        {
+            throw new IllegalArgumentException("no \"type\" parameter found from metaData: " + m_metaData);
+        }
+
+        switch (type)
+        {
+            case ServiceDependency:
+                dp = createServiceDependency(b, dm);
+                break;
+
+            case ConfigurationDependency:
+                dp = createConfigurationDependency(dm);
+                break;
+
+            case BundleDependency:
+                dp = createBundleDependency(dm);
+                break;
+
+            case ResourceDependency:
+                dp = createResourceDependency(dm);
+                break;
+            
+            default:
+                throw new IllegalArgumentException("Can't build service dependency: " + type);
+        }
+        return dp;
+    }
+
+    private Dependency createServiceDependency(Bundle b, DependencyManager dm)
+        throws ClassNotFoundException
+    {
+        String service = m_metaData.getString(Params.service);
+        Class<?> serviceClass = b.loadClass(service);
+        String serviceFilter = m_metaData.getString(Params.filter, null);
+        String defaultServiceImpl = m_metaData.getString(Params.defaultImpl, null);
+        Class<?> defaultServiceImplClass =
+            (defaultServiceImpl != null) ? b.loadClass(defaultServiceImpl) : null;
+        String added = m_metaData.getString(Params.added, null);
+        long timeout = m_metaData.getLong(Params.timeout, -1L);
+        String changed = timeout != -1 ? null : m_metaData.getString(Params.changed, null);
+        String removed = timeout != -1 ? null : m_metaData.getString(Params.removed, null);
+        String autoConfigField = m_metaData.getString(Params.autoConfig, null);
+        boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
+        boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
+
+        Dependency dp = createServiceDependency(dm, serviceClass,
+            serviceFilter, defaultServiceImplClass, added, changed,
+            removed, autoConfigField, timeout, required, propagate);
+        return dp;
+    }
+
+    private Dependency createServiceDependency(DependencyManager dm, Class<?> serviceClass, 
+        String serviceFilter, Class<?> defaultServiceImplClass, String added,
+        String changed, String removed, String autoConfigField, long timeout, boolean required,
+        boolean propagate)
+    {
+        ServiceDependency sd = timeout != -1 ? dm.createTemporalServiceDependency(timeout)
+            : dm.createServiceDependency();
+        sd.setService(serviceClass, serviceFilter);
+        if (defaultServiceImplClass != null)
+        {
+            sd.setDefaultImplementation(defaultServiceImplClass);
+        }
+        sd.setCallbacks(added, changed, removed);
+        if (autoConfigField != null)
+        {
+            sd.setAutoConfig(autoConfigField);
+        }
+        if (timeout == -1)
+        {
+            sd.setRequired(required);
+        }
+        
+        sd.setPropagate(propagate);
+        return sd;
+    }
+
+    private Dependency createConfigurationDependency(DependencyManager dm)
+    {
+        String pid = m_metaData.getString(Params.pid);
+        boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
+        String callback = m_metaData.getString(Params.updated, "updated");
+        Dependency dp = createConfigurationDependency(dm, pid, callback, propagate);
+        return dp;
+    }
+
+    private Dependency createConfigurationDependency(DependencyManager dm, String pid, String callback,
+    	boolean propagate)
+    {
+        if (pid == null)
+        {
+            throw new IllegalArgumentException(
+                "pid attribute not provided in ConfigurationDependency declaration");
+        }
+        ConfigurationDependency cd = dm.createConfigurationDependency();
+        cd.setPid(pid);
+        cd.setCallback(callback);
+        cd.setPropagate(propagate);
+        return cd;
+    }
+
+    /**
+     * Creates a BundleDependency that we parsed from a component descriptor entry.
+     * @param b
+     * @param dm
+     * @param parser
+     * @return
+     */
+    private Dependency createBundleDependency(DependencyManager dm)
+    {
+        String added = m_metaData.getString(Params.added, null);
+        String changed = m_metaData.getString(Params.changed, null);
+        String removed = m_metaData.getString(Params.removed, null);
+        boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
+        String filter = m_metaData.getString(Params.filter, null);
+        int stateMask = m_metaData.getInt(Params.stateMask, -1);
+        boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
+
+        Dependency dp = createBundleDependency(dm, added, changed, removed, required, propagate, filter,
+            stateMask);
+        return dp;
+    }
+
+    private Dependency createBundleDependency(DependencyManager dm, String added, String changed,
+        String removed, boolean required, boolean propagate, String filter, int stateMask)
+    {
+        BundleDependency bd = dm.createBundleDependency();
+        bd.setCallbacks(added, changed, removed);
+        bd.setRequired(required);
+        bd.setPropagate(propagate);
+        if (filter != null)
+        {
+            bd.setFilter(filter);
+        }
+        if (stateMask != -1)
+        {
+            bd.setStateMask(stateMask);
+        }
+        return bd;
+    }
+
+    private Dependency createResourceDependency(DependencyManager dm)
+    {
+        String added = m_metaData.getString(Params.added, null);
+        String changed = m_metaData.getString(Params.changed, null);
+        String removed = m_metaData.getString(Params.removed, null);
+        String filter = m_metaData.getString(Params.filter, null);
+        boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
+        boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
+        String autoConfigField = m_metaData.getString(Params.autoConfig, null);
+
+        Dependency dp = createResourceDependency(dm, added, changed, removed, required, filter, 
+                                                 propagate, autoConfigField);
+        return dp;
+    }
+
+    private Dependency createResourceDependency(DependencyManager dm, String added,
+        String changed, String removed, boolean required, String filter, boolean propagate, 
+        String autoConfigField)
+    {
+        ResourceDependency rd = dm.createResourceDependency();
+        rd.setCallbacks(added, changed, removed);
+        rd.setRequired(required);
+        if (filter != null)
+        {
+            rd.setFilter(filter);
+        }
+        if (autoConfigField != null)
+        {
+            rd.setAutoConfig(autoConfigField);
+        }
+        rd.setPropagate(propagate);
+        return rd;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyManagerRuntime.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
new file mode 100644
index 0000000..b6994f8
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/**
+ * This class parses service descriptors generated by the annotation bnd processor.
+ * The descriptors are located under META-INF/dependencymanager directory. Such files are actually 
+ * referenced by a specific "DependendencyManager-Component" manifest header.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DependencyManagerRuntime
+{
+    /**
+     * Map between bundles and their corresponding DependencyManager objects used to create bundle's components.
+     * Notice that we can safely use this map without synchronization because we are relying on the new DM4 thread
+     * model which serialize all component events safely.
+     */
+    private final Map<Bundle, DependencyManager> m_managers = new HashMap<Bundle, DependencyManager>();
+    
+    /**
+     * Parser used to scan component descriptors defined in bundles meta data.
+     */
+    private final DescriptorParser m_parser;
+    
+    /**
+     * We use the PackageAdmin service to allow support for annotations in fragment bundles.
+     */
+    private volatile PackageAdmin m_packageAdmin;
+    
+    /**
+     * Our constructor. We'll initialize here our DM component builders.
+     */
+    public DependencyManagerRuntime()
+    {
+        // Instantiates our descriptor parser, and register our service builders into it.
+        m_parser = new DescriptorParser();
+        m_parser.addBuilder(new ComponentBuilder());
+        m_parser.addBuilder(new AspectServiceBuilder());
+        m_parser.addBuilder(new AdapterServiceBuilder());
+        m_parser.addBuilder(new BundleAdapterServiceBuilder());
+        m_parser.addBuilder(new FactoryConfigurationAdapterServiceBuilder());
+        m_parser.addBuilder(new ResourceAdapterServiceBuilder());
+    }
+    
+    /**
+     * Return our Object Composition (the Activator will inject dependencies into it)
+     */
+    protected Object[] getComposition()
+    {
+        return new Object[] { this, Log.instance() };
+    }
+
+    /**
+     * Starts our Service (at this point, we have been injected with our bundle context, as well
+     * as with our log service. We'll listen to bundle start/stop events (we implement the 
+     * SynchronousBundleListener interface).
+     */
+    protected void start()
+    {
+        Log.instance().info("Starting Dependency Manager annotation runtime");
+    }
+
+    /**
+     * Stops our service. We'll stop all activated DependencyManager services.
+     */
+    protected void stop()
+    {
+        Log.instance().info("Runtime: stopping services");
+        for (DependencyManager dm : m_managers.values())
+        {
+            List<Component> services = new ArrayList<Component>(dm.getComponents());
+            for (Component service : services)
+            {
+                dm.remove(service);
+            }
+        }
+
+        m_managers.clear();
+    }
+
+    /**
+     * Load the DM descriptors from the started bundle. We also check possible fragments 
+     * attached to the bundle, which might also contain some DM descriptors. 
+     * @param bundle the started bundle which contains a DependencyManager-Component header
+     */
+    protected void bundleStarted(Bundle bundle)
+    {
+        Log.instance().info("Scanning started bundle %s", bundle.getSymbolicName());
+        List<URL> descriptorURLs = new ArrayList<URL>();
+        collectDescriptors(bundle, descriptorURLs);
+        Bundle[] fragments = m_packageAdmin.getFragments(bundle);
+        if (fragments != null)
+        {
+            for (Bundle fragment : fragments)
+            {
+                collectDescriptors(fragment, descriptorURLs);
+            }
+        }
+        for (URL descriptorURL : descriptorURLs)
+        {
+            loadDescriptor(bundle, descriptorURL);
+        }
+    }
+    
+    /**
+     * Unregisters all services for a stopping bundle.
+     * @param b
+     */
+    protected void bundleStopped(Bundle b)
+    {
+        Log.instance().info("Runtime: Removing services from stopping bundle: %s", b.getSymbolicName());
+        DependencyManager dm = m_managers.remove(b);
+        if (dm != null)
+        {
+            List<Component> services = new ArrayList<Component>(dm.getComponents());
+            for (Component service : services)
+            {
+                Log.instance().info("Runtime: Removing service: %s", service);
+                dm.remove(service);
+            }
+        }
+    }
+
+    /**
+     * Collect all descriptors found from a given bundle, including its possible attached fragments.
+     * @param bundle a started bundle containing some DM descriptors
+     * @param out the list of descriptors' URLS found from the started bundle, as well as from possibly
+     *        attached fragments.
+     */
+    private void collectDescriptors(Bundle bundle, List<URL> out) {
+        String descriptorPaths = (String) bundle.getHeaders().get("DependencyManager-Component");
+        if (descriptorPaths == null)
+        {
+            return;
+        }
+
+        for (String descriptorPath : descriptorPaths.split(","))
+        {
+            URL descriptorURL = bundle.getEntry(descriptorPath);
+            if (descriptorURL == null)
+            {
+                Log.instance()
+                        .error("Runtime: " + "DependencyManager component descriptor not found: %s",
+                               descriptorPath);
+                continue;
+            }
+            out.add(descriptorURL);
+        }        
+    }
+    
+    /**
+     * Load a DependencyManager component descriptor from a given bundle.
+     * @param b
+     * @param descriptorURL
+     */
+    private void loadDescriptor(Bundle b, URL descriptorURL)
+    {
+        Log.instance().debug("Parsing descriptor %s from bundle %s", descriptorURL, b.getSymbolicName());
+
+        BufferedReader in = null;
+        try
+        {
+            in = new BufferedReader(new InputStreamReader(descriptorURL.openStream()));
+            DependencyManager dm = m_managers.get(b);
+            if (dm == null)
+            {
+                dm = new DependencyManager(b.getBundleContext());
+                m_managers.put(b, dm);
+            }
+
+            m_parser.parse(in, b, dm);
+        }
+
+        catch (Throwable t)
+        {
+            Log.instance().error("Runtime: Error while parsing descriptor %s from bundle %s",
+                                 t,
+                                 descriptorURL,
+                                 b.getSymbolicName());
+        }
+
+        finally
+        {
+            if (in != null)
+            {
+                try
+                {
+                    in.close();
+                }
+                catch (IOException ignored)
+                {
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DescriptorParser.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DescriptorParser.java
new file mode 100644
index 0000000..2c162b1
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/DescriptorParser.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.io.BufferedReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.dm.DependencyManager;
+import org.json.JSONObject;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class parses files generated in META-INF/*.dm by the DependencyManager bnd plugin.
+ * Each descriptor contains a JSON definition of a Service, along with its corresponding  
+ * dependencies.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DescriptorParser
+{
+    private Map<String, AbstractBuilder> m_builders = new HashMap<String, AbstractBuilder>();
+
+    public void addBuilder(AbstractBuilder sb)
+    {
+        m_builders.put(sb.getType(), sb);
+    }
+
+    public void parse(BufferedReader reader, Bundle b, DependencyManager dm) throws Exception
+    {
+        String line;
+
+        // The first line is a Service Component (a Service, an Aspect Service, etc ...)
+        line = reader.readLine();
+        Log.instance().debug("DescriptorParser: parsing service %s", line);
+        JSONObject json = new JSONObject(line);
+        JSONMetaData serviceMetaData = new JSONMetaData(json);
+
+        String type = (String) json.get("type");
+        if (type == null)
+        {
+            throw new IllegalArgumentException("Invalid descriptor"
+                    + ": no \"type\" parameter found in first line");
+        }
+
+        AbstractBuilder builder = m_builders.get(type);
+        if (builder == null)
+        {
+            throw new IllegalArgumentException("Invalid descriptor"
+                    + ": invalid \"type\" parameter found in first line");
+        }
+
+        // Parse the rest of the lines (dependencies)
+        List<MetaData> serviceDependencies = new ArrayList<MetaData>();
+        while ((line = reader.readLine()) != null)
+        {
+            Log.instance().debug("Parsing dependency %s", line);
+            JSONObject dep = new JSONObject(line);
+            serviceDependencies.add(new JSONMetaData(dep));
+        }
+
+        // and Invoke the builder
+        builder.build(serviceMetaData, serviceDependencies, b, dm);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
new file mode 100644
index 0000000..0f4eb09
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build a factory configuration adapter service using metadata found from DependencyManager runtime
+ * meta-inf descriptor.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FactoryConfigurationAdapterServiceBuilder extends AbstractBuilder
+{
+    private final static String TYPE = "FactoryConfigurationAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm) 
+        throws Exception
+    {
+        Class<?> implClass = b.loadClass(srvMeta.getString(Params.impl));
+        String factoryPid = srvMeta.getString(Params.factoryPid);
+        String updated = srvMeta.getString(Params.updated);
+        String[] provides = srvMeta.getStrings(Params.provides, null);
+        Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
+        Component c = dm.createFactoryConfigurationAdapterService(factoryPid, updated, propagate);
+        c.setInterface(provides, properties);
+        String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+        if (factoryMethod == null)
+        {
+            c.setImplementation(implClass);
+        } 
+        else
+        {
+            c.setFactory(implClass, factoryMethod);
+        }
+        setCommonServiceParams(c, srvMeta);
+        c.setComposition(srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+        dm.add(c);
+    }    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactorySet.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactorySet.java
new file mode 100644
index 0000000..6d042f3
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/FactorySet.java
@@ -0,0 +1,528 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.Method;
+import java.util.AbstractSet;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class implements a <code>java.util.Set</code> which acts as a service factory.
+ * When a <code>Service</annotation> contains a <code>factory</code> attribute, this class is provided
+ * into the OSGi registry with a <code>dm.factory.name</code> service property. So, another factory component
+ * may be injected with this Set. And each time a Dictionary configuration is registered in the Set,
+ * then a new Service instance will be instantiated, and will be provided with the Dictionary passed to the
+ * Service instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings( { "unchecked", "rawtypes"})
+public class FactorySet extends AbstractSet<Dictionary>
+{
+    /**
+     * When a Dictionary is registered in a factory Set, we use this special 
+     * property key, whose value may provide the instance to use when
+     * creating a service.
+     */
+    private final static String DM_FACTORY_INSTANCE = "dm.factory.instance";
+    
+    /**
+     * The actual Service instance that is allocated for each dictionaries added in this Set.
+     */
+    private volatile Object m_impl;
+
+    /**
+     * The Service provided in the OSGi registry.
+     */
+    private final String[] m_provide;
+
+    /**
+     * The properties to be provided by the Service.
+     */
+    private final Dictionary m_serviceProperties;
+
+    /**
+     * The configure Service callback used to pass configuration added in this Set.
+     */
+    private final String m_configure;
+
+    /**
+     * The map between our Dictionaries and corresponding Service instances. 
+     * This map is modified from our serial executor, or from the add method.
+     */
+    private final ConcurrentHashMap<ServiceKey, Object> m_services = new ConcurrentHashMap<ServiceKey, Object>();
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final MetaData m_srvMeta;
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final List<MetaData> m_depsMeta;
+
+    /**
+     * The DependencyManager which is used to create Service instances.
+     */
+    private volatile DependencyManager m_dm;
+
+    /**
+     * This class is used to serialize concurrent method calls, and allow to leave our methods unsynchronized.
+     * This is required because some of our methods may invoke some Service callbacks, which must be called outside 
+     * synchronized block (in order to avoid potential dead locks).
+     */
+    private final SerialExecutor m_serialExecutor = new SerialExecutor();
+
+    /**
+     * Flag used to check if our service is Active.
+     */
+    private volatile boolean m_active;
+
+    /**
+     * The bundle containing the Service annotated with the factory attribute.
+     */
+    private final Bundle m_bundle;
+
+    /**
+     * Flag used to check if a service is being created
+     */
+    private final static Object SERVICE_CREATING = new Object();
+
+    /**
+     * This class wraps <tt>Dictionary</tt>, allowing to store the dictionary into a Map, using
+     * reference-equality in place of object-equality when getting the Dictionary from the Map.
+     */
+    private static class ServiceKey
+    {
+        private Dictionary m_dictionary;
+
+        public ServiceKey(Dictionary dictionary)
+        {
+            m_dictionary = dictionary;
+        }
+
+        Dictionary getDictionary()
+        {
+            return m_dictionary;
+        }
+
+        @Override
+        public boolean equals(Object that)
+        {
+            return that instanceof ServiceKey ? (((ServiceKey) that).getDictionary() == m_dictionary)
+                : false;
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return System.identityHashCode(m_dictionary);
+        }
+
+        @Override
+        public String toString()
+        {
+            return Dictionary.class.getName() + "@" + System.identityHashCode(m_dictionary);
+        }
+    }
+
+    /**
+     * Sole constructor.
+     * @param b the bundle containing the Service annotated with the factory attribute
+     * @param impl The Service implementation class
+     * @param serviceProperties The Service properties
+     * @param provides The Services provided by this Service
+     * @param factoryConfigure The configure callback invoked in order to pass configurations added in this Set.
+     */
+    public FactorySet(Bundle b, MetaData srvMeta, List<MetaData> depsMeta)
+    {
+        m_serviceProperties = srvMeta.getDictionary(Params.properties, null);
+        m_provide = srvMeta.getStrings(Params.provides, null);
+        m_configure = srvMeta.getString(Params.factoryConfigure, null);
+        m_bundle = b;
+        m_srvMeta = srvMeta;
+        m_depsMeta = depsMeta;
+    }
+
+    /**
+     * Our Service is starting. 
+     */
+    public void start(Component c)
+    {
+        m_active = true;
+        m_dm = c.getDependencyManager();
+    }
+
+    /**
+     * Our Service is stopping: we have to remove all Service instances that we have created.
+     */
+    public void stop()
+    {
+        try
+        {
+            clear();
+        }
+        finally
+        {
+            m_active = false;
+        }
+    }
+
+    /**
+     * Create or Update a Service.
+     */
+    @Override
+    @SuppressWarnings({ "synthetic-access" })
+    public boolean add(final Dictionary configuration)
+    {
+        // Check parameter validity
+        if (configuration == null)
+        {
+            throw new NullPointerException("configuration parameter can't be null");
+        }
+
+        // Check if our service is running.
+        checkServiceAvailable();
+
+        // Check if service is being created
+        ServiceKey serviceKey = new ServiceKey(configuration);
+        boolean creating = m_services.putIfAbsent(serviceKey, SERVICE_CREATING) == null;
+        
+        // Create or Update the Service.
+        m_serialExecutor.enqueue(new Runnable()
+        {
+            public void run()
+            {
+                doAdd(configuration);
+            }
+        });
+
+        m_serialExecutor.execute();
+        return creating;
+    }
+
+    /**
+     * Another Service wants to remove an existing Service.
+     * This method is not synchronized but uses a SerialExecutor for serializing concurrent method call.
+     * (This avoid potential dead locks, especially when Service callback methods are invoked).
+     */
+    @Override
+    @SuppressWarnings("synthetic-access")
+    public boolean remove(final Object configuration)
+    {
+        // Check parameter validity.
+        if (configuration == null)
+        {
+            throw new NullPointerException("configuration parameter can't be null");
+        }
+        if (!(configuration instanceof Dictionary))
+        {
+            throw new IllegalArgumentException("configuration must be an instance of a Dictionary");
+        }
+
+        // Check if our service is active.
+        checkServiceAvailable();
+
+        // Check if service is created (or creating)
+        boolean found = m_services.containsKey(new ServiceKey((Dictionary) configuration));
+        if (found)
+        {
+            // Create or Update the Service.
+            m_serialExecutor.enqueue(new Runnable()
+            {
+                public void run()
+                {
+                    doRemove((Dictionary) configuration);
+                }
+            });
+            m_serialExecutor.execute();
+        }
+        return found;
+    }
+
+    /**
+     * Another Service wants to remove all existing Services.
+     * This method is not synchronized but uses a SerialExecutor for serializing concurrent method call.
+     * (This avoid potential dead locks, especially when Service callback methods are invoked).
+     */
+    @Override
+    @SuppressWarnings("synthetic-access")
+    public void clear()
+    {
+        if (!m_active)
+        {
+            return;
+        }
+
+        // Make sure add/update/clear events are handled in FIFO order (serially).
+        m_serialExecutor.enqueue(new Runnable()
+        {
+            public void run()
+            {
+                doClear();
+            }
+        });
+        m_serialExecutor.execute();
+    }
+
+    /**
+     * returns the list of active Service instances configurations.
+     */
+    @Override
+    public Iterator<Dictionary> iterator()
+    {
+        throw new UnsupportedOperationException(
+            "iterator method is not supported by DependencyManager Set's service factories");
+    }
+
+    @Override
+    public String toString()
+    {
+        return FactorySet.class.getName() + "(" + m_services.size() + " active instances)";
+    }
+
+    /**
+     * Returns the number of active Service instances.
+     */
+    @Override
+    public int size()
+    {
+        if (!m_active)
+        {
+            return 0;
+        }
+        return m_services.size();
+    }
+
+    /**
+     * Checks if our Service is available (we are not stopped").
+     */
+    private void checkServiceAvailable()
+    {
+        if (!m_active)
+        {
+            throw new IllegalStateException("Service not available");
+        }
+    }
+
+    /**
+     * Add or create a new Service instance, given its configuration. This method is invoked by the
+     * SerialExecutor, hence it's thread safe and we'll invoke Service's callbacks without being
+     * synchronized (hence this will avoid potential dead locks).
+     */
+    private void doAdd(Dictionary configuration)
+    {
+        // Check if the service exists.
+        ServiceKey serviceKey = new ServiceKey(configuration);
+        Object service = m_services.get(serviceKey);
+
+        if (service == null || service == SERVICE_CREATING)
+        {
+            try
+            {
+                // Create the Service / impl, unless it is explicitly provided from the
+                // configuration (using the specific key "dm.factory.instance").
+                Component s = m_dm.createComponent();
+                Class<?> implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
+                Object impl = configuration.get(DM_FACTORY_INSTANCE);
+                if (impl == null)
+                {
+                    String factoryMethod = m_srvMeta.getString(Params.factoryMethod, null);
+                    if (factoryMethod == null)
+                    {
+                        m_impl = implClass.newInstance();
+                    }
+                    else
+                    {
+                        Method m = implClass.getDeclaredMethod(factoryMethod);
+                        m.setAccessible(true);
+                        m_impl = m.invoke(null);
+                    }
+                }
+                else
+                {
+                    m_impl = impl;
+                }
+
+                // Invoke "configure" callback
+                if (m_configure != null)
+                {
+                    invokeConfigure(m_impl, m_configure, configuration);
+                }
+
+                // Create Service
+                s.setImplementation(m_impl);
+                if (m_provide != null)
+                {
+                     // Merge service properties with the configuration provided by the factory.
+                    Dictionary serviceProperties = mergeSettings(m_serviceProperties, configuration);
+                    s.setInterface(m_provide, serviceProperties);
+                }
+
+                s.setComposition(m_srvMeta.getString(Params.composition, null));
+                ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(s, m_bundle, m_dm,
+                    m_srvMeta, m_depsMeta);
+                // The dependencies will be plugged by our lifecycle handler.
+                s.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+
+                // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+                for (MetaData dependency: m_depsMeta)
+                {
+                    String name = dependency.getString(Params.name, null);
+                    if (name == null)
+                    {
+                        DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                        Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s",
+                                            dependency, m_srvMeta);
+                        Dependency d = depBuilder.build(m_bundle, m_dm);
+                        s.add(d);
+                    }
+                }
+
+                // Register the Service instance, and keep track of it.
+                Log.instance().info("ServiceFactory: created service %s", m_srvMeta);
+                m_dm.add(s);
+                m_services.put(serviceKey, s);
+            }
+            catch (Throwable t)
+            {
+                // Make sure the SERVICE_CREATING flag is also removed
+                m_services.remove(serviceKey);
+                Log.instance().error("ServiceFactory: could not instantiate service %s",
+                                     t, m_srvMeta);
+            }
+        }
+        else
+        {
+            // Reconfigure an already existing Service.
+            if (m_configure != null)
+            {
+                Log.instance().info("ServiceFactory: updating service %s", m_impl);
+                invokeConfigure(m_impl, m_configure, configuration);
+            }
+
+            // Update service properties
+            if (m_provide != null)
+            {
+                Dictionary settings = mergeSettings(m_serviceProperties, configuration);
+                ((Component) service).setServiceProperties(settings);
+            }
+        }
+    }
+
+    private void doRemove(Dictionary configuraton)
+    {
+        Log.instance().info("ServiceFactory: removing service %s", m_srvMeta);
+        ServiceKey serviceKey = new ServiceKey(configuraton);
+        Object service = m_services.remove(serviceKey);
+        if (service != null && service != SERVICE_CREATING)
+        {
+            m_dm.remove((Component) service);
+        }
+    }
+
+    private void doClear()
+    {
+        for (Object service : m_services.values())
+        {
+            if (service instanceof Component)
+            {
+                m_dm.remove((Component) service);
+            }
+        }
+        m_services.clear();
+    }
+
+    /**
+     * Merge factory configuration settings with the service properties. The private factory configuration 
+     * settings are ignored. A factory configuration property is private if its name starts with a dot (".").
+     * 
+     * @param serviceProperties
+     * @param factoryConfiguration
+     * @return
+     */
+    private Dictionary mergeSettings(Dictionary serviceProperties, Dictionary factoryConfiguration)
+    {
+        Dictionary props = new Hashtable();
+
+        if (serviceProperties != null)
+        {
+            Enumeration keys = serviceProperties.keys();
+            while (keys.hasMoreElements())
+            {
+                Object key = keys.nextElement();
+                Object val = serviceProperties.get(key);
+                props.put(key, val);
+            }
+        }
+
+        Enumeration keys = factoryConfiguration.keys();
+        while (keys.hasMoreElements())
+        {
+            Object key = keys.nextElement();
+            if (!key.toString().startsWith("."))
+            {
+                // public properties are propagated
+                Object val = factoryConfiguration.get(key);
+                props.put(key, val);
+            }
+        }
+        return props;
+    }
+
+    /**
+     * Invokes the configure callback method on the service instance implemenatation.
+     * @param impl
+     * @param configure
+     * @param config
+     */
+    private void invokeConfigure(Object impl, String configure, Dictionary config)
+    {
+        try
+        {
+            InvocationUtil.invokeCallbackMethod(impl, configure,
+                                                new Class[][] { { Dictionary.class } },
+                                                new Object[][] { { config } });
+        }
+
+        catch (Throwable t)
+        {
+            if (t instanceof RuntimeException)
+            {
+                throw (RuntimeException) t;
+            }
+            else
+            {
+                throw new RuntimeException("Could not invoke method " + configure
+                                           + " on object " + impl, t);
+            }
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java
new file mode 100644
index 0000000..fb4456b
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Java reflexion utility methods.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class InvocationUtil
+{
+    public static Object invokeCallbackMethod(Object instance,
+                                              String methodName,
+                                              Class<?>[][] signatures,
+                                              Object[][] parameters)
+        throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
+        InvocationTargetException
+    {
+        Class<?> currentClazz = instance.getClass();
+        while (currentClazz != null)
+        {
+            try
+            {
+                return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+            }
+            catch (NoSuchMethodException nsme)
+            {
+                // ignore
+            }
+            currentClazz = currentClazz.getSuperclass();
+        }
+        throw new NoSuchMethodException(methodName);
+    }
+
+    public static Object invokeMethod(Object object,
+                                      Class<?> clazz,
+                                      String name,
+                                      Class<?>[][] signatures,
+                                      Object[][] parameters,
+                                      boolean isSuper)
+        throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException,
+        IllegalAccessException
+    {
+        if (object == null)
+        {
+            throw new IllegalArgumentException("Instance cannot be null");
+        }
+        if (clazz == null)
+        {
+            throw new IllegalArgumentException("Class cannot be null");
+        }
+
+        // If we're talking to a proxy here, dig one level deeper to expose the
+        // underlying invocation handler ...
+
+        if (Proxy.isProxyClass(clazz))
+        {
+            object = Proxy.getInvocationHandler(object);
+            clazz = object.getClass();
+        }
+
+        for (int i = 0; i < signatures.length; i++)
+        {
+            Class<?>[] signature = signatures[i];
+            try
+            {
+                final Method m = clazz.getDeclaredMethod(name, signature);
+                if (!(isSuper && Modifier.isPrivate(m.getModifiers())))
+                {
+                    AccessController.doPrivileged(new PrivilegedAction<Object>()
+                    {
+                        public Object run()
+                        {
+                            m.setAccessible(true);
+                            return null;
+                        }
+                    });
+                    return m.invoke(object, parameters[i]);
+                }
+            }
+            catch (NoSuchMethodException e)
+            {
+                // ignore this and keep looking
+            }
+        }
+        throw new NoSuchMethodException(name);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/JSONMetaData.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/JSONMetaData.java
new file mode 100644
index 0000000..0548394
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/JSONMetaData.java
@@ -0,0 +1,482 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.Array;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Thsi class represents the parsed data found from meta-inf dependencymanager descriptors.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class JSONMetaData implements MetaData, Cloneable
+{
+    /**
+     * The parsed Dependency or Service metadata. The map value is either a String, a String[],
+     * or a Dictionary, whose values are String or String[]. 
+     */
+    private HashMap<String, Object> m_metadata = new HashMap<String, Object>();
+
+    /**
+     * Decodes Json metadata for either a Service or a Dependency descriptor entry.
+     * The JSON object has the following form:
+     * 
+     * entry            ::= String | String[] | dictionary
+     * dictionary       ::= key-value-pair*
+     * key-value-pair   ::= key value
+     * value            ::= String | String[] | value-type
+     * value-type       ::= jsonObject with value-type-info
+     * value-type-info  ::= "type"=primitive java type
+     *                      "value"=String|String[]
+     *                      
+     * Exemple:
+     * 
+     * {"string-param" : "string-value",
+     *  "string-array-param" : ["string1", "string2"],
+     *  "properties" : {
+     *      "string-param" : "string-value",
+     *      "string-array-param" : ["str1", "str2],
+     *      "long-param" : {"type":"java.lang.Long", "value":"1"}}
+     *      "long-array-param" : {"type":"java.lang.Long", "value":["1"]}}
+     *  }
+     * }
+     *   
+     * @param jso the JSON object that corresponds to a dependency manager descriptor entry line.
+     * @throws JSONException 
+     */
+    @SuppressWarnings("unchecked")
+    public JSONMetaData(JSONObject jso) throws JSONException
+    {
+        // Decode json object into our internal map.
+        Iterator<String> it = jso.keys();
+        while (it.hasNext())
+        {
+            String key = it.next();
+            Object value = jso.get(key);
+            if (value instanceof String)
+            {
+                m_metadata.put(key, value);
+            }
+            else if (value instanceof JSONArray)
+            {
+                m_metadata.put(key, decodeStringArray((JSONArray) value));
+            }
+            else if (value instanceof JSONObject)
+            {
+                m_metadata.put(key, parseProperties((JSONObject) value));
+            }
+        }
+    }
+
+    private Hashtable<String, Object> parseProperties(JSONObject properties) throws JSONException {
+        Hashtable<String, Object> parsedProps = new Hashtable<String, Object>();
+        @SuppressWarnings("unchecked")
+        Iterator<String> it = properties.keys();
+        while (it.hasNext())
+        {
+            String key = it.next();
+            Object value = properties.get(key);
+            if (value instanceof String)
+            {
+                // This property type is a simple string
+                parsedProps.put(key, value);
+            }
+            else if (value instanceof JSONArray)
+            {
+                // This property type is a simple string array
+                parsedProps.put(key, decodeStringArray((JSONArray) value));
+            }
+            else if (value instanceof JSONObject)
+            {
+                // This property type is a typed value, encoded as a JSONObject with two keys: "type"/"value"
+                JSONObject json = ((JSONObject) value);
+                String type = json.getString("type");
+                Object typeValue = json.get("value");
+
+                if (type == null)
+                {
+                    throw new JSONException("missing type attribute in json metadata for key " + key);
+                }
+                if (typeValue == null)
+                {
+                    throw new JSONException("missing type value attribute in json metadata for key " + key);
+                }
+
+                Class<?> typeClass;
+                try
+                {
+                    typeClass = Class.forName(type);
+                }
+                catch (ClassNotFoundException e)
+                {
+                    throw new JSONException("invalid type attribute (" + type + ") in json metadata for key "
+                        + key);
+                }
+
+                if (typeValue instanceof JSONArray)
+                {
+                    parsedProps.put(key, toPrimitiveTypeArray(typeClass, (JSONArray) typeValue));
+                }
+                else
+                {
+                    parsedProps.put(key, toPrimitiveType(typeClass, typeValue.toString()));
+                }
+            }
+        }
+        return parsedProps;
+    }
+
+    private Object toPrimitiveType(Class<?> type, String value) throws JSONException {
+        if (type.equals(String.class))
+        {
+            return value;
+        }
+        else if (type.equals(Long.class))
+        {
+            return Long.parseLong(value);
+        }
+        else if (type.equals(Double.class))
+        {
+            return Double.valueOf(value);
+        }
+        else if (type.equals(Float.class))
+        {
+            return Float.valueOf(value);
+        }
+        else if (type.equals(Integer.class))
+        {
+            return Integer.valueOf(value);
+        }
+        else if (type.equals(Byte.class))
+        {
+            return Byte.valueOf(value);
+        }
+        else if (type.equals(Character.class))
+        {
+            return Character.valueOf((char) Integer.parseInt(value));
+        }
+        else if (type.equals(Boolean.class))
+        {
+            return Boolean.valueOf(value);
+        }
+        else if (type.equals(Short.class))
+        {
+            return Short.valueOf(value);
+        }
+        else
+        {
+            throw new JSONException("invalid type (" + type + ") attribute in json metadata");
+        }
+    }
+
+    private Object toPrimitiveTypeArray(Class<?> type, JSONArray array) throws JSONException {
+        int len = array.length();
+        Object result = Array.newInstance(type, len);
+
+        if (type.equals(String.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, array.getString(i));
+            }
+        } 
+        else if (type.equals(Long.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Long.valueOf(array.getString(i)));
+            }
+        }
+        else if (type.equals(Double.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Double.valueOf(array.getString(i)));
+            }
+        } 
+        else if (type.equals(Float.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Float.valueOf(array.getString(i)));
+            }
+        }
+        else if (type.equals(Integer.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Integer.valueOf(array.getString(i)));
+            }
+        }
+        else if (type.equals(Byte.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Byte.valueOf(array.getString(i)));
+            }
+        }
+        else if (type.equals(Character.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i,  Character.valueOf((char) Integer.parseInt(array.getString(i))));
+            }
+        }
+        else if (type.equals(Boolean.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Boolean.valueOf(array.getString(i)));
+            }
+        } 
+        else if (type.equals(Short.class))
+        {
+            for (int i = 0; i < len; i ++) {
+                Array.set(result, i, Short.valueOf(array.getString(i)));
+            }
+        }
+        else 
+        {
+            throw new JSONException("invalid type (" + type + ") attribute in json metadata");
+        }   
+        return result;
+    }
+
+    /**
+     * Close this class instance to another one.
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone() throws CloneNotSupportedException
+    {
+        JSONMetaData clone = (JSONMetaData) super.clone();
+        clone.m_metadata = (HashMap<String, Object>) m_metadata.clone();
+        return clone;
+    }
+
+    public String getString(Params key)
+    {
+        Object value = m_metadata.get(key.toString());
+        if (value == null)
+        {
+            throw new IllegalArgumentException("Parameter " + key + " not found");
+        }
+        return value.toString();
+    }
+
+    public String getString(Params key, String def)
+    {
+        try
+        {
+            return getString(key);
+        }
+        catch (IllegalArgumentException e)
+        {
+            return def;
+        }
+    }
+
+    public int getInt(Params key)
+    {
+        Object value = m_metadata.get(key.toString());
+        if (value != null)
+        {
+            try
+            {
+                if (value instanceof Integer) {
+                    return ((Integer) value).intValue();
+                }
+                return Integer.parseInt(value.toString());
+            }
+            catch (NumberFormatException e)
+            {
+                throw new IllegalArgumentException("parameter " + key
+                    + " is not an int value: "
+                    + value);
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("missing " + key
+                + " parameter from annotation");
+        }
+    }
+
+    public int getInt(Params key, int def)
+    {
+        Object value = m_metadata.get(key.toString());
+        if (value != null)
+        {
+            try
+            {
+                if (value instanceof Integer) {
+                    return ((Integer) value).intValue();
+                }
+                return Integer.parseInt(value.toString());
+            }
+            catch (NumberFormatException e)
+            {
+                throw new IllegalArgumentException("parameter " + key
+                    + " is not an int value: "
+                    + value);
+            }
+        }
+        else
+        {
+            return def;
+        }
+    }
+
+    public long getLong(Params key)
+    {
+        Object value = m_metadata.get(key.toString());
+        if (value != null)
+        {
+            try
+            {
+                if (value instanceof Long) {
+                    return ((Long) value).longValue();
+                }
+                return Long.parseLong(value.toString());
+            }
+            catch (NumberFormatException e)
+            {
+                throw new IllegalArgumentException("parameter " + key
+                    + " is not a long value: "
+                    + value);
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("missing " + key
+                + " parameter from annotation");
+        }
+    }
+
+    public long getLong(Params key, long def)
+    {
+        Object value = m_metadata.get(key.toString());
+        if (value != null)
+        {
+            try
+            {
+                if (value instanceof Long) {
+                    return (Long) value;
+                }
+                return Long.parseLong(value.toString());
+            }
+            catch (NumberFormatException e)
+            {
+                throw new IllegalArgumentException("parameter " + key
+                    + " is not a long value: "
+                    + value);
+            }
+        }
+        else
+        {
+            return def;
+        }
+    }
+
+    public String[] getStrings(Params key)
+    {
+        Object array = m_metadata.get(key.toString());
+        if (array == null)
+        {
+            throw new IllegalArgumentException("Parameter " + key + " not found");
+        }
+
+        if (!(array instanceof String[]))
+        {
+            throw new IllegalArgumentException("Parameter " + key + " is not a String[] (" + array.getClass()
+                + ")");
+        }
+        return (String[]) array;
+    }
+
+    public String[] getStrings(Params key, String[] def)
+    {
+        try
+        {
+            return getStrings(key);
+        }
+        catch (IllegalArgumentException t)
+        {
+            return def;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Dictionary<String, Object> getDictionary(Params key,
+        Dictionary<String, Object> def)
+    {
+        Object dictionary = m_metadata.get(key.toString());
+        if (dictionary == null)
+        {
+            return def;
+        }
+
+        if (!(dictionary instanceof Dictionary<?, ?>))
+        {
+            throw new IllegalArgumentException("Parameter " + key + " is not a Dictionary ("
+                + dictionary.getClass() + ")");
+        }
+
+        return (Dictionary<String, Object>) dictionary;
+    }
+
+    @Override
+    public String toString()
+    {
+        return m_metadata.toString();
+    }
+
+    public void setDictionary(Params key, Dictionary<String, Object> dictionary)
+    {
+        m_metadata.put(key.toString(), dictionary);
+    }
+
+    public void setString(Params key, String value)
+    {
+        m_metadata.put(key.toString(), value);
+    }
+
+    public void setStrings(Params key, String[] values)
+    {
+        m_metadata.put(key.toString(), values);
+    }
+    
+    /**
+     * Decodes a JSONArray into a String array (all JSON array values are supposed to be strings).
+     */
+    private String[] decodeStringArray(JSONArray array) throws JSONException
+    {
+        String[] arr = new String[array.length()];
+        for (int i = 0; i < array.length(); i++)
+        {
+            Object value = array.get(i);
+            if (!(value instanceof String))
+            {
+                throw new IllegalArgumentException("JSON array is not an array of Strings: " + array);
+            }
+            arr[i] = value.toString();
+        }
+        return arr;
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Log.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Log.java
new file mode 100644
index 0000000..f23ba0e
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Log.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import org.osgi.service.log.LogService;
+
+/**
+ * This class logs some formattable strings into the OSGi Log Service.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Log
+{
+    /** The wrap log service which is actually used (Injected by Activator) */
+    private volatile LogService m_logService;
+    
+    /** Our sole instance */
+    private static Log m_instance = new Log();
+    
+    public static Log instance()
+    {
+        return m_instance;
+    }
+    
+    public void error(String format, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_ERROR, String.format(format, args));
+    }
+    
+    public void error(String format, Throwable t, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_ERROR, String.format(format, args), t);
+    }
+    
+    public void warn(String format, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_WARNING, String.format(format, args));
+    }
+    
+    public void warn(String format, Throwable t, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_WARNING, String.format(format, args), t);
+    }
+    
+    public void info(String format, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_INFO, String.format(format, args));
+    }
+    
+    public void info(String format, Throwable t, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_INFO, String.format(format, args), t);
+    }
+    
+    public void debug(String format, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_DEBUG, String.format(format, args));
+    }
+    
+    public void debug(String format, Throwable t, Object ... args) 
+    {
+        m_logService.log(LogService.LOG_DEBUG, String.format(format, args), t);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/MetaData.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/MetaData.java
new file mode 100644
index 0000000..435f958
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/MetaData.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+
+/**
+ * This class represents the meta data parsed from a descriptor entry (json) line.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface MetaData extends Cloneable
+{
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    String getString(Params key);
+
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    String getString(Params key, String def);
+
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    int getInt(Params key);
+
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    int getInt(Params key, int def);
+    
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    long getLong(Params key);
+
+    /**
+     * Returns a String descriptor entry parameter value.
+     */
+    long getLong(Params key, long def);
+
+    /**
+     * Returns a String array descriptor entry parameter value.
+     */
+    String[] getStrings(Params key);
+
+    /**
+     * Returns a String array descriptor entry parameter value.
+     */
+    String[] getStrings(Params key, String[] def);
+
+    /**
+     * Returns a descriptor entry value which is a complex value.
+     */
+    Dictionary<String, Object> getDictionary(Params key, Dictionary<String, Object> def);
+    
+    /**
+     * Modifies a key Sring value
+     */
+    void setString(Params key, String value);
+    
+    /**
+     * Modifies a String[] value.
+     */
+    void setStrings(Params key, String[] values);
+    
+    /**
+     * Modifies a String[] value.
+     */
+    void setDictionary(Params key, Dictionary<String, Object> dictionary);
+    
+    /**
+     * Clone this MetaData object.
+     */
+    Object clone() throws CloneNotSupportedException;
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java
new file mode 100644
index 0000000..37f251f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+/**
+ * List of descriptor parameters.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public enum Params
+{
+    type,
+    init,
+    start,
+    stop,
+    destroy,
+    impl,
+    provides,
+    properties,
+    composition,
+    service,
+    filter,
+    defaultImpl,
+    required,
+    added,
+    changed,
+    removed,
+    swap,
+    autoConfig,
+    pid,
+    propagate,
+    updated,
+    timeout,
+    adapteeService,
+    adapteeFilter,
+    stateMask,
+    ranking,
+    factoryPid,    
+    factorySet,
+    factoryName,
+    factoryConfigure,
+    factoryMethod,
+    name,
+    field,
+    starter,
+    stopper, 
+    bundleContextField, 
+    dependencyManagerField, 
+    componentField,
+    registered, 
+    unregistered
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
new file mode 100644
index 0000000..7174396
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build a resource adapter service using metadata found from DependencyManager runtime
+ * meta-inf descriptor.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResourceAdapterServiceBuilder extends AbstractBuilder
+{
+    private final static String TYPE = "ResourceAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void build(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm) 
+        throws Exception
+    {
+        String filter = srvMeta.getString(Params.filter, null);
+        Class<?> implClass = b.loadClass(srvMeta.getString(Params.impl));
+        String[] provides = srvMeta.getStrings(Params.provides, null);
+        Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
+        String changed = srvMeta.getString(Params.changed, null /* no change callback if not specified explicitly */);
+        Component c = dm.createResourceAdapterService(filter, propagate, null, changed);
+        c.setInterface(provides, properties);
+        String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+        if (factoryMethod == null)
+        {
+            c.setImplementation(implClass);
+        } 
+        else
+        {
+            c.setFactory(implClass, factoryMethod);
+        }
+        setCommonServiceParams(c, srvMeta);
+        c.setComposition(srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(c, b, dm, srvMeta, depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        c.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        addUnamedDependencies(b, dm, c, srvMeta, depsMeta);
+        dm.add(c);
+    }    
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/SerialExecutor.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/SerialExecutor.java
new file mode 100644
index 0000000..b7dae8f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/SerialExecutor.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+
+/**
+ * Allows you to enqueue tasks from multiple threads and then execute
+ * them on one thread sequentially. It assumes more than one thread will
+ * try to execute the tasks and it will make an effort to pick the first
+ * task that comes along whilst making sure subsequent tasks return
+ * without waiting.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class SerialExecutor {
+	private static final Runnable DUMMY_RUNNABLE = new Runnable() { public void run() {} };
+    private final LinkedList<Runnable> m_workQueue = new LinkedList<>();
+    private Runnable m_active;
+    
+    /**
+     * Enqueue a new task for later execution. This method is
+     * thread-safe, so multiple threads can contribute tasks.
+     * 
+     * @param runnable the runnable containing the actual task
+     */
+    public synchronized void enqueue(final Runnable runnable) {
+    	m_workQueue.addLast(new Runnable() {
+			public void run() {
+				try {
+					runnable.run();
+				}
+				finally {
+					scheduleNext();
+				}
+			}
+		});
+    }
+    
+    /**
+     * Execute any pending tasks. This method is thread safe,
+     * so multiple threads can try to execute the pending
+     * tasks, but only the first will be used to actually do
+     * so. Other threads will return immediately.
+     */
+    public void execute() {
+    	Runnable active;
+    	synchronized (this) {
+    		active = m_active;
+    		// for now just put some non-null value in there so we can never
+    		// get a race condition when two threads enter this section after
+    		// one another (causing sheduleNext() to be invoked twice below)
+    		m_active = DUMMY_RUNNABLE;
+    	}
+    	if (active == null) {
+    		scheduleNext();
+    	}
+    }
+
+    private void scheduleNext() {
+    	Runnable active;
+    	synchronized (this) {
+    		try {
+    			m_active = (Runnable) m_workQueue.removeFirst();
+    		}
+    		catch (NoSuchElementException e) {
+    			m_active = null;
+    		}
+    		active = m_active;
+    	}
+    	if (active != null) {
+            active.run();
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
new file mode 100644
index 0000000..4058988
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
@@ -0,0 +1,456 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Caution: this class *MUST* be immutable, because it may be shared between Aspects/Adapters 
+ * and concrete Aspect/Adapter instance.
+ * 
+ * This class allows Services to configure dynamically their dependency filters from their init() method.
+ * Basically, this class acts as a service implementation lifecycle handler. When we detect that the Service is
+ * called in its init() method, and if init() returns a Map, then the Map is assumed to contain
+ * dependency filters, which will be applied to all named dependencies. The Map optionally returned by
+ * Service's init method may contain the following keys:
+ * <ul>
+ *   <li>name.filter: the value must be a valid OSGi filter, and the "name" prefix must match a ServiceDependency 
+ *   name attribute</li>
+ *   <li>name.required: the value is a boolean ("true"|"false") and the "name" prefix must match a 
+ *   ServiceDependency name attribute</li>
+ * </ul>
+ * 
+ * <p>Dependencies which provide a name attribute will be activated after the init method returns. Other
+ * dependencies are injected before the init method.
+ * 
+ * <p>Example of a Service whose dependency filter is configured from ConfigAdmin:
+ * 
+ * <blockquote><pre>
+ *  &#47;**
+ *    * A Service whose service dependency filter/require attribute may be configured from ConfigAdmin
+ *    *&#47;
+ *  &#64;Service
+ *  class X {
+ *      private Dictionary m_config;
+ *      
+ *      &#64;ConfigurationDependency(pid="MyPid")
+ *      void configure(Dictionary conf) {
+ *           // Initialize our service from config ...
+ *           
+ *           // And store the config for later usage (from our init method)
+ *           m_config = config;
+ *      }
+ *      
+ *      &#64;ServiceDependency(name="dependency1") 
+ *      void bindOtherService(OtherService other) {
+ *         // the filter and required flag will be configured from our init method.
+ *      }
+ *
+ *      // The returned Map will be used to configure our "dependency1" Dependency.
+ *      &#64;Init
+ *      Map init() {
+ *          return new HashMap() {{
+ *              put("dependency1.filter", m_config.get("filter"));
+ *              put("dependency1.required", m_config.get("required"));
+ *          }};
+ *      } 
+ *  }
+ *  </pre></blockquote>
+ *  
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceLifecycleHandler
+{
+    private final String m_init;
+    private final String m_start;
+    private final String m_stop;
+    private final String m_destroy;
+    private final MetaData m_srvMeta;
+    private final List<MetaData> m_depsMeta;
+    private final Bundle m_bundle;
+    private final static Object SYNC = new Object();
+
+    /**
+     * Makes a new ServiceLifecycleHandler object. This objects allows to decorate the "init" service callback, in
+     * order to see if "init" callback returns a dependency customization map.
+     * 
+     * @param srv The Service for the annotated class
+     * @param srvBundle the Service bundle
+     * @param dm The DependencyManager that was used to create the service
+     * @param srvMeta The Service MetaData
+     * @param depMeta The Dependencies MetaData
+     */
+    public ServiceLifecycleHandler(Component srv, Bundle srvBundle, DependencyManager dm,
+                                   MetaData srvMeta, List<MetaData> depMeta)
+    {
+        m_srvMeta = srvMeta;
+        m_init = srvMeta.getString(Params.init, null);
+        m_start = srvMeta.getString(Params.start, null);
+        m_stop = srvMeta.getString(Params.stop, null);
+        m_destroy = srvMeta.getString(Params.destroy, null);
+        m_bundle = srvBundle;
+        m_depsMeta = depMeta;
+    }
+
+    /**
+     * Handles an "init" lifecycle service callback. We just catch the "init" method, and callback 
+     * the actual Service' init method, to see if a dependency customization map is returned.
+     * We also check if a Lifecycle Controller is used. In this case, we add a hidden custom dependency,
+     * allowing to take control of when the component is actually started/stopped.
+     * We also handle an edge case described in FELIX-4050, where component state calculation 
+     * may mess up if some dependencies are added using the API from the init method.
+     * 
+     * @param c The Annotated Component
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void init(Component c)
+        throws Exception
+    {
+        Object serviceInstance = c.getInstances()[0];
+        DependencyManager dm = c.getDependencyManager();
+
+        // Check if a lifecycle controller is defined for this service. If true, then 
+        // We'll use the ToggleServiceDependency in order to manually activate/deactivate 
+        // the component ...
+        String starter = m_srvMeta.getString(Params.starter, null);
+        String stopper = m_srvMeta.getString(Params.stopper, null);
+
+        List<Dependency> instanceBoundDeps = new ArrayList<>();
+            
+        if (starter != null)
+        {
+            // We'll inject two runnables: one that will start or service, when invoked, and the other
+            // that will stop our service, when invoked. We'll use a shared atomic boolean in order to
+            // synchronize both runnables.
+            Log.instance().debug("Setting up a lifecycle controller for service %s", serviceInstance);
+            String componentName = serviceInstance.getClass().getName();
+            // Create a toggle service, used to start/stop our service.
+            ToggleServiceDependency toggle = new ToggleServiceDependency();
+            AtomicBoolean startFlag = new AtomicBoolean(false);
+            // Add the toggle to the service.
+            instanceBoundDeps.add(toggle);
+            // Inject the runnable that will start our service, when invoked.
+            setField(serviceInstance, starter, Runnable.class, new ComponentStarter(componentName, toggle, startFlag));
+            if (stopper != null) {
+                // Inject the runnable that will stop our service, when invoked.
+                setField(serviceInstance, stopper, Runnable.class, new ComponentStopper(componentName, toggle, startFlag));
+            }
+        }
+
+        // Before invoking an optional init method, we have to handle an edge case (FELIX-4050), where
+        // init may add dependencies using the API and also return a map for configuring some
+        // named dependencies. We have to add a hidden toggle dependency in the component, which we'll 
+        // active *after* the init method is called, and possibly *after* named dependencies are configured.
+        
+        ToggleServiceDependency initToggle = null;
+        if (m_init != null) 
+        {
+            initToggle = new ToggleServiceDependency();
+            c.add(initToggle); 
+        }
+        
+        // Invoke component and all composites init methods, and for each one, check if a dependency
+        // customization map is returned by the method. This map will be used to configure 
+        // some dependency filters (or required flag).
+
+        Map<String, String> customization = new HashMap<String, String>();
+        Object[] composites = c.getInstances();
+        for (Object composite: composites)
+        {
+            Object o = invokeMethod(composite, m_init, dm, c);
+            if (o != null && Map.class.isAssignableFrom(o.getClass()))
+            {
+                customization.putAll((Map) o);
+            }
+        }
+
+        Log.instance().debug("ServiceLifecycleHandler.init: invoked init method from service %s " +
+                             ", returned map: %s", serviceInstance, customization);
+        
+        // Apply name dependency filters possibly returned by the init() method.
+        
+        for (MetaData dependency: m_depsMeta)
+        {
+            // Check if this dependency has a name, and if we find the name from the 
+            // customization map, then apply filters and required flag from the map into it.
+            // Also parse optional pid/propagate flags for named Configuration dependencies
+
+            String name = dependency.getString(Params.name, null);
+            if (name != null)
+            {
+                String filter = customization.get(name + ".filter");
+                String required = customization.get(name + ".required");
+                String pid = customization.get(name + ".pid");
+                String propagate = customization.get(name + ".propagate");
+
+                if (filter != null || required != null || pid != null || propagate != null)
+                {
+                    dependency = (MetaData) dependency.clone();
+                    if (filter != null)
+                    {
+                        dependency.setString(Params.filter, filter);
+                    }
+                    if (required != null)
+                    {
+                        dependency.setString(Params.required, required);
+                    }
+                    if (pid != null)
+                    {
+                        dependency.setString(Params.pid, pid);
+                    }
+                    if (propagate != null)
+                    {
+                        dependency.setString(Params.propagate, propagate);
+                    }
+                }
+
+                DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s",
+                                   dependency, m_srvMeta);
+                Dependency d = depBuilder.build(m_bundle, dm);
+                instanceBoundDeps.add(d);
+            }            
+        }
+        
+        // Add all extra dependencies in one shot, in order to calculate state changes for all dependencies at a time.
+        if (instanceBoundDeps.size() > 0) 
+        {
+            Log.instance().info("ServiceLifecycleHandler.init: adding extra/named dependencies %s",
+                instanceBoundDeps);
+            c.add(instanceBoundDeps.toArray(new Dependency[instanceBoundDeps.size()]));
+        }    
+
+        // init method fully handled, and all possible named dependencies have been configured. Now, activate the 
+        // hidden toggle, and then remove it from the component, because we don't need it anymore.
+        if (initToggle != null) 
+        {
+            c.remove(initToggle);
+        } 
+    }
+
+    /**
+     * Handles the Service's start lifecycle callback. We just invoke the service "start" service callback on 
+     * the service instance, as well as on all eventual service composites.
+     * We take care to check if a start callback returns a Map, which is meant to contain
+     * some additional properties which must be appended to existing service properties.
+     * Such extra properties takes precedence over existing service properties.
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void start(Component service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        // Check if some extra service properties are returned by start method.
+        
+        DependencyManager dm = service.getDependencyManager();
+        Map<String, String> extraProperties = new HashMap<String, String>();
+        Object[] composites = service.getInstances();
+        for (Object composite: composites)
+        {
+            Object o = invokeMethod(composite, m_start, dm, service);
+            if (o != null && Map.class.isAssignableFrom(o.getClass()))
+            {
+                extraProperties.putAll((Map) o);
+            }
+        }
+
+        if (extraProperties.size() > 0)
+        {
+            // Store extra properties returned by start callbacks into existing service properties
+            Dictionary existingProperties = service.getServiceProperties();
+            if (existingProperties != null)
+            {
+                Hashtable props = new Hashtable();
+                Enumeration e = existingProperties.keys();
+                while (e.hasMoreElements())
+                {
+                    Object key = e.nextElement();
+                    props.put(key, existingProperties.get(key));
+                }
+                props.putAll(extraProperties);
+                service.setServiceProperties(props);
+            }
+            else
+            {
+                service.setServiceProperties(new Hashtable(extraProperties));
+            }
+        }        
+    }
+
+    /**
+     * Handles the Service's stop lifecycle callback. We just invoke the service "stop" callback on 
+     * the service instance, as well as on all eventual service composites.
+     */
+    public void stop(Component service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        callbackComposites(service, m_stop);
+    }
+
+    /**
+     * Handles the Service's destroy lifecycle callback. We just invoke the service "destroy" callback on 
+     * the service instance, as well as on all eventual service composites.
+     */
+    public void destroy(Component service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        callbackComposites(service, m_destroy);
+    }
+
+    /**
+     * Invoke a callback on all Service compositions.
+     */
+    private void callbackComposites(Component service, String callback)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        Object[] composites = service.getInstances();
+        for (Object composite: composites)
+        {
+            invokeMethod(composite, callback, service.getDependencyManager(), service);
+        }
+    }
+
+    /**
+     * Invoke a callback on an Object instance.
+     */
+    private Object invokeMethod(Object serviceInstance, String method, DependencyManager dm, Component c)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        if (method != null)
+        {
+            try
+            {
+                return InvocationUtil.invokeCallbackMethod(serviceInstance, method,
+                                                           new Class[][] { { Component.class }, {} },
+                                                           new Object[][] { { c }, {} }
+                    );
+            }
+
+            catch (NoSuchMethodException e)
+            {
+                // ignore this
+            }
+
+            // Other exception will be thrown up to the ServiceImpl.invokeCallbackMethod(), which is 
+            // currently invoking our method. So, no need to log something here, since the invokeCallbackMethod 
+            // method is already logging any thrown exception.
+        }
+        return null;
+    }
+
+    /**
+     * Sets a field of an object by reflexion.
+     */
+    private void setField(Object instance, String fieldName, Class<?> fieldClass, Object fieldValue)
+    {
+        Object serviceInstance = instance;
+        Class<?> serviceClazz = serviceInstance.getClass();
+        if (Proxy.isProxyClass(serviceClazz))
+        {
+            serviceInstance = Proxy.getInvocationHandler(serviceInstance);
+            serviceClazz = serviceInstance.getClass();
+        }
+        while (serviceClazz != null)
+        {
+            Field[] fields = serviceClazz.getDeclaredFields();
+            for (int j = 0; j < fields.length; j++)
+            {
+                Field field = fields[j];
+                Class<?> type = field.getType();
+                if (field.getName().equals(fieldName) && type.isAssignableFrom(fieldClass))
+                {
+                    try
+                    {
+                        field.setAccessible(true);
+                        // synchronized makes sure the field is actually written to immediately
+                        synchronized (SYNC)
+                        {
+                            field.set(serviceInstance, fieldValue);
+                        }
+                    }
+                    catch (Throwable e)
+                    {
+                        throw new RuntimeException("Could not set field " + field, e);
+                    }
+                }
+            }
+            serviceClazz = serviceClazz.getSuperclass();
+        }
+    }
+    
+    private static class ComponentStarter implements Runnable {
+        private final String m_componentName;
+        private final ToggleServiceDependency m_toggle;
+        private final AtomicBoolean m_startFlag;
+
+        public ComponentStarter(String name, ToggleServiceDependency toggle, AtomicBoolean startFlag)
+        {
+            m_componentName = name;
+            m_toggle = toggle;
+            m_startFlag = startFlag;
+        }
+
+        @SuppressWarnings("synthetic-access")
+        public void run()
+        {
+            if (m_startFlag.compareAndSet(false, true)) {
+                Log.instance().debug("Lifecycle controller is activating the component %s",
+                                     m_componentName);
+                m_toggle.activate(true);
+            }
+        }
+    }
+    
+    private static class ComponentStopper implements Runnable {
+        private final Object m_componentName;
+        private final ToggleServiceDependency m_toggle;
+        private final AtomicBoolean m_startFlag;
+
+        public ComponentStopper(String componentName, ToggleServiceDependency toggle, AtomicBoolean startFlag)
+        {
+            m_componentName = componentName;
+            m_toggle = toggle;
+            m_startFlag = startFlag;
+        }
+
+        @SuppressWarnings("synthetic-access")
+        public void run()
+        {
+            if (m_startFlag.compareAndSet(true, false)) {
+                Log.instance().debug("Lifecycle controller is deactivating the component %s",
+                                    m_componentName);
+                m_toggle.activate(false);
+            }
+        }
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ToggleServiceDependency.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ToggleServiceDependency.java
new file mode 100644
index 0000000..43adcd3
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ToggleServiceDependency.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import org.apache.felix.dm.context.AbstractDependency;
+import org.apache.felix.dm.context.DependencyContext;
+import org.apache.felix.dm.context.Event;
+import org.apache.felix.dm.context.EventType;
+
+/**
+ * This is a custom DependencyManager Dependency, allowing to take control of
+ * when the dependency is available or not. It's used in the context of the
+ * LifecycleController class, in order to activate/deactivate a Component on
+ * demand.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ToggleServiceDependency extends AbstractDependency<ToggleServiceDependency> {    
+    public ToggleServiceDependency() {
+        super.setRequired(true);
+    }
+
+    public ToggleServiceDependency(ToggleServiceDependency prototype) {
+        super(prototype);
+    }
+
+    @Override
+    public DependencyContext createCopy() {
+        return new ToggleServiceDependency(this);
+    }
+
+    public void activate(boolean active) {
+        m_component.handleEvent(this, active ? EventType.ADDED : EventType.REMOVED, new Event(active));
+    }
+
+    @Override
+    public String getSimpleName() {
+        return "" + isAvailable();
+    }
+
+    @Override
+    public String getType() {
+        return "toggle";
+    }
+
+    @Override
+    public Class<?> getAutoConfigType() {
+        return null; // we don't support auto config mode.
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java
new file mode 100644
index 0000000..1a05f6f
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime.api;
+
+/**
+ * Exception thrown when a Component can't be instantiated using a {@link ComponentFactory#newInstance(java.util.Dictionary)} 
+ * service.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@SuppressWarnings("serial")
+public class ComponentException extends RuntimeException {
+    public ComponentException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java
new file mode 100644
index 0000000..26e42d2
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime.api;
+
+import java.util.Dictionary;
+
+/**
+ * When a Component is annotated with a DM "Component" annotation with a "factoryName" attribute, a corresponding
+ * ComponentFactory is registered in the OSGi service registry with a @link {@link ComponentFactory#FACTORY_NAME} 
+ * servie property with the Component "factoryName" value.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ComponentFactory {
+    /**
+     * Instantiates a Component instance. Any properties starts with a "." are considered as private. Other properties will be
+     * published as the component instance service properties (if the component provides a services).
+     * @param conf the properties passed to the component "configure" method which is specified with the "configure" attribute
+     * of the @Component annotation.  
+     * @return the component instance.
+     */
+    ComponentInstance newInstance(Dictionary<String, ?> conf);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java
new file mode 100644
index 0000000..49ca071
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime.api;
+
+import java.util.Dictionary;
+
+/**
+ * A Component instance created using a {@link ComponentFactory} service
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ComponentInstance {
+    /**
+     * Destroy the component instance.
+     */
+    void dispose();
+    
+    /**
+     * Updates the component instance.
+     * @param conf the properties used to update the component.
+     */
+    void update(Dictionary<String, ?> conf);
+}
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo
new file mode 100644
index 0000000..a4f1546
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/test/.gitignore b/dependencymanager/org.apache.felix.dependencymanager.runtime/test/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/test/.gitignore