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

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

initial import of LiRK3

File size: 29.1 KB
Line 
1/*
2 * Copyright 2003-2005 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
20import java.util.Enumeration;
21import java.util.Hashtable;
22import java.util.HashSet;
23import java.util.Iterator;
24import java.util.Properties;
25import java.util.Set;
26import java.util.Stack;
27
28import java.util.Vector;
29import java.io.InputStream;
30import java.io.IOException;
31import java.lang.ref.WeakReference;
32import java.lang.reflect.Modifier;
33
34import org.apache.tools.ant.taskdefs.Typedef;
35
36/**
37 * Component creation and configuration.
38 *
39 * The class is based around handing component
40 * definitions in an AntTypeTable.
41 *
42 * The old task/type methods have been kept
43 * for backward compatibly.
44 * Project will just delegate its calls to this class.
45 *
46 * A very simple hook mechanism is provided that allows users to plug
47 * in custom code. It is also possible to replace the default behavior
48 * ( for example in an app embedding ant )
49 *
50 * @since Ant1.6
51 */
52public class ComponentHelper {
53 /** Map from component name to anttypedefinition */
54 private AntTypeTable antTypeTable;
55
56 /** Map of tasks generated from antTypeTable */
57 private Hashtable taskClassDefinitions = new Hashtable();
58 /** flag to rebuild taskClassDefinitions */
59 private boolean rebuildTaskClassDefinitions = true;
60
61 /** Map of types generated from antTypeTable */
62 private Hashtable typeClassDefinitions = new Hashtable();
63 /** flag to rebuild typeClassDefinitions */
64 private boolean rebuildTypeClassDefinitions = true;
65
66 /** Set of namespaces that have been checked for antlibs */
67 private Set checkedNamespaces = new HashSet();
68
69 /**
70 * Stack of antlib contexts used to resolve definitions while
71 * processing antlib
72 */
73 private Stack antLibStack = new Stack();
74 /** current antlib uri */
75 private String antLibCurrentUri = null;
76
77 /**
78 * Map from task names to vectors of created tasks
79 * (String to Vector of Task). This is used to invalidate tasks if
80 * the task definition changes.
81 */
82 private Hashtable createdTasks = new Hashtable();
83
84 private ComponentHelper next;
85 private Project project;
86
87 /**
88 * Find a project component for a specific project, creating
89 * it if it does not exist.
90 * @param project the project.
91 * @return the project component for a specific project.
92 */
93 public static ComponentHelper getComponentHelper(Project project) {
94 // Singleton for now, it may change ( per/classloader )
95 ComponentHelper ph = (ComponentHelper) project.getReference(
96 "ant.ComponentHelper");
97 if (ph != null) {
98 return ph;
99 }
100 ph = new ComponentHelper();
101 ph.setProject(project);
102
103 project.addReference("ant.ComponentHelper", ph);
104 return ph;
105 }
106
107 /**
108 * Creates a new ComponentHelper instance.
109 */
110 protected ComponentHelper() {
111 }
112
113 /**
114 * Set the next chained component helper.
115 *
116 * @param next the next chained component helper.
117 */
118 public void setNext(ComponentHelper next) {
119 this.next = next;
120 }
121
122 /**
123 * Get the next chained component helper.
124 *
125 * @return the next chained component helper.
126 */
127 public ComponentHelper getNext() {
128 return next;
129 }
130
131 /**
132 * Sets the project for this component helper.
133 *
134 * @param project the project for this helper.
135 */
136 public void setProject(Project project) {
137 this.project = project;
138 antTypeTable = new AntTypeTable(project);
139 }
140
141 /**
142 * Used with creating child projects. Each child
143 * project inherits the component definitions
144 * from its parent.
145 * @param helper the component helper of the parent project.
146 */
147 public void initSubProject(ComponentHelper helper) {
148 // add the types of the parent project
149 AntTypeTable typeTable = helper.antTypeTable;
150 for (Iterator i = typeTable.values().iterator(); i.hasNext();) {
151 AntTypeDefinition def = (AntTypeDefinition) i.next();
152 antTypeTable.put(def.getName(), def);
153 }
154 // add the parsed namespaces of the parent project
155 for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) {
156 checkedNamespaces.add(i.next());
157 }
158 }
159
160 /**
161 * Factory method to create the components.
162 *
163 * This should be called by UnknownElement.
164 *
165 * @param ue The Unknown Element creating this component.
166 * @param ns Namespace URI. Also available as ue.getNamespace().
167 * @param componentType The component type,
168 * Also available as ue.getComponentName().
169 * @return the created component.
170 * @throws BuildException if an error occurs.
171 */
172 public Object createComponent(UnknownElement ue,
173 String ns,
174 String componentType)
175 throws BuildException {
176 Object component = createComponent(componentType);
177 if (component instanceof Task) {
178 Task task = (Task) component;
179 task.setLocation(ue.getLocation());
180 task.setTaskType(componentType);
181 task.setTaskName(ue.getTaskName());
182 task.setOwningTarget(ue.getOwningTarget());
183 task.init();
184 addCreatedTask(componentType, task);
185 }
186 return component;
187 }
188
189 /**
190 * Create an object for a component.
191 *
192 * @param componentName the name of the component, if
193 * the component is in a namespace, the
194 * name is prefixed with the namespace uri and ":".
195 * @return the class if found or null if not.
196 */
197 public Object createComponent(String componentName) {
198 AntTypeDefinition def = getDefinition(componentName);
199 return (def == null) ? null : def.create(project);
200 }
201
202 /**
203 * Return the class of the component name.
204 *
205 * @param componentName the name of the component, if
206 * the component is in a namespace, the
207 * name is prefixed with the namespace uri and ":".
208 * @return the class if found or null if not.
209 */
210 public Class getComponentClass(String componentName) {
211 AntTypeDefinition def = getDefinition(componentName);
212 return (def == null) ? null : def.getExposedClass(project);
213 }
214
215 /**
216 * Return the antTypeDefinition for a componentName.
217 * @param componentName the name of the component.
218 * @return the ant definition or null if not present.
219 */
220 public AntTypeDefinition getDefinition(String componentName) {
221 checkNamespace(componentName);
222 return antTypeTable.getDefinition(componentName);
223 }
224
225 /**
226 * This method is initialization code implementing the original ant component
227 * loading from /org/apache/tools/ant/taskdefs/default.properties
228 * and /org/apache/tools/ant/types/default.properties.
229 */
230 public void initDefaultDefinitions() {
231 initTasks();
232 initTypes();
233 }
234
235 /**
236 * Adds a new task definition to the project.
237 * Attempting to override an existing definition with an
238 * equivalent one (i.e. with the same classname) results in
239 * a verbose log message. Attempting to override an existing definition
240 * with a different one results in a warning log message and
241 * invalidates any tasks which have already been created with the
242 * old definition.
243 *
244 * @param taskName The name of the task to add.
245 * Must not be <code>null</code>.
246 * @param taskClass The full name of the class implementing the task.
247 * Must not be <code>null</code>.
248 *
249 * @exception BuildException if the class is unsuitable for being an Ant
250 * task. An error level message is logged before
251 * this exception is thrown.
252 *
253 * @see #checkTaskClass(Class)
254 */
255 public void addTaskDefinition(String taskName, Class taskClass) {
256 checkTaskClass(taskClass);
257 AntTypeDefinition def = new AntTypeDefinition();
258 def.setName(taskName);
259 def.setClassLoader(taskClass.getClassLoader());
260 def.setClass(taskClass);
261 def.setAdapterClass(TaskAdapter.class);
262 def.setClassName(taskClass.getName());
263 def.setAdaptToClass(Task.class);
264 updateDataTypeDefinition(def);
265 }
266
267 /**
268 * Checks whether or not a class is suitable for serving as Ant task.
269 * Ant task implementation classes must be public, concrete, and have
270 * a no-arg constructor.
271 *
272 * @param taskClass The class to be checked.
273 * Must not be <code>null</code>.
274 *
275 * @exception BuildException if the class is unsuitable for being an Ant
276 * task. An error level message is logged before
277 * this exception is thrown.
278 */
279 public void checkTaskClass(final Class taskClass) throws BuildException {
280 if (!Modifier.isPublic(taskClass.getModifiers())) {
281 final String message = taskClass + " is not public";
282 project.log(message, Project.MSG_ERR);
283 throw new BuildException(message);
284 }
285 if (Modifier.isAbstract(taskClass.getModifiers())) {
286 final String message = taskClass + " is abstract";
287 project.log(message, Project.MSG_ERR);
288 throw new BuildException(message);
289 }
290 try {
291 taskClass.getConstructor((Class[]) null);
292 // don't have to check for public, since
293 // getConstructor finds public constructors only.
294 } catch (NoSuchMethodException e) {
295 final String message = "No public no-arg constructor in "
296 + taskClass;
297 project.log(message, Project.MSG_ERR);
298 throw new BuildException(message);
299 }
300 if (!Task.class.isAssignableFrom(taskClass)) {
301 TaskAdapter.checkTaskClass(taskClass, project);
302 }
303 }
304
305 /**
306 * Returns the current task definition hashtable. The returned hashtable is
307 * "live" and so should not be modified.
308 *
309 * @return a map of from task name to implementing class
310 * (String to Class).
311 */
312 public Hashtable getTaskDefinitions() {
313 synchronized (taskClassDefinitions) {
314 synchronized (antTypeTable) {
315 if (rebuildTaskClassDefinitions) {
316 taskClassDefinitions.clear();
317 for (Iterator i = antTypeTable.keySet().iterator();
318 i.hasNext();) {
319 String name = (String) i.next();
320 Class clazz =
321 (Class) antTypeTable.getExposedClass(name);
322 if (clazz == null) {
323 continue;
324 }
325 if (Task.class.isAssignableFrom(clazz)) {
326 taskClassDefinitions.put(
327 name, antTypeTable.getTypeClass(name));
328 }
329 }
330 rebuildTaskClassDefinitions = false;
331 }
332 }
333 }
334 return taskClassDefinitions;
335 }
336
337
338 /**
339 * Returns the current type definition hashtable. The returned hashtable is
340 * "live" and so should not be modified.
341 *
342 * @return a map of from type name to implementing class
343 * (String to Class).
344 */
345 public Hashtable getDataTypeDefinitions() {
346 synchronized (typeClassDefinitions) {
347 synchronized (antTypeTable) {
348 if (rebuildTypeClassDefinitions) {
349 typeClassDefinitions.clear();
350 for (Iterator i = antTypeTable.keySet().iterator();
351 i.hasNext();) {
352 String name = (String) i.next();
353 Class clazz =
354 (Class) antTypeTable.getExposedClass(name);
355 if (clazz == null) {
356 continue;
357 }
358 if (!(Task.class.isAssignableFrom(clazz))) {
359 typeClassDefinitions.put(
360 name, antTypeTable.getTypeClass(name));
361 }
362 }
363 rebuildTypeClassDefinitions = false;
364 }
365 }
366 }
367 return typeClassDefinitions;
368 }
369
370 /**
371 * Adds a new datatype definition.
372 * Attempting to override an existing definition with an
373 * equivalent one (i.e. with the same classname) results in
374 * a verbose log message. Attempting to override an existing definition
375 * with a different one results in a warning log message, but the
376 * definition is changed.
377 *
378 * @param typeName The name of the datatype.
379 * Must not be <code>null</code>.
380 * @param typeClass The full name of the class implementing the datatype.
381 * Must not be <code>null</code>.
382 */
383 public void addDataTypeDefinition(String typeName, Class typeClass) {
384 AntTypeDefinition def = new AntTypeDefinition();
385 def.setName(typeName);
386 def.setClass(typeClass);
387 updateDataTypeDefinition(def);
388 project.log(" +User datatype: " + typeName + " "
389 + typeClass.getName(), Project.MSG_DEBUG);
390 }
391
392 /**
393 * Describe <code>addDataTypeDefinition</code> method here.
394 *
395 * @param def an <code>AntTypeDefinition</code> value.
396 */
397 public void addDataTypeDefinition(AntTypeDefinition def) {
398 updateDataTypeDefinition(def);
399 }
400
401 /**
402 * Returns the current datatype definition hashtable. The returned
403 * hashtable is "live" and so should not be modified.
404 *
405 * @return a map of from datatype name to implementing class
406 * (String to Class).
407 */
408 public Hashtable getAntTypeTable() {
409 return antTypeTable;
410 }
411
412 /**
413 * Creates a new instance of a task, adding it to a list of
414 * created tasks for later invalidation. This causes all tasks
415 * to be remembered until the containing project is removed
416 *
417 * Called from Project.createTask(), which can be called by tasks.
418 * The method should be deprecated, as it doesn't support ns and libs.
419 *
420 * @param taskType The name of the task to create an instance of.
421 * Must not be <code>null</code>.
422 *
423 * @return an instance of the specified task, or <code>null</code> if
424 * the task name is not recognised.
425 *
426 * @exception BuildException if the task name is recognised but task
427 * creation fails.
428 */
429 public Task createTask(String taskType) throws BuildException {
430 Task task = createNewTask(taskType);
431 if (task == null && taskType.equals("property")) {
432 // quick fix for Ant.java use of property before
433 // initializing the project
434 addTaskDefinition("property",
435 org.apache.tools.ant.taskdefs.Property.class);
436 task = createNewTask(taskType);
437 }
438 if (task != null) {
439 addCreatedTask(taskType, task);
440 }
441 return task;
442 }
443
444 /**
445 * Creates a new instance of a task. This task is not
446 * cached in the createdTasks list.
447 * @since ant1.6
448 * @param taskType The name of the task to create an instance of.
449 * Must not be <code>null</code>.
450 *
451 * @return an instance of the specified task, or <code>null</code> if
452 * the task name is not recognised.
453 *
454 * @exception BuildException if the task name is recognised but task
455 * creation fails.
456 */
457 private Task createNewTask(String taskType) throws BuildException {
458 Class c = getComponentClass(taskType);
459 if (c == null || !(Task.class.isAssignableFrom(c))) {
460 return null;
461 }
462 Task task = (Task) createComponent(taskType);
463 if (task == null) {
464 return null;
465 }
466 task.setTaskType(taskType);
467
468 // set default value, can be changed by the user
469 task.setTaskName(taskType);
470
471 project.log(" +Task: " + taskType, Project.MSG_DEBUG);
472 return task;
473 }
474
475 /**
476 * Keeps a record of all tasks that have been created so that they
477 * can be invalidated if a new task definition overrides the current one.
478 *
479 * @param type The name of the type of task which has been created.
480 * Must not be <code>null</code>.
481 *
482 * @param task The freshly created task instance.
483 * Must not be <code>null</code>.
484 */
485 private void addCreatedTask(String type, Task task) {
486 synchronized (createdTasks) {
487 Vector v = (Vector) createdTasks.get(type);
488 if (v == null) {
489 v = new Vector();
490 createdTasks.put(type, v);
491 }
492 v.addElement(new WeakReference(task));
493 }
494 }
495
496 /**
497 * Mark tasks as invalid which no longer are of the correct type
498 * for a given taskname.
499 *
500 * @param type The name of the type of task to invalidate.
501 * Must not be <code>null</code>.
502 */
503 private void invalidateCreatedTasks(String type) {
504 synchronized (createdTasks) {
505 Vector v = (Vector) createdTasks.get(type);
506 if (v != null) {
507 Enumeration taskEnum = v.elements();
508 while (taskEnum.hasMoreElements()) {
509 WeakReference ref = (WeakReference) taskEnum.nextElement();
510 Task t = (Task) ref.get();
511 //being a weak ref, it may be null by this point
512 if (t != null) {
513 t.markInvalid();
514 }
515 }
516 v.removeAllElements();
517 createdTasks.remove(type);
518 }
519 }
520 }
521
522 /**
523 * Creates a new instance of a data type.
524 *
525 * @param typeName The name of the data type to create an instance of.
526 * Must not be <code>null</code>.
527 *
528 * @return an instance of the specified data type, or <code>null</code> if
529 * the data type name is not recognised.
530 *
531 * @exception BuildException if the data type name is recognised but
532 * instance creation fails.
533 */
534 public Object createDataType(String typeName) throws BuildException {
535 return createComponent(typeName);
536 }
537
538 /**
539 * Returns a description of the type of the given element.
540 * <p>
541 * This is useful for logging purposes.
542 *
543 * @param element The element to describe.
544 * Must not be <code>null</code>.
545 *
546 * @return a description of the element type.
547 *
548 * @since Ant 1.6
549 */
550 public String getElementName(Object element) {
551 // PR: I do not know what to do if the object class
552 // has multiple defines
553 // but this is for logging only...
554 Class elementClass = element.getClass();
555 for (Iterator i = antTypeTable.values().iterator(); i.hasNext();) {
556 AntTypeDefinition def = (AntTypeDefinition) i.next();
557 if (elementClass == def.getExposedClass(project)) {
558 return "The <" + def.getName() + "> type";
559 }
560 }
561 return "Class " + elementClass.getName();
562 }
563
564
565 /**
566 * Check if definition is a valid definition - it
567 * may be a definition of an optional task that
568 * does not exist.
569 * @param def the definition to test.
570 * @return true if exposed type of definition is present.
571 */
572 private boolean validDefinition(AntTypeDefinition def) {
573 return !(def.getTypeClass(project) == null
574 || def.getExposedClass(project) == null);
575 }
576
577 /**
578 * Check if two definitions are the same.
579 * @param def the new definition.
580 * @param old the old definition.
581 * @return true if the two definitions are the same.
582 */
583 private boolean sameDefinition(
584 AntTypeDefinition def, AntTypeDefinition old) {
585 boolean defValid = validDefinition(def);
586 boolean sameValidity = (defValid == validDefinition(old));
587 //must have same validity; then if they are valid they must also be the same:
588 return sameValidity && (!defValid || def.sameDefinition(old, project));
589 }
590
591 /**
592 * Update the component definition table with a new or
593 * modified definition.
594 * @param def the definition to update or insert.
595 */
596 private void updateDataTypeDefinition(AntTypeDefinition def) {
597 String name = def.getName();
598 synchronized (antTypeTable) {
599 rebuildTaskClassDefinitions = true;
600 rebuildTypeClassDefinitions = true;
601 AntTypeDefinition old = antTypeTable.getDefinition(name);
602 if (old != null) {
603 if (sameDefinition(def, old)) {
604 return;
605 }
606 Class oldClass = antTypeTable.getExposedClass(name);
607 boolean isTask =
608 (oldClass != null && Task.class.isAssignableFrom(oldClass));
609 project.log("Trying to override old definition of "
610 + (isTask ? "task " : "datatype ") + name,
611 (def.similarDefinition(old, project))
612 ? Project.MSG_VERBOSE : Project.MSG_WARN);
613 if (isTask) {
614 invalidateCreatedTasks(name);
615 }
616 }
617 project.log(" +Datatype " + name + " " + def.getClassName(),
618 Project.MSG_DEBUG);
619 antTypeTable.put(name, def);
620 }
621 }
622
623 /**
624 * Called at the start of processing an antlib.
625 * @param uri the uri that is associated with this antlib.
626 */
627 public void enterAntLib(String uri) {
628 antLibCurrentUri = uri;
629 antLibStack.push(uri);
630 }
631
632 /**
633 * @return the current antlib uri.
634 */
635 public String getCurrentAntlibUri() {
636 return antLibCurrentUri;
637 }
638
639 /**
640 * Called at the end of processing an antlib.
641 */
642 public void exitAntLib() {
643 antLibStack.pop();
644 antLibCurrentUri = (antLibStack.size() == 0)
645 ? null : (String) antLibStack.peek();
646 }
647
648 /**
649 * Load ant's tasks.
650 */
651 private void initTasks() {
652 ClassLoader classLoader = null;
653 if (project.getCoreLoader() != null
654 && !("only".equals(project.getProperty("build.sysclasspath")))) {
655 classLoader = project.getCoreLoader();
656 }
657 String dataDefs = "/org/apache/tools/ant/taskdefs/defaults.properties";
658
659 InputStream in = null;
660 try {
661 Properties props = new Properties();
662 in = this.getClass().getResourceAsStream(dataDefs);
663 if (in == null) {
664 throw new BuildException("Can't load default task list");
665 }
666 props.load(in);
667
668 Enumeration e = props.propertyNames();
669 while (e.hasMoreElements()) {
670 String name = (String) e.nextElement();
671 String className = props.getProperty(name);
672 AntTypeDefinition def = new AntTypeDefinition();
673 def.setName(name);
674 def.setClassName(className);
675 def.setClassLoader(classLoader);
676 def.setAdaptToClass(Task.class);
677 def.setAdapterClass(TaskAdapter.class);
678 antTypeTable.put(name, def);
679 }
680 } catch (IOException ex) {
681 throw new BuildException("Can't load default type list");
682 } finally {
683 if (in != null) {
684 try {
685 in.close();
686 } catch (Exception ignore) {
687 // Ignore
688 }
689 }
690 }
691 }
692
693 /**
694 * Load ant's datatypes.
695 */
696 private void initTypes() {
697 ClassLoader classLoader = null;
698 if (project.getCoreLoader() != null
699 && !("only".equals(project.getProperty("build.sysclasspath")))) {
700 classLoader = project.getCoreLoader();
701 }
702 String dataDefs = "/org/apache/tools/ant/types/defaults.properties";
703
704 InputStream in = null;
705 try {
706 Properties props = new Properties();
707 in = this.getClass().getResourceAsStream(dataDefs);
708 if (in == null) {
709 throw new BuildException("Can't load default datatype list");
710 }
711 props.load(in);
712
713 Enumeration e = props.propertyNames();
714 while (e.hasMoreElements()) {
715 String name = (String) e.nextElement();
716 String className = props.getProperty(name);
717 AntTypeDefinition def = new AntTypeDefinition();
718 def.setName(name);
719 def.setClassName(className);
720 def.setClassLoader(classLoader);
721 antTypeTable.put(name, def);
722 }
723 } catch (IOException ex) {
724 throw new BuildException("Can't load default type list");
725 } finally {
726 if (in != null) {
727 try {
728 in.close();
729 } catch (Exception ignore) {
730 // ignore
731 }
732 }
733 }
734 }
735
736 /**
737 * Called for each component name, check if the
738 * associated URI has been examined for antlibs.
739 */
740 private synchronized void checkNamespace(String componentName) {
741 String uri = ProjectHelper.extractUriFromComponentName(componentName);
742 if ("".equals(uri)) {
743 uri = ProjectHelper.ANT_CORE_URI;
744 }
745 if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) {
746 return; // namespace that does not contain antlib
747 }
748 if (checkedNamespaces.contains(uri)) {
749 return; // Already processed
750 }
751 checkedNamespaces.add(uri);
752 Typedef definer = new Typedef();
753 definer.setProject(project);
754 definer.setURI(uri);
755 definer.setResource(
756 uri.substring("antlib:".length()).replace('.', '/')
757 + "/antlib.xml");
758 // a fishing expedition :- ignore errors if antlib not present
759 definer.setOnError(new Typedef.OnError("ignore"));
760 definer.init();
761 definer.execute();
762 }
763
764 /**
765 * Map that contains the component definitions.
766 */
767 private static class AntTypeTable extends Hashtable {
768 private Project project;
769
770 public AntTypeTable(Project project) {
771 this.project = project;
772 }
773
774 public AntTypeDefinition getDefinition(String key) {
775 return (AntTypeDefinition) (super.get(key));
776 }
777
778 /** Equivalent to getTypeType */
779 public Object get(Object key) {
780 return getTypeClass((String) key);
781 }
782
783 public Object create(String name) {
784 AntTypeDefinition def = getDefinition(name);
785 return (def == null) ? null : def.create(project);
786 }
787
788 public Class getTypeClass(String name) {
789 AntTypeDefinition def = getDefinition(name);
790 return (def == null) ? null : def.getTypeClass(project);
791 }
792
793 public Class getExposedClass(String name) {
794 AntTypeDefinition def = getDefinition(name);
795 return (def == null) ? null : def.getExposedClass(project);
796 }
797
798 public boolean contains(Object clazz) {
799 boolean found = false;
800 if (clazz instanceof Class) {
801 for (Iterator i = values().iterator(); i.hasNext() && !found;) {
802 found |= (((AntTypeDefinition) (i.next())).getExposedClass(
803 project) == clazz);
804 }
805 }
806 return found;
807 }
808
809 public boolean containsValue(Object value) {
810 return contains(value);
811 }
812 }
813
814}
Note: See TracBrowser for help on using the repository browser.