001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.ant;
024:
025: import java.lang.reflect.InvocationTargetException;
026: import java.util.Collection;
027: import java.util.Iterator;
028: import java.util.LinkedList;
029: import java.util.List;
030:
031: import org.apache.tools.ant.AntClassLoader;
032: import org.apache.tools.ant.BuildException;
033: import org.apache.tools.ant.Task;
034: import org.apache.tools.ant.types.Path;
035:
036: import biz.hammurapi.config.ConfigurationException;
037: import biz.hammurapi.config.Parameterizable;
038:
039: /**
040: * Object entry. Base class for configurable objects.
041: * @ant.element name="objectentry"
042: * @author Pavel Vlasov
043: * @version $Revision: 1.5 $
044: */
045: public class ObjectEntry extends Task {
046: private String className;
047: private String value;
048: private List parameters = new LinkedList();
049:
050: /**
051: * Configuration parameter. Object entry class must implement biz.hammurapi.config.Parameterizable
052: * @ant.non-required
053: * @param parameter
054: * @throws BuildException
055: */
056: public void addConfiguredParameter(Param parameter)
057: throws BuildException {
058: if (parameter.getName() == null) {
059: throw new BuildException("Unnamed parameter");
060: }
061: parameters.add(parameter);
062: }
063:
064: /**
065: * Either value or class name is required. If both class name and value are
066: * specified then that class should have a constructor with one String parameter.
067: * @ant.non-required
068: * @param className
069: */
070: public void setClassName(String className) {
071: this .className = className;
072: }
073:
074: /**
075: * Not required if class name is set.
076: * @ant.non-required
077: * @param value
078: */
079: public void setValue(String value) {
080: this .value = value;
081: }
082:
083: /**
084: * @ant.ignore
085: * @return
086: */
087: public Collection getParameters() {
088: return parameters;
089: }
090:
091: private Object theObject;
092:
093: protected void validateClass(Class clazz) throws BuildException {
094:
095: }
096:
097: protected void validateInstance(Object instance)
098: throws BuildException {
099:
100: }
101:
102: public Object getObject(ClassLoader masterClassLoader)
103: throws BuildException {
104: if (theObject == null) {
105: if (className == null) {
106: if (parameters.isEmpty()) {
107: if (value == null) {
108: return null;
109: }
110: theObject = value;
111: } else {
112: throw new BuildException(
113: "Nested parameters supported only if classname attribute is set");
114: }
115: } else {
116: try {
117: ClassLoader classLoader = masterClassLoader == null ? getProject()
118: .getCoreLoader()
119: : masterClassLoader;
120: if (classPath != null) {
121: if (masterClassLoader == null) {
122: classLoader = new AntClassLoader(
123: getProject(), classPath);
124: } else {
125: classLoader = new AntClassLoader(
126: masterClassLoader, getProject(),
127: classPath, false);
128: }
129: }
130:
131: if (classLoader == null) {
132: classLoader = getClass().getClassLoader();
133: }
134:
135: Class theClass = classLoader.loadClass(className);
136: validateClass(theClass);
137: if (!(parameters.isEmpty() || Parameterizable.class
138: .isAssignableFrom(theClass))) {
139: throw new BuildException(className
140: + " does not support parameters");
141: }
142:
143: if (value == null) {
144: theObject = theClass.newInstance();
145: } else {
146: theObject = theClass.getConstructor(
147: new Class[] { String.class })
148: .newInstance(new Object[] { value });
149: }
150:
151: if (!parameters.isEmpty()) {
152: // Double check
153: if (theObject instanceof Parameterizable) {
154: Iterator it = parameters.iterator();
155: while (it.hasNext()) {
156: Param param = (Param) it.next();
157: try {
158: if (!((Parameterizable) theObject)
159: .setParameter(
160: param.getName(),
161: param
162: .getObject(masterClassLoader))) {
163: throw new BuildException(
164: theObject.getClass()
165: .getName()
166: + " does not support parameter "
167: + param
168: .getName());
169: }
170: } catch (ConfigurationException e) {
171: throw new BuildException(
172: "Could not set parameter "
173: + param.getName()
174: + " for object entry "
175: + theObject
176: .getClass()
177: .getName(),
178: e);
179: }
180: }
181: } else {
182: throw new BuildException(className
183: + " does not support parameters");
184: }
185: }
186: validateInstance(theObject);
187: } catch (ClassNotFoundException e) {
188: throw new BuildException("Class not found: "
189: + className, e);
190: } catch (InstantiationException e) {
191: throw new BuildException("Can not instantiate: "
192: + className, e);
193: } catch (IllegalAccessException e) {
194: throw new BuildException("Can not instantiate: "
195: + className, e);
196: } catch (InvocationTargetException e) {
197: throw new BuildException("Can not instantiate: "
198: + className, e);
199: } catch (NoSuchMethodException e) {
200: throw new BuildException("Constructor " + className
201: + "(String) not found", e);
202: }
203: }
204: }
205: return theObject;
206: }
207:
208: /**
209: * @return
210: */
211: protected String getClassName() {
212: return className;
213: }
214:
215: /**
216: * @return
217: */
218: protected String getValue() {
219: return value;
220: }
221:
222: /**
223: * Classpath for loading classes
224: * @ant:non-required
225: */
226: private Path classPath;
227:
228: public void setClassPath(Path classPath) {
229: if (this .classPath == null) {
230: this .classPath = classPath;
231: } else {
232: this .classPath.append(classPath);
233: }
234: }
235:
236: /**
237: * Maybe creates a nested classpath element.
238: * @ant:non-required
239: */
240: public Path createClasspath() {
241: if (classPath == null) {
242: classPath = new Path(getProject());
243: }
244: return classPath.createPath();
245: }
246:
247: public void addText(String text) {
248: this.value = text;
249: }
250: }
|