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 }