You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2016/01/05 10:44:15 UTC

svn commit: r1723026 - /aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java

Author: gnodet
Date: Tue Jan  5 09:44:15 2016
New Revision: 1723026

URL: http://svn.apache.org/viewvc?rev=1723026&view=rev
Log:
[ARIES-1480] Refactor parsing, support custom namespaces

Modified:
    aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java

Modified: aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java?rev=1723026&r1=1723025&r2=1723026&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java (original)
+++ aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java Tue Jan  5 09:44:15 2016
@@ -20,7 +20,6 @@ import java.net.URI;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -39,13 +38,53 @@ import org.osgi.service.blueprint.reflec
 import org.osgi.service.blueprint.reflect.Target;
 import org.springframework.util.Assert;
 import org.springframework.util.StringUtils;
-import org.w3c.dom.*;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 public class SpringOsgiNamespaceHandler implements NamespaceHandler {
 
     public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
     public static final String SPRING_NAMESPACE = "http://www.springframework.org/schema/beans";
+
     public static final String BEAN_ELEMENT = "bean";
+    public static final String BEAN_NAME_ELEMENT = "bean-name";
+    public static final String FILTER_ATTRIBUTE = "filter";
+    public static final String INTERFACE_ATTRIBUTE = "interface";
+    public static final String TIMEOUT_ATTRIBUTE = "timeout";
+    public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
+    public static final String CARDINALITY_ATTRIBUTE = "cardinality";
+    public static final String LISTENER_ELEMENT = "listener";
+    public static final String REF_ATTRIBUTE = "ref";
+    public static final String BIND_METHOD_ATTRIBUTE = "bind-method";
+    public static final String UNBIND_METHOD_ATTRIBUTE = "unbind-method";
+    public static final String ID_ATTRIBUTE = "id";
+    public static final String CARDINALITY_0_1 = "0..1";
+    public static final String VALUE_ATTRIBUTE = "value";
+    public static final String VALUE_REF_ATTRIBUTE = "value-ref";
+    public static final String KEY_ATTRIBUTE = "key";
+    public static final String KEY_REF_ATTRIBUTE = "key-ref";
+    public static final String ENTRY_ELEMENT = "entry";
+    public static final String SERVICE_PROPERTIES_ELEMENT = "service-properties";
+    public static final String REGISTRATION_LISTENER_ELEMENT = "registration-listener";
+    public static final String INTERFACES_ELEMENT = "interfaces";
+    public static final String VALUE_ELEMENT = "value";
+    public static final String AUTO_EXPORT_ATTRIBUTE = "auto-export";
+    public static final String AUTO_EXPORT_INTERFACES = "interfaces";
+    public static final String AUTO_EXPORT_CLASS_HIERARCHY = "class-hierarchy";
+    public static final String AUTO_EXPORT_ALL_CLASSES = "all-classes";
+    public static final String RANKING_ATTRIBUTE = "ranking";
+    public static final String REFERENCE_ELEMENT = "reference";
+    public static final String SERVICE_ELEMENT = "service";
+    public static final String BUNDLE_ELEMENT = "bundle";
+    public static final String SET_ELEMENT = "set";
+    public static final String LIST_ELEMENT = "list";
+    public static final int DEFAULT_TIMEOUT = 300000;
+    public static final String REGISTRATION_METHOD_ATTRIBUTE = "registration-method";
+    public static final String UNREGISTRATION_METHOD_ATTRIBUTE = "unregistration-method";
 
     private int idCounter;
 
@@ -68,204 +107,255 @@ public class SpringOsgiNamespaceHandler
 
     @Override
     public Metadata parse(Element element, ParserContext context) {
-        if ("reference".equals(element.getLocalName())) {
-            MutableReferenceMetadata metadata = context.createMetadata(MutableReferenceMetadata.class);
-            // Parse attributes
-            if (element.hasAttribute("id")) {
-                metadata.setId(element.getAttribute("id"));
-            } else {
-                metadata.setId(generateId(context));
-            }
-            metadata.setAvailability("0..1".equals(element.getAttribute("cardinality"))
-                    ? ReferenceMetadata.AVAILABILITY_OPTIONAL
-                    : ReferenceMetadata.AVAILABILITY_MANDATORY);
-            metadata.setTimeout(getLong(element.getAttribute("timeout"), 300000));
-            metadata.setInterface(element.getAttribute("interface"));
-            metadata.setFilter(element.getAttribute("filter"));
-            String[] dependsOn = StringUtils.tokenizeToStringArray(element.getAttribute("depends-on"), ",; ");
-            metadata.setDependsOn(dependsOn != null ? Arrays.asList(dependsOn) : null);
-            metadata.setComponentName(element.getAttribute("bean-name"));
-            // TODO: @context-class-loader
-            // Parse child elements
-            for (Element child : getChildren(element)) {
-                if (element.getNamespaceURI().equals(child.getNamespaceURI())) {
-                    if ("interfaces".equals(child.getLocalName())) {
-                        List<String> extra = new ArrayList<String>();
-                        for (Element e : getChildren(child)) {
-                            if ("value".equals(e.getLocalName())) {
-                                extra.add(getTextValue(e));
-                            } else {
-                                // TODO: support other elements ?
-                                throw new UnsupportedOperationException("Unsupported child: " + element.getLocalName());
-                            }
-                        }
-                        metadata.setExtraInterfaces(extra);
+        if (REFERENCE_ELEMENT.equals(element.getLocalName())) {
+            return parseReference(element, context);
+        }
+        else if (SERVICE_ELEMENT.equals(element.getLocalName())) {
+            return parseService(element, context);
+        }
+        else if (BUNDLE_ELEMENT.equals(element.getLocalName())) {
+            return parseBundle(element, context);
+        }
+        else if (SET_ELEMENT.equals(element.getLocalName())) {
+            return parseSet(element, context);
+        }
+        else if (LIST_ELEMENT.equals(element.getLocalName())) {
+            return parseList(element, context);
+        }
+        else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private Metadata parseBundle(Element element, ParserContext context) {
+        throw new UnsupportedOperationException();
+    }
+
+    private Metadata parseList(Element element, ParserContext context) {
+        // TODO: support list
+        throw new UnsupportedOperationException();
+    }
+
+    private Metadata parseSet(Element element, ParserContext context) {
+        // TODO: support set
+        throw new UnsupportedOperationException();
+    }
+
+    private Metadata parseService(Element element, ParserContext context) {
+        MutableServiceMetadata metadata = context.createMetadata(MutableServiceMetadata.class);
+        // Parse attributes
+        if (element.hasAttribute(ID_ATTRIBUTE)) {
+            metadata.setId(element.getAttribute(ID_ATTRIBUTE));
+        } else {
+            metadata.setId(generateId(context));
+        }
+        if (nonEmpty(element.getAttribute(REF_ATTRIBUTE)) != null) {
+            MutableRefMetadata ref = context.createMetadata(MutableRefMetadata.class);
+            ref.setComponentId(element.getAttribute(REF_ATTRIBUTE));
+            metadata.setServiceComponent(ref);
+        }
+        metadata.setRanking(nonEmpty(element.getAttribute(RANKING_ATTRIBUTE)) != null
+                ? Integer.parseInt(element.getAttribute(RANKING_ATTRIBUTE))
+                : 0);
+        String itf = nonEmpty(element.getAttribute(INTERFACE_ATTRIBUTE));
+        if (itf != null) {
+            metadata.addInterface(itf);
+        }
+        String[] dependsOn = StringUtils.tokenizeToStringArray(nonEmpty(element.getAttribute(DEPENDS_ON_ATTRIBUTE)), ",; ");
+        metadata.setDependsOn(dependsOn != null ? Arrays.asList(dependsOn) : null);
+        String autoExp = nonEmpty(element.getAttribute(AUTO_EXPORT_ATTRIBUTE));
+        if (AUTO_EXPORT_INTERFACES.equals(autoExp)) {
+            metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_INTERFACES);
+        } else if (AUTO_EXPORT_CLASS_HIERARCHY.equals(autoExp)) {
+            metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
+        } else if (AUTO_EXPORT_ALL_CLASSES.equals(autoExp)) {
+            metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
+        } else {
+            metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_DISABLED);
+        }
+        // TODO: @context-class-loader
+        // Parse child elements
+        for (Element child : getChildren(element)) {
+            if (element.getNamespaceURI().equals(child.getNamespaceURI())) {
+                if (INTERFACES_ELEMENT.equals(child.getLocalName())) {
+                    List<String> itfs = parseInterfaces(child);
+                    for (String intf : itfs) {
+                        metadata.addInterface(intf);
                     }
-                    else if ("listener".equals(child.getLocalName())) {
-                        // TODO: listener
-                        String bindMethod = nonEmpty(child.getAttribute("bind-method"));
-                        String unbindMethod = nonEmpty(child.getAttribute("unbind-method"));
-                        String refStr = nonEmpty(child.getAttribute("ref"));
-                        Target listenerComponent = null;
-                        if (refStr != null) {
-                            MutableRefMetadata ref = context.createMetadata(MutableRefMetadata.class);
-                            ref.setComponentId(refStr);
-                            listenerComponent = ref;
+                }
+                else if (REGISTRATION_LISTENER_ELEMENT.equals(child.getLocalName())) {
+                    String regMethod = nonEmpty(child.getAttribute(REGISTRATION_METHOD_ATTRIBUTE));
+                    String unregMethod = nonEmpty(child.getAttribute(UNREGISTRATION_METHOD_ATTRIBUTE));
+                    String refStr = nonEmpty(child.getAttribute(REF_ATTRIBUTE));
+                    Target listenerComponent = null;
+                    if (refStr != null) {
+                        MutableRefMetadata ref = context.createMetadata(MutableRefMetadata.class);
+                        ref.setComponentId(refStr);
+                        listenerComponent = ref;
+                    }
+                    for (Element cchild : getChildren(child)) {
+                        if (listenerComponent != null) {
+                            throw new IllegalArgumentException("Only one of @ref attribute or inlined bean definition element is allowed");
                         }
-                        for (Element cchild : getChildren(child)) {
-                            if (BLUEPRINT_NAMESPACE.equals(cchild.getNamespaceURI())
-                                    && BEAN_ELEMENT.equals(cchild.getLocalName())) {
-                                if (listenerComponent != null) {
-                                    throw new IllegalArgumentException("Only one of @ref attribute and bean element is allowed");
-                                }
-                                listenerComponent = context.parseElement(BeanMetadata.class, metadata, cchild);
-                            }
-                            else if (SPRING_NAMESPACE.equals(cchild.getNamespaceURI())
-                                    && BEAN_ELEMENT.equals(cchild.getLocalName())) {
-                                if (listenerComponent != null) {
-                                    throw new IllegalArgumentException("Only one of @ref attribute or inlined bean definition element is allowed");
-                                }
-                                listenerComponent = (Target) context.getNamespaceHandler(URI.create(SPRING_NAMESPACE))
-                                        .parse(cchild, context);
+                        listenerComponent = parseInlinedTarget(context, metadata, cchild);
+                    }
+                    if (listenerComponent == null) {
+                        throw new IllegalArgumentException("Missing @ref attribute or inlined bean definition element");
+                    }
+                    metadata.addRegistrationListener(listenerComponent, regMethod, unregMethod);
+                }
+                else if (SERVICE_PROPERTIES_ELEMENT.equals(child.getLocalName())) {
+                    // TODO: @key-type
+                    for (Element e : getChildren(child)) {
+                        if (ENTRY_ELEMENT.equals(e.getLocalName())) {
+                            NonNullMetadata key;
+                            Metadata val;
+                            boolean hasKeyAttribute = e.hasAttribute(KEY_ATTRIBUTE);
+                            boolean hasKeyRefAttribute = e.hasAttribute(KEY_REF_ATTRIBUTE);
+                            if (hasKeyRefAttribute && !hasKeyAttribute) {
+                                MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class);
+                                r.setComponentId(e.getAttribute(KEY_REF_ATTRIBUTE));
+                                key = r;
+                            } else if (hasKeyAttribute && !hasKeyRefAttribute) {
+                                MutableValueMetadata v = context.createMetadata(MutableValueMetadata.class);
+                                v.setStringValue(e.getAttribute(KEY_ATTRIBUTE));
+                                key = v;
+                            } else {
+                                throw new IllegalStateException("Either key or key-ref must be specified");
                             }
-                            else {
-                                throw new IllegalArgumentException("Unsupported element " + cchild.getLocalName());
+                            // TODO: support key
+                            boolean hasValAttribute = e.hasAttribute(VALUE_ATTRIBUTE);
+                            boolean hasValRefAttribute = e.hasAttribute(VALUE_REF_ATTRIBUTE);
+                            if (hasValRefAttribute && !hasValAttribute) {
+                                MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class);
+                                r.setComponentId(e.getAttribute(VALUE_REF_ATTRIBUTE));
+                                val = r;
+                            } else if (hasValAttribute && !hasValRefAttribute) {
+                                MutableValueMetadata v = context.createMetadata(MutableValueMetadata.class);
+                                v.setStringValue(e.getAttribute(VALUE_ATTRIBUTE));
+                                val = v;
+                            } else {
+                                throw new IllegalStateException("Either val or val-ref must be specified");
                             }
+                            // TODO: support children elements ?
+                            metadata.addServiceProperty(key, val);
                         }
-                        if (listenerComponent == null) {
-                            throw new IllegalArgumentException("Missing @ref attribute or inlined bean definition element");
-                        }
-                        metadata.addServiceListener(listenerComponent, bindMethod, unbindMethod);
                     }
                 }
-                else {
-                    throw new UnsupportedOperationException("Custom namespaces not supported");
-                }
             }
-            return metadata;
-        }
-        else if ("service".equals(element.getLocalName())) {
-            MutableServiceMetadata metadata = context.createMetadata(MutableServiceMetadata.class);
-            // Parse attributes
-            if (element.hasAttribute("id")) {
-                metadata.setId(element.getAttribute("id"));
-            } else {
-                metadata.setId(generateId(context));
-            }
-            if (nonEmpty(element.getAttribute("ref")) != null) {
-                MutableRefMetadata ref = context.createMetadata(MutableRefMetadata.class);
-                ref.setComponentId(element.getAttribute("ref"));
-                metadata.setServiceComponent(ref);
-            }
-            metadata.setRanking(nonEmpty(element.getAttribute("ranking")) != null
-                    ? Integer.parseInt(element.getAttribute("ranking"))
-                    : 0);
-            String itf = nonEmpty(element.getAttribute("interface"));
-            if (itf != null) {
-                metadata.addInterface(itf);
+            else if (BLUEPRINT_NAMESPACE.equals(child.getNamespaceURI())
+                    && BEAN_ELEMENT.equals(child.getLocalName())) {
+                if (metadata.getServiceComponent() != null) {
+                    throw new IllegalArgumentException("Only one of @ref attribute and bean element is allowed");
+                }
+                Target bean = context.parseElement(BeanMetadata.class, metadata, child);
+                metadata.setServiceComponent(bean);
             }
-            String[] dependsOn = StringUtils.tokenizeToStringArray(nonEmpty(element.getAttribute("depends-on")), ",; ");
-            metadata.setDependsOn(dependsOn != null ? Arrays.asList(dependsOn) : null);
-            String autoExp = nonEmpty(element.getAttribute("auto-export"));
-            if ("interfaces".equals(autoExp)) {
-                metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_INTERFACES);
-            } else if ("class-hierarchy".equals(autoExp)) {
-                metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
-            } else if ("all-classes".equals(autoExp)) {
-                metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
-            } else {
-                metadata.setAutoExport(ServiceMetadata.AUTO_EXPORT_DISABLED);
+            else {
+                if (metadata.getServiceComponent() != null) {
+                    throw new IllegalArgumentException("Only one of @ref attribute or inlined bean definition element is allowed");
+                }
+                NamespaceHandler handler = context.getNamespaceHandler(URI.create(child.getNamespaceURI()));
+                if (handler == null) {
+                    throw new IllegalStateException("No NamespaceHandler found for " + child.getNamespaceURI());
+                }
+                Metadata md = handler.parse(child, context);
+                if (!(md instanceof Target)) {
+                    throw new IllegalStateException("NamespaceHandler did not return a Target instance but " + md);
+                }
+                metadata.setServiceComponent((Target) md);
             }
-            // TODO: @context-class-loader
-            // Parse child elements
-            for (Element child : getChildren(element)) {
-                if (element.getNamespaceURI().equals(child.getNamespaceURI())) {
-                    if ("interfaces".equals(child.getLocalName())) {
-                        for (Element e : getChildren(child)) {
-                            if ("value".equals(e.getLocalName())) {
-                                metadata.addInterface(getTextValue(e));
-                            } else {
-                                // TODO: support other elements ?
-                                throw new UnsupportedOperationException("Unsupported child: " + element.getLocalName());
-                            }
-                        }
-                    }
-                    else if ("registration-listener".equals(child.getLocalName())) {
-                        // TODO: registration-listener
+        }
+        return metadata;
+    }
 
+    private Metadata parseReference(Element element, ParserContext context) {
+        MutableReferenceMetadata metadata = context.createMetadata(MutableReferenceMetadata.class);
+        // Parse attributes
+        if (element.hasAttribute(ID_ATTRIBUTE)) {
+            metadata.setId(element.getAttribute(ID_ATTRIBUTE));
+        } else {
+            metadata.setId(generateId(context));
+        }
+        metadata.setAvailability(CARDINALITY_0_1.equals(element.getAttribute(CARDINALITY_ATTRIBUTE))
+                ? ReferenceMetadata.AVAILABILITY_OPTIONAL
+                : ReferenceMetadata.AVAILABILITY_MANDATORY);
+        metadata.setTimeout(getLong(element.getAttribute(TIMEOUT_ATTRIBUTE), DEFAULT_TIMEOUT));
+        metadata.setInterface(element.getAttribute(INTERFACE_ATTRIBUTE));
+        metadata.setFilter(element.getAttribute(FILTER_ATTRIBUTE));
+        String[] dependsOn = StringUtils.tokenizeToStringArray(element.getAttribute(DEPENDS_ON_ATTRIBUTE), ",; ");
+        metadata.setDependsOn(dependsOn != null ? Arrays.asList(dependsOn) : null);
+        metadata.setComponentName(element.getAttribute(BEAN_NAME_ELEMENT));
+        // TODO: @context-class-loader
+        // Parse child elements
+        for (Element child : getChildren(element)) {
+            if (element.getNamespaceURI().equals(child.getNamespaceURI())) {
+                if (INTERFACES_ELEMENT.equals(child.getLocalName())) {
+                    List<String> itfs = parseInterfaces(child);
+                    metadata.setExtraInterfaces(itfs);
+                }
+                else if (LISTENER_ELEMENT.equals(child.getLocalName())) {
+                    String bindMethod = nonEmpty(child.getAttribute(BIND_METHOD_ATTRIBUTE));
+                    String unbindMethod = nonEmpty(child.getAttribute(UNBIND_METHOD_ATTRIBUTE));
+                    String refStr = nonEmpty(child.getAttribute(REF_ATTRIBUTE));
+                    Target listenerComponent = null;
+                    if (refStr != null) {
+                        MutableRefMetadata ref = context.createMetadata(MutableRefMetadata.class);
+                        ref.setComponentId(refStr);
+                        listenerComponent = ref;
                     }
-                    else if ("service-properties".equals(child.getLocalName())) {
-                        // TODO: @key-type
-                        for (Element e : getChildren(child)) {
-                            if ("entry".equals(e.getLocalName())) {
-                                NonNullMetadata key;
-                                Metadata val;
-                                boolean hasKeyAttribute = e.hasAttribute("key");
-                                boolean hasKeyRefAttribute = e.hasAttribute("key-ref");
-                                if (hasKeyRefAttribute && !hasKeyAttribute) {
-                                    MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class);
-                                    r.setComponentId(e.getAttribute("key-ref"));
-                                    key = r;
-                                } else if (hasKeyAttribute && !hasKeyRefAttribute) {
-                                    MutableValueMetadata v = context.createMetadata(MutableValueMetadata.class);
-                                    v.setStringValue(e.getAttribute("key"));
-                                    key = v;
-                                } else {
-                                    throw new IllegalStateException("Either key or key-ref must be specified");
-                                }
-                                // TODO: support children elements ?
-                                boolean hasValAttribute = e.hasAttribute("value");
-                                boolean hasValRefAttribute = e.hasAttribute("value-ref");
-                                if (hasValRefAttribute && !hasValAttribute) {
-                                    MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class);
-                                    r.setComponentId(e.getAttribute("value-ref"));
-                                    val = r;
-                                } else if (hasValAttribute && !hasValRefAttribute) {
-                                    MutableValueMetadata v = context.createMetadata(MutableValueMetadata.class);
-                                    v.setStringValue(e.getAttribute("value"));
-                                    val = v;
-                                } else {
-                                    throw new IllegalStateException("Either val or val-ref must be specified");
-                                }
-                                // TODO: support children elements ?
-                                metadata.addServiceProperty(key, val);
-                            }
+                    for (Element cchild : getChildren(child)) {
+                        if (listenerComponent != null) {
+                            throw new IllegalArgumentException("Only one of @ref attribute or inlined bean definition element is allowed");
                         }
+                        listenerComponent = parseInlinedTarget(context, metadata, cchild);
                     }
-                }
-                else if (BLUEPRINT_NAMESPACE.equals(child.getNamespaceURI())
-                        && BEAN_ELEMENT.equals(child.getLocalName())) {
-                    if (metadata.getServiceComponent() != null) {
-                        throw new IllegalArgumentException("Only one of @ref attribute and bean element is allowed");
+                    if (listenerComponent == null) {
+                        throw new IllegalArgumentException("Missing @ref attribute or inlined bean definition element");
                     }
-                    Target bean = context.parseElement(BeanMetadata.class, metadata, child);
-                    metadata.setServiceComponent(bean);
-                }
-                else if (SPRING_NAMESPACE.equals(child.getNamespaceURI())
-                        && BEAN_ELEMENT.equals(child.getLocalName())) {
-                    if (metadata.getServiceComponent() != null) {
-                        throw new IllegalArgumentException("Only one of @ref attribute or inlined bean definition element is allowed");
-                    }
-                    Target bean = (Target) context.getNamespaceHandler(URI.create(SPRING_NAMESPACE))
-                            .parse(child, context);
-                    metadata.setServiceComponent(bean);
-                }
-                else {
-                    throw new IllegalArgumentException("Unsupported element " + child.getLocalName());
+                    metadata.addServiceListener(listenerComponent, bindMethod, unbindMethod);
                 }
             }
-            return metadata;
+            else {
+                throw new UnsupportedOperationException("Custom namespaces not supported");
+            }
         }
-        else if ("bundle".equals(element.getLocalName())) {
+        return metadata;
+    }
 
+    private Target parseInlinedTarget(ParserContext context, ComponentMetadata metadata, Element element) {
+        Target listenerComponent;
+        if (BLUEPRINT_NAMESPACE.equals(element.getNamespaceURI())
+                && BEAN_ELEMENT.equals(element.getLocalName())) {
+            listenerComponent = context.parseElement(BeanMetadata.class, metadata, element);
         }
-        else if ("set".equals(element.getLocalName())) {
-
+        else {
+            NamespaceHandler handler = context.getNamespaceHandler(URI.create(element.getNamespaceURI()));
+            if (handler == null) {
+                throw new IllegalStateException("No NamespaceHandler found for " + element.getNamespaceURI());
+            }
+            Metadata md = handler.parse(element, context);
+            if (!(md instanceof Target)) {
+                throw new IllegalStateException("NamespaceHandler did not return a Target instance but " + md);
+            }
+            listenerComponent = (Target) md;
         }
-        else if ("list".equals(element.getLocalName())) {
+        return listenerComponent;
+    }
 
+    private List<String> parseInterfaces(Element element) {
+        List<String> extra = new ArrayList<String>();
+        for (Element e : getChildren(element)) {
+            if (VALUE_ELEMENT.equals(e.getLocalName())) {
+                extra.add(getTextValue(e));
+            } else {
+                // The schema support all kind of children for a list type
+                // The type for the spring property is converted to a Class[] array
+                // TODO: support other elements ?
+                throw new UnsupportedOperationException("Unsupported child: " + element.getLocalName());
+            }
         }
-        throw new UnsupportedOperationException();
+        return extra;
     }
 
     private String nonEmpty(String ref) {
@@ -307,7 +397,7 @@ public class SpringOsgiNamespaceHandler
         Assert.notNull(valueEle, "Element must not be null");
         StringBuilder sb = new StringBuilder();
         NodeList nl = valueEle.getChildNodes();
-        for(int i = 0; i < nl.getLength(); ++i) {
+        for(int i = 0, l = nl.getLength(); i < l; ++i) {
             Node item = nl.item(i);
             if(item instanceof CharacterData && !(item instanceof Comment) || item instanceof EntityReference) {
                 sb.append(item.getNodeValue());