001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.util.xml;
011:
012: import org.mmbase.util.Casting;
013:
014: import java.util.*;
015: import java.lang.reflect.*;
016: import org.w3c.dom.*;
017:
018: import org.mmbase.util.logging.*;
019:
020: /**
021: * Utilities to use an XML to instantiate Java objects, using reflection.
022: *
023: * @since MMBase-1.9
024: * @author Michiel Meeuwissen
025: * @version $Id: Instantiator.java,v 1.2 2007/12/28 17:14:57 michiel Exp $
026: */
027: public abstract class Instantiator {
028:
029: private static final Logger log = Logging
030: .getLoggerInstance(Instantiator.class);
031:
032: /**
033: * Instantiates any object using an Dom Element and constructor arguments. Sub-param tags are
034: * used on set-methods on the newly created object. This is a pretty generic method, it should
035: * perhaps be moved to org.mmbase.util.
036: */
037: public static Object getInstance(Element classElement,
038: Object... args) throws org.xml.sax.SAXException,
039: ClassNotFoundException, NoSuchMethodException,
040: InstantiationException, IllegalAccessException,
041: java.lang.reflect.InvocationTargetException {
042: String className = classElement.getAttribute("name");
043: if ("".equals(className))
044: className = classElement.getAttribute("class"); // for urlconverters config (not ok yet)
045: Class claz = Class.forName(className);
046: List<Class> argTypes = new ArrayList<Class>(args.length);
047: for (Object arg : args) {
048: argTypes.add(arg.getClass());
049: }
050: Class[] argTypesArray = argTypes.toArray(new Class[] {});
051: Constructor constructor = null;
052: for (Constructor c : claz.getConstructors()) {
053: Class[] parameterTypes = c.getParameterTypes();
054: if (parameterTypes.length != argTypesArray.length)
055: continue;
056: for (int i = 0; i < parameterTypes.length; i++) {
057: if (!parameterTypes[i]
058: .isAssignableFrom(argTypesArray[i]))
059: continue;
060: }
061: constructor = c;
062: break;
063: }
064: if (constructor == null)
065: throw new NoSuchMethodError("No constructors found for "
066: + args);
067: log.debug("Found constructor " + constructor);
068:
069: Object o = constructor.newInstance(args);
070:
071: NodeList params = classElement.getChildNodes();
072: for (int i = 0; i < params.getLength(); i++) {
073: try {
074: Node node = params.item(i);
075: if (node instanceof Element
076: && node.getNodeName().equals("param")) {
077: Element param = (Element) node;
078: String name = param.getAttribute("name");
079: String value = org.mmbase.util.xml.DocumentReader
080: .getNodeTextValue(param);
081: String methodName = "set"
082: + name.substring(0, 1).toUpperCase()
083: + name.substring(1);
084: try {
085: Method method = claz.getMethod(methodName,
086: String.class);
087: method.invoke(o, value);
088: } catch (NoSuchMethodException nsme) {
089: try {
090: Method method = claz.getMethod(methodName,
091: Boolean.TYPE);
092: method.invoke(o, Casting.toBoolean(value));
093: } catch (NoSuchMethodException nsme2) {
094: Method method = claz.getMethod(methodName,
095: Integer.TYPE);
096: method.invoke(o, Casting.toInt(value));
097: }
098: }
099: }
100: } catch (Exception e) {
101: log.error(e.getMessage(), e);
102: }
103: }
104: return o;
105: }
106:
107: public static Object getInstanceWithSubElement(Element element,
108: Object... args) throws org.xml.sax.SAXException,
109: ClassNotFoundException, NoSuchMethodException,
110: InstantiationException, IllegalAccessException,
111: java.lang.reflect.InvocationTargetException {
112: NodeList childs = element.getChildNodes();
113: Object instance = null;
114: for (int i = 0; i < childs.getLength(); i++) {
115: Node node = childs.item(i);
116: if (node instanceof Element
117: && node.getNodeName().equals("class")) {
118: instance = getInstance((Element) node, args);
119: }
120: }
121: return instance;
122: }
123:
124: }
|