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 PropertyApplicator propertyAdapter = 047 new PropertyApplicator(createComponentAdapter(className, classLoader)); 048 java.util.Properties properties = createProperties(element.getChildNodes()); 049 propertyAdapter.setProperties(properties); 050 instance = propertyAdapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class); 051 } 052 return instance; 053 } 054 055 @SuppressWarnings("unchecked") 056 private ComponentAdapter createComponentAdapter(String className, ClassLoader classLoader) { 057 Class implementation = loadClass(classLoader, className); 058 ComponentFactory factory = new AdaptingInjection(); 059 return factory.createComponentAdapter(new NullComponentMonitor(), new NullLifecycleStrategy(), new Properties(), className, implementation); 060 } 061 062 private Class<?> loadClass(final ClassLoader classLoader, final String className) { 063 try { 064 return classLoader.loadClass(className); 065 } catch (ClassNotFoundException e) { 066 throw new PicoClassNotFoundException(className, e); 067 } 068 } 069 070 private java.util.Properties createProperties(NodeList nodes) { 071 java.util.Properties properties = new java.util.Properties(); 072 for (int i = 0; i < nodes.getLength(); i++) { 073 Node n = nodes.item(i); 074 if (n.getNodeType() == Node.ELEMENT_NODE) { 075 String name = n.getNodeName(); 076 077 //Provide for a new 'name' attribute in properties. 078 if (n.hasAttributes()) { 079 String mappedName = n.getAttributes().getNamedItem(NAME_ATTRIBUTE).getNodeValue(); 080 if (mappedName != null) { 081 name = mappedName; 082 } 083 } 084 085 String value = n.getFirstChild().getNodeValue(); 086 properties.setProperty(name, value); 087 } 088 } 089 return properties; 090 } 091 }