/****************************************************************************** * Copyright (c) 2006, 2010 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0 * is available at http://www.opensource.org/licenses/apache2.0.php. * You may elect to redistribute this code under either of these licenses. * * Contributors: * VMware Inc. *****************************************************************************/ package org.eclipse.gemini.blueprint.config.internal.util; import java.util.Set; import org.eclipse.gemini.blueprint.config.internal.adapter.OsgiServiceRegistrationListenerAdapter; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.Conventions; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Utils class for parsing various elements of a service declaration. * * @author Costin Leau */ public abstract class ServiceParsingUtils { private static final String REF = "ref"; private static final String TARGET_BEAN_NAME_PROP = "targetBeanName"; private static final String TARGET_PROP = "target"; private static final String INTERFACE = "interface"; private static final String INTERFACES_PROP = "interfaces"; private static final String INTERFACES_ID = "interfaces"; private static final String PROPS_ID = "service-properties"; public static BeanDefinition parseListener(ParserContext context, Element element, BeanDefinitionBuilder builder) { // filter elements NodeList nl = element.getChildNodes(); // wrapped object Object target = null; // target bean name (used for cycles) String targetName = null; // discover if we have listener with ref and nested bean declaration for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element nestedDefinition = (Element) node; // check shortcut on the parent if (element.hasAttribute(REF)) context.getReaderContext().error( "nested bean declaration is not allowed if 'ref' attribute has been specified", nestedDefinition); target = context.getDelegate().parsePropertySubElement(nestedDefinition, builder.getBeanDefinition()); // if this is a bean reference (nested <ref>), extract the name if (target instanceof RuntimeBeanReference) { targetName = ((RuntimeBeanReference) target).getBeanName(); } } } // extract registration/unregistration attributes from // <osgi:registration-listener> BeanDefinitionBuilder localBuilder = BeanDefinitionBuilder.rootBeanDefinition(OsgiServiceRegistrationListenerAdapter.class); localBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); NamedNodeMap attrs = element.getAttributes(); for (int x = 0; x < attrs.getLength(); x++) { Attr attribute = (Attr) attrs.item(x); String name = attribute.getLocalName(); if (REF.equals(name)) targetName = attribute.getValue(); else localBuilder.addPropertyValue(Conventions.attributeNameToPropertyName(name), attribute.getValue()); } // set the target name (if we have one) if (targetName != null) localBuilder.addPropertyValue(TARGET_BEAN_NAME_PROP, targetName); // else set the actual target else localBuilder.addPropertyValue(TARGET_PROP, target); return localBuilder.getBeanDefinition(); } public static boolean parseInterfaces(Element parent, Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String name = element.getLocalName(); // osgi:interfaces if (INTERFACES_ID.equals(name)) { // check shortcut on the parent if (parent.hasAttribute(INTERFACE)) { parserContext.getReaderContext().error( "either 'interface' attribute or <intefaces> sub-element has be specified", parent); } Set interfaces = parserContext.getDelegate().parseSetElement(element, builder.getBeanDefinition()); builder.addPropertyValue(INTERFACES_PROP, interfaces); return true; } return false; } // osgi:service-properties public static boolean parseServiceProperties(Element parent, Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String name = element.getLocalName(); if (PROPS_ID.equals(name)) { if (DomUtils.getChildElementsByTagName(element, BeanDefinitionParserDelegate.ENTRY_ELEMENT).size() > 0) { Object props = parserContext.getDelegate().parseMapElement(element, builder.getRawBeanDefinition()); builder.addPropertyValue(Conventions.attributeNameToPropertyName(PROPS_ID), props); } else { parserContext.getReaderContext().error("Invalid service property type", element); } return true; } return false; } }