- Reworked design of the runtime bundle.
- Reworked design of the annotation scanner.
- Replaced proprietary runtime parser by JSON.
- Fixed BundleDependency.
- Allow to configure annotated service dependency filters from config admin (work in progress).
- Reworked Logging.
- Allow to specify service property arrays.



git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@947379 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/LICENSE.json b/dependencymanager/annotation/LICENSE.json
new file mode 100644
index 0000000..87d1411
--- /dev/null
+++ b/dependencymanager/annotation/LICENSE.json
@@ -0,0 +1,21 @@
+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/annotation/pom.xml b/dependencymanager/annotation/pom.xml
index c3bab2d..da380f3 100644
--- a/dependencymanager/annotation/pom.xml
+++ b/dependencymanager/annotation/pom.xml
@@ -79,6 +79,13 @@
       <version>2.0</version>
       <scope>compile</scope>
     </dependency>
+
+    <dependency>
+       <groupId>org.json</groupId>
+       <artifactId>json</artifactId>
+       <version>20070829</version>
+       <scope>compile</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Property.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Property.java
index 6800747..c87d7e8 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Property.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Property.java
@@ -25,7 +25,7 @@
 
 /**
  * Annotation used to describe a property key-value pair. It is used when
- * declaring {@link Service#properties()} attribute, as well as {@link PropertyMetaData#options()} attribute.
+ * declaring {@link Service#properties()} attribute.
  */
 @Retention(RetentionPolicy.CLASS)
 @Target( { ElementType.ANNOTATION_TYPE })
@@ -41,5 +41,11 @@
      * Returns the property value
      * @return this property value
      */
-    String value();
+    String value() default "";
+    
+    /**
+     * Returns the property values as a String array).
+     * @return this property value as a String array
+     */
+    String[] values() default {};
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
index 5c41695..a955ef3 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/PropertyMetaData.java
@@ -106,10 +106,16 @@
     boolean required() default true;
 
     /**
-     * Return a list of valid options for this property.
-     * The Options are defined using the {@link Property} annotation, where the {@link Property#name()} attribute is used to
-     * reference the option label, and the {@link Property#value()} attribute is used to reference the option value.
-     * @return the list of valid options for this property.
+     * Return a list of valid option labels for this property. The purpose of this method is to allow menus with localized labels.
+     * It is associated with the {@link #optionValues()} attribute. The labels returned here are ordered in the same way as the 
+     * {@link #optionValues()} attribute values. 
+     * @return the list of valid option labels for this property.
      */
-    Property[] options() default {};
+    String[] optionLabels() default {};
+    
+    /**
+     * Return a list of option values that this property can take. This list must be in the same sequence as the {@link #optionLabels()} 
+     * attribute.
+     */
+   String[] optionValues() default {};
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Service.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Service.java
index 8abbf91..725e588 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Service.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/Service.java
@@ -102,7 +102,7 @@
  *    *&#47;
  *  &#64;Service 
  *  class Y {
- *      &#64;ServiceDependency(filter="(dm.factory.name=MyServiceFactory))
+ *      &#64;ServiceDependency(filter="(dm.factory.name=MyServiceFactory)")
  *      Set&lt;Dictionary&gt; _XFactory; // This Set acts as a Factory API for creating X Service instances.
  *    
  *      &#64;Start
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
index adac069..85bb686 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/dependency/ServiceDependency.java
@@ -32,42 +32,38 @@
 public @interface ServiceDependency
 {
     /**
-     * Returns the Service dependency type (by default, the type is method parameter type).
-     * @return the Service dependency type.
+     * The type if the service this dependency is applying on. By default, the type is method parameter or the class field type.
      */
     Class<?> service() default Object.class;
 
     /**
-     * Returns the Service dependency OSGi filter.
-     * @return The Service dependency filter.
+     * The Service dependency OSGi filter.
      */
     String filter() default "";
 
     /**
-     * Returns the class for the default implementation, if the dependency is not available.
-     * @return The default class used when the dependency is not available.
+     * The class for the default implementation, if the dependency is not available.
      */
     Class<?> defaultImpl() default Object.class;
 
     /**
-     * Returns whether the Service dependency is required or not.
-     * @return true if the dependency is required, false if not.
+     * Whether the Service dependency is required or not.
      */
     boolean required() default true;
 
     /**
-     * Returns the callback method to be invoked when the service is available. This attribute is only meaningful when 
+     * The callback method to be invoked when the service is available. This attribute is only meaningful when 
      * the annotation is applied on a class field.
      */
     String added() default "";
 
     /**
-     * Returns the callback method to be invoked when the service properties have changed.
+     * The callback method to be invoked when the service properties have changed.
      */
     String changed() default "";
 
     /**
-     * Returns the callback method to invoke when the service is lost.
+     * The callback method to invoke when the service is lost.
      */
     String removed() default "";
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
index 105e7c9..a192057 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
@@ -26,8 +26,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.felix.dm.annotation.api.AspectService;
 import org.apache.felix.dm.annotation.api.Composition;
@@ -95,7 +93,7 @@
     private String m_method;
     private String m_descriptor;
     private Set<String> m_methods = new HashSet<String>();
-    private List<Info> m_infos = new ArrayList<Info>(); // Last elem is either Service or AspectService
+    private List<EntryWriter> m_writers = new ArrayList<EntryWriter>(); // Last elem is either Service or AspectService
     private MetaType m_metaType;
     private String m_startMethod;
     private String m_stopMethod;
@@ -103,193 +101,10 @@
     private String m_destroyMethod;
     private String m_compositionMethod;
 
-    // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)" or "bind(BundleContext, Type)"
-    private final static Pattern m_bindClassPattern = Pattern.compile("\\((L[^;]+;)?L([^;]+);\\)V");
-
-    // Pattern used to parse classes from class descriptors;
-    private final static Pattern m_classPattern = Pattern.compile("L([^;]+);");
-
-    // Pattern used to check if a method is void and does not take any params
-    private final static Pattern m_voidMethodPattern = Pattern.compile("\\(\\)V");
-
-    // Pattern used to check if a method returns an array of Objects
-    private final static Pattern m_methodCompoPattern = Pattern.compile("\\(\\)\\[Ljava/lang/Object;");
-
-    // List of component descriptor entry types
-    enum EntryTypes
-    {
-        Service, 
-        AspectService,
-        AdapterService,
-        BundleAdapterService,
-        ResourceAdapterService,
-        FactoryConfigurationAdapterService,
-        ServiceDependency, 
-        TemporalServiceDependency, 
-        ConfigurationDependency,
-        BundleDependency,
-        ResourceDependency,
-    };
-
-    // List of component descriptor parameters
-    enum Params
-    {
-        init, 
-        start, 
-        stop, 
-        destroy, 
-        impl, 
-        provide, 
-        properties, 
-        composition, 
-        service, 
-        filter, 
-        defaultImpl, 
-        required, 
-        added, 
-        changed,
-        removed,
-        autoConfig, 
-        pid, 
-        factoryPid,
-        propagate, 
-        updated, 
-        timeout,
-        adapterService,
-        adapterProperties,
-        adapteeService,
-        adapteeFilter,
-        stateMask,
-        ranking,
-        factory,
-        factoryConfigure,
-    };
-
     /**
-     * This class represents a parsed DependencyManager component descriptor entry.
-     * (either a Service, a ServiceDependency, or a ConfigurationDependency descriptor entry).
+     * This class represents a DependencyManager component descriptor entry.
+     * (Service, a ServiceDependency ... see EntryType enum).
      */
-    private class Info
-    {
-        /** The component descriptor entry type: either Service, (Temporal)ServiceDependency, or ConfigurationDependency */
-        EntryTypes m_entry;
-
-        /** The component descriptor entry parameters (init/start/stop ...) */
-        Map<Params, Object> m_params = new HashMap<Params, Object>();
-
-        /**
-         * Makes a new component descriptor entry.
-         * @param entry the component descriptor entry type (either Service, ServiceDependency, or ConfigurationDependency)
-         */
-        Info(EntryTypes entry)
-        {
-            m_entry = entry;
-        }
-
-        /**
-         * Returns a string representation for the given component descriptor line entry.
-         */
-        @Override
-        public String toString()
-        {
-            StringBuilder sb = new StringBuilder();
-            sb.append(m_entry);
-            sb.append(":").append(" ");
-            for (Map.Entry<Params, Object> e : m_params.entrySet())
-            {
-                sb.append(e.getKey());
-                sb.append("=");
-                sb.append(e.getValue());
-                sb.append("; ");
-            }
-            return sb.toString();
-        }
-
-        /**
-         * Adds a parameter to this component descriptor entry.
-         * @param param the param name
-         * @param value the param value
-         */
-        void addParam(Params param, String value)
-        {
-            String old = (String) m_params.get(param);
-            if (old != null)
-            {
-                value = old + "," + value;
-            }
-            m_params.put(param, value);
-        }
-
-        /**
-         * Adds an annotation parameter to this component descriptor entry.
-         * @param annotation the annotation where the parameter has been parsed
-         * @param param the param name
-         * @param def the default value to add, if the param is not present in the parsed annotation.
-         */
-        void addParam(Annotation annotation, Params param, Object def)
-        {
-            Object value = annotation.get(param.toString());
-            if (value == null && def != null)
-            {
-                value = def;
-            }
-            if (value != null)
-            {
-                if (value instanceof Object[])
-                {
-                    for (Object v : ((Object[]) value))
-                    {
-                        addParam(param, v.toString());
-                    }
-                }
-                else
-                {
-                    addParam(param, value.toString());
-                }
-            }
-        }
-
-        /**
-         * Adds a annotation parameter of type 'class' to this component descriptor entry.
-         * The parsed class parameter has the format "Lfull.package.ClassName;"
-         * @param annotation the annotation where the class parameter has been parsed
-         * @param param the annotation class param name
-         * @param def the default class name to add if the param is not present in the parsed annotation.
-         */
-        void addClassParam(Annotation annotation, Params param, Object def)
-        {
-            Pattern pattern = m_classPattern;
-            Object value = annotation.get(param.toString());
-            if (value == null && def != null)
-            {
-                value = def;
-                pattern = null;
-            }
-            if (value != null)
-            {
-                if (value instanceof Object[])
-                {
-                    for (Object v : ((Object[]) value))
-                    {
-                        if (pattern != null)
-                        {
-                            v = parseClass(v.toString(), pattern, 1);
-                        }
-                        addParam(param, v.toString());
-                    }
-                }
-                else
-                {
-                    if (pattern != null)
-                    {
-                        value = parseClass(value.toString(), pattern, 1);
-                    }
-                    addParam(param, value.toString());
-                }
-            }
-
-        }
-    }
 
     /**
      * Makes a new Collector for parsing a given class.
@@ -368,11 +183,11 @@
     public void annotation(Annotation annotation)
     {
         m_reporter.trace("Parsed annotation: %s", annotation);
-        
+
         if (annotation.getName().equals(A_SERVICE))
         {
             parseServiceAnnotation(annotation);
-        } 
+        }
         else if (annotation.getName().equals(A_ASPECT_SERVICE))
         {
             parseAspectService(annotation);
@@ -395,27 +210,31 @@
         }
         else if (annotation.getName().equals(A_INIT))
         {
-            checkMethod(m_voidMethodPattern);
+            //Patterns.parseMethod(m_method, m_descriptor, Patterns.VOID);
+            // TODO check if method takes optional params like Service, DependencyManager, etc ...
             m_initMethod = m_method;
         }
         else if (annotation.getName().equals(A_START))
         {
-            checkMethod(m_voidMethodPattern);
+            //Patterns.parseMethod(m_method, m_descriptor, Patterns.VOID);
+            // TODO check if method takes optional params like Service, DependencyManager, etc ...
             m_startMethod = m_method;
         }
         else if (annotation.getName().equals(A_STOP))
         {
-            checkMethod(m_voidMethodPattern);
+            //Patterns.parseMethod(m_method, m_descriptor, Patterns.VOID);
+            // TODO check if method takes optional params like Service, DependencyManager, etc ...
             m_stopMethod = m_method;
         }
         else if (annotation.getName().equals(A_DESTROY))
         {
-            checkMethod(m_voidMethodPattern);
+            //Patterns.parseMethod(m_method, m_descriptor, Patterns.VOID);
+            // TODO check if method takes optional params like Service, DependencyManager, etc ...
             m_destroyMethod = m_method;
         }
         else if (annotation.getName().equals(A_COMPOSITION))
         {
-            checkMethod(m_methodCompoPattern);
+            Patterns.parseMethod(m_method, m_descriptor, Patterns.COMPOSITION);
             m_compositionMethod = m_method;
         }
         else if (annotation.getName().equals(A_SERVICE_DEP))
@@ -429,12 +248,12 @@
         else if (annotation.getName().equals(A_TEMPORAL_SERVICE_DEPENDENCY))
         {
             parseServiceDependencyAnnotation(annotation, true);
-        } 
-        else if (annotation.getName().equals(A_BUNDLE_DEPENDENCY)) 
+        }
+        else if (annotation.getName().equals(A_BUNDLE_DEPENDENCY))
         {
             parseBundleDependencyAnnotation(annotation);
         }
-        else if (annotation.getName().equals(A_RESOURCE_DEPENDENCY)) 
+        else if (annotation.getName().equals(A_RESOURCE_DEPENDENCY))
         {
             parseRersourceDependencyAnnotation(annotation);
         }
@@ -446,50 +265,55 @@
      */
     private void parseServiceAnnotation(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.Service);
-        m_infos.add(info);
+        EntryWriter writer = new EntryWriter(EntryType.Service);
+        m_writers.add(writer);
 
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
-        
+        addCommonServiceParams(writer);
+
         // impl attribute
-        info.addParam(Params.impl, m_className);
+        writer.put(EntryParam.impl, m_className);
 
         // properties attribute
-        parseParameters(annotation, Params.properties, info);
+        parseProperties(annotation, EntryParam.properties, writer);
 
         // provide attribute
-        info.addClassParam(annotation, Params.provide, m_interfaces);
-        
+        writer.putClassArray(annotation, EntryParam.provide, m_interfaces);
+
         // factory attribute
-        info.addParam(annotation, Params.factory, null);
-        
+        writer.putString(annotation, EntryParam.factory, null);
+
         // factoryPropertiesCallback attribute
-        info.addParam(annotation, Params.factoryConfigure, null);
+        writer.putString(annotation, EntryParam.factoryConfigure, null);
     }
 
-    private void addCommonServiceParams(Info info)
+    private void addCommonServiceParams(EntryWriter writer)
     {
-        if (m_initMethod != null) {
-            info.addParam(Params.init, m_initMethod);
+        if (m_initMethod != null)
+        {
+            writer.put(EntryParam.init, m_initMethod);
         }
-        
-        if (m_startMethod != null) {
-            info.addParam(Params.start, m_startMethod);
+
+        if (m_startMethod != null)
+        {
+            writer.put(EntryParam.start, m_startMethod);
         }
-        
-        if (m_stopMethod != null) {
-            info.addParam(Params.stop, m_stopMethod);
+
+        if (m_stopMethod != null)
+        {
+            writer.put(EntryParam.stop, m_stopMethod);
         }
-        
-        if (m_destroyMethod != null) {
-            info.addParam(Params.destroy, m_destroyMethod);
+
+        if (m_destroyMethod != null)
+        {
+            writer.put(EntryParam.destroy, m_destroyMethod);
         }
-        
+
         // Register Composition method
-        if (m_compositionMethod != null) {
-            info.addParam(Params.composition, m_compositionMethod);
-        }        
+        if (m_compositionMethod != null)
+        {
+            writer.put(EntryParam.composition, m_compositionMethod);
+        }
     }
 
     /**
@@ -498,65 +322,68 @@
      */
     private void parseServiceDependencyAnnotation(Annotation annotation, boolean temporal)
     {
-        Info info = new Info(temporal ? EntryTypes.TemporalServiceDependency
-            : EntryTypes.ServiceDependency);
-        m_infos.add(info);
+        EntryWriter writer = new EntryWriter(temporal ? EntryType.TemporalServiceDependency
+            : EntryType.ServiceDependency);
+        m_writers.add(writer);
 
         // service attribute
-        String service = annotation.get(Params.service.toString());
+        String service = annotation.get(EntryParam.service.toString());
         if (service != null)
         {
-            service = parseClass(service, m_classPattern, 1);
+            service = Patterns.parseClass(service, Patterns.CLASS, 1);
         }
         else
         {
             if (m_isField)
             {
-                service = parseClass(m_descriptor, m_classPattern, 1);
+                service = Patterns.parseClass(m_descriptor, Patterns.CLASS, 1);
             }
             else
             {
-                service = parseClass(m_descriptor, m_bindClassPattern, 2);
+                service = Patterns.parseClass(m_descriptor, Patterns.BIND_CLASS, 2);
             }
         }
-        info.addParam(Params.service, service);
+        writer.put(EntryParam.service, service);
 
         // autoConfig attribute
         if (m_isField)
         {
-            info.addParam(Params.autoConfig, m_field);
+            writer.put(EntryParam.autoConfig, m_field);
         }
 
         // filter attribute
-        String filter = annotation.get(Params.filter.toString());
+        String filter = annotation.get(EntryParam.filter.toString());
         if (filter != null)
         {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
 
         // defaultImpl attribute
-        info.addClassParam(annotation, Params.defaultImpl, null);
+        writer.putClass(annotation, EntryParam.defaultImpl, null);
 
         // added callback
-        info.addParam(annotation, Params.added, (!m_isField) ? m_method : null);
+        writer.putString(annotation, EntryParam.added, (!m_isField) ? m_method : null);
 
         if (temporal)
         {
             // timeout attribute (only valid if parsing a temporal service dependency)
-            info.addParam(annotation, Params.timeout, null);
+            writer.putString(annotation, EntryParam.timeout, null);
         }
         else
         {
             // required attribute (not valid if parsing a temporal service dependency)
-            info.addParam(annotation, Params.required, null);
+            writer.putString(annotation, EntryParam.required, null);
 
             // changed callback
-            info.addParam(annotation, Params.changed, null);
+            writer.putString(annotation, EntryParam.changed, null);
 
             // removed callback
-            info.addParam(annotation, Params.removed, null);
+            writer.putString(annotation, EntryParam.removed, null);
         }
+        
+        // id attribute
+        writer.putString(annotation, EntryParam.name, null);
     }
 
     /**
@@ -565,17 +392,17 @@
      */
     private void parseConfigurationDependencyAnnotation(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.ConfigurationDependency);
-        m_infos.add(info);
+        EntryWriter writer = new EntryWriter(EntryType.ConfigurationDependency);
+        m_writers.add(writer);
 
         // pid attribute
-        info.addParam(annotation, Params.pid, m_className);
+        writer.putString(annotation, EntryParam.pid, m_className);
 
         // propagate attribute
-        info.addParam(annotation, Params.propagate, null);
+        writer.putString(annotation, EntryParam.propagate, null);
 
         // Property Meta Types
-        String pid = get(annotation, Params.pid.toString(), m_className);
+        String pid = get(annotation, EntryParam.pid.toString(), m_className);
         parseMetaTypes(annotation, pid, false);
     }
 
@@ -585,47 +412,52 @@
      */
     private void parseAspectService(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.AspectService);
-        m_infos.add(info);        
+        EntryWriter writer = new EntryWriter(EntryType.AspectService);
+        m_writers.add(writer);
 
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
-                
+        addCommonServiceParams(writer);
+
         // Parse service filter
-        String filter = annotation.get(Params.filter.toString());
-        if (filter != null) {
+        String filter = annotation.get(EntryParam.filter.toString());
+        if (filter != null)
+        {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
-        
+
         // Parse service aspect ranking
-        Integer ranking = annotation.get(Params.ranking.toString());
-        info.addParam(Params.ranking, ranking.toString());
-                
+        Integer ranking = annotation.get(EntryParam.ranking.toString());
+        writer.put(EntryParam.ranking, ranking.toString());
+
         // Generate Aspect Implementation
-        info.addParam(Params.impl, m_className);
-        
+        writer.put(EntryParam.impl, m_className);
+
         // Parse Aspect properties.
-        parseParameters(annotation, Params.properties, info);
-        
+        parseProperties(annotation, EntryParam.properties, writer);
+
         // Parse service interface this aspect is applying to
-        Object service = annotation.get(Params.service.toString());
-        if (service == null) {
+        Object service = annotation.get(EntryParam.service.toString());
+        if (service == null)
+        {
             if (m_interfaces == null)
             {
                 throw new IllegalStateException("Invalid AspectService annotation: " +
-                    "the service attribute has not been set and the class " + m_className + " does not implement any interfaces");
+                    "the service attribute has not been set and the class " + m_className
+                    + " does not implement any interfaces");
             }
-            if (m_interfaces.length != 1) 
+            if (m_interfaces.length != 1)
             {
                 throw new IllegalStateException("Invalid AspectService annotation: " +
-                    "the service attribute has not been set and the class " + m_className + " implements more than one interface");
+                    "the service attribute has not been set and the class " + m_className
+                    + " implements more than one interface");
             }
-            
-            info.addParam(Params.service, m_interfaces[0]);
-        } else
+
+            writer.put(EntryParam.service, m_interfaces[0]);
+        }
+        else
         {
-            info.addClassParam(annotation, Params.service, null);
+            writer.putClassArray(annotation, EntryParam.service, null);
         }
     }
 
@@ -633,33 +465,33 @@
      * Parses an AspectService annotation.
      * @param annotation
      */
-    private void parseAdapterService(Annotation annotation) 
+    private void parseAdapterService(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.AdapterService);
-        m_infos.add(info);
-        
+        EntryWriter writer = new EntryWriter(EntryType.AdapterService);
+        m_writers.add(writer);
+
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
-        
+        addCommonServiceParams(writer);
+
         // Generate Adapter Implementation
-        info.addParam(Params.impl, m_className);
-      
+        writer.put(EntryParam.impl, m_className);
+
         // Parse adaptee filter
-        String adapteeFilter = annotation.get(Params.adapteeFilter.toString());
+        String adapteeFilter = annotation.get(EntryParam.adapteeFilter.toString());
         if (adapteeFilter != null)
         {
             Verifier.verifyFilter(adapteeFilter, 0);
-            info.addParam(Params.adapteeFilter, adapteeFilter);
+            writer.put(EntryParam.adapteeFilter, adapteeFilter);
         }
-        
+
         // Parse the mandatory adapted service interface.
-        info.addClassParam(annotation, Params.adapteeService, null);
-        
+        writer.putClass(annotation, EntryParam.adapteeService, null);
+
         // Parse Adapter properties.
-        parseParameters(annotation, Params.adapterProperties, info);
+        parseProperties(annotation, EntryParam.adapterProperties, writer);
 
         // Parse the optional adapter service (use directly implemented interface by default).
-        info.addClassParam(annotation, Params.adapterService, m_interfaces);
+        writer.putClassArray(annotation, EntryParam.adapterService, m_interfaces);
     }
 
     /**
@@ -668,34 +500,35 @@
      */
     private void parseBundleAdapterService(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.BundleAdapterService);
-        m_infos.add(info);
-        
+        EntryWriter writer = new EntryWriter(EntryType.BundleAdapterService);
+        m_writers.add(writer);
+
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
-        
+        addCommonServiceParams(writer);
+
         // Generate Adapter Implementation
-        info.addParam(Params.impl, m_className);
-      
+        writer.put(EntryParam.impl, m_className);
+
         // Parse bundle filter
-        String filter = annotation.get(Params.filter.toString());
+        String filter = annotation.get(EntryParam.filter.toString());
         if (filter != null)
         {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
-        
+
         // Parse stateMask attribute
-        info.addParam(annotation, Params.stateMask, Integer.valueOf(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE));
-        
+        writer.putString(annotation, EntryParam.stateMask, Integer.valueOf(
+            Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE).toString());
+
         // Parse Adapter properties.
-        parseParameters(annotation, Params.properties, info);
+        parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse the optional adapter service (use directly implemented interface by default).
-        info.addClassParam(annotation, Params.service, m_interfaces);
-        
+        writer.putClassArray(annotation, EntryParam.service, m_interfaces);
+
         // Parse propagate attribute
-        info.addParam(annotation, Params.propagate, Boolean.FALSE);
+        writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
     }
 
     /**
@@ -704,31 +537,31 @@
      */
     private void parseResourceAdapterService(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.ResourceAdapterService);
-        m_infos.add(info);
-        
+        EntryWriter writer = new EntryWriter(EntryType.ResourceAdapterService);
+        m_writers.add(writer);
+
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
-        
+        addCommonServiceParams(writer);
+
         // Generate Adapter Implementation
-        info.addParam(Params.impl, m_className);
-      
+        writer.put(EntryParam.impl, m_className);
+
         // Parse resource filter
-        String filter = annotation.get(Params.filter.toString());
+        String filter = annotation.get(EntryParam.filter.toString());
         if (filter != null)
         {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
-                
+
         // Parse Adapter properties.
-        parseParameters(annotation, Params.properties, info);
+        parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse the optional adapter service (use directly implemented interface by default).
-        info.addClassParam(annotation, Params.service, m_interfaces);
-        
+        writer.putClassArray(annotation, EntryParam.service, m_interfaces);
+
         // Parse propagate attribute
-        info.addParam(annotation, Params.propagate, Boolean.FALSE);
+        writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
     }
 
     /**
@@ -737,79 +570,79 @@
      */
     private void parseFactoryConfigurationAdapterService(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.FactoryConfigurationAdapterService);
-        m_infos.add(info);
-        
+        EntryWriter writer = new EntryWriter(EntryType.FactoryConfigurationAdapterService);
+        m_writers.add(writer);
+
         // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
-        addCommonServiceParams(info);
+        addCommonServiceParams(writer);
 
         // Generate Adapter Implementation
-        info.addParam(Params.impl, m_className);
+        writer.put(EntryParam.impl, m_className);
 
         // Parse factory Pid
-        info.addParam(annotation, Params.factoryPid, m_className);
-        
+        writer.putString(annotation, EntryParam.factoryPid, m_className);
+
         // Parse updated callback
-        info.addParam(annotation, Params.updated, "updated");
-        
+        writer.putString(annotation, EntryParam.updated, "updated");
+
         // propagate attribute
-        info.addParam(annotation, Params.propagate, Boolean.FALSE);
-        
+        writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
+
         // Parse the optional adapter service (use directly implemented interface by default).
-        info.addClassParam(annotation, Params.service, m_interfaces);
+        writer.putClassArray(annotation, EntryParam.service, m_interfaces);
 
         // Parse Adapter properties.
-        parseParameters(annotation, Params.properties, info);
+        parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse optional meta types for configuration description.
-        String factoryPid = get(annotation, Params.factoryPid.toString(), m_className);
-        parseMetaTypes(annotation, factoryPid, true);        
+        String factoryPid = get(annotation, EntryParam.factoryPid.toString(), m_className);
+        parseMetaTypes(annotation, factoryPid, true);
     }
 
-
     private void parseBundleDependencyAnnotation(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.BundleDependency);
-        m_infos.add(info);
+        EntryWriter writer = new EntryWriter(EntryType.BundleDependency);
+        m_writers.add(writer);
 
-        String filter = annotation.get(Params.filter.toString());
+        String filter = annotation.get(EntryParam.filter.toString());
         if (filter != null)
         {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
 
-        info.addParam(annotation, Params.added, m_method);
-        info.addParam(annotation, Params.changed, null); // TODO check if "changed" callback exists
-        info.addParam(annotation, Params.removed, null); // TODO check if "removed" callback exists
-        info.addParam(annotation, Params.required, null);
-        info.addParam(annotation, Params.stateMask, null);
-        info.addParam(annotation, Params.propagate, null);
+        writer.putString(annotation, EntryParam.added, m_method);
+        writer.putString(annotation, EntryParam.changed, null);
+        writer.putString(annotation, EntryParam.removed, null);
+        writer.putString(annotation, EntryParam.required, null);
+        writer.putString(annotation, EntryParam.stateMask, null);
+        writer.putString(annotation, EntryParam.propagate, null);
     }
-    
+
     private void parseRersourceDependencyAnnotation(Annotation annotation)
     {
-        Info info = new Info(EntryTypes.ResourceDependency);
-        m_infos.add(info);
+        EntryWriter writer = new EntryWriter(EntryType.ResourceDependency);
+        m_writers.add(writer);
 
-        String filter = annotation.get(Params.filter.toString());
+        String filter = annotation.get(EntryParam.filter.toString());
         if (filter != null)
         {
             Verifier.verifyFilter(filter, 0);
-            info.addParam(Params.filter, filter);
+            writer.put(EntryParam.filter, filter);
         }
 
-        info.addParam(annotation, Params.added, m_method);
-        info.addParam(annotation, Params.changed, null); // TODO check if "changed" callback exists
-        info.addParam(annotation, Params.removed, null); // TODO check if "removed" callback exists
-        info.addParam(annotation, Params.required, null);
-        info.addParam(annotation, Params.propagate, null);        
+        writer.putString(annotation, EntryParam.added, m_method);
+        writer.putString(annotation, EntryParam.changed, null);
+        writer.putString(annotation, EntryParam.removed, null);
+        writer.putString(annotation, EntryParam.required, null);
+        writer.putString(annotation, EntryParam.propagate, null);
     }
 
     /**
      * Parse optional meta types annotation attributes
      * @param annotation
      */
+    @SuppressWarnings("null")
     private void parseMetaTypes(Annotation annotation, String pid, boolean factory)
     {
         if (annotation.get("metadata") != null)
@@ -818,13 +651,13 @@
             String propertiesDesc = annotation.get("description");
 
             MetaType.OCD ocd = new MetaType.OCD(pid, propertiesHeading, propertiesDesc);
-            for (Object p : (Object[]) annotation.get("metadata"))
+            for (Object p: (Object[]) annotation.get("metadata"))
             {
                 Annotation property = (Annotation) p;
                 String heading = property.get("heading");
                 String id = property.get("id");
                 String type = (String) property.get("type");
-                type = (type != null) ? parseClass(type, m_classPattern, 1) : null;
+                type = (type != null) ? Patterns.parseClass(type, Patterns.CLASS, 1) : null;
                 Object[] defaults = (Object[]) property.get("defaults");
                 String description = property.get("description");
                 Integer cardinality = property.get("cardinality");
@@ -832,16 +665,31 @@
 
                 MetaType.AD ad = new MetaType.AD(id, type, defaults, heading, description,
                     cardinality, required);
-                Object[] options = property.get("options");
-                if (options != null)
+
+                Object[] optionLabels = property.get("optionLabels");
+                Object[] optionValues = property.get("optionValues");
+
+                if (optionLabels == null
+                    && optionValues != null
+                    ||
+                    optionLabels != null
+                    && optionValues == null
+                    ||
+                    (optionLabels != null && optionValues != null && optionLabels.length != optionValues.length))
                 {
-                    for (Object o : (Object[]) property.get("options"))
+                    throw new IllegalArgumentException("invalid option labels/values specified for property "
+                        + id +
+                        " in PropertyMetadata annotation from class " + m_className);
+                }
+
+                if (optionValues != null)
+                {
+                    for (int i = 0; i < optionValues.length; i++)
                     {
-                        Annotation option = (Annotation) o;
-                        ad.add(new MetaType.Option((String) option.get("name"),
-                            (String) option.get("value")));
+                        ad.add(new MetaType.Option(optionValues[i].toString(), optionLabels[i].toString()));
                     }
                 }
+
                 ocd.add(ad);
             }
 
@@ -849,78 +697,63 @@
             MetaType.Designate designate = new MetaType.Designate(pid, factory);
             m_metaType.add(designate);
             m_reporter.warning("Parsed MetaType Properties from class " + m_className);
-        }          
+        }
     }
 
     /**
-     * Parses a Param annotation (which represents a list of key-value pari).
+     * Parses a Property annotation (which represents a list of key-value pair).
      * @param annotation the annotation where the Param annotation is defined
      * @param attribute the attribute name which is of Param type
-     * @param info the Info object where the parsed attributes are written
+     * @param writer the object where the parsed attributes are written
      */
-    private void parseParameters(Annotation annotation, Params attribute, Info info) {
+    private void parseProperties(Annotation annotation, EntryParam attribute, EntryWriter writer)
+    {
         Object[] parameters = annotation.get(attribute.toString());
+        Map<String, Object> properties = new HashMap<String, Object>();
         if (parameters != null)
         {
-            for (Object p : parameters)
+            for (Object p: parameters)
             {
-                Annotation a = (Annotation) p; 
-                String prop = a.get("name") + ":" + a.get("value");
-                info.addParam(attribute, prop);
+                Annotation a = (Annotation) p;
+                String name = (String) a.get("name");
+                String value = (String) a.get("value");
+                if (value != null)
+                {
+                    properties.put(name, value);
+                }
+                else
+                {
+                    Object[] values = a.get("values");
+                    if (values != null)
+                    {
+                        // the values is an Object array of actual strings, and we must convert it into a String array.
+                        properties.put(name, Arrays.asList(values).toArray(new String[values.length]));
+                    }
+                    else
+                    {
+                        throw new IllegalArgumentException("Invalid Property attribyte \"" + attribute
+                            + " from annotation " + annotation + " in class " + m_className);
+                    }
+                }
             }
-        }
-    }
-    
-    /**
-     * Parses a class.
-     * @param clazz the class to be parsed (the package is "/" separated).
-     * @param pattern the pattern used to match the class.
-     * @param group the pattern group index where the class can be retrieved.
-     * @return the parsed class.
-     */
-    private String parseClass(String clazz, Pattern pattern, int group)
-    {
-        Matcher matcher = pattern.matcher(clazz);
-        if (matcher.matches())
-        {
-            return matcher.group(group).replace("/", ".");
-        }
-        else
-        {
-            m_reporter.warning("Invalid class descriptor: %s", clazz);
-            throw new IllegalArgumentException("Invalid class descriptor: " + clazz);
+            writer.putProperties(attribute, properties);
         }
     }
 
     /**
-     * Checks if a method descriptor matches a given pattern. 
-     * @param pattern the pattern used to check the method signature descriptor
-     * @throws IllegalArgumentException if the method signature descriptor does not match the given pattern.
-     */
-    private void checkMethod(Pattern pattern)
-    {
-        Matcher matcher = pattern.matcher(m_descriptor);
-        if (!matcher.matches())
-        {
-            m_reporter.warning("Invalid method %s : wrong signature: %s", m_method, m_descriptor);
-            throw new IllegalArgumentException("Invalid method " + m_method + ", wrong signature: "
-                + m_descriptor);
-        }
-    }
-    
-    /**
      * Checks if the class is annotated with some given annotations. Notice that the Service
-     * is always parsed at end of parsing, so, we have to check the last element of our m_infos
+     * is always parsed at end of parsing, so, we have to check the last element of our m_writers
      * List.
      * @return true if one of the provided annotations has been found from the parsed class.
      */
-    private void checkServiceDeclared(EntryTypes ... types) {
+    private void checkServiceDeclared(EntryType... types)
+    {
         boolean ok = false;
-        if (m_infos.size() > 0)
+        if (m_writers.size() > 0)
         {
-            for (EntryTypes type : types)
+            for (EntryType type: types)
             {
-                if (m_infos.get(m_infos.size() - 1).m_entry == type)
+                if (m_writers.get(m_writers.size() - 1).getEntryType() == type)
                 {
                     ok = true;
                     break;
@@ -944,6 +777,7 @@
      * @param defaultValue the default value to return if the attribute is not found in the annotation
      * @return the annotation attribute value, or the defaultValue if not found
      */
+    @SuppressWarnings("unchecked")
     private <T> T get(Annotation properties, String name, T defaultValue)
     {
         T value = (T) properties.get(name);
@@ -956,21 +790,22 @@
      */
     public boolean finish()
     {
-        if (m_infos.size() == 0)
+        if (m_writers.size() == 0)
         {
             return false;
         }
 
         // We must have at least a Service or an AspectService annotation.
-        checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService, EntryTypes.AdapterService, EntryTypes.BundleAdapterService,
-            EntryTypes.ResourceAdapterService, EntryTypes.FactoryConfigurationAdapterService);
+        checkServiceDeclared(EntryType.Service, EntryType.AspectService, EntryType.AdapterService,
+            EntryType.BundleAdapterService,
+            EntryType.ResourceAdapterService, EntryType.FactoryConfigurationAdapterService);
 
         StringBuilder sb = new StringBuilder();
         sb.append("Parsed annotation for class ");
         sb.append(m_className);
-        for (int i = m_infos.size() - 1; i >= 0; i--)
+        for (int i = m_writers.size() - 1; i >= 0; i--)
         {
-            sb.append("\n\t").append(m_infos.get(i).toString());
+            sb.append("\n\t").append(m_writers.get(i).toString());
         }
         m_reporter.warning(sb.toString());
         return true;
@@ -983,10 +818,10 @@
      */
     public void writeTo(PrintWriter pw)
     {
-        // The last element our our m_infos list contains either the Service, or the AspectService descriptor.
-        for (int i = m_infos.size() - 1; i >= 0; i--)
+        // The last element our our m_writers list contains either the Service, or the AspectService descriptor.
+        for (int i = m_writers.size() - 1; i >= 0; i--)
         {
-            pw.println(m_infos.get(i).toString());
+            pw.println(m_writers.get(i).toString());
         }
     }
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java
new file mode 100644
index 0000000..703effd
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java
@@ -0,0 +1,38 @@
+package org.apache.felix.dm.annotation.plugin.bnd;
+
+/**
+ * The type of parameters which can be found in a component descriptor.
+ */
+public enum EntryParam
+{
+    init, 
+    start, 
+    stop, 
+    destroy, 
+    impl, 
+    provide, 
+    properties, 
+    composition, 
+    service, 
+    filter, 
+    defaultImpl, 
+    required, 
+    added, 
+    changed,
+    removed,
+    autoConfig, 
+    pid, 
+    factoryPid,
+    propagate, 
+    updated, 
+    timeout,
+    adapterService,
+    adapterProperties,
+    adapteeService,
+    adapteeFilter,
+    stateMask,
+    ranking,
+    factory,
+    factoryConfigure,
+    name
+}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java
new file mode 100644
index 0000000..bdbd005
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryType.java
@@ -0,0 +1,19 @@
+package org.apache.felix.dm.annotation.plugin.bnd;
+
+/**
+ * The type of each entry (lines) stored in a component descriptor.
+ */
+public enum EntryType
+{
+    Service, 
+    AspectService,
+    AdapterService,
+    BundleAdapterService,
+    ResourceAdapterService,
+    FactoryConfigurationAdapterService,
+    ServiceDependency, 
+    TemporalServiceDependency, 
+    ConfigurationDependency,
+    BundleDependency,
+    ResourceDependency,
+}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
new file mode 100644
index 0000000..3e5c8c7
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
@@ -0,0 +1,251 @@
+package org.apache.felix.dm.annotation.plugin.bnd;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import aQute.lib.osgi.Annotation;
+
+/**
+ * This class encodes a component descriptor entry line, using json.
+ */
+public class EntryWriter
+{
+    // Every descriptor entries contains a type parameter for identifying the kind of entry
+    private final static String TYPE = "type";
+
+    /** All parameters as stored in a json object */
+    private JSONObject m_json;
+
+    /** The entry type */
+    private EntryType m_type;
+
+    /**
+     * Makes a new component descriptor entry.
+     */
+    public EntryWriter(EntryType type)
+    {
+        m_type = type;
+        m_json = new JSONObject();
+        try
+        {
+            m_json.put("type", type.toString());
+        }
+        catch (JSONException e)
+        {
+            throw new RuntimeException("could not initialize json object", e);
+        }
+    }
+
+    /**
+     * Returns this entry type.
+     */
+    EntryType getEntryType()
+    {
+        return m_type;
+    }
+
+    /**
+     * Returns a string representation for the given component descriptor entry.
+     */
+    @Override
+    public String toString()
+    {
+        return m_json.toString();
+    }
+
+    /**
+     * Put a String parameter in this descritor entry.
+     */
+    public void put(EntryParam param, String value)
+    {
+        checkType(param.toString());
+        try
+        {
+            m_json.put(param.toString(), value);
+        }
+        catch (JSONException e)
+        {
+            throw new IllegalArgumentException("could not add param " + param + ":" + value, e);
+        }
+    }
+
+    /**
+     * Put a String[] parameter in this descriptor entry.
+     */
+    public void put(EntryParam param, String[] array)
+    {
+        checkType(param.toString());
+        try
+        {
+            m_json.put(param.toString(), new JSONArray(Arrays.asList(array)));
+        }
+        catch (JSONException e)
+        {
+            throw new IllegalArgumentException("could not add param " + param + ":"
+                + Arrays.toString(array), e);
+        }
+    }
+
+    /**
+     * Put a Map parameter in the descriptor entry. The map values must be either Strings or Strings arrays.
+     */
+    public void putProperties(EntryParam param, Map<String, Object> properties)
+    {
+        checkType(param.toString());
+
+        try
+        {
+            JSONObject props = new JSONObject();
+            for (String key: properties.keySet())
+            {
+                Object value = properties.get(key);
+                if (value instanceof String)
+                {
+                    props.put(key, value);
+                }
+                else if (value instanceof String[])
+                {
+                    props.put(key, new JSONArray(Arrays.asList((String[]) value)));
+                }
+                else
+                {
+                    throw new IllegalArgumentException("invalid property value: " + value);
+                }
+            }
+            m_json.put(param.toString(), props);
+        }
+
+        catch (JSONException e)
+        {
+            throw new IllegalArgumentException("invalid properties for " + param + ": "
+                + properties, e);
+        }
+    }
+
+    /**
+     * Get a String attribute value from an annotation and write it into this descriptor entry.
+     */
+    public void putString(Annotation annotation, EntryParam param, String def)
+    {
+        checkType(param.toString());
+        Object value = annotation.get(param.toString());
+        if (value == null && def != null)
+        {
+            value = def;
+        }
+        if (value != null)
+        {
+            put(param, value.toString());
+        }
+    }
+
+    /**
+     * Get a String array attribute value from an annotation and write it into this descriptor entry.
+     */
+    public void putStringArray(Annotation annotation, EntryParam param, String[] def)
+    {
+        checkType(param.toString());
+        Object value = annotation.get(param.toString());
+        if (value == null && def != null)
+        {
+            value = def;
+        }
+        if (value != null)
+        {
+            for (Object v: ((Object[]) value))
+            {
+                try
+                {
+                    m_json.append(param.toString(), v.toString());
+                }
+                catch (JSONException e)
+                {
+                    throw new IllegalArgumentException("Could not add param " + param + ":"
+                        + value.toString(), e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Get a class attribute value from an annotation and write it into this descriptor entry.
+     */
+    public void putClass(Annotation annotation, EntryParam param, Object def)
+    {
+        checkType(param.toString());
+
+        Pattern pattern = Patterns.CLASS;
+        Object value = annotation.get(param.toString());
+        if (value == null && def != null)
+        {
+            value = def;
+            pattern = null;
+        }
+        if (value != null)
+        {
+            if (pattern != null)
+            {
+                value = Patterns.parseClass(value.toString(), pattern, 1);
+            }
+            put(param, value.toString());
+        }
+    }
+
+    /**
+     * Get a class array attribute value from an annotation and write it into this descriptor entry.
+     */
+    public void putClassArray(Annotation annotation, EntryParam param, Object def)
+    {
+        checkType(param.toString());
+
+        Pattern pattern = Patterns.CLASS;
+        Object value = annotation.get(param.toString());
+        if (value == null && def != null)
+        {
+            value = def;
+            pattern = null;
+        }
+        if (value != null)
+        {
+            if (!(value instanceof Object[]))
+            {
+                throw new IllegalArgumentException("annotation parameter " + param
+                    + " has not a class array type");
+            }
+
+            for (Object v: ((Object[]) value))
+            {
+                if (pattern != null)
+                {
+                    v = Patterns.parseClass(v.toString(), pattern, 1);
+                }
+                try
+                {
+                    m_json.append(param.toString(), v.toString());
+                }
+                catch (JSONException e)
+                {
+                    throw new IllegalArgumentException("Could not add param " + param + ":"
+                            + value.toString(), e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Check if the written key is not equals to "type" ("type" is an internal attribute we are using
+     * in order to identify a kind of descriptor entry (Service, ServiceDependency, etc ...).
+     */
+    private void checkType(String key)
+    {
+        if (TYPE.equals(key))
+        {
+            throw new IllegalArgumentException("\"" + TYPE + "\" parameter can't be overriden");
+        }
+    }
+}
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Patterns.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Patterns.java
new file mode 100644
index 0000000..7e9b15b
--- /dev/null
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/Patterns.java
@@ -0,0 +1,54 @@
+package org.apache.felix.dm.annotation.plugin.bnd;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Patterns
+{
+    // Pattern used to check if a method is void and does not take any params
+    public final static Pattern VOID = Pattern.compile("\\(\\)V");
+
+    // Pattern used to check if a method returns an array of Objects
+    public final static Pattern COMPOSITION = Pattern.compile("\\(\\)\\[Ljava/lang/Object;");
+
+   // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)" or "bind(BundleContext, Type)"
+    public final static Pattern BIND_CLASS = Pattern.compile("\\((L[^;]+;)?L([^;]+);\\)V");
+
+    // Pattern used to parse classes from class descriptors;
+    public final static Pattern CLASS = Pattern.compile("L([^;]+);");
+
+    /**
+     * Parses a class.
+     * @param clazz the class to be parsed (the package is "/" separated).
+     * @param pattern the pattern used to match the class.
+     * @param group the pattern group index where the class can be retrieved.
+     * @return the parsed class.
+     */
+    public static String parseClass(String clazz, Pattern pattern, int group)
+    {
+        Matcher matcher = pattern.matcher(clazz);
+        if (matcher.matches())
+        {
+            return matcher.group(group).replace("/", ".");
+        }
+        else
+        {
+            throw new IllegalArgumentException("Invalid class descriptor: " + clazz);
+        }
+    }
+    
+    /**
+     * Checks if a method descriptor matches a given pattern. 
+     * @param pattern the pattern used to check the method signature descriptor
+     * @throws IllegalArgumentException if the method signature descriptor does not match the given pattern.
+     */
+    public static void parseMethod(String method, String descriptor, Pattern pattern)
+    {
+        Matcher matcher = pattern.matcher(descriptor);
+        if (!matcher.matches())
+        {
+            throw new IllegalArgumentException("Invalid method " + method + ", wrong signature: "
+                + descriptor);
+        }
+    }
+}
diff --git a/dependencymanager/runtime/LICENSE.json b/dependencymanager/runtime/LICENSE.json
new file mode 100644
index 0000000..87d1411
--- /dev/null
+++ b/dependencymanager/runtime/LICENSE.json
@@ -0,0 +1,21 @@
+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/runtime/pom.xml b/dependencymanager/runtime/pom.xml
index 1d6bd15..b528af0 100644
--- a/dependencymanager/runtime/pom.xml
+++ b/dependencymanager/runtime/pom.xml
@@ -52,6 +52,12 @@
       <artifactId>org.apache.felix.dependencymanager</artifactId>
       <version>3.0.0-SNAPSHOT</version>
     </dependency>
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+      <version>20070829</version>
+      <scope>provided</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -77,7 +83,8 @@
             <Bundle-Description>A bundle that loads components descriptors from started bundles</Bundle-Description>
             <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
             <Private-Package>org.apache.felix.dm.runtime.*</Private-Package>
-            <Import-Package>org.apache.felix.dm;org.apache.felix.dm.dependencies;org.apache.felix.dm.service;version="[3.0.0,4.0.0)", *</Import-Package>
+            <Import-Package>org.apache.felix.dm;org.apache.felix.dm.dependencies;org.apache.felix.dm.service;version="[3.0.0,4.0.0)",*</Import-Package>
+	    <Embed-Dependency>json</Embed-Dependency>
             <Bundle-Activator>org.apache.felix.dm.runtime.Activator</Bundle-Activator>
           </instructions>
         </configuration>
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Activator.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Activator.java
index 14a2c0d..82dde28 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Activator.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Activator.java
@@ -31,6 +31,9 @@
  */
 public class Activator extends DependencyActivatorBase
 {
+    /**
+     * Our bundle is starting: initialize our DependencyManager Runtime service.
+     */
     @Override
     public void init(BundleContext context, DependencyManager dm) throws Exception
     {
@@ -42,15 +45,19 @@
 
         boolean logActive = "true".equals(context.getProperty("dm.log"));
         dm.add(createService()
-               .setImplementation(ComponentManager.class)
+               .setImplementation(DependencyManagerRuntime.class)
                .add(createServiceDependency()
                    .setService(LogService.class)
                    .setRequired(logActive)
-                   .setAutoConfig(true)));
+                   .setAutoConfig("m_log")
+                   .setCallbacks("bind", null)));
     }
 
+    /**
+     * Our bundle is stopping: shutdown our Dependency Manager Runtime service.
+     */
     @Override
     public void destroy(BundleContext context, DependencyManager dm) throws Exception
     {
-    }
+    }    
 }
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
new file mode 100644
index 0000000..90a66d6
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+/**
+ * Builded called when the JSON parser find an adapter service descriptor.
+ */
+public class AdapterServiceBuilder extends ServiceComponentBuilder
+{
+    /** The type attribute specified in the JSON descriptor */
+    private final static String TYPE = "AdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData serviceMetaData,
+        List<MetaData> serviceDependencies,
+        Bundle b, DependencyManager dm) throws Exception
+    {
+        Class<?> adapterImpl = b.loadClass(serviceMetaData.getString(Params.impl));
+        String[] adapterService = serviceMetaData.getStrings(Params.adapterService, null);
+        Dictionary<String, Object> adapterProperties = serviceMetaData.getDictionary(Params.adapterProperties, null);
+        Class<?> adapteeService = b.loadClass(serviceMetaData.getString(Params.adapteeService));
+        String adapteeFilter = serviceMetaData.getString(Params.adapteeFilter, null);     
+        Service service = dm.createAdapterService(adapteeService, adapteeFilter, adapterService, adapterImpl, adapterProperties);
+        setCommonServiceParams(service, serviceMetaData);
+        for (MetaData dependencyMetaData: serviceDependencies)
+        {
+            Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+            service.add(dp);
+        }
+        dm.add(service);
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
new file mode 100644
index 0000000..e7ee17f
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
@@ -0,0 +1,67 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.LogService;
+
+public class AspectServiceBuilder extends ServiceComponentBuilder
+{
+    private final static String TYPE = "AspectService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData serviceMetaData,
+        List<MetaData> serviceDependencies,
+        Bundle b, DependencyManager dm) throws Exception
+    {
+        Log.instance().log(LogService.LOG_DEBUG, "building aspect service: service metadata=" + serviceMetaData
+            + ", dependencyMetaData=" + serviceDependencies);
+
+        Class<?> serviceInterface = b.loadClass(serviceMetaData.getString(Params.service));
+        String serviceFilter = serviceMetaData.getString(Params.filter, null);
+        Dictionary<String, Object> aspectProperties = serviceMetaData.getDictionary(Params.properties,
+            null);
+        int ranking = serviceMetaData.getInt(Params.ranking, 1);
+        String implClass = serviceMetaData.getString(Params.impl);
+        Object impl = b.loadClass(implClass);
+        // TODO add attribute name
+        Service service = dm.createAspectService(serviceInterface, serviceFilter, ranking, null)
+                            .setImplementation(impl)
+                            .setServiceProperties(aspectProperties);
+        setCommonServiceParams(service, serviceMetaData);
+        for (MetaData dependencyMetaData: serviceDependencies)
+        {
+            Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+            service.add(dp);
+        }
+        dm.add(service);
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
new file mode 100644
index 0000000..f41f6d4
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+public class BundleAdapterServiceBuilder extends ServiceComponentBuilder
+{
+    private final static String TYPE = "BundleAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData serviceMetaData,
+        List<MetaData> serviceDependencies,
+        Bundle b, DependencyManager dm) throws Exception
+    {
+        int stateMask = serviceMetaData.getInt(Params.stateMask, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE);
+        String filter = serviceMetaData.getString(Params.filter, null);
+        Class<?> adapterImpl = b.loadClass(serviceMetaData.getString(Params.impl));
+        String[] service = serviceMetaData.getStrings(Params.service, null);
+        Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+        Service srv = dm.createBundleAdapterService(stateMask, filter, adapterImpl, service, properties, propagate);  
+        setCommonServiceParams(srv, serviceMetaData);
+        for (MetaData dependencyMetaData: serviceDependencies)
+        {
+            Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+            srv.add(dp);
+        }
+        dm.add(srv);
+    }    
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java
deleted file mode 100644
index 069a79b..0000000
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * 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.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.dependencies.BundleDependency;
-import org.apache.felix.dm.dependencies.ConfigurationDependency;
-import org.apache.felix.dm.dependencies.Dependency;
-import org.apache.felix.dm.dependencies.ResourceDependency;
-import org.apache.felix.dm.dependencies.ServiceDependency;
-import org.apache.felix.dm.dependencies.TemporalServiceDependency;
-import org.apache.felix.dm.service.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.SynchronousBundleListener;
-import org.osgi.service.log.LogService;
-
-/**
- * This class parses service descriptors generated by the annotation bnd processor.
- * The descriptors are located under OSGI-INF/dependencymanager directory. Such files are actually 
- * referenced by a specific "DependendencyManager-Component" manifest header.
- */
-public class ComponentManager implements SynchronousBundleListener
-{
-    private HashMap<Bundle, List<Service>> m_services = new HashMap<Bundle, List<Service>>();
-    private LogService m_logService; // Injected
-    private BundleContext m_bctx; // Injected
-    private ServiceFactory m_serviceFactory;
-
-    /**
-     * 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()
-    {
-        for (Bundle b : m_bctx.getBundles())
-        {
-            if (b.getState() == Bundle.ACTIVE)
-            {
-                bundleChanged(new BundleEvent(Bundle.ACTIVE, b));
-            }
-        }
-        m_bctx.addBundleListener(this);
-    }
-
-    /**
-     * Stops our service. We'll stop all activated DependencyManager services.
-     */
-    protected void stop()
-    {
-        for (List<Service> services : m_services.values())
-        {
-            for (Service service : services)
-            {
-                service.stop();
-            }
-        }
-        m_services.clear();
-    }
-
-    /**
-     * Handle a bundle event, and eventually parse started bundles.
-     */
-    public void bundleChanged(BundleEvent event)
-    {
-        Bundle b = event.getBundle();
-        if (b.getState() == Bundle.ACTIVE)
-        {
-            bundleStarted(b);
-        }
-        else if (b.getState() == Bundle.STOPPING)
-        {
-            bundleStopped(b);
-        }
-    }
-
-    /**
-     * Checks if a started bundle have some DependencyManager descriptors 
-     * referenced in the "DependencyManager-Component" OSGi header.
-     * @param b the started bundle.
-     */
-    void bundleStarted(Bundle b)
-    {
-        String descriptorPaths = (String) b.getHeaders().get("DependencyManager-Component");
-        if (descriptorPaths == null)
-        {
-            return;
-        }
-
-        for (String descriptorPath : descriptorPaths.split(","))
-        {
-            URL descriptorURL = b.getEntry(descriptorPath);
-            if (descriptorURL == null)
-            {
-                m_logService.log(LogService.LOG_ERROR,
-                    "DependencyManager component descriptor not found: " + descriptorPath);
-                continue;
-            }
-            loadDescriptor(b, descriptorURL);
-        }
-    }
-
-    /**
-     * Load a DependencyManager component descriptor from a given bundle.
-     * @param b
-     * @param descriptorURL
-     */
-    @SuppressWarnings("null")
-    private void loadDescriptor(Bundle b, URL descriptorURL)
-    {
-        m_logService.log(LogService.LOG_DEBUG, "Parsing descriptor " + descriptorURL
-            + " from bundle " + b.getSymbolicName());
-
-        BufferedReader in = null;
-        try
-        {
-            DescriptorParser parser = new DescriptorParser(m_logService);
-            in = new BufferedReader(new InputStreamReader(descriptorURL.openStream()));
-            DependencyManager dm = new DependencyManager(b.getBundleContext());
-            Service service = null;
-            String line;
-            m_serviceFactory = null;
-
-            while ((line = in.readLine()) != null)
-            {
-                Dependency dp = null;
-                switch (parser.parse(line))
-                {
-                    case Service:
-                        service = createService(b, dm, parser);
-                        break;
-
-                    case AspectService:
-                        service = createAspectService(b, dm, parser);
-                        break;
-                        
-                    case AdapterService:
-                        service = createAdapterService(b, dm, parser);
-                        break;
-                        
-                    case BundleAdapterService:
-                        service = createBundleAdapterService(b, dm, parser);
-                        break;
-
-                    case ResourceAdapterService:
-                        service = createResourceAdapterService(b, dm, parser);
-                        break;
-                        
-                    case FactoryConfigurationAdapterService:
-                        service = createFactoryConfigurationAdapterService(b, dm, parser);
-                        break;
-
-                    case ServiceDependency:
-                        dp = createServiceDependency(b, dm, parser, false);
-                        break;
-
-                    case TemporalServiceDependency:
-                        dp = createServiceDependency(b, dm, parser, true);
-                        break;
-
-                    case ConfigurationDependency:
-                        dp = createConfigurationDependency(b, dm, parser);
-                        break;
-                        
-                    case BundleDependency:
-                        dp = createBundleDependency(b, dm, parser);
-                        break;
-                        
-                    case ResourceDependency:
-                        dp = createResourceDependency(b, dm, parser);
-                        break;
-                }
-                
-                // If we parsed a dependency: add it in the current parsed service, unless the service is a factory service.
-                // In this case, the dependency is just buffered in the service factory, which will register it at 
-                // each instantiation time.
-                
-                if (dp != null)
-                {
-                    checkServiceParsed(service);
-                    if (m_serviceFactory != null)
-                    {
-                        // The dependency is buffered and will be used once this factory fires a service instantiation.
-                        m_serviceFactory.addDependency(dp);
-                    }
-                    else
-                    {
-                        service.add(dp);
-                    }
-                }
-            }
-            
-            List<Service> services = m_services.get(b);
-            if (services == null)
-            {
-                services = new ArrayList<Service>();
-                m_services.put(b, services);
-            }
-            services.add(service);
-            dm.add(service);
-        }
-        catch (Throwable t)
-        {
-            m_logService.log(LogService.LOG_ERROR, "Error while parsing descriptor "
-                + descriptorURL + " from bundle " + b.getSymbolicName(), t);
-        }
-        finally
-        {
-            if (in != null)
-            {
-                try
-                {
-                    in.close();
-                }
-                catch (IOException ignored)
-                {
-                }
-            }
-        }
-    }
-
-    /**
-     * Unregisters all services for a stopping bundle.
-     * @param b
-     */
-    private void bundleStopped(Bundle b)
-    {
-        m_logService.log(LogService.LOG_INFO, "bundle stopped: " + b.getSymbolicName());
-        List<Service> services = m_services.remove(b);
-        if (services != null)
-        {
-            for (Service s : services)
-            {
-                m_logService.log(LogService.LOG_INFO, "stopping service " + s);
-                s.stop();
-            }
-        }
-    }
-
-    /**
-     * Check if we have already parsed the Service entry from a given DM component descriptor file.
-     * Each descriptor must start with a Service definition entry.
-     * @param service the parsed service
-     * @throws IllegalArgumentException if the service has not been parsed.
-     */
-    private void checkServiceParsed(Service service)
-    {
-        if (service == null)
-        {
-            throw new IllegalArgumentException("Service not declared in the first descriptor line");
-        }
-    }
-
-    /**
-     * Creates a Service that we parsed from a component descriptor entry.
-     * @param b the bundle from where the service is started
-     * @param dm the DependencyManager framework
-     * @param parser the parser that just parsed the descriptor "Service" entry
-     * @return the created DependencyManager Service
-     * @throws ClassNotFoundException if the service implementation could not be instantiated
-     */
-    private Service createService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        Service service = dm.createService();
-        String factory = parser.getString(DescriptorParam.factory, null);
-        String factoryConfigure = parser.getString(DescriptorParam.factoryConfigure, null);
-        String impl = parser.getString(DescriptorParam.impl);
-        String init = parser.getString(DescriptorParam.init, null);
-        String start = parser.getString(DescriptorParam.start, null);
-        String stop = parser.getString(DescriptorParam.stop, null);
-        String destroy = parser.getString(DescriptorParam.destroy, null);
-        String composition = parser.getString(DescriptorParam.composition, null);
-        Dictionary<String, String> serviceProperties = parser.getDictionary(DescriptorParam.properties, null);
-        String[] provide = parser.getStrings(DescriptorParam.provide, null);
-
-        if (factory == null)
-        {
-            service.setImplementation(b.loadClass(impl));
-            service.setCallbacks(init, start, stop, destroy);
-            if (composition != null)
-            {
-                service.setComposition(composition);
-            }
-            if (provide != null)
-            {
-                service.setInterface(provide, serviceProperties);
-            }
-        }
-        else
-        {
-            m_serviceFactory = new ServiceFactory(b.loadClass(impl), init, start, stop, destroy,
-                                                  composition, serviceProperties, provide, factoryConfigure);
-            service.setImplementation(m_serviceFactory);
-            service.setCallbacks(null, "start", "stop", null);
-            Hashtable<String, String> props = new Hashtable<String, String>();
-            props.put("dm.factory.name", factory);
-            service.setInterface(Set.class.getName(), props);
-        }
-
-        return service;
-    }
-
-    /**
-     * Set common Service parameters, if provided from our Component descriptor
-     * @param service
-     * @param parser
-     */
-    private void setCommonServiceParams(Service service, DescriptorParser parser)
-    {
-        String init = parser.getString(DescriptorParam.init, null);
-        String start = parser.getString(DescriptorParam.start, null);
-        String stop = parser.getString(DescriptorParam.stop, null);
-        String destroy = parser.getString(DescriptorParam.destroy, null);
-        service.setCallbacks(init, start, stop, destroy);
-        String composition = parser.getString(DescriptorParam.composition, null);
-        if (composition != null)
-        {
-            service.setComposition(composition);
-        }
-    }
-
-    /**
-     * Creates an Aspect Service.
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Service createAspectService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        Service service = null;
-
-        Class<?> serviceInterface = b.loadClass(parser.getString(DescriptorParam.service));
-        String serviceFilter = parser.getString(DescriptorParam.filter, null);
-        Dictionary<String, String> aspectProperties = parser.getDictionary(DescriptorParam.properties, null);
-        int ranking = parser.getInt(DescriptorParam.ranking, 1);          
-        String implClass = parser.getString(DescriptorParam.impl);
-        Object impl = b.loadClass(implClass);
-        service = dm.createAspectService(serviceInterface, serviceFilter, ranking, impl, aspectProperties);
-        setCommonServiceParams(service, parser);
-        return service;
-    }
-
-    /**
-     * Creates an Adapter Service.
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Service createAdapterService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        Class<?> adapterImpl = b.loadClass(parser.getString(DescriptorParam.impl));
-        String[] adapterService = parser.getStrings(DescriptorParam.adapterService, null);
-        Dictionary<String, String> adapterProperties = parser.getDictionary(DescriptorParam.adapterProperties, null);
-        Class<?> adapteeService = b.loadClass(parser.getString(DescriptorParam.adapteeService));
-        String adapteeFilter = parser.getString(DescriptorParam.adapteeFilter, null);     
-        Service service = dm.createAdapterService(adapteeService, adapteeFilter, adapterService, adapterImpl, adapterProperties);
-        setCommonServiceParams(service, parser);
-        return service;
-    }
-
-    /**
-     * Creates a Bundle Adapter Service.
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Service createBundleAdapterService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        int stateMask = parser.getInt(DescriptorParam.stateMask, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE);
-        String filter = parser.getString(DescriptorParam.filter, null);
-        Class<?> adapterImpl = b.loadClass(parser.getString(DescriptorParam.impl));
-        String service = parser.getString(DescriptorParam.service, null);
-        Dictionary<String, String> properties = parser.getDictionary(DescriptorParam.properties, null);
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
-        Service srv = dm.createBundleAdapterService(stateMask, filter, adapterImpl, service, properties, propagate);  
-        setCommonServiceParams(srv, parser);
-        return srv;
-    }
-
-    /**
-     * Creates a Resource Adapter Service.
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Service createResourceAdapterService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        String filter = parser.getString(DescriptorParam.filter, null);
-        Class<?> impl = b.loadClass(parser.getString(DescriptorParam.impl));
-        String service = parser.getString(DescriptorParam.service, null);
-        Dictionary<String, String> properties = parser.getDictionary(DescriptorParam.properties, null);
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
-        Service srv = dm.createResourceAdapterService(filter, null, service, properties, impl, propagate);  
-        setCommonServiceParams(srv, parser);
-        return srv;
-    }
-
-    /**
-     * Creates a Factory Configuration Adapter Service
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Service createFactoryConfigurationAdapterService(Bundle b, DependencyManager dm, DescriptorParser parser)
-        throws ClassNotFoundException
-    {
-        Class<?> impl = b.loadClass(parser.getString(DescriptorParam.impl));
-        String factoryPid = parser.getString(DescriptorParam.factoryPid);
-        String updated = parser.getString(DescriptorParam.updated);
-        String[] services = parser.getStrings(DescriptorParam.service, null);
-        Dictionary<String, String> properties = parser.getDictionary(DescriptorParam.properties, null);
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
-        Service srv = dm.createFactoryConfigurationAdapterService(factoryPid, updated, impl, services, properties, propagate);
-        setCommonServiceParams(srv, parser);
-        return srv;
-    }
-
-
-    /**
-     * Creates a ServiceDependency that we parsed from a component descriptor "ServiceDependency" entry.
-     */
-    private Dependency createServiceDependency(Bundle b, DependencyManager dm, DescriptorParser parser, boolean temporal) 
-        throws ClassNotFoundException
-    {
-        String service = parser.getString(DescriptorParam.service);
-        Class<?> serviceClass = b.loadClass(service);
-        String serviceFilter = parser.getString(DescriptorParam.filter, null);
-        String defaultServiceImpl = parser.getString(DescriptorParam.defaultImpl, null);
-        Class<?> defaultServiceImplClass = (defaultServiceImpl != null) ? b.loadClass(defaultServiceImpl) : null;
-        String added = parser.getString(DescriptorParam.added, null);
-        String changed = temporal ? null : parser.getString(DescriptorParam.changed, null);
-        String removed = temporal ? null : parser.getString(DescriptorParam.removed, null);
-        String autoConfigField = parser.getString(DescriptorParam.autoConfig, null);
-        boolean required = "true".equals(parser.getString(DescriptorParam.required, "true"));
-        String timeout = parser.getString(DescriptorParam.timeout, null);
-
-        Dependency dp = createServiceDependency(dm, temporal, serviceClass, serviceFilter,
-                                                defaultServiceImplClass, added, changed, removed,
-                                                autoConfigField, timeout, required);
-        return dp;
-    }
-    
-    private Dependency createServiceDependency(DependencyManager dm, boolean temporal, Class<?> serviceClass,
-        String serviceFilter, Class<?> defaultServiceImplClass, String added, String changed, String removed,
-        String autoConfigField, String timeout, boolean required) 
-    {
-        ServiceDependency sd = temporal ? dm.createTemporalServiceDependency()
-            : dm.createServiceDependency();
-        sd.setService(serviceClass, serviceFilter);
-        if (defaultServiceImplClass != null)
-        {
-            sd.setDefaultImplementation(defaultServiceImplClass);
-        }
-        sd.setCallbacks(added, changed, removed);
-        if (autoConfigField != null)
-        {
-            sd.setAutoConfig(autoConfigField);
-        }
-        if (temporal)
-        {
-            // Set the timeout value for a temporal service dependency
-            if (timeout != null)
-            {
-                ((TemporalServiceDependency) sd).setTimeout(Long.parseLong(timeout));
-            }
-            // Set required flag (always true for a temporal dependency)
-            sd.setRequired(true);
-        } else {
-            // for ServiceDependency, get required flag.
-            sd.setRequired(required);
-        }
-        return sd;
-    }
-
-    /**
-     * Creates a ConfigurationDependency that we parsed from a component descriptor entry.
-     * @param b
-     * @param dm
-     * @param parser
-     * @return
-     */
-    private Dependency createConfigurationDependency(Bundle b, DependencyManager dm,
-        DescriptorParser parser)
-    {
-        String pid = parser.getString(DescriptorParam.pid);
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
-        String callback = parser.getString(DescriptorParam.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(Bundle b, DependencyManager dm,
-        DescriptorParser parser)
-    {
-        String added = parser.getString(DescriptorParam.added, null);
-        String changed = parser.getString(DescriptorParam.changed, null);
-        String removed = parser.getString(DescriptorParam.removed, null);
-        boolean required = "true".equals(parser.getString(DescriptorParam.required, "true"));
-        String filter = parser.getString(DescriptorParam.filter, null);
-        int stateMask = parser.getInt(DescriptorParam.stateMask, -1);
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.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(@SuppressWarnings("unused") Bundle b, DependencyManager dm,
-        DescriptorParser parser)
-    {
-        String added = parser.getString(DescriptorParam.added, null);
-        String changed = parser.getString(DescriptorParam.changed, null);
-        String removed = parser.getString(DescriptorParam.removed, null);
-        String filter = parser.getString(DescriptorParam.filter, null);
-        boolean required = "true".equals(parser.getString(DescriptorParam.required, "true"));
-        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
-
-        Dependency dp = createResourceDependency(dm, added, changed, removed, required, filter, propagate);
-        return dp;
-    }
-    
-    private Dependency createResourceDependency(DependencyManager dm, String added, String changed, String removed, boolean required, String filter, boolean propagate)
-    {
-        ResourceDependency rd = dm.createResourceDependency();
-        rd.setCallbacks(added, changed, removed);
-        rd.setRequired(required);
-        if (filter != null) 
-        {
-            rd.setFilter(filter);
-        }
-        rd.setPropagate(propagate);
-        return rd;
-    }
-}
\ No newline at end of file
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
new file mode 100644
index 0000000..42fdf89
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
@@ -0,0 +1,250 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.BundleDependency;
+import org.apache.felix.dm.dependencies.ConfigurationDependency;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.dependencies.ResourceDependency;
+import org.apache.felix.dm.dependencies.ServiceDependency;
+import org.apache.felix.dm.dependencies.TemporalServiceDependency;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class used to build a concrete dependency from meta data.
+ */
+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
+    {
+        return build(b, dm, false);
+    }
+
+    public Dependency build(Bundle b, DependencyManager dm, boolean instanceBound)
+        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, false, instanceBound);
+                break;
+
+            case TemporalServiceDependency:
+                dp = createServiceDependency(b, dm, true, instanceBound);
+                break;
+
+            case ConfigurationDependency:
+                dp = createConfigurationDependency(dm, instanceBound);
+                break;
+
+            case BundleDependency:
+                dp = createBundleDependency(dm, instanceBound);
+                break;
+
+            case ResourceDependency:
+                dp = createResourceDependency(dm, instanceBound);
+                break;
+        }
+        return dp;
+    }
+
+    private Dependency createServiceDependency(Bundle b, DependencyManager dm, boolean temporal,
+        boolean instanceBound)
+        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);
+        String changed = temporal ? null : m_metaData.getString(Params.changed, null);
+        String removed = temporal ? 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"));
+        String timeout = m_metaData.getString(Params.timeout, null);
+
+        Dependency dp = createServiceDependency(dm, temporal, serviceClass,
+            serviceFilter, defaultServiceImplClass, added, changed,
+            removed, autoConfigField, timeout, required, instanceBound);
+        return dp;
+    }
+
+    private Dependency createServiceDependency(DependencyManager dm, boolean temporal,
+        Class<?> serviceClass, String serviceFilter, Class<?> defaultServiceImplClass, String added,
+        String changed, String removed, String autoConfigField, String timeout, boolean required,
+        boolean instanceBound)
+    {
+        ServiceDependency sd = temporal ? dm.createTemporalServiceDependency()
+            : dm.createServiceDependency();
+        sd.setService(serviceClass, serviceFilter);
+        if (defaultServiceImplClass != null)
+        {
+            sd.setDefaultImplementation(defaultServiceImplClass);
+        }
+        sd.setCallbacks(added, changed, removed);
+        if (autoConfigField != null)
+        {
+            sd.setAutoConfig(autoConfigField);
+        }
+        if (temporal)
+        {
+            // Set the timeout value for a temporal service dependency
+            if (timeout != null)
+            {
+                ((TemporalServiceDependency) sd).setTimeout(Long.parseLong(timeout));
+            }
+            // Set required flag (always true for a temporal dependency)
+            sd.setRequired(true);
+        }
+        else
+        {
+            // for ServiceDependency, get required flag.
+            sd.setRequired(required);
+        }
+        
+        sd.setInstanceBound(instanceBound);
+        return sd;
+    }
+
+    private Dependency createConfigurationDependency(DependencyManager dm, boolean instanceBound)
+    {
+        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, instanceBound);
+        return dp;
+    }
+
+    private Dependency createConfigurationDependency(DependencyManager dm, String pid, String callback,
+        boolean propagate, boolean instanceBound)
+    {
+        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);
+        cd.setInstanceBound(instanceBound);
+        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, boolean instanceBound)
+    {
+        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, instanceBound);
+        return dp;
+    }
+
+    private Dependency createBundleDependency(DependencyManager dm, String added, String changed,
+        String removed, boolean required, boolean propagate, String filter, int stateMask, boolean instanceBound)
+    {
+        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);
+        }
+        bd.setInstanceBound(instanceBound);
+        return bd;
+    }
+
+    private Dependency createResourceDependency(DependencyManager dm, boolean instanceBound)
+    {
+        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"));
+
+        Dependency dp = createResourceDependency(dm, added, changed, removed, required, filter, propagate, instanceBound);
+        return dp;
+    }
+
+    private Dependency createResourceDependency(DependencyManager dm, String added,
+        String changed, String removed, boolean required, String filter, boolean propagate, boolean instanceBound)
+    {
+        ResourceDependency rd = dm.createResourceDependency();
+        rd.setCallbacks(added, changed, removed);
+        rd.setRequired(required);
+        if (filter != null)
+        {
+            rd.setFilter(filter);
+        }
+        rd.setPropagate(propagate);
+        rd.setInstanceBound(instanceBound);
+        return rd;
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
new file mode 100644
index 0000000..92b4b62
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
@@ -0,0 +1,218 @@
+/*
+ * 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.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.service.log.LogService;
+
+/**
+ * This class parses service descriptors generated by the annotation bnd processor.
+ * The descriptors are located under OSGI-INF/dependencymanager directory. Such files are actually 
+ * referenced by a specific "DependendencyManager-Component" manifest header.
+ */
+public class DependencyManagerRuntime implements SynchronousBundleListener
+{
+    private ConcurrentHashMap<Bundle, DependencyManager> m_managers = new ConcurrentHashMap<Bundle, DependencyManager>();
+    private static LogService m_log; // Injected
+    private BundleContext m_bctx; // Injected
+    private DescriptorParser m_parser;
+
+    /**
+     * 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()
+    {
+        // Register our log service.
+        Log.instance().setLogService(m_log);
+        
+        // Instantiates our descriptor parser, and register our service builders into it.
+        m_parser = new DescriptorParser();
+        m_parser.addBuilder(new ServiceBuilder());
+        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());
+
+        // Load already started bundles
+        for (Bundle b: m_bctx.getBundles())
+        {
+            if (b.getState() == Bundle.ACTIVE)
+            {
+                bundleChanged(new BundleEvent(Bundle.ACTIVE, b));
+            }
+        }
+
+        // Track bundles
+        m_bctx.addBundleListener(this);
+    }
+
+    /**
+     * Stops our service. We'll stop all activated DependencyManager services.
+     */
+    @SuppressWarnings("unchecked")
+    protected void stop()
+    {
+        m_log.log(LogService.LOG_INFO, "DependencyManager Runtime stopping: removing services");
+
+        for (DependencyManager dm: m_managers.values())
+        {
+            List<Service> services = new ArrayList<Service>(dm.getServices());
+            for (Service service: services)
+            {
+                m_log.log(LogService.LOG_INFO, "DependencyManager Runtime stopping: removing service: "
+                    + service);
+                dm.remove(service);
+            }
+        }
+
+        m_managers.clear();
+    }
+
+    /**
+     * Register a LogService, so other components may use it
+     */
+    protected void bind(LogService logService) {
+        m_log = logService;
+        Log.instance().setLogService(logService);
+    }
+    
+    /**
+     * Handle a bundle event, and eventually parse started bundles.
+     */
+    public void bundleChanged(BundleEvent event)
+    {
+        Bundle b = event.getBundle();
+        if (b.getState() == Bundle.ACTIVE)
+        {
+            bundleStarted(b);
+        }
+        else if (b.getState() == Bundle.STOPPING)
+        {
+            bundleStopping(b);
+        }
+    }
+
+    /**
+     * Checks if a started bundle have some DependencyManager descriptors 
+     * referenced in the "DependencyManager-Component" OSGi header.
+     * @param b the started bundle.
+     */
+    void bundleStarted(Bundle b)
+    {
+        String descriptorPaths = (String) b.getHeaders().get("DependencyManager-Component");
+        if (descriptorPaths == null)
+        {
+            return;
+        }
+
+        for (String descriptorPath: descriptorPaths.split(","))
+        {
+            URL descriptorURL = b.getEntry(descriptorPath);
+            if (descriptorURL == null)
+            {
+                m_log.log(LogService.LOG_ERROR,
+                          "DependencyManager component descriptor not found: " + descriptorPath);
+                continue;
+            }
+            loadDescriptor(b, descriptorURL);
+        }
+    }
+
+    /**
+     * Unregisters all services for a stopping bundle.
+     * @param b
+     */
+    @SuppressWarnings("unchecked")
+    private void bundleStopping(Bundle b)
+    {
+        m_log.log(LogService.LOG_INFO, "Removing services from stopping bundle: " + b.getSymbolicName());
+        DependencyManager dm = m_managers.remove(b);
+        if (dm != null)
+        {
+            List<Service> services = new ArrayList(dm.getServices());
+            for (Service service: services)
+            {
+                m_log.log(LogService.LOG_INFO, "Removing service service: " + service);
+                dm.remove(service);
+            }
+        }
+    }
+
+    /**
+     * Load a DependencyManager component descriptor from a given bundle.
+     * @param b
+     * @param descriptorURL
+     */
+    private void loadDescriptor(Bundle b, URL descriptorURL)
+    {
+        m_log.log(LogService.LOG_DEBUG, "Parsing descriptor " + descriptorURL
+            + " from bundle " + 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);
+            m_managers.put(b, dm);
+        }
+
+        catch (Throwable t)
+        {
+            m_log.log(LogService.LOG_ERROR, "Error while parsing descriptor "
+                + descriptorURL + " from bundle " + b.getSymbolicName(), t);
+        }
+
+        finally
+        {
+            if (in != null)
+            {
+                try
+                {
+                    in.close();
+                }
+                catch (IOException ignored)
+                {
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java
deleted file mode 100644
index c208a9a..0000000
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.EnumSet;
-
-/**
- * List of all valid attribute a DependencyManager component descriptor may contain.
- * @see DescriptorParser for the descriptor syntax.
- */
-public enum DescriptorParam
-{
-    /* Service attribute for the init method (the parsed value is a String) */
-    init,
-
-    /* Service attribute for the start method (the parsed value is a String) */
-    start,
-
-    /* Stop attribute for the stop method (the parsed value is a String) */
-    stop,
-
-    /* Service attribute for the destroy method (the parsed value is a String) */
-    destroy,
-
-    /* Service attribute for the impl service class name (the parsed value is a String) */
-    impl,
-
-    /* Service attribute for the provided services class names (the parsed value is a String[]) */
-    provide,
-
-    /* Service attribute for the provided service properties (the parsed value is a Hashtable) */
-    properties,
-
-    /* Service attribute for the composition method name (the parsed value is a String) */
-    composition,
-
-    /* ServiceDependency attribute for the interface we depend on (the parsed value is a String) */
-    service,
-
-    /* ServiceDependency attribute for the service filter (the parsed value is a String) */
-    filter,
-
-    /* ServiceDependency attribute for the service default impl (the parsed value is a String) */
-    defaultImpl,
-
-    /* ServiceDependency attribute for the required boolean (the parsed value is a String ("false"|"true") */
-    required,
-
-    /* ServiceDependency attribute for the added callback name (the parsed value is a String) */
-    added,
-
-    /* ServiceDependency attribute for the added changed name (the parsed value is a String) */
-    changed,
-
-    /* ServiceDependency attribute for the added removed name (the parsed value is a String) */
-    removed,
-
-    /* ServiceDependency attribute for the auto config field name (the parsed value is a String) */
-    autoConfig,
-
-    /* ConfigurationDependency attribute for the PID (the parsed value is a String) */
-    pid,
-
-    /* ConfigurationDependency attribute for the propagate boolean (the parsed value is a String ("false"|"true") */
-    propagate,
-
-    /* ConfigurationDependency attribute for the updated callback method (the parsed value is a String */
-    updated,
-    
-    /* TemporalServiceDependency attribute for the timeout (the parsed value is a String) */
-    timeout,
-    
-    /* AdapterService attribute for the adapter interface (the parsed value is a String) */
-    adapterService,
-    
-    /* AdapterService attribute for the adapter service properties (the parsed value is a Hashtable) */
-    adapterProperties,
-    
-    /* AdapterService attribute for the adaptee service (the parsed value is a String) */
-    adapteeService,
-    
-    /* AdapterService attribute for the adaptee service filter (the parsed value is a String) */
-    adapteeFilter,
-    
-    /* BundleDependency attribute for the state mask bundle (the parsed value is a string) */
-    stateMask,
-    
-    /* The ranking of an aspect (the parsed value is an int) */
-    ranking,
-    
-    /* The factory pid of an FactoryConfigurationAdapterService annotation (the parsed value is a string) */
-    factoryPid,    
-    
-    /* the factory attribute for the Service annotation (the parsed value is a string) */
-    factory,
-    
-    /* the factoryConfigure attribute for the Service annotation (the parsed value is a string) */
-    factoryConfigure
-}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
index 9804973..81728f8 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
@@ -18,323 +18,58 @@
  */
 package org.apache.felix.dm.runtime;
 
+import java.io.BufferedReader;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
+import org.apache.felix.dm.DependencyManager;
+import org.json.JSONObject;
+import org.osgi.framework.Bundle;
 import org.osgi.service.log.LogService;
 
 /**
  * This class parses files generated in OSGI-INF/*.dm by the DependencyManager bnd plugin.
- * Each descriptor contains the definition of a Service, along with its corresponding service dependency or configuration dependencies.
- * Here is an example of a typical descriptor syntax:
- *   
- *    Service: start=start; stop=stop; impl=org.apache.felix.dm.test.annotation.ServiceConsumer; 
- *    ServiceDependency: service=org.apache.felix.dm.test.annotation.ServiceInterface; autoConfig=m_service; 
- *    ServiceDependency: added=bind; service=org.apache.felix.dm.test.annotation.ServiceInterface; 
- * 
- * Notice that the descriptor must start with a "Service" definition. (Dependencies must be declared after the "Service" entry).
- * <p>
- * 
- * Now, here is the formal BNF definition of the descriptor syntax:
- *
- *    line := <type> ':' <params>
- *    
- *    type := service|aspectservice|serviceDependency|configurationDependency|temporalServiceDependency
- *    service := 'Service'
- *    aspectservice := 'AspectService'
- *    serviceDependency := 'ServiceDependency'
- *    configurationDependency := 'ConfigurationDependency'
- *    temporalServiceDependency := 'TemporalServiceDependency'
- *    
- *    params := paramName '=' paramValue ( ';' paramName '=' paramValue )*
- *    
- *    paramName := init | start | stop | destroy | impl | provide | properties | factory | factoryMethod | composition | service | filter | 
- *                 defaultImpl | required | added | changed | removed | autoConfig | pid | propagate | updated | timeout |
- *                 adapterService | adapterProperties | adapteeService | adapteeFilter
- *    init := 'init'
- *    start := 'start'
- *    stop := 'stop'
- *    destroy := 'destroy'
- *    impl := 'impl'
- *    provide := 'provide'
- *    properties := 'properties'
- *    factory := 'factory'
- *    factoryMethod := 'factoryMethod'
- *    composition := 'composition'
- *    service := 'service'
- *    filter := 'filter'
- *    defaultImpl := 'defaultImpl'
- *    required := 'required'
- *    added := 'added'
- *    changed := 'changed'
- *    removed := 'removed'
- *    autoConfig := 'autoConfig'
- *    pid := 'pid'
- *    propagate := 'propagate'
- *    updated := 'updated'
- *    timeout := 'timeout'
- *    adapterService := 'adapterService'
- *    adapterProperties := 'adapterProperties'
- *    adapteeService := 'adapteeService'
- *    adapteeFilter := 'adapteeFilter'
- *     
- *    paramValue := strings | attributes
- *    strings := string ( ',' string )*
- *    attributes := string ':' string ( ',' string : string )*
- *    string := [alphanum string]
+ * Each descriptor contains a JSON definition of a Service, along with its corresponding service dependency or configuration dependencies.
  */
 public class DescriptorParser
 {
-    private LogService m_logService;
-    private Map<DescriptorParam, Object> m_params = new HashMap<DescriptorParam, Object>();
+    private Map<String, ServiceComponentBuilder> m_builders = new HashMap<String, ServiceComponentBuilder>();
 
-    private final static Pattern linePattern = Pattern.compile("(\\w+):\\s*(.*)", Pattern.COMMENTS);
-    private final static Pattern paramPattern = Pattern.compile("([^=]+)=([^;]+);?");
-    private final static Pattern stringsPattern = Pattern.compile("([^,]+)");
-    private final static Pattern attributesPattern = Pattern.compile("([^:]+):([^,]+),?");
-
-    public DescriptorParser(LogService service)
+    public void addBuilder(ServiceComponentBuilder sb)
     {
-        m_logService = service;
+        m_builders.put(sb.getType(), sb);
     }
 
-    /*
-     * Parses a DependencyManager component descriptor entry (either a Service, a ServiceDependency, or a ConfigurationDependency entry).
-     * @return DescriptorEntry.Service, DescriptorEntry.ServiceDependency, or DescriptorEntry.ConfigurationDependency 
-     */
-    public DescriptorEntry parse(String line)
+    public void parse(BufferedReader reader, Bundle b, DependencyManager dm) throws Exception
     {
-        m_params.clear();
-        Matcher lineMatcher = linePattern.matcher(line);
-        if (lineMatcher.matches())
-        {
-            DescriptorEntry entry = DescriptorEntry.valueOf(lineMatcher.group(1).trim());
-            Matcher paramMatcher = paramPattern.matcher(lineMatcher.group(2).trim());
-            while (paramMatcher.find())
-            {
-                DescriptorParam paramName = DescriptorParam.valueOf(paramMatcher.group(1).trim());
-                String paramValue = paramMatcher.group(2).trim();
-                Matcher attributesMatcher = attributesPattern.matcher(paramValue);
-                boolean matched = false;
+        String line;
 
-                Hashtable<String, String> attributes = new Hashtable<String, String>();
-                while (attributesMatcher.find())
-                {
-                    matched = true;
-                    attributes.put(attributesMatcher.group(1).trim(),
-                        attributesMatcher.group(2).trim());
-                }
-                m_params.put(paramName, attributes);
+        // The first line is a Service Component (a Service, an Aspect Service, etc ...)
+        line = reader.readLine();
+        Log.instance().log(LogService.LOG_DEBUG, "Parsing destriptor entry line: " + line);
+        JSONObject json = new JSONObject(line);
+        JSONMetaData serviceMetaData = new JSONMetaData(json);
 
-                if (!matched)
-                {
-                    Matcher stringsMatcher = stringsPattern.matcher(paramValue);
-                    if (stringsMatcher.groupCount() > 0)
-                    {
-                        List<String> strings = new ArrayList<String>();
-                        while (stringsMatcher.find())
-                        {
-                            strings.add(stringsMatcher.group(1).trim());
-                        }
-                        m_params.put(paramName, strings.toArray(new String[strings.size()]));
-                    }
-                }
-            }
+        String type = (String) json.get("type");
+        ServiceComponentBuilder builder = m_builders.get(type);
+        if (builder == null)
+        {
+            throw new IllegalArgumentException("Invalid descriptor"
+                + ": no \"type\" parameter found in first line");
+        }
 
-            m_logService.log(LogService.LOG_DEBUG, "Parsed " + entry + ": " + toString());
-            return entry;
-        }
-        else
+        // Parse the rest of the lines (dependencies)
+        List<MetaData> serviceDependencies = new ArrayList<MetaData>();
+        while ((line = reader.readLine()) != null)
         {
-            throw new IllegalArgumentException("Invalid descriptor entry: " + line);
+            Log.instance().log(LogService.LOG_DEBUG, "Parsing destriptor entry line: " + line);
+            JSONObject dep = new JSONObject(line);
+            serviceDependencies.add(new JSONMetaData(dep));
         }
-    }
 
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     * @param param
-     * @return
-     */
-    public String getString(DescriptorParam param)
-    {
-        Object value = m_params.get(param);
-        if (value == null)
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not found");
-        }
-        if (!(value instanceof String[]))
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not a String array");
-        }
-        String[] array = (String[]) value;
-        if (array.length < 1)
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not found");
-        }
-        return (array[0]);
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     *
-     * @param param
-     * @param def
-     * @return
-     */
-    public String getString(DescriptorParam param, String def)
-    {
-        try
-        {
-            return getString(param);
-        }
-        catch (IllegalArgumentException e)
-        {
-            return def;
-        }
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     *
-     * @param param
-     * @param def
-     * @return
-     */
-    public int getInt(DescriptorParam param)
-    {
-        String value = getString(param, null);
-        if (value != null)
-        {
-            try
-            {
-                return Integer.parseInt(value);
-            }
-            catch (NumberFormatException e)
-            {
-                throw new IllegalArgumentException("parameter " + param + " is not an int value: "
-                    + value);
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException("missing " + param + " parameter from annotation");
-        }
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     *
-     * @param param
-     * @param def
-     * @return
-     */
-    public int getInt(DescriptorParam param, int def)
-    {
-        String value = getString(param, null);
-        if (value != null)
-        {
-            try
-            {
-                return Integer.parseInt(value);
-            }
-            catch (NumberFormatException e)
-            {
-                throw new IllegalArgumentException("parameter " + param + " is not an int value: "
-                    + value);
-            }
-        }
-        else
-        {
-            return def;
-        }
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     * @param param
-     * @return
-     */
-    public String[] getStrings(DescriptorParam param)
-    {
-        Object value = m_params.get(param);
-        if (value == null)
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not found");
-        }
-        if (!(value instanceof String[]))
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not a String array");
-        }
-        return (String[]) value;
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     * @param param
-     * @return
-     */
-    public String[] getStrings(DescriptorParam param, String[] def)
-    {
-        try
-        {
-            return getStrings(param);
-        }
-        catch (IllegalArgumentException e)
-        {
-            return def;
-        }
-    }
-
-    /**
-     * Once a component descriptor entry line is parsed, you can retrieve entry attributes using this method.
-     * @param param
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public Dictionary<String, String> getDictionary(DescriptorParam param, Dictionary<String, String> def)
-    {
-        Object value = m_params.get(param);
-        if (value == null)
-        {
-            return def;
-        }
-        if (!(value instanceof Dictionary))
-        {
-            throw new IllegalArgumentException("Parameter " + param + " not Dictionary");
-        }
-        return (Dictionary<String, String>) value;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-        for (Map.Entry<DescriptorParam, Object> entry : m_params.entrySet())
-        {
-            sb.append(entry.getKey());
-            sb.append("=");
-            Object val = entry.getValue();
-            if (val instanceof String || val instanceof Dictionary<?, ?>)
-            {
-                sb.append(val.toString());
-            }
-            else if (val instanceof String[])
-            {
-                sb.append(Arrays.toString((String[]) val));
-            }
-            else
-            {
-                sb.append(val.toString());
-            }
-            sb.append(";");
-        }
-        return sb.toString();
+        // and Invoke the builder
+        builder.buildService(serviceMetaData, serviceDependencies, b, dm);
     }
 }
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
new file mode 100644
index 0000000..dc8ce75
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+public class FactoryConfigurationAdapterServiceBuilder extends ServiceComponentBuilder
+{
+    private final static String TYPE = "FactoryConfigurationAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData serviceMetaData,
+        List<MetaData> serviceDependencies,
+        Bundle b, DependencyManager dm) throws Exception
+    {
+        Class<?> impl = b.loadClass(serviceMetaData.getString(Params.impl));
+        String factoryPid = serviceMetaData.getString(Params.factoryPid);
+        String updated = serviceMetaData.getString(Params.updated);
+        String[] services = serviceMetaData.getStrings(Params.service, null);
+        Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+        Service srv = dm.createFactoryConfigurationAdapterService(factoryPid, updated, impl, services, properties, propagate);
+        setCommonServiceParams(srv, serviceMetaData);
+        for (MetaData dependencyMetaData: serviceDependencies)
+        {
+            Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+            srv.add(dp);
+        }
+        dm.add(srv);
+    }    
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java
new file mode 100644
index 0000000..7fc7054
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/JSONMetaData.java
@@ -0,0 +1,259 @@
+/*
+ * 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.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * A JSON MetaData.
+ */
+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 a JSON metadata for either a Service or a Dependency descriptor entry.
+     * The JSON object values contains either some of the following types: a String, a String[], or a Dictionary of String/String[].
+     * @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)
+            {
+                String[] array = decodeStringArray((JSONArray) value);
+                m_metadata.put(key, array);
+            }
+            else if (value instanceof JSONObject)
+            {
+                Hashtable<String, Object> h = new Hashtable<String, Object>();
+                JSONObject obj = ((JSONObject) value);
+                Iterator<String> it2 = obj.keys();
+                while (it2.hasNext())
+                {
+                    String key2 = it2.next();
+                    Object value2 = obj.get(key2);
+                    if (value2 instanceof String)
+                    {
+                        h.put(key2, value2);
+                    }
+                    else if (value2 instanceof JSONArray)
+                    {
+                        String[] array = decodeStringArray((JSONArray) value2);
+                        h.put(key2, array);
+                    }
+                    else
+                    {
+                        throw new IllegalArgumentException("Could not decode JSON metadata: key " + key +
+                                "contains an invalid dictionary key: " + key
+                                + " (the value is neither a String nor a String[]).");
+                    }
+                }
+                m_metadata.put(key, h);
+            }
+        }
+    }
+
+    /**
+     * 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)
+    {
+        String value = (String) m_metadata.get(key.toString());
+        if (value == null)
+        {
+            throw new IllegalArgumentException("Parameter " + key + " not found");
+        }
+        return value;
+    }
+
+    public String getString(Params key, String def)
+    {
+        try
+        {
+            return getString(key);
+        }
+        catch (IllegalArgumentException e)
+        {
+            return def;
+        }
+    }
+
+    public int getInt(Params key)
+    {
+        String value = getString(key, null);
+        if (value != null)
+        {
+            try
+            {
+                return Integer.parseInt(value);
+            }
+            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)
+    {
+        String value = getString(key, null);
+        if (value != null)
+        {
+            try
+            {
+                return Integer.parseInt(value);
+            }
+            catch (NumberFormatException e)
+            {
+                throw new IllegalArgumentException("parameter " + key
+                    + " is not an int 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/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java
new file mode 100644
index 0000000..198a6a9
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java
@@ -0,0 +1,60 @@
+/*
+ * 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.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+public class Log implements LogService
+{
+    /** The log service */
+    private static LogService m_logService;
+    
+    /** Our sole instance */
+    private static Log m_instance = new Log();
+    
+    public static Log instance()
+    {
+        return m_instance;
+    }
+    
+    public void setLogService(LogService logService) {
+        m_logService = logService;
+    }
+    
+    public void log(int level, String message, Throwable exception)
+    {
+        m_logService.log(level, message, exception);
+    }
+
+    public void log(int level, String message)
+    {
+        m_logService.log(level, message);
+    }
+
+    public void log(ServiceReference sr, int level, String message, Throwable exception)
+    {
+        m_logService.log(sr, level, message, exception);
+    }
+
+    public void log(ServiceReference sr, int level, String message)
+    {
+        m_logService.log(sr, level, message);
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
new file mode 100644
index 0000000..7c56a30
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+
+/**
+ * This class represents the meta data parsed from a descriptor entry (json) line.
+ */
+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 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);
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
similarity index 63%
rename from dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java
rename to dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
index 3a5e769..264d3da 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
@@ -19,20 +19,39 @@
 package org.apache.felix.dm.runtime;
 
 /**
- * Type of each DependendencyManager component descriptor entry.
- * @see DescriptorParser for more informations about the descriptor syntax.
+ * List of descriptor parameters.
  */
-public enum DescriptorEntry
+public enum Params
 {
-    Service,
-    AspectService,
-    AdapterService,
-    BundleAdapterService,
-    ResourceAdapterService,
-    FactoryConfigurationAdapterService,
-    ServiceDependency,
-    TemporalServiceDependency,
-    ConfigurationDependency,
-    BundleDependency,
-    ResourceDependency
+    type,
+    init,
+    start,
+    stop,
+    destroy,
+    impl,
+    provide,
+    properties,
+    composition,
+    service,
+    filter,
+    defaultImpl,
+    required,
+    added,
+    changed,
+    removed,
+    autoConfig,
+    pid,
+    propagate,
+    updated,
+    timeout,
+    adapterService,
+    adapterProperties,
+    adapteeService,
+    adapteeFilter,
+    stateMask,
+    ranking,
+    factoryPid,    
+    factory,
+    factoryConfigure,
+    name
 }
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
new file mode 100644
index 0000000..e172f30
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
@@ -0,0 +1,58 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+public class ResourceAdapterServiceBuilder extends ServiceComponentBuilder
+{
+    private final static String TYPE = "ResourceAdapterService";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData serviceMetaData,
+        List<MetaData> serviceDependencies,
+        Bundle b, DependencyManager dm) throws Exception
+    {
+        String filter = serviceMetaData.getString(Params.filter, null);
+        Class<?> impl = b.loadClass(serviceMetaData.getString(Params.impl));
+        String[] service = serviceMetaData.getStrings(Params.service, null);
+        Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
+        boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+        Service srv = dm.createResourceAdapterService(filter, null, service, properties, impl, propagate);  
+        setCommonServiceParams(srv, serviceMetaData);
+        for (MetaData dependencyMetaData: serviceDependencies)
+        {
+            Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+            srv.add(dp);
+        }
+        dm.add(srv);
+    }    
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java
new file mode 100644
index 0000000..5e51daa
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java
@@ -0,0 +1,114 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.LogService;
+
+public class ServiceBuilder extends ServiceComponentBuilder
+{
+    private final static String TYPE = "Service";
+
+    @Override
+    public String getType()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public void buildService(MetaData srvMeta, List<MetaData> srvDeps, Bundle b, DependencyManager dm)
+        throws Exception
+    {
+        Log.instance().log(LogService.LOG_DEBUG, "building service: service metadata=" + srvMeta
+            + ", dependencyMetaData=" + srvDeps);
+
+        // Get service parameters (lifecycle callbacks, composition, factory, etc ...)
+
+        Service service = dm.createService();
+        String factory = srvMeta.getString(Params.factory, null);
+        String factoryConfigure = srvMeta.getString(Params.factoryConfigure, null);
+        String impl = srvMeta.getString(Params.impl);
+        String init = srvMeta.getString(Params.init, null);
+        String start = srvMeta.getString(Params.start, null);
+        String stop = srvMeta.getString(Params.stop, null);
+        String destroy = srvMeta.getString(Params.destroy, null);
+        String composition = srvMeta.getString(Params.composition, null);
+        Dictionary<String, Object> serviceProperties = srvMeta.getDictionary(Params.properties, null);
+        String[] provide = srvMeta.getStrings(Params.provide, null);
+
+        // Check if we must provide a Set Factory.
+        if (factory == null)
+        {
+            // No: instantiate the service.
+            service.setImplementation(b.loadClass(impl));
+            if (composition != null)
+            {
+                service.setComposition(composition);
+            }
+            if (provide != null)
+            {
+                service.setInterface(provide, serviceProperties);
+            }
+
+            // Creates a ServiceHandler, which will filter all service lifecycle callbacks.
+            /*
+            ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(service, b, dm, srvMeta,
+                                                                               srvDeps);
+            service.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+            String confDependency = DependencyBuilder.DependencyType.ConfigurationDependency.toString();
+            */
+            // TODO REMOVE
+            for (MetaData depMeta: srvDeps)
+            {
+                Dependency dp = new DependencyBuilder(depMeta).build(b, dm);
+                service.add(dp);
+            }
+        }
+        else
+        {
+            // 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 use registers some
+            // service configurations into it in order to fire some service instantiations.
+
+            ServiceFactory serviceFactory =  new ServiceFactory(b.loadClass(impl), init, start, stop, destroy, 
+                                                                composition, serviceProperties, provide, 
+                                                                factoryConfigure);
+            for (MetaData dependencyMetaData: srvDeps)
+            {
+                Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
+                serviceFactory.addDependency(dp);
+            }
+            service.setImplementation(serviceFactory);
+            service.setCallbacks(null, "start", "stop", null);
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put("dm.factory.name", factory);
+            service.setInterface(Set.class.getName(), props);
+        }
+
+        dm.add(service);
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceComponentBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceComponentBuilder.java
new file mode 100644
index 0000000..607375e
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceComponentBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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.DependencyManager;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+/**
+ * The builder which creates a DependencyManager Service (a Service and all its derived classes (Aspect/Adapters).
+ */
+public abstract class ServiceComponentBuilder
+{
+    /**
+     * 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 buildService(MetaData serviceMetaData, List<MetaData> serviceDependencies, Bundle b,
+        DependencyManager dm)
+        throws Exception;
+
+    /**
+     * Set common Service parameters, if provided from our Component descriptor
+     */
+    protected void setCommonServiceParams(Service service, MetaData serviceMetaData)
+        throws Exception
+    {
+        String init = serviceMetaData.getString(Params.init, null);
+        String start = serviceMetaData.getString(Params.start, null);
+        String stop = serviceMetaData.getString(Params.stop, null);
+        String destroy = serviceMetaData.getString(Params.destroy, null);
+        service.setCallbacks(init, start, stop, destroy);
+        String composition = serviceMetaData.getString(Params.composition, null);
+        if (composition != null)
+        {
+            service.setComposition(composition);
+        }
+    }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
new file mode 100644
index 0000000..e8cc435
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
@@ -0,0 +1,203 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class acts as a service implementation lifecycle handler. If the actual service implementation
+ * init method returns a Map, then this map will is inspected for dependency filters, which will be 
+ * applied to the dependencies specified in the service.
+ */
+public class ServiceLifecycleHandler
+{
+    private String m_init;
+    private String m_start;
+    private String m_stop;
+    private String m_destroy;
+    private List<MetaData> m_dependencies = new ArrayList<MetaData>();
+    private Map<String, MetaData> m_namedDependencies = new HashMap<String, MetaData>();
+    private Bundle m_bundle;
+
+    public ServiceLifecycleHandler(Service srv, Bundle srvBundle, DependencyManager dm,
+                                   MetaData srvMetaData, List<MetaData> srvDep)
+        throws Exception
+    {
+        m_init = srvMetaData.getString(Params.init, null);
+        m_start = srvMetaData.getString(Params.start, null);
+        m_stop = srvMetaData.getString(Params.stop, null);
+        m_destroy = srvMetaData.getString(Params.destroy, null);
+        m_bundle = srvBundle;
+
+        String confDependency = DependencyBuilder.DependencyType.ConfigurationDependency.toString();
+        for (MetaData depMeta: srvDep)
+        {
+            if (depMeta.getString(Params.type).equals(confDependency))
+            {
+                // Register Configuration dependencies now
+                Dependency dp = new DependencyBuilder(depMeta).build(m_bundle, dm);
+                srv.add(dp);
+            }
+            else
+            {
+                String name = depMeta.getString(Params.name, null);
+                if (name != null)
+                {
+                    m_namedDependencies.put(name, depMeta);
+                }
+                else
+                {
+                    m_dependencies.add(depMeta);
+                }
+            }
+        }
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public void init(Object serviceInstance, DependencyManager dm, Service service)
+        throws Exception
+    {
+        // Invoke the service instance actual init method.
+        Object o = invokeMethod(serviceInstance, m_init, dm, service);
+
+        // If the init method returned a Map, then apply all filters found from it into
+        // the service dependencies. Keys = Dependency name / values = Dependency filter
+        if (o != null && Map.class.isAssignableFrom(o.getClass()))
+        {
+            Map<String, String> filters = (Map<String, String>) o;
+            for (Map.Entry<String, String> entry: filters.entrySet())
+            {
+                String name = entry.getKey();
+                String filter = entry.getValue();
+
+                MetaData dependency = m_namedDependencies.remove(name);
+                if (dependency != null)
+                {
+                    dependency.setString(Params.filter, filter);
+                    DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                    Dependency d = depBuilder.build(m_bundle, dm, true);
+                    service.add(d);
+                }
+                else
+                {
+                    throw new IllegalArgumentException("Invalid filter Map: the filter key " + name
+                        + " does not correspond " +
+                        " to a known Dependency.");
+                }
+            }
+        }
+
+        plugDependencies(m_namedDependencies.values(), dm, service);
+        plugDependencies(m_dependencies, dm, service);
+    }
+
+    public void start(Object serviceInstance, DependencyManager dm, Service service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        invokeMethod(serviceInstance, m_start, dm, service);
+    }
+
+    public void stop(Object serviceInstance, DependencyManager dm, Service service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        invokeMethod(serviceInstance, m_stop, dm, service);
+    }
+
+    public void destroy(Object serviceInstance, DependencyManager dm, Service service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        invokeMethod(serviceInstance, m_destroy, dm, service);
+    }
+
+    private Object invokeMethod(Object serviceInstance, String method, DependencyManager dm, Service service)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        return invokeMethod(serviceInstance,
+            method,
+            new Class[][] {
+                            { Object.class, DependencyManager.class, Service.class },
+                            { DependencyManager.class, Service.class },
+                            { Object.class },
+                            {}
+            },
+            new Object[][] {
+                            { serviceInstance, dm, service },
+                            { dm, service },
+                            { serviceInstance },
+                            {}
+            });
+    }
+
+    private Object invokeMethod(Object instance, String method, Class<?>[][] signatures, Object[][] params)
+        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
+    {
+        if (method == null)
+        {
+            // The annotated class did not provide an annotation for this lifecycle callback.
+            return null;
+        }
+
+        Class clazz = instance.getClass();
+
+        while (clazz != null)
+        {
+            for (int i = 0; i < signatures.length; i++)
+            {
+                Class<?>[] signature = signatures[i];
+                try
+                {
+                    // Don't use getMethod because getMethod only look for public methods !
+                    Method m = instance.getClass().getDeclaredMethod(method, signature);
+                    m.setAccessible(true);
+                    return m.invoke(instance, params[i]);
+                }
+                catch (NoSuchMethodException e)
+                {
+                    // ignore this and keep looking
+                }
+            }
+            clazz = clazz.getSuperclass();
+        }
+
+        return null;
+    }
+
+    private void plugDependencies(Collection<MetaData> dependencies, DependencyManager dm, Service service)
+        throws Exception
+    {
+        for (MetaData dependency: dependencies)
+        {
+            DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+            Dependency d = depBuilder.build(m_bundle, dm, true);
+            service.add(d);
+        }
+    }
+}