source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/AntTypeDefinition.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 11.4 KB
Line 
1/*
2 * Copyright 2003-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant;
19
20
21/**
22 * This class contains all the information
23 * on a particular ant type,
24 * the classname, adaptor and the class
25 * it should be assignable from.
26 * This type replaces the task/datatype split
27 * of pre ant 1.6.
28 *
29 */
30public class AntTypeDefinition {
31 private String name;
32 private Class clazz;
33 private Class adapterClass;
34 private Class adaptToClass;
35 private String className;
36 private ClassLoader classLoader;
37
38 /**
39 * set the definition's name
40 * @param name the name of the definition
41 */
42 public void setName(String name) {
43 this.name = name;
44 }
45
46 /**
47 * return the definition's name
48 * @return the name of the definition
49 */
50 public String getName() {
51 return name;
52 }
53
54 /**
55 * set the class of the definition.
56 * as a side-effect may set the classloader and classname
57 * @param clazz the class of this definition
58 */
59 public void setClass(Class clazz) {
60 this.clazz = clazz;
61 if (clazz == null) {
62 return;
63 }
64 if (classLoader == null) {
65 this.classLoader = clazz.getClassLoader();
66 }
67 if (className == null) {
68 this.className = clazz.getName();
69 }
70 }
71
72 /**
73 * set the classname of the definition
74 * @param className the classname of this definition
75 */
76 public void setClassName(String className) {
77 this.className = className;
78 }
79
80 /**
81 * get the classname of the definition
82 * @return the name of the class of this definition
83 */
84 public String getClassName() {
85 return className;
86 }
87
88 /**
89 * set the adapter class for this definition.
90 * this class is used to adapt the definitions class if
91 * required.
92 * @param adapterClass the adapterClass
93 */
94 public void setAdapterClass(Class adapterClass) {
95 this.adapterClass = adapterClass;
96 }
97
98 /**
99 * set the assignable class for this definition.
100 * @param adaptToClass the assignable class
101 */
102
103 public void setAdaptToClass(Class adaptToClass) {
104 this.adaptToClass = adaptToClass;
105 }
106
107 /**
108 * set the classloader to use to create an instance
109 * of the definition
110 * @param classLoader the classLoader
111 */
112 public void setClassLoader(ClassLoader classLoader) {
113 this.classLoader = classLoader;
114 }
115
116 /**
117 * get the classloader for this definition
118 * @return the classloader for this definition
119 */
120 public ClassLoader getClassLoader() {
121 return classLoader;
122 }
123
124 /**
125 * get the exposed class for this
126 * definition. This will be a proxy class
127 * (adapted class) if there is an adapter
128 * class and the definition class is not
129 * assignable from the assignable class.
130 * @param project the current project
131 * @return the exposed class
132 */
133 public Class getExposedClass(Project project) {
134 if (adaptToClass != null) {
135 Class z = getTypeClass(project);
136 if (z == null) {
137 return null;
138 }
139 if (adaptToClass.isAssignableFrom(z)) {
140 return z;
141 }
142 }
143 if (adapterClass != null) {
144 return adapterClass;
145 }
146 return getTypeClass(project);
147 }
148
149 /**
150 * get the definition class
151 * @param project the current project
152 * @return the type of the definition
153 */
154 public Class getTypeClass(Project project) {
155 if (clazz != null) {
156 return clazz;
157 }
158
159 try {
160 if (classLoader == null) {
161 clazz = Class.forName(className);
162 } else {
163 clazz = classLoader.loadClass(className);
164 }
165 } catch (NoClassDefFoundError ncdfe) {
166 project.log("Could not load a dependent class ("
167 + ncdfe.getMessage() + ") for type "
168 + name, Project.MSG_DEBUG);
169 } catch (ClassNotFoundException cnfe) {
170 project.log("Could not load class (" + className
171 + ") for type " + name, Project.MSG_DEBUG);
172 }
173 return clazz;
174 }
175
176 /**
177 * create an instance of the definition.
178 * The instance may be wrapped in a proxy class.
179 * @param project the current project
180 * @return the created object
181 */
182 public Object create(Project project) {
183 return icreate(project);
184 }
185
186 /**
187 * Create a component object based on
188 * its definition
189 */
190 private Object icreate(Project project) {
191 Class c = getTypeClass(project);
192 if (c == null) {
193 return null;
194 }
195
196 Object o = createAndSet(project, c);
197 if (o == null || adapterClass == null) {
198 return o;
199 }
200
201 if (adaptToClass != null) {
202 if (adaptToClass.isAssignableFrom(o.getClass())) {
203 return o;
204 }
205 }
206
207 TypeAdapter adapterObject = (TypeAdapter) createAndSet(
208 project, adapterClass);
209 if (adapterObject == null) {
210 return null;
211 }
212
213 adapterObject.setProxy(o);
214 return adapterObject;
215 }
216
217 /**
218 * Checks if the attributes are correct.
219 * <dl>
220 * <li>if the class can be created.</li>
221 * <li>if an adapter class can be created</li>
222 * <li>if the type is assignable from adapto</li>
223 * <li>if the type can be used with the adapter class</li>
224 * </dl>
225 * @param project the current project
226 */
227 public void checkClass(Project project) {
228 if (clazz == null) {
229 clazz = getTypeClass(project);
230 if (clazz == null) {
231 throw new BuildException(
232 "Unable to create class for " + getName());
233 }
234 }
235 // check adapter
236 if (adapterClass != null) {
237 boolean needToCheck = true;
238 if (adaptToClass != null
239 && adaptToClass.isAssignableFrom(clazz)) {
240 needToCheck = false;
241 }
242 if (needToCheck) {
243 TypeAdapter adapter = (TypeAdapter) createAndSet(
244 project, adapterClass);
245 if (adapter == null) {
246 throw new BuildException("Unable to create adapter object");
247 }
248 adapter.checkProxyClass(clazz);
249 }
250 }
251 }
252
253 /**
254 * get the constructor of the definition
255 * and invoke it.
256 */
257 private Object createAndSet(Project project, Class c) {
258 try {
259 java.lang.reflect.Constructor ctor = null;
260 boolean noArg = false;
261 // DataType can have a "no arg" constructor or take a single
262 // Project argument.
263 try {
264 ctor = c.getConstructor(new Class[0]);
265 noArg = true;
266 } catch (NoSuchMethodException nse) {
267 ctor = c.getConstructor(new Class[] {Project.class});
268 noArg = false;
269 }
270
271 Object o = null;
272 if (noArg) {
273 o = ctor.newInstance(new Object[0]);
274 } else {
275 o = ctor.newInstance(new Object[] {project});
276 }
277 project.setProjectReference(o);
278 return o;
279 } catch (java.lang.reflect.InvocationTargetException ex) {
280 Throwable t = ex.getTargetException();
281 throw new BuildException(
282 "Could not create type " + name + " due to " + t, t);
283 } catch (NoClassDefFoundError ncdfe) {
284 String msg = "Type " + name + ": A class needed by class "
285 + c + " cannot be found: " + ncdfe.getMessage();
286 throw new BuildException(msg, ncdfe);
287 } catch (Throwable t) {
288 throw new BuildException(
289 "Could not create type " + name + " due to " + t, t);
290 }
291 }
292
293 /**
294 * Equality method for this definition (assumes the names are the same)
295 *
296 * @param other another definition
297 * @param project the project the definition
298 * @return true if the definitions are the same
299 */
300 public boolean sameDefinition(AntTypeDefinition other, Project project) {
301 if (other == null) {
302 return false;
303 }
304 if (other.getClass() != this.getClass()) {
305 return false;
306 }
307 if (!(other.getTypeClass(project).equals(getTypeClass(project)))) {
308 return false;
309 }
310 if (!other.getExposedClass(project).equals(getExposedClass(project))) {
311 return false;
312 }
313 if (other.adapterClass != adapterClass) {
314 return false;
315 }
316 if (other.adaptToClass != adaptToClass) {
317 return false;
318 }
319 return true;
320 }
321
322 /**
323 * Similar definition
324 * used to compare two definitions defined twice with the same
325 * name and the same types.
326 * the classloader may be different but have the same
327 * path so #sameDefinition cannot
328 * be used.
329 * @param other the definition to compare to
330 * @param project the current project
331 * @return true if the definitions are the same
332 */
333 public boolean similarDefinition(AntTypeDefinition other, Project project) {
334 if (other == null) {
335 return false;
336 }
337 if (getClass() != other.getClass()) {
338 return false;
339 }
340 if (!getClassName().equals(other.getClassName())) {
341 return false;
342 }
343 if (!extractClassname(adapterClass).equals(
344 extractClassname(other.adapterClass))) {
345 return false;
346 }
347 if (!extractClassname(adaptToClass).equals(
348 extractClassname(other.adaptToClass))) {
349 return false;
350 }
351 // all the names are the same: check if the class path of the loader
352 // is the same
353 ClassLoader oldLoader = other.getClassLoader();
354 ClassLoader newLoader = this.getClassLoader();
355 if (oldLoader == newLoader) {
356 return true;
357 }
358 return
359 newLoader != null
360 && oldLoader != null
361 && oldLoader instanceof AntClassLoader
362 && newLoader instanceof AntClassLoader
363 && ((AntClassLoader) oldLoader).getClasspath()
364 .equals(((AntClassLoader) newLoader).getClasspath());
365 }
366
367 private String extractClassname(Class c) {
368 if (c == null) {
369 return "<null>";
370 } else {
371 return c.getClass().getName();
372 }
373 }
374}
Note: See TracBrowser for help on using the repository browser.