001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    
021    package org.apache.xbean.blueprint.cm;
022    
023    import java.net.URL;
024    import java.util.ArrayList;
025    import java.util.Arrays;
026    import java.util.HashSet;
027    import java.util.List;
028    import java.util.Set;
029    
030    import org.apache.aries.blueprint.ComponentDefinitionRegistry;
031    import org.apache.aries.blueprint.NamespaceHandler;
032    import org.apache.aries.blueprint.ParserContext;
033    import org.apache.aries.blueprint.ext.ExtNamespaceHandler;
034    import org.apache.aries.blueprint.ext.PlaceholdersUtils;
035    import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
036    import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
037    import org.apache.aries.blueprint.mutable.MutableComponentMetadata;
038    import org.apache.aries.blueprint.mutable.MutableIdRefMetadata;
039    import org.apache.aries.blueprint.mutable.MutableMapMetadata;
040    import org.apache.aries.blueprint.mutable.MutableRefMetadata;
041    import org.apache.aries.blueprint.mutable.MutableReferenceMetadata;
042    import org.apache.aries.blueprint.mutable.MutableValueMetadata;
043    import org.osgi.service.blueprint.container.BlueprintContainer;
044    import org.osgi.service.blueprint.container.ComponentDefinitionException;
045    import org.osgi.service.blueprint.reflect.BeanMetadata;
046    import org.osgi.service.blueprint.reflect.BeanProperty;
047    import org.osgi.service.blueprint.reflect.CollectionMetadata;
048    import org.osgi.service.blueprint.reflect.ComponentMetadata;
049    import org.osgi.service.blueprint.reflect.IdRefMetadata;
050    import org.osgi.service.blueprint.reflect.Metadata;
051    import org.osgi.service.blueprint.reflect.RefMetadata;
052    import org.osgi.service.blueprint.reflect.ReferenceMetadata;
053    import org.osgi.service.blueprint.reflect.ValueMetadata;
054    import org.osgi.service.cm.ConfigurationAdmin;
055    import org.slf4j.Logger;
056    import org.slf4j.LoggerFactory;
057    import org.w3c.dom.CharacterData;
058    import org.w3c.dom.Comment;
059    import org.w3c.dom.Element;
060    import org.w3c.dom.EntityReference;
061    import org.w3c.dom.Node;
062    import org.w3c.dom.NodeList;
063    
064    /**
065     * Modified from aries CmNamespaceHandler
066     *
067     * @version $Rev: 907189 $ $Date: 2010-02-06 03:01:43 -0500 (Sat, 06 Feb 2010) $
068     */
069    public class CmNamespaceHandler implements NamespaceHandler {
070    
071        public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
072        public static final String XBEAN_CM_NAMESPACE = "http://xbean.apache.org/blueprint/xmlns/xbean-cm/v1.0.0";
073    
074        public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
075    //    public static final String MANAGED_PROPERTIES_ELEMENT = "managed-properties";
076    //    public static final String MANAGED_SERVICE_FACTORY_ELEMENT = "managed-service-factory";
077        public static final String CM_PROPERTIES_ELEMENT = "cm-properties";
078        public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
079        public static final String PROPERTY_ELEMENT = "property";
080        public static final String INTERFACES_ELEMENT = "interfaces";
081        public static final String VALUE_ELEMENT = "value";
082        public static final String MANAGED_COMPONENT_ELEMENT = "managed-component";
083    
084        public static final String ID_ATTRIBUTE = "id";
085        public static final String PERSISTENT_ID_ATTRIBUTE = "persistent-id";
086        public static final String PLACEHOLDER_PREFIX_ATTRIBUTE = "placeholder-prefix";
087        public static final String PLACEHOLDER_SUFFIX_ATTRIBUTE = "placeholder-suffix";
088        public static final String DEFAULTS_REF_ATTRIBUTE = "defaults-ref";
089        public static final String UPDATE_STRATEGY_ATTRIBUTE = "update-strategy";
090        public static final String UPDATE_METHOD_ATTRIBUTE = "update-method";
091        public static final String FACTORY_PID_ATTRIBUTE = "factory-pid";
092        public static final String AUTO_EXPORT_ATTRIBUTE = "auto-export";
093        public static final String RANKING_ATTRIBUTE = "ranking";
094        public static final String INTERFACE_ATTRIBUTE = "interface";
095        public static final String UPDATE_ATTRIBUTE = "update";
096    
097        public static final String AUTO_EXPORT_DISABLED = "disabled";
098        public static final String AUTO_EXPORT_INTERFACES = "interfaces";
099        public static final String AUTO_EXPORT_CLASS_HIERARCHY = "class-hierarchy";
100        public static final String AUTO_EXPORT_ALL = "all-classes";
101        public static final String AUTO_EXPORT_DEFAULT = AUTO_EXPORT_DISABLED;
102        public static final String RANKING_DEFAULT = "0";
103    
104        private static final String MANAGED_OBJECT_MANAGER_NAME = "org.apache.aries.managedObjectManager";
105    
106        private static final Logger LOGGER = LoggerFactory.getLogger(CmNamespaceHandler.class);
107    
108    //    private final ConfigurationAdmin configAdmin;
109    
110        private int idCounter;
111    
112    //    public CmNamespaceHandler(ConfigurationAdmin configAdmin) {
113    //        this.configAdmin = configAdmin;
114    //    }
115    
116        public URL getSchemaLocation(String namespace) {
117            return getClass().getResource("xbean-cm.xsd");
118        }
119    
120        public Set<Class> getManagedClasses() {
121            return new HashSet<Class>(Arrays.asList(
122                    JexlPropertyPlaceholder.class
123            ));
124        }
125    
126        public Metadata parse(Element element, ParserContext context) {
127            LOGGER.debug("Parsing element {{}}{}", element.getNamespaceURI(), element.getLocalName());
128            ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
129    //        registerManagedObjectManager(context, registry);
130            if (nodeNameEquals(element, PROPERTY_PLACEHOLDER_ELEMENT)) {
131                return parsePropertyPlaceholder(context, element);
132    //        } else if (nodeNameEquals(element, MANAGED_SERVICE_FACTORY_ELEMENT)) {
133    //            return parseManagedServiceFactory(context, element);
134            } else {
135                throw new ComponentDefinitionException("Unsupported element: " + element.getNodeName());
136            }
137        }
138    
139        public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
140            LOGGER.debug("Decorating node {{}}{}", node.getNamespaceURI(), node.getLocalName());
141            ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
142    //        registerManagedObjectManager(context, registry);
143            if (node instanceof Element) {
144    //            if (nodeNameEquals(node, MANAGED_PROPERTIES_ELEMENT)) {
145    //                return decorateManagedProperties(context, (Element) node, component);
146    //            } else
147    //            if (nodeNameEquals(node, CM_PROPERTIES_ELEMENT)) {
148    //                return decorateCmProperties(context, (Element) node, component);
149    //            } else {
150                throw new ComponentDefinitionException("Unsupported element: " + node.getNodeName());
151    //            }
152            } else {
153                throw new ComponentDefinitionException("Illegal use of blueprint cm namespace");
154            }
155        }
156    
157        private ComponentMetadata parsePropertyPlaceholder(ParserContext context, Element element) {
158            MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
159            metadata.setProcessor(true);
160            metadata.setId(getId(context, element));
161            metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
162            metadata.setRuntimeClass(JexlPropertyPlaceholder.class);
163            metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
164    //        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
165            metadata.addProperty("configAdmin", createReference(context, ConfigurationAdmin.class.getName()));
166            metadata.addProperty("persistentId", createValue(context, element.getAttribute(PERSISTENT_ID_ATTRIBUTE)));
167    //        metadata.addArgument(createRef(context, "blueprintContainer"), BlueprintContainer.class.getName(), 0);
168    //        metadata.addArgument(createReference(context, ConfigurationAdmin.class.getName()), ConfigurationAdmin.class.getName(), 1);
169    //        metadata.addArgument(createValue(context, element.getAttribute(PERSISTENT_ID_ATTRIBUTE)), String.class.getName(), 2);
170            String prefix = element.hasAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
171                    ? element.getAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
172                    : "${";
173            metadata.addProperty("placeholderPrefix", createValue(context, prefix));
174            String suffix = element.hasAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
175                    ? element.getAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
176                    : "}";
177            metadata.addProperty("placeholderSuffix", createValue(context, suffix));
178            String defaultsRef = element.hasAttribute(DEFAULTS_REF_ATTRIBUTE) ? element.getAttribute(DEFAULTS_REF_ATTRIBUTE) : null;
179            if (defaultsRef != null) {
180                metadata.addProperty("defaultProperties", createRef(context, defaultsRef));
181            }
182            String ignoreMissingLocations = element.hasAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.IGNORE_MISSING_LOCATIONS_ATTRIBUTE)
183                    ? element.getAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.IGNORE_MISSING_LOCATIONS_ATTRIBUTE) : null;
184            if (ignoreMissingLocations != null) {
185                metadata.addProperty("ignoreMissingLocations", createValue(context, ignoreMissingLocations));
186            }
187            String systemProperties = element.hasAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.SYSTEM_PROPERTIES_ATTRIBUTE)
188                    ? element.getAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.SYSTEM_PROPERTIES_ATTRIBUTE) : null;
189            if (systemProperties == null) {
190                systemProperties = ExtNamespaceHandler.SYSTEM_PROPERTIES_NEVER;
191            }
192            metadata.addProperty("systemProperties", createValue(context, systemProperties));
193            // Parse elements
194            List<String> locations = new ArrayList<String>();
195            NodeList nl = element.getChildNodes();
196            for (int i = 0; i < nl.getLength(); i++) {
197                Node node = nl.item(i);
198                if (node instanceof Element) {
199                    Element e = (Element) node;
200                    if (XBEAN_CM_NAMESPACE.equals(e.getNamespaceURI())) {
201                        if (nodeNameEquals(e, DEFAULT_PROPERTIES_ELEMENT)) {
202                            if (defaultsRef != null) {
203                                throw new ComponentDefinitionException("Only one of " + DEFAULTS_REF_ATTRIBUTE + " attribute or " + DEFAULT_PROPERTIES_ELEMENT + " element is allowed");
204                            }
205                            Metadata props = parseDefaultProperties(context, metadata, e);
206                            metadata.addProperty("defaultProperties", props);
207                        }
208                    } else if (ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE.equals(e.getNamespaceURI())) {
209                        if (nodeNameEquals(e, ExtNamespaceHandler.LOCATION_ELEMENT)) {
210                            locations.add(getTextValue(e));
211                        }
212                    }
213                }
214            }
215            if (!locations.isEmpty()) {
216                metadata.addProperty("locations", createList(context, locations));
217            }
218    
219    //        PlaceholdersUtils.validatePlaceholder(metadata, context.getComponentDefinitionRegistry());
220    
221            return metadata;
222        }
223    
224        private Metadata parseDefaultProperties(ParserContext context, MutableBeanMetadata enclosingComponent, Element element) {
225            MutableMapMetadata props = context.createMetadata(MutableMapMetadata.class);
226            NodeList nl = element.getChildNodes();
227            for (int i = 0; i < nl.getLength(); i++) {
228                Node node = nl.item(i);
229                if (node instanceof Element) {
230                    Element e = (Element) node;
231                    if (XBEAN_CM_NAMESPACE.equals(e.getNamespaceURI())) {
232                        if (nodeNameEquals(e, PROPERTY_ELEMENT)) {
233                            BeanProperty prop = context.parseElement(BeanProperty.class, enclosingComponent, e);
234                            props.addEntry(createValue(context, prop.getName(), String.class.getName()), prop.getValue());
235                        }
236                    }
237                }
238            }
239            return props;
240        }
241    
242    //    private ComponentMetadata parseManagedServiceFactory(ParserContext context, Element element) {
243    //        String id = getId(context, element);
244    //
245    //        MutableBeanMetadata factoryMetadata = context.createMetadata(MutableBeanMetadata.class);
246    //        generateIdIfNeeded(context, factoryMetadata);
247    //        factoryMetadata.addProperty("id", createValue(context, factoryMetadata.getId()));
248    //        factoryMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
249    //        factoryMetadata.setRuntimeClass(CmManagedServiceFactory.class);
250    //        factoryMetadata.setInitMethod("init");
251    //        factoryMetadata.setDestroyMethod("destroy");
252    //        factoryMetadata.addProperty("configAdmin", createConfigAdminProxy(context));
253    //        factoryMetadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
254    //        factoryMetadata.addProperty("factoryPid", createValue(context, element.getAttribute(FACTORY_PID_ATTRIBUTE)));
255    //        String autoExport = element.hasAttribute(AUTO_EXPORT_ATTRIBUTE) ? element.getAttribute(AUTO_EXPORT_ATTRIBUTE) : AUTO_EXPORT_DEFAULT;
256    //        if (AUTO_EXPORT_DISABLED.equals(autoExport)) {
257    //            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_DISABLED);
258    //        } else if (AUTO_EXPORT_INTERFACES.equals(autoExport)) {
259    //            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_INTERFACES);
260    //        } else if (AUTO_EXPORT_CLASS_HIERARCHY.equals(autoExport)) {
261    //            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
262    //        } else if (AUTO_EXPORT_ALL.equals(autoExport)) {
263    //            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
264    //        } else {
265    //            throw new ComponentDefinitionException("Illegal value (" + autoExport + ") for " + AUTO_EXPORT_ATTRIBUTE + " attribute");
266    //        }
267    //        factoryMetadata.addProperty("autoExport", createValue(context, autoExport));
268    //        String ranking = element.hasAttribute(RANKING_ATTRIBUTE) ? element.getAttribute(RANKING_ATTRIBUTE) : RANKING_DEFAULT;
269    //        factoryMetadata.addProperty("ranking", createValue(context, ranking));
270    //
271    //        List<String> interfaces = null;
272    //        if (element.hasAttribute(INTERFACE_ATTRIBUTE)) {
273    //            interfaces = Collections.singletonList(element.getAttribute(INTERFACE_ATTRIBUTE));
274    //            factoryMetadata.addProperty("interfaces", createList(context, interfaces));
275    //        }
276    //
277    //        Parser parser = getParser(context);
278    //
279    //        // Parse elements
280    //        List<RegistrationListener> listeners = new ArrayList<RegistrationListener>();
281    //        NodeList nl = element.getChildNodes();
282    //        for (int i = 0; i < nl.getLength(); i++) {
283    //            Node node = nl.item(i);
284    //            if (node instanceof Element) {
285    //                Element e = (Element) node;
286    //                if (isBlueprintNamespace(e.getNamespaceURI())) {
287    //                    if (nodeNameEquals(e, INTERFACES_ELEMENT)) {
288    //                        if (interfaces != null) {
289    //                            throw new ComponentDefinitionException("Only one of " + Parser.INTERFACE_ATTRIBUTE + " attribute or " + INTERFACES_ELEMENT + " element must be used");
290    //                        }
291    //                        interfaces = parseInterfaceNames(e);
292    //                        factoryMetadata.addProperty("interfaces", createList(context, interfaces));
293    //                    } else if (nodeNameEquals(e, Parser.SERVICE_PROPERTIES_ELEMENT)) {
294    //                        MapMetadata map = parser.parseServiceProperties(e, factoryMetadata);
295    //                        factoryMetadata.addProperty("serviceProperties", map);
296    //                    } else if (nodeNameEquals(e, Parser.REGISTRATION_LISTENER_ELEMENT)) {
297    //                        listeners.add(parser.parseRegistrationListener(e, factoryMetadata));
298    //                    }
299    //                } else if (XBEAN_CM_NAMESPACE.equals(e.getNamespaceURI())) {
300    //                    if (nodeNameEquals(e, MANAGED_COMPONENT_ELEMENT)) {
301    //                        MutableBeanMetadata managedComponent = context.parseElement(MutableBeanMetadata.class, null, e);
302    //                        generateIdIfNeeded(context, managedComponent);
303    //                        managedComponent.setScope(BeanMetadata.SCOPE_PROTOTYPE);
304    //                        // destroy-method on managed-component has different signature than on regular beans
305    //                        // so we'll handle it differently
306    //                        String destroyMethod = managedComponent.getDestroyMethod();
307    //                        if (destroyMethod != null) {
308    //                            factoryMetadata.addProperty("componentDestroyMethod", createValue(context, destroyMethod));
309    //                            managedComponent.setDestroyMethod(null);
310    //                        }
311    //                        context.getComponentDefinitionRegistry().registerComponentDefinition(managedComponent);
312    //                        factoryMetadata.addProperty("managedComponentName", createIdRef(context, managedComponent.getId()));
313    //                    }
314    //                }
315    //            }
316    //        }
317    //
318    //        MutableCollectionMetadata listenerCollection = context.createMetadata(MutableCollectionMetadata.class);
319    //        listenerCollection.setCollectionClass(List.class);
320    //        for (RegistrationListener listener : listeners) {
321    //            MutableBeanMetadata bean = context.createMetadata(MutableBeanMetadata.class);
322    //            bean.setRuntimeClass(ServiceListener.class);
323    //            bean.addProperty("listener", listener.getListenerComponent());
324    //            bean.addProperty("registerMethod", createValue(context, listener.getRegistrationMethod()));
325    //            bean.addProperty("unregisterMethod", createValue(context, listener.getUnregistrationMethod()));
326    //            listenerCollection.addValue(bean);
327    //        }
328    //        factoryMetadata.addProperty("listeners", listenerCollection);
329    //
330    //        context.getComponentDefinitionRegistry().registerComponentDefinition(factoryMetadata);
331    //
332    //        MutableBeanMetadata mapMetadata = context.createMetadata(MutableBeanMetadata.class);
333    //        mapMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
334    //        mapMetadata.setId(id);
335    //        mapMetadata.setFactoryComponent(createRef(context, factoryMetadata.getId()));
336    //        mapMetadata.setFactoryMethod("getServiceMap");
337    //        return mapMetadata;
338    //    }
339    
340    //    private ComponentMetadata decorateCmProperties(ParserContext context, Element element, ComponentMetadata component) {
341    //        generateIdIfNeeded(context, ((MutableComponentMetadata) component));
342    //        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
343    //        metadata.setProcessor(true);
344    //        metadata.setId(getId(context, element));
345    //        metadata.setRuntimeClass(CmProperties.class);
346    //        String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
347    //        // if persistentId is "" the cm-properties element in nested in managed-service-factory
348    //        // and the configuration object will come from the factory. So we only really need to register
349    //        // ManagedService if the persistentId is not an empty string.
350    //        if (persistentId.length() > 0) {
351    //            metadata.setInitMethod("init");
352    //            metadata.setDestroyMethod("destroy");
353    //        }
354    //        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
355    //        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
356    //        metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
357    //        metadata.addProperty("persistentId", createValue(context, persistentId));
358    //        if (element.hasAttribute(UPDATE_ATTRIBUTE)) {
359    //            metadata.addProperty("update", createValue(context, element.getAttribute(UPDATE_ATTRIBUTE)));
360    //        }
361    //        metadata.addProperty("serviceId", createIdRef(context, component.getId()));
362    //        context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
363    //        return component;
364    //    }
365    
366    //    private ComponentMetadata decorateManagedProperties(ParserContext context, Element element, ComponentMetadata component) {
367    //        if (!(component instanceof MutableBeanMetadata)) {
368    //            throw new ComponentDefinitionException("Element " + MANAGED_PROPERTIES_ELEMENT + " must be used inside a <bp:bean> element");
369    //        }
370    //        generateIdIfNeeded(context, ((MutableBeanMetadata) component));
371    //        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
372    //        metadata.setProcessor(true);
373    //        metadata.setId(getId(context, element));
374    //        metadata.setRuntimeClass(CmManagedProperties.class);
375    //        String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
376    //        // if persistentId is "" the managed properties element in nested in managed-service-factory
377    //        // and the configuration object will come from the factory. So we only really need to register
378    //        // ManagedService if the persistentId is not an empty string.
379    //        if (persistentId.length() > 0) {
380    //            metadata.setInitMethod("init");
381    //            metadata.setDestroyMethod("destroy");
382    //        }
383    //        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
384    //        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
385    //        metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
386    //        metadata.addProperty("persistentId", createValue(context, persistentId));
387    //        String updateStrategy = element.getAttribute(UPDATE_STRATEGY_ATTRIBUTE);
388    //        if (updateStrategy != null) {
389    //            metadata.addProperty("updateStrategy", createValue(context, updateStrategy));
390    //        }
391    //        if (element.hasAttribute(UPDATE_METHOD_ATTRIBUTE)) {
392    //            metadata.addProperty("updateMethod", createValue(context, element.getAttribute(UPDATE_METHOD_ATTRIBUTE)));
393    //        } else if ("component-managed".equals(updateStrategy)) {
394    //            throw new ComponentDefinitionException(UPDATE_METHOD_ATTRIBUTE + " attribute must be set when " + UPDATE_STRATEGY_ATTRIBUTE + " is set to 'component-managed'");
395    //        }
396    //        metadata.addProperty("beanName", createIdRef(context, component.getId()));
397    //        context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
398    //        return component;
399    //    }
400    
401        /**
402         * Create a reference to the ConfigurationAdmin service if not already done
403         * and add it to the registry.
404         *
405         * @param context the parser context
406         * @return a metadata pointing to the config admin
407         */
408        private Metadata createConfigAdminProxy(ParserContext context) {
409            MutableBeanMetadata bean = context.createMetadata(MutableBeanMetadata.class);
410            bean.setRuntimeClass(CmNamespaceHandler.class);
411            bean.setFactoryMethod("getConfigAdmin");
412            bean.setActivation(MutableBeanMetadata.ACTIVATION_LAZY);
413            bean.setScope(MutableBeanMetadata.SCOPE_PROTOTYPE);
414            return bean;
415        }
416    
417    //    private void registerManagedObjectManager(ParserContext context, ComponentDefinitionRegistry registry) {
418    //        if (registry.getComponentDefinition(MANAGED_OBJECT_MANAGER_NAME) == null) {
419    //            MutableBeanMetadata beanMetadata = context.createMetadata(MutableBeanMetadata.class);
420    //            beanMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
421    //            beanMetadata.setId(MANAGED_OBJECT_MANAGER_NAME);
422    //            beanMetadata.setRuntimeClass(ManagedObjectManager.class);
423    //            registry.registerComponentDefinition(beanMetadata);
424    //        }
425    //    }
426    
427        private static ValueMetadata createValue(ParserContext context, String value) {
428            return createValue(context, value, null);
429        }
430    
431        private static ValueMetadata createValue(ParserContext context, String value, String type) {
432            MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
433            m.setStringValue(value);
434            m.setType(type);
435            return m;
436        }
437    
438        private static RefMetadata createRef(ParserContext context, String value) {
439            MutableRefMetadata m = context.createMetadata(MutableRefMetadata.class);
440            m.setComponentId(value);
441            return m;
442        }
443        private static ReferenceMetadata createReference(ParserContext context, String interfaceName) {
444            MutableReferenceMetadata m = context.createMetadata(MutableReferenceMetadata.class);
445            m.setInterface(interfaceName);
446            return m;
447        }
448    
449        private static IdRefMetadata createIdRef(ParserContext context, String value) {
450            MutableIdRefMetadata m = context.createMetadata(MutableIdRefMetadata.class);
451            m.setComponentId(value);
452            return m;
453        }
454    
455        private static CollectionMetadata createList(ParserContext context, List<String> list) {
456            MutableCollectionMetadata m = context.createMetadata(MutableCollectionMetadata.class);
457            m.setCollectionClass(List.class);
458            m.setValueType(String.class.getName());
459            for (String v : list) {
460                m.addValue(createValue(context, v, String.class.getName()));
461            }
462            return m;
463        }
464    
465        private static String getTextValue(Element element) {
466            StringBuffer value = new StringBuffer();
467            NodeList nl = element.getChildNodes();
468            for (int i = 0; i < nl.getLength(); i++) {
469                Node item = nl.item(i);
470                if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
471                    value.append(item.getNodeValue());
472                }
473            }
474            return value.toString();
475        }
476    
477        private static boolean nodeNameEquals(Node node, String name) {
478            return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
479        }
480    
481        public static boolean isBlueprintNamespace(String ns) {
482            return BLUEPRINT_NAMESPACE.equals(ns);
483        }
484    
485        public String getId(ParserContext context, Element element) {
486            if (element.hasAttribute(ID_ATTRIBUTE)) {
487                return element.getAttribute(ID_ATTRIBUTE);
488            } else {
489                return generateId(context);
490            }
491        }
492    
493        public void generateIdIfNeeded(ParserContext context, MutableComponentMetadata metadata) {
494            if (metadata.getId() == null) {
495                metadata.setId(generateId(context));
496            }
497        }
498    
499        private String generateId(ParserContext context) {
500            String id;
501            do {
502                id = ".cm-" + ++idCounter;
503            } while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
504            return id;
505        }
506    
507    //    private Parser getParser(ParserContext ctx) {
508    //        if (ctx instanceof ParserContextImpl) {
509    //            return ((ParserContextImpl) ctx).getParser();
510    //        }
511    //        throw new RuntimeException("Unable to get parser");
512    //    }
513    
514        public List<String> parseInterfaceNames(Element element) {
515            List<String> interfaceNames = new ArrayList<String>();
516            NodeList nl = element.getChildNodes();
517            for (int i = 0; i < nl.getLength(); i++) {
518                Node node = nl.item(i);
519                if (node instanceof Element) {
520                    Element e = (Element) node;
521                    if (nodeNameEquals(e, VALUE_ELEMENT)) {
522                        String v = getTextValue(e).trim();
523                        if (interfaceNames.contains(v)) {
524                            throw new ComponentDefinitionException("The element " + INTERFACES_ELEMENT + " should not contain the same interface twice");
525                        }
526                        interfaceNames.add(getTextValue(e));
527                    } else {
528                        throw new ComponentDefinitionException("Unsupported element " + e.getNodeName() + " inside an " + INTERFACES_ELEMENT + " element");
529                    }
530                }
531            }
532            return interfaceNames;
533        }
534    
535    }