001    /*****************************************************************************
002     * Copyright (C) PicoContainer 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.picocontainer.script.xml;
010    
011    import org.picocontainer.ComponentAdapter;
012    import org.picocontainer.PicoContainer;
013    import org.picocontainer.PicoClassNotFoundException;
014    import org.picocontainer.lifecycle.NullLifecycleStrategy;
015    import org.picocontainer.monitors.NullComponentMonitor;
016    import org.picocontainer.injectors.AdaptingInjection;
017    import org.picocontainer.behaviors.PropertyApplicator;
018    import org.picocontainer.ComponentFactory;
019    
020    import java.util.Properties;
021    
022    import org.w3c.dom.Element;
023    import org.w3c.dom.Node;
024    import org.w3c.dom.NodeList;
025    
026    /**
027     * Implementation of XMLComponentInstanceFactory that uses PropertyApplicator
028     * to create instances from DOM elements.
029     *
030     * @author Paul Hammant
031     * @author Marcos Tarruella
032     * @author Mauro Talevi
033     */
034    public class BeanComponentInstanceFactory implements XMLComponentInstanceFactory {
035        
036        private static final String NAME_ATTRIBUTE = "name";
037        
038        @SuppressWarnings("unchecked")
039        public Object makeInstance(PicoContainer pico, Element element, ClassLoader classLoader) {
040            String className = element.getNodeName();
041            Object instance;
042    
043            if (element.getChildNodes().getLength() == 1) {
044                instance = PropertyApplicator.convert(className, element.getFirstChild().getNodeValue(), classLoader);
045            } else {
046    
047                //TODO componentMonitor.newBehavior( .. ) stuff
048    
049                PropertyApplicator propertyAdapter =
050                        new PropertyApplicator(createComponentAdapter(className, classLoader));
051                java.util.Properties properties = createProperties(element.getChildNodes());
052                propertyAdapter.setProperties(properties);
053                instance = propertyAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
054            }
055            return instance;
056        }
057    
058        @SuppressWarnings("unchecked")
059        private ComponentAdapter createComponentAdapter(String className, ClassLoader classLoader)  {
060            Class implementation = loadClass(classLoader, className);
061            ComponentFactory factory = new AdaptingInjection();
062            return factory.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), new Properties(), className, implementation);
063        }
064    
065        private Class<?> loadClass(final ClassLoader classLoader, final String className) {
066            try {
067                return classLoader.loadClass(className);
068            } catch (ClassNotFoundException e) {
069                throw new PicoClassNotFoundException(className, e);
070            }
071        }
072    
073        private java.util.Properties createProperties(NodeList nodes) {
074            java.util.Properties properties = new java.util.Properties();
075            for (int i = 0; i < nodes.getLength(); i++) {
076                Node n = nodes.item(i);
077                if (n.getNodeType() == Node.ELEMENT_NODE) {
078                    String name = n.getNodeName();
079                    
080                    //Provide for a new 'name' attribute in properties.
081                    if (n.hasAttributes()) {
082                        String mappedName = n.getAttributes().getNamedItem(NAME_ATTRIBUTE).getNodeValue();
083                        if (mappedName != null) {
084                            name = mappedName;
085                        }
086                    }
087    
088                    String value = n.getFirstChild().getNodeValue();
089                    properties.setProperty(name, value);
090                }
091            }
092            return properties;
093        }
094    }