KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > AntTypeDefinition


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant;
20
21 import java.lang.reflect.InvocationTargetException JavaDoc;
22 import java.lang.reflect.Constructor JavaDoc;
23
24
25 /**
26  * This class contains all the information
27  * on a particular ant type,
28  * the classname, adaptor and the class
29  * it should be assignable from.
30  * This type replaces the task/datatype split
31  * of pre ant 1.6.
32  *
33  */

34 public class AntTypeDefinition {
35     private String JavaDoc name;
36     private Class JavaDoc clazz;
37     private Class JavaDoc adapterClass;
38     private Class JavaDoc adaptToClass;
39     private String JavaDoc className;
40     private ClassLoader JavaDoc classLoader;
41
42     /**
43      * Set the definition's name.
44      * @param name the name of the definition.
45      */

46     public void setName(String JavaDoc name) {
47         this.name = name;
48     }
49
50     /**
51      * Return the definition's name.
52      * @return the name of the definition.
53      */

54     public String JavaDoc getName() {
55         return name;
56     }
57
58     /**
59      * Set the class of the definition.
60      * As a side-effect may set the classloader and classname.
61      * @param clazz the class of this definition.
62      */

63     public void setClass(Class JavaDoc clazz) {
64         this.clazz = clazz;
65         if (clazz == null) {
66             return;
67         }
68         this.classLoader = (classLoader == null)
69             ? clazz.getClassLoader() : classLoader;
70         this.className = (className == null) ? clazz.getName() : className;
71     }
72
73     /**
74      * Set the classname of the definition.
75      * @param className the classname of this definition.
76      */

77     public void setClassName(String JavaDoc className) {
78         this.className = className;
79     }
80
81     /**
82      * Get the classname of the definition.
83      * @return the name of the class of this definition.
84      */

85     public String JavaDoc getClassName() {
86         return className;
87     }
88
89     /**
90      * Set the adapter class for this definition.
91      * This class is used to adapt the definitions class if
92      * required.
93      * @param adapterClass the adapterClass.
94      */

95     public void setAdapterClass(Class JavaDoc adapterClass) {
96         this.adapterClass = adapterClass;
97     }
98
99     /**
100      * Set the assignable class for this definition.
101      * @param adaptToClass the assignable class.
102      */

103
104     public void setAdaptToClass(Class JavaDoc adaptToClass) {
105         this.adaptToClass = adaptToClass;
106     }
107
108     /**
109      * Set the classloader to use to create an instance
110      * of the definition.
111      * @param classLoader the ClassLoader.
112      */

113     public void setClassLoader(ClassLoader JavaDoc classLoader) {
114         this.classLoader = classLoader;
115     }
116
117     /**
118      * Get the classloader for this definition.
119      * @return the classloader for this definition.
120      */

121     public ClassLoader JavaDoc getClassLoader() {
122         return classLoader;
123     }
124
125     /**
126      * Get the exposed class for this
127      * definition. This will be a proxy class
128      * (adapted class) if there is an adapter
129      * class and the definition class is not
130      * assignable from the assignable class.
131      * @param project the current project.
132      * @return the exposed class.
133      */

134     public Class JavaDoc getExposedClass(Project project) {
135         if (adaptToClass != null) {
136             Class JavaDoc z = getTypeClass(project);
137             if (z == null || adaptToClass.isAssignableFrom(z)) {
138                 return z;
139             }
140         }
141         return (adapterClass == null) ? getTypeClass(project) : adapterClass;
142     }
143
144     /**
145      * Get the definition class.
146      * @param project the current project.
147      * @return the type of the definition.
148      */

149     public Class JavaDoc getTypeClass(Project project) {
150         try {
151             return innerGetTypeClass();
152         } catch (NoClassDefFoundError JavaDoc ncdfe) {
153             project.log("Could not load a dependent class ("
154                         + ncdfe.getMessage() + ") for type "
155                         + name, Project.MSG_DEBUG);
156         } catch (ClassNotFoundException JavaDoc cnfe) {
157             project.log("Could not load class (" + className
158                         + ") for type " + name, Project.MSG_DEBUG);
159         }
160         return null;
161     }
162
163     /**
164      * Try and load a class, with no attempt to catch any fault.
165      * @return the class that implements this component
166      * @throws ClassNotFoundException if the class cannot be found.
167      * @throws NoClassDefFoundError if the there is an error
168      * finding the class.
169      */

170     public Class JavaDoc innerGetTypeClass() throws ClassNotFoundException JavaDoc {
171         if (clazz != null) {
172             return clazz;
173         }
174         if (classLoader == null) {
175             clazz = Class.forName(className);
176         } else {
177             clazz = classLoader.loadClass(className);
178         }
179         return clazz;
180     }
181
182     /**
183      * Create an instance of the definition.
184      * The instance may be wrapped in a proxy class.
185      * @param project the current project.
186      * @return the created object.
187      */

188     public Object JavaDoc create(Project project) {
189         return icreate(project);
190     }
191
192     /**
193      * Create a component object based on
194      * its definition.
195      * @return the component as an <code>Object</code>.
196      */

197     private Object JavaDoc icreate(Project project) {
198         Class JavaDoc c = getTypeClass(project);
199         if (c == null) {
200             return null;
201         }
202         Object JavaDoc o = createAndSet(project, c);
203         if (o == null || adapterClass == null) {
204             return o;
205         }
206         if (adaptToClass != null) {
207             if (adaptToClass.isAssignableFrom(o.getClass())) {
208                 return o;
209             }
210         }
211         TypeAdapter adapterObject = (TypeAdapter) createAndSet(
212             project, adapterClass);
213         if (adapterObject == null) {
214             return null;
215         }
216         adapterObject.setProxy(o);
217         return adapterObject;
218     }
219
220     /**
221      * Checks if the attributes are correct.
222      * <dl>
223      * <li>if the class can be created.</li>
224      * <li>if an adapter class can be created</li>
225      * <li>if the type is assignable from adapto</li>
226      * <li>if the type can be used with the adapter class</li>
227      * </dl>
228      * @param project the current project.
229      */

230     public void checkClass(Project project) {
231         if (clazz == null) {
232             clazz = getTypeClass(project);
233             if (clazz == null) {
234                 throw new BuildException(
235                     "Unable to create class for " + getName());
236             }
237         }
238         // check adapter
239
if (adapterClass != null && (adaptToClass == null
240             || !adaptToClass.isAssignableFrom(clazz))) {
241             TypeAdapter adapter = (TypeAdapter) createAndSet(
242                 project, adapterClass);
243             if (adapter == null) {
244                 throw new BuildException("Unable to create adapter object");
245             }
246             adapter.checkProxyClass(clazz);
247         }
248     }
249
250     /**
251      * Get the constructor of the definition
252      * and invoke it.
253      * @return the instantiated <code>Object</code>.
254      */

255     private Object JavaDoc createAndSet(Project project, Class JavaDoc c) {
256         try {
257             Object JavaDoc o = innerCreateAndSet(c, project);
258             return o;
259         } catch (InvocationTargetException JavaDoc ex) {
260             Throwable JavaDoc t = ex.getTargetException();
261             throw new BuildException(
262                 "Could not create type " + name + " due to " + t, t);
263         } catch (NoClassDefFoundError JavaDoc ncdfe) {
264             String JavaDoc msg = "Type " + name + ": A class needed by class "
265                 + c + " cannot be found: " + ncdfe.getMessage();
266             throw new BuildException(msg, ncdfe);
267         } catch (NoSuchMethodException JavaDoc nsme) {
268             throw new BuildException("Could not create type " + name
269                     + " as the class " + c + " has no compatible constructor");
270         } catch (InstantiationException JavaDoc nsme) {
271             throw new BuildException("Could not create type "
272                     + name + " as the class " + c + " is abstract");
273         } catch (IllegalAccessException JavaDoc e) {
274             throw new BuildException("Could not create type "
275                     + name + " as the constructor " + c + " is not accessible");
276         } catch (Throwable JavaDoc t) {
277             throw new BuildException(
278                 "Could not create type " + name + " due to " + t, t);
279         }
280     }
281
282     /**
283      * Inner implementation of the {@link #createAndSet(Project, Class)} logic, with no
284      * exception catching
285      * @param newclass class to create
286      * @param project the project to use
287      * @return a newly constructed and bound instance.
288      * @throws NoSuchMethodException no good construtor.
289      * @throws InstantiationException cannot initialize the object.
290      * @throws IllegalAccessException cannot access the object.
291      * @throws InvocationTargetException error in invocation.
292      */

293     public Object JavaDoc innerCreateAndSet(Class JavaDoc newclass, Project project)
294             throws NoSuchMethodException JavaDoc,
295             InstantiationException JavaDoc,
296             IllegalAccessException JavaDoc,
297             InvocationTargetException JavaDoc {
298         Constructor JavaDoc ctor = null;
299         boolean noArg = false;
300         // DataType can have a "no arg" constructor or take a single
301
// Project argument.
302
try {
303             ctor = newclass.getConstructor(new Class JavaDoc[0]);
304             noArg = true;
305         } catch (NoSuchMethodException JavaDoc nse) {
306             //can throw the same exception, if there is no this(Project) ctor.
307
ctor = newclass.getConstructor(new Class JavaDoc[] {Project.class});
308             noArg = false;
309         }
310         //now we instantiate
311
Object JavaDoc o = ctor.newInstance(
312             ((noArg) ? new Object JavaDoc[0] : new Object JavaDoc[] {project}));
313
314         //set up project references.
315
project.setProjectReference(o);
316         return o;
317     }
318
319     /**
320      * Equality method for this definition (assumes the names are the same).
321      *
322      * @param other another definition.
323      * @param project the project the definition.
324      * @return true if the definitions are the same.
325      */

326     public boolean sameDefinition(AntTypeDefinition other, Project project) {
327         return (other != null && other.getClass() == getClass()
328             && other.getTypeClass(project).equals(getTypeClass(project))
329             && other.getExposedClass(project).equals(getExposedClass(project))
330             && other.adapterClass == adapterClass
331             && other.adaptToClass == adaptToClass);
332     }
333
334     /**
335      * Similar definition;
336      * used to compare two definitions defined twice with the same
337      * name and the same types.
338      * The classloader may be different but have the same
339      * path so #sameDefinition cannot
340      * be used.
341      * @param other the definition to compare to.
342      * @param project the current project.
343      * @return true if the definitions are the same.
344      */

345     public boolean similarDefinition(AntTypeDefinition other, Project project) {
346         if (other == null
347             || getClass() != other.getClass()
348             || !getClassName().equals(other.getClassName())
349             || !extractClassname(adapterClass).equals(
350             extractClassname(other.adapterClass))
351             || !extractClassname(adaptToClass).equals(
352             extractClassname(other.adaptToClass))) {
353             return false;
354         }
355         // all the names are the same: check if the class path of the loader
356
// is the same
357
ClassLoader JavaDoc oldLoader = other.getClassLoader();
358         ClassLoader JavaDoc newLoader = getClassLoader();
359         return oldLoader == newLoader
360             || (oldLoader instanceof AntClassLoader
361             && newLoader instanceof AntClassLoader
362             && ((AntClassLoader) oldLoader).getClasspath()
363             .equals(((AntClassLoader) newLoader).getClasspath()));
364     }
365
366     private String JavaDoc extractClassname(Class JavaDoc c) {
367         return (c == null) ? "<null>" : c.getClass().getName();
368     }
369 }
370
Popular Tags