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 }