    001    /*****************************************************************************
    002     * Copyright (C) NanoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *                                                                           *
    008     *****************************************************************************/
    009    package org.nanocontainer.script.xml;
    010
    011    import org.picocontainer.ComponentAdapter;
    012    import org.picocontainer.Parameter;
    013    import org.picocontainer.PicoContainer;
    014    import org.picocontainer.defaults.BeanPropertyComponentAdapter;
    015    import org.picocontainer.defaults.ComponentAdapterFactory;
    016    import org.picocontainer.defaults.DefaultComponentAdapterFactory;
    017    import org.w3c.dom.Element;
    018    import org.w3c.dom.Node;
    019    import org.w3c.dom.NodeList;
    020
    021    import java.net.MalformedURLException;
    022    import java.util.Properties;
    023
    024    /**
    025     * Implementation of XMLComponentInstanceFactory that uses BeanPropertyComponentAdapter
    026     * to create instances from DOM elements.
    027     *
    028     * @author Paul Hammant
    029     * @author Marcos Tarruella
    030     * @author Mauro Talevi
    031     */
    032    public class BeanComponentInstanceFactory implements XMLComponentInstanceFactory {
    033
    034        private static final String NAME_ATTRIBUTE = "name";
    035
    036        public Object makeInstance(PicoContainer pico, Element element, ClassLoader classLoader) throws ClassNotFoundException, MalformedURLException {
    037            String className = element.getNodeName();
    038            Object instance = null;
    039
    040            if (element.getChildNodes().getLength() == 1) {
    041                instance = BeanPropertyComponentAdapter.convert(className, element.getFirstChild().getNodeValue(), classLoader);
    042            } else {
    043                BeanPropertyComponentAdapter propertyComponentAdapter =
    044                        new BeanPropertyComponentAdapter(createComponentAdapter(className, classLoader));
    045                Properties properties = createProperties(element.getChildNodes());
    046                propertyComponentAdapter.setProperties(properties);
    047                instance = propertyComponentAdapter.getComponentInstance(pico);
    048            }
    049            return instance;
    050        }
    051
    052        private ComponentAdapter createComponentAdapter(String className, ClassLoader classLoader) throws ClassNotFoundException {
    053            Class implementation = classLoader.loadClass(className);
    054            ComponentAdapterFactory factory = new DefaultComponentAdapterFactory();
    055            return factory.createComponentAdapter(className, implementation, new Parameter[]{});
    056        }
    057
    058        private Properties createProperties(NodeList nodes) {
    059            Properties properties = new Properties();
    060            for (int i = 0; i < nodes.getLength(); i++) {
    061                Node n = nodes.item(i);
    062                if (n.getNodeType() == Node.ELEMENT_NODE) {
    063                    String name = n.getNodeName();
    064
    065                    //Provide for a new 'name' attribute in properties.
    066                    if (n.hasAttributes()) {
    067                        String mappedName = n.getAttributes().getNamedItem(NAME_ATTRIBUTE).getNodeValue();
    068                        if (mappedName != null) {
    069                            name = mappedName;
    070                        }
    071                    }
    072
    073                    String value = n.getFirstChild().getNodeValue();
    074                    properties.setProperty(name, value);
    075                }
    076            }
    077            return properties;
    078        }
    079    }