Return-Path: X-Original-To: apmail-aries-commits-archive@www.apache.org Delivered-To: apmail-aries-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 337EF184A9 for ; Tue, 5 Jan 2016 09:44:27 +0000 (UTC) Received: (qmail 49503 invoked by uid 500); 5 Jan 2016 09:44:27 -0000 Delivered-To: apmail-aries-commits-archive@aries.apache.org Received: (qmail 49440 invoked by uid 500); 5 Jan 2016 09:44:27 -0000 Mailing-List: contact commits-help@aries.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aries.apache.org Delivered-To: mailing list commits@aries.apache.org Received: (qmail 49429 invoked by uid 99); 5 Jan 2016 09:44:26 -0000 Received: from Unknown (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Jan 2016 09:44:26 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 7B3A3C0CFF for ; Tue, 5 Jan 2016 09:44:26 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 0.447 X-Spam-Level: X-Spam-Status: No, score=0.447 tagged_above=-999 required=6.31 tests=[KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.554, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id xFo--PthkhZm for ; Tue, 5 Jan 2016 09:44:16 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with ESMTP id 690A942ADC for ; Tue, 5 Jan 2016 09:44:16 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id D2959E0566 for ; Tue, 5 Jan 2016 09:44:15 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 8D6F93A026D for ; Tue, 5 Jan 2016 09:44:15 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1723026 - /aries/trunk/blueprint/blueprint-spring-extender/src/main/java/org/apache/aries/blueprint/spring/extender/SpringOsgiNamespaceHandler.java Date: Tue, 05 Jan 2016 09:44:15 -0000 To: commits@aries.apache.org From: gnodet@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160105094415.8D6F93A026D@svn01-us-west.apache.org> 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 extra = new ArrayList(); - 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 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 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 parseInterfaces(Element element) { + List extra = new ArrayList(); + 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());