You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ComponentHelper.java 42 kB

PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
23 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  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. package org.apache.tools.ant;
  19. import java.lang.reflect.Modifier;
  20. import java.lang.reflect.InvocationTargetException;
  21. import java.io.InputStream;
  22. import java.io.IOException;
  23. import java.io.File;
  24. import java.io.StringWriter;
  25. import java.io.PrintWriter;
  26. import java.util.Enumeration;
  27. import java.util.Hashtable;
  28. import java.util.HashSet;
  29. import java.util.Iterator;
  30. import java.util.Properties;
  31. import java.util.Set;
  32. import java.util.Stack;
  33. import java.util.List;
  34. import java.util.ArrayList;
  35. import java.util.Map;
  36. import java.util.HashMap;
  37. import org.apache.tools.ant.taskdefs.Typedef;
  38. import org.apache.tools.ant.taskdefs.Definer;
  39. import org.apache.tools.ant.launch.Launcher;
  40. import org.apache.tools.ant.util.FileUtils;
  41. /**
  42. * Component creation and configuration.
  43. *
  44. * The class is based around handing component
  45. * definitions in an AntTypeTable.
  46. *
  47. * The old task/type methods have been kept
  48. * for backward compatibly.
  49. * Project will just delegate its calls to this class.
  50. *
  51. * A very simple hook mechanism is provided that allows users to plug
  52. * in custom code. It is also possible to replace the default behavior
  53. * ( for example in an app embedding ant )
  54. *
  55. * @since Ant1.6
  56. */
  57. public class ComponentHelper {
  58. /** Map of component name to lists of restricted definitions */
  59. private Map restrictedDefinitions = new HashMap();
  60. /** Map from component name to anttypedefinition */
  61. private AntTypeTable antTypeTable;
  62. /** Map of tasks generated from antTypeTable */
  63. private Hashtable taskClassDefinitions = new Hashtable();
  64. /** flag to rebuild taskClassDefinitions */
  65. private boolean rebuildTaskClassDefinitions = true;
  66. /** Map of types generated from antTypeTable */
  67. private Hashtable typeClassDefinitions = new Hashtable();
  68. /** flag to rebuild typeClassDefinitions */
  69. private boolean rebuildTypeClassDefinitions = true;
  70. /** Set of namespaces that have been checked for antlibs */
  71. private Set checkedNamespaces = new HashSet();
  72. /**
  73. * Stack of antlib contexts used to resolve definitions while
  74. * processing antlib
  75. */
  76. private Stack antLibStack = new Stack();
  77. /** current antlib uri */
  78. private String antLibCurrentUri = null;
  79. /**
  80. * this does not appear to be used anywhere in the Ant codebase
  81. * even via its accessors
  82. */
  83. private ComponentHelper next;
  84. /**
  85. * Project that owns a component helper
  86. */
  87. private Project project;
  88. /**
  89. * Error string when the file taskdefs/defaults.properties cannot be found
  90. */
  91. private static final String ERROR_NO_TASK_LIST_LOAD = "Can't load default task list";
  92. /**
  93. * Error string when the typedefs/defaults.properties cannot be found
  94. */
  95. private static final String ERROR_NO_TYPE_LIST_LOAD = "Can't load default type list";
  96. /**
  97. * reference under which we register ourselves with a project -{@value}
  98. */
  99. public static final String COMPONENT_HELPER_REFERENCE = "ant.ComponentHelper";
  100. /**
  101. * string used to control build.syspath policy {@value}
  102. */
  103. private static final String BUILD_SYSCLASSPATH_ONLY = "only";
  104. /**
  105. * special name of ant's property task -{@value}. There is some
  106. * contrived work here to enable this early.
  107. */
  108. private static final String ANT_PROPERTY_TASK = "property";
  109. // {tasks, types}
  110. private static Properties[] defaultDefinitions = new Properties[2];
  111. /**
  112. * Get the project.
  113. * @return the project owner of this helper.
  114. */
  115. public Project getProject() {
  116. return project;
  117. }
  118. /**
  119. * Find a project component for a specific project, creating
  120. * it if it does not exist.
  121. * @param project the project.
  122. * @return the project component for a specific project.
  123. */
  124. public static ComponentHelper getComponentHelper(Project project) {
  125. if (project == null) {
  126. return null;
  127. }
  128. // Singleton for now, it may change ( per/classloader )
  129. ComponentHelper ph = (ComponentHelper) project.getReference(COMPONENT_HELPER_REFERENCE);
  130. if (ph != null) {
  131. return ph;
  132. }
  133. ph = new ComponentHelper();
  134. ph.setProject(project);
  135. project.addReference(COMPONENT_HELPER_REFERENCE, ph);
  136. return ph;
  137. }
  138. /**
  139. * Creates a new ComponentHelper instance.
  140. */
  141. protected ComponentHelper() {
  142. }
  143. /**
  144. * Set the next chained component helper.
  145. *
  146. * @param next the next chained component helper.
  147. */
  148. public void setNext(ComponentHelper next) {
  149. this.next = next;
  150. }
  151. /**
  152. * Get the next chained component helper.
  153. *
  154. * @return the next chained component helper.
  155. */
  156. public ComponentHelper getNext() {
  157. return next;
  158. }
  159. /**
  160. * Sets the project for this component helper.
  161. *
  162. * @param project the project for this helper.
  163. */
  164. public void setProject(Project project) {
  165. this.project = project;
  166. antTypeTable = new AntTypeTable(project);
  167. }
  168. /**
  169. * Used with creating child projects. Each child
  170. * project inherits the component definitions
  171. * from its parent.
  172. * @param helper the component helper of the parent project.
  173. */
  174. public void initSubProject(ComponentHelper helper) {
  175. // add the types of the parent project
  176. AntTypeTable typeTable = helper.antTypeTable;
  177. for (Iterator i = typeTable.values().iterator(); i.hasNext();) {
  178. AntTypeDefinition def = (AntTypeDefinition) i.next();
  179. antTypeTable.put(def.getName(), def);
  180. }
  181. // add the parsed namespaces of the parent project
  182. for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) {
  183. checkedNamespaces.add(i.next());
  184. }
  185. // Add the restricted definitions
  186. for (Iterator i = helper.restrictedDefinitions.entrySet().iterator();
  187. i.hasNext();) {
  188. Map.Entry entry = (Map.Entry) i.next();
  189. restrictedDefinitions.put(
  190. entry.getKey(), new ArrayList((List) entry.getValue()));
  191. }
  192. }
  193. /**
  194. * Factory method to create the components.
  195. *
  196. * This should be called by UnknownElement.
  197. *
  198. * @param ue The Unknown Element creating this component.
  199. * @param ns Namespace URI. Also available as ue.getNamespace().
  200. * @param componentType The component type,
  201. * Also available as ue.getComponentName().
  202. * @return the created component.
  203. * @throws BuildException if an error occurs.
  204. */
  205. public Object createComponent(UnknownElement ue, String ns, String componentType)
  206. throws BuildException {
  207. Object component = createComponent(componentType);
  208. if (component instanceof Task) {
  209. Task task = (Task) component;
  210. task.setLocation(ue.getLocation());
  211. task.setTaskType(componentType);
  212. task.setTaskName(ue.getTaskName());
  213. task.setOwningTarget(ue.getOwningTarget());
  214. task.init();
  215. }
  216. return component;
  217. }
  218. /**
  219. * Create an object for a component.
  220. *
  221. * @param componentName the name of the component, if
  222. * the component is in a namespace, the
  223. * name is prefixed with the namespace uri and ":".
  224. * @return the class if found or null if not.
  225. */
  226. public Object createComponent(String componentName) {
  227. AntTypeDefinition def = getDefinition(componentName);
  228. return def == null ? null : def.create(project);
  229. }
  230. /**
  231. * Return the class of the component name.
  232. *
  233. * @param componentName the name of the component, if
  234. * the component is in a namespace, the
  235. * name is prefixed with the namespace uri and ":".
  236. * @return the class if found or null if not.
  237. */
  238. public Class getComponentClass(String componentName) {
  239. AntTypeDefinition def = getDefinition(componentName);
  240. return def == null ? null : def.getExposedClass(project);
  241. }
  242. /**
  243. * Return the antTypeDefinition for a componentName.
  244. * @param componentName the name of the component.
  245. * @return the ant definition or null if not present.
  246. */
  247. public AntTypeDefinition getDefinition(String componentName) {
  248. checkNamespace(componentName);
  249. return antTypeTable.getDefinition(componentName);
  250. }
  251. /**
  252. * This method is initialization code implementing the original ant component
  253. * loading from /org/apache/tools/ant/taskdefs/default.properties
  254. * and /org/apache/tools/ant/types/default.properties.
  255. */
  256. public void initDefaultDefinitions() {
  257. initTasks();
  258. initTypes();
  259. }
  260. /**
  261. * Adds a new task definition to the project.
  262. * Attempting to override an existing definition with an
  263. * equivalent one (i.e. with the same classname) results in
  264. * a verbose log message. Attempting to override an existing definition
  265. * with a different one results in a warning log message.
  266. *
  267. * @param taskName The name of the task to add.
  268. * Must not be <code>null</code>.
  269. * @param taskClass The full name of the class implementing the task.
  270. * Must not be <code>null</code>.
  271. *
  272. * @exception BuildException if the class is unsuitable for being an Ant
  273. * task. An error level message is logged before
  274. * this exception is thrown.
  275. *
  276. * @see #checkTaskClass(Class)
  277. */
  278. public void addTaskDefinition(String taskName, Class taskClass) {
  279. checkTaskClass(taskClass);
  280. AntTypeDefinition def = new AntTypeDefinition();
  281. def.setName(taskName);
  282. def.setClassLoader(taskClass.getClassLoader());
  283. def.setClass(taskClass);
  284. def.setAdapterClass(TaskAdapter.class);
  285. def.setClassName(taskClass.getName());
  286. def.setAdaptToClass(Task.class);
  287. updateDataTypeDefinition(def);
  288. }
  289. /**
  290. * Checks whether or not a class is suitable for serving as Ant task.
  291. * Ant task implementation classes must be public, concrete, and have
  292. * a no-arg constructor.
  293. *
  294. * @param taskClass The class to be checked.
  295. * Must not be <code>null</code>.
  296. *
  297. * @exception BuildException if the class is unsuitable for being an Ant
  298. * task. An error level message is logged before
  299. * this exception is thrown.
  300. */
  301. public void checkTaskClass(final Class taskClass) throws BuildException {
  302. if (!Modifier.isPublic(taskClass.getModifiers())) {
  303. final String message = taskClass + " is not public";
  304. project.log(message, Project.MSG_ERR);
  305. throw new BuildException(message);
  306. }
  307. if (Modifier.isAbstract(taskClass.getModifiers())) {
  308. final String message = taskClass + " is abstract";
  309. project.log(message, Project.MSG_ERR);
  310. throw new BuildException(message);
  311. }
  312. try {
  313. taskClass.getConstructor((Class[]) null);
  314. // don't have to check for public, since
  315. // getConstructor finds public constructors only.
  316. } catch (NoSuchMethodException e) {
  317. final String message = "No public no-arg constructor in " + taskClass;
  318. project.log(message, Project.MSG_ERR);
  319. throw new BuildException(message);
  320. }
  321. if (!Task.class.isAssignableFrom(taskClass)) {
  322. TaskAdapter.checkTaskClass(taskClass, project);
  323. }
  324. }
  325. /**
  326. * Returns the current task definition hashtable. The returned hashtable is
  327. * "live" and so should not be modified.
  328. *
  329. * @return a map of from task name to implementing class
  330. * (String to Class).
  331. */
  332. public Hashtable getTaskDefinitions() {
  333. synchronized (taskClassDefinitions) {
  334. synchronized (antTypeTable) {
  335. if (rebuildTaskClassDefinitions) {
  336. taskClassDefinitions.clear();
  337. for (Iterator i = antTypeTable.keySet().iterator(); i.hasNext();) {
  338. String name = (String) i.next();
  339. Class clazz = antTypeTable.getExposedClass(name);
  340. if (clazz == null) {
  341. continue;
  342. }
  343. if (Task.class.isAssignableFrom(clazz)) {
  344. taskClassDefinitions.put(name, antTypeTable.getTypeClass(name));
  345. }
  346. }
  347. rebuildTaskClassDefinitions = false;
  348. }
  349. }
  350. }
  351. return taskClassDefinitions;
  352. }
  353. /**
  354. * Returns the current type definition hashtable. The returned hashtable is
  355. * "live" and so should not be modified.
  356. *
  357. * @return a map of from type name to implementing class
  358. * (String to Class).
  359. */
  360. public Hashtable getDataTypeDefinitions() {
  361. synchronized (typeClassDefinitions) {
  362. synchronized (antTypeTable) {
  363. if (rebuildTypeClassDefinitions) {
  364. typeClassDefinitions.clear();
  365. for (Iterator i = antTypeTable.keySet().iterator(); i.hasNext();) {
  366. String name = (String) i.next();
  367. Class clazz = antTypeTable.getExposedClass(name);
  368. if (clazz == null) {
  369. continue;
  370. }
  371. if (!(Task.class.isAssignableFrom(clazz))) {
  372. typeClassDefinitions.put(name, antTypeTable.getTypeClass(name));
  373. }
  374. }
  375. rebuildTypeClassDefinitions = false;
  376. }
  377. }
  378. }
  379. return typeClassDefinitions;
  380. }
  381. /**
  382. * This returns a list of restricted definitions for a name.
  383. * @param componentName the name to use.
  384. * @return the list of restricted definitions for a particular name.
  385. */
  386. public List getRestrictedDefinitions(String componentName) {
  387. return (List) restrictedDefinitions.get(componentName);
  388. }
  389. /**
  390. * Adds a new datatype definition.
  391. * Attempting to override an existing definition with an
  392. * equivalent one (i.e. with the same classname) results in
  393. * a verbose log message. Attempting to override an existing definition
  394. * with a different one results in a warning log message, but the
  395. * definition is changed.
  396. *
  397. * @param typeName The name of the datatype.
  398. * Must not be <code>null</code>.
  399. * @param typeClass The full name of the class implementing the datatype.
  400. * Must not be <code>null</code>.
  401. */
  402. public void addDataTypeDefinition(String typeName, Class typeClass) {
  403. AntTypeDefinition def = new AntTypeDefinition();
  404. def.setName(typeName);
  405. def.setClass(typeClass);
  406. updateDataTypeDefinition(def);
  407. project.log(" +User datatype: " + typeName + " " + typeClass.getName(),
  408. Project.MSG_DEBUG);
  409. }
  410. /**
  411. * Describe <code>addDataTypeDefinition</code> method here.
  412. *
  413. * @param def an <code>AntTypeDefinition</code> value.
  414. */
  415. public void addDataTypeDefinition(AntTypeDefinition def) {
  416. if (!def.isRestrict()) {
  417. updateDataTypeDefinition(def);
  418. } else {
  419. updateRestrictedDefinition(def);
  420. }
  421. }
  422. /**
  423. * Returns the current datatype definition hashtable. The returned
  424. * hashtable is "live" and so should not be modified.
  425. *
  426. * @return a map of from datatype name to implementing class
  427. * (String to Class).
  428. */
  429. public Hashtable getAntTypeTable() {
  430. return antTypeTable;
  431. }
  432. /**
  433. * Creates a new instance of a task.
  434. *
  435. * Called from Project.createTask(), which can be called by tasks.
  436. *
  437. * @param taskType The name of the task to create an instance of.
  438. * Must not be <code>null</code>.
  439. *
  440. * @return an instance of the specified task, or <code>null</code> if
  441. * the task name is not recognised.
  442. *
  443. * @exception BuildException if the task name is recognised but task
  444. * creation fails.
  445. */
  446. public Task createTask(String taskType) throws BuildException {
  447. Task task = createNewTask(taskType);
  448. if (task == null && taskType.equals(ANT_PROPERTY_TASK)) {
  449. // quick fix for Ant.java use of property before
  450. // initializing the project
  451. addTaskDefinition(ANT_PROPERTY_TASK, org.apache.tools.ant.taskdefs.Property.class);
  452. task = createNewTask(taskType);
  453. }
  454. return task;
  455. }
  456. /**
  457. * Creates a new instance of a task.
  458. * @since ant1.6
  459. * @param taskType The name of the task to create an instance of.
  460. * Must not be <code>null</code>.
  461. *
  462. * @return an instance of the specified task, or <code>null</code> if
  463. * the task name is not recognised.
  464. *
  465. * @exception BuildException if the task name is recognised but task
  466. * creation fails.
  467. */
  468. private Task createNewTask(String taskType) throws BuildException {
  469. Class c = getComponentClass(taskType);
  470. if (c == null || !(Task.class.isAssignableFrom(c))) {
  471. return null;
  472. }
  473. Object obj = createComponent(taskType);
  474. if (obj == null) {
  475. return null;
  476. }
  477. if (!(obj instanceof Task)) {
  478. throw new BuildException("Expected a Task from '" + taskType
  479. + "' but got an instance of " + obj.getClass().getName() + " instead");
  480. }
  481. Task task = (Task) obj;
  482. task.setTaskType(taskType);
  483. // set default value, can be changed by the user
  484. task.setTaskName(taskType);
  485. project.log(" +Task: " + taskType, Project.MSG_DEBUG);
  486. return task;
  487. }
  488. /**
  489. * Creates a new instance of a data type.
  490. *
  491. * @param typeName The name of the data type to create an instance of.
  492. * Must not be <code>null</code>.
  493. *
  494. * @return an instance of the specified data type, or <code>null</code> if
  495. * the data type name is not recognised.
  496. *
  497. * @exception BuildException if the data type name is recognised but
  498. * instance creation fails.
  499. */
  500. public Object createDataType(String typeName) throws BuildException {
  501. return createComponent(typeName);
  502. }
  503. /**
  504. * Returns a description of the type of the given element.
  505. * <p>
  506. * This is useful for logging purposes.
  507. *
  508. * @param element The element to describe.
  509. * Must not be <code>null</code>.
  510. *
  511. * @return a description of the element type.
  512. *
  513. * @since Ant 1.6
  514. */
  515. public String getElementName(Object element) {
  516. return getElementName(element, false);
  517. }
  518. /**
  519. * Returns a description of the type of the given element.
  520. * <p>
  521. * This is useful for logging purposes.
  522. *
  523. * @param o The element to describe.
  524. * Must not be <code>null</code>.
  525. * @param brief whether to use a brief description.
  526. * @return a description of the element type.
  527. *
  528. * @since Ant 1.7
  529. */
  530. public String getElementName(Object o, boolean brief) {
  531. // PR: I do not know what to do if the object class
  532. // has multiple defines
  533. // but this is for logging only...
  534. Class elementClass = o.getClass();
  535. String elementClassname = elementClass.getName();
  536. for (Iterator i = antTypeTable.values().iterator(); i.hasNext();) {
  537. AntTypeDefinition def = (AntTypeDefinition) i.next();
  538. if (elementClassname.equals(def.getClassName())
  539. && (elementClass == def.getExposedClass(project))) {
  540. String name = def.getName();
  541. return brief ? name : "The <" + name + "> type";
  542. }
  543. }
  544. return getUnmappedElementName(o.getClass(), brief);
  545. }
  546. /**
  547. * Convenient way to get some element name even when you may not have a
  548. * Project context.
  549. * @param p The optional Project instance.
  550. * @param o The element to describe.
  551. * Must not be <code>null</code>.
  552. * @param brief whether to use a brief description.
  553. * @return a description of the element type.
  554. * @since Ant 1.7
  555. */
  556. public static String getElementName(Project p, Object o, boolean brief) {
  557. if (p == null) {
  558. p = Project.getProject(o);
  559. }
  560. return p == null ? getUnmappedElementName(o.getClass(), brief) : getComponentHelper(p)
  561. .getElementName(o, brief);
  562. }
  563. private static String getUnmappedElementName(Class c, boolean brief) {
  564. if (brief) {
  565. String name = c.getName();
  566. return name.substring(name.lastIndexOf('.') + 1);
  567. }
  568. return c.toString();
  569. }
  570. /**
  571. * Check if definition is a valid definition--it may be a
  572. * definition of an optional task that does not exist.
  573. * @param def the definition to test.
  574. * @return true if exposed type of definition is present.
  575. */
  576. private boolean validDefinition(AntTypeDefinition def) {
  577. return !(def.getTypeClass(project) == null || def.getExposedClass(project) == null);
  578. }
  579. /**
  580. * Check if two definitions are the same.
  581. * @param def the new definition.
  582. * @param old the old definition.
  583. * @return true if the two definitions are the same.
  584. */
  585. private boolean sameDefinition(AntTypeDefinition def, AntTypeDefinition old) {
  586. boolean defValid = validDefinition(def);
  587. boolean sameValidity = (defValid == validDefinition(old));
  588. //must have same validity; then if they are valid they must also be the same:
  589. return sameValidity && (!defValid || def.sameDefinition(old, project));
  590. }
  591. /**
  592. * update the restricted definition table with a new or
  593. * modified definition.
  594. */
  595. private void updateRestrictedDefinition(AntTypeDefinition def) {
  596. String name = def.getName();
  597. synchronized (restrictedDefinitions) {
  598. List list = (List) restrictedDefinitions.get(name);
  599. if (list == null) {
  600. list = new ArrayList();
  601. restrictedDefinitions.put(name, list);
  602. }
  603. // Check if the classname is already present and remove it
  604. // if it is
  605. for (Iterator i = list.iterator(); i.hasNext();) {
  606. AntTypeDefinition current = (AntTypeDefinition) i.next();
  607. if (current.getClassName().equals(def.getClassName())) {
  608. i.remove();
  609. break;
  610. }
  611. }
  612. list.add(def);
  613. }
  614. }
  615. /**
  616. * Update the component definition table with a new or
  617. * modified definition.
  618. * @param def the definition to update or insert.
  619. */
  620. private void updateDataTypeDefinition(AntTypeDefinition def) {
  621. String name = def.getName();
  622. synchronized (antTypeTable) {
  623. rebuildTaskClassDefinitions = true;
  624. rebuildTypeClassDefinitions = true;
  625. AntTypeDefinition old = antTypeTable.getDefinition(name);
  626. if (old != null) {
  627. if (sameDefinition(def, old)) {
  628. return;
  629. }
  630. Class oldClass = antTypeTable.getExposedClass(name);
  631. boolean isTask = oldClass != null && Task.class.isAssignableFrom(oldClass);
  632. project.log("Trying to override old definition of "
  633. + (isTask ? "task " : "datatype ") + name, (def.similarDefinition(old,
  634. project)) ? Project.MSG_VERBOSE : Project.MSG_WARN);
  635. }
  636. project.log(" +Datatype " + name + " " + def.getClassName(), Project.MSG_DEBUG);
  637. antTypeTable.put(name, def);
  638. }
  639. }
  640. /**
  641. * Called at the start of processing an antlib.
  642. * @param uri the uri that is associated with this antlib.
  643. */
  644. public synchronized void enterAntLib(String uri) {
  645. antLibCurrentUri = uri;
  646. antLibStack.push(uri);
  647. }
  648. /**
  649. * @return the current antlib uri.
  650. */
  651. public String getCurrentAntlibUri() {
  652. return antLibCurrentUri;
  653. }
  654. /**
  655. * Called at the end of processing an antlib.
  656. */
  657. public synchronized void exitAntLib() {
  658. antLibStack.pop();
  659. antLibCurrentUri = (antLibStack.size() == 0) ? null : (String) antLibStack.peek();
  660. }
  661. /**
  662. * Load ant's tasks.
  663. */
  664. private void initTasks() {
  665. ClassLoader classLoader = getClassLoader(null);
  666. Properties props = getDefaultDefinitions(false);
  667. Enumeration e = props.propertyNames();
  668. while (e.hasMoreElements()) {
  669. String name = (String) e.nextElement();
  670. String className = props.getProperty(name);
  671. AntTypeDefinition def = new AntTypeDefinition();
  672. def.setName(name);
  673. def.setClassName(className);
  674. def.setClassLoader(classLoader);
  675. def.setAdaptToClass(Task.class);
  676. def.setAdapterClass(TaskAdapter.class);
  677. antTypeTable.put(name, def);
  678. }
  679. }
  680. private ClassLoader getClassLoader(ClassLoader classLoader) {
  681. String buildSysclasspath = project.getProperty(MagicNames.BUILD_SYSCLASSPATH);
  682. if (project.getCoreLoader() != null
  683. && !(BUILD_SYSCLASSPATH_ONLY.equals(buildSysclasspath))) {
  684. classLoader = project.getCoreLoader();
  685. }
  686. return classLoader;
  687. }
  688. /**
  689. * Load default task or type definitions - just the names,
  690. * no class loading.
  691. * Caches results between calls to reduce overhead.
  692. * @param type true for typedefs, false for taskdefs
  693. * @return a mapping from definition names to class names
  694. * @throws BuildException if there was some problem loading
  695. * or parsing the definitions list
  696. */
  697. private static synchronized Properties getDefaultDefinitions(boolean type)
  698. throws BuildException {
  699. int idx = type ? 1 : 0;
  700. if (defaultDefinitions[idx] == null) {
  701. String resource = type ? MagicNames.TYPEDEFS_PROPERTIES_RESOURCE
  702. : MagicNames.TASKDEF_PROPERTIES_RESOURCE;
  703. String errorString = type ? ERROR_NO_TYPE_LIST_LOAD : ERROR_NO_TASK_LIST_LOAD;
  704. InputStream in = null;
  705. try {
  706. in = ComponentHelper.class.getResourceAsStream(resource);
  707. if (in == null) {
  708. throw new BuildException(errorString);
  709. }
  710. Properties p = new Properties();
  711. p.load(in);
  712. defaultDefinitions[idx] = p;
  713. } catch (IOException e) {
  714. throw new BuildException(errorString, e);
  715. } finally {
  716. FileUtils.close(in);
  717. }
  718. }
  719. return defaultDefinitions[idx];
  720. }
  721. /**
  722. * Load ant's datatypes.
  723. */
  724. private void initTypes() {
  725. ClassLoader classLoader = getClassLoader(null);
  726. Properties props = getDefaultDefinitions(true);
  727. Enumeration e = props.propertyNames();
  728. while (e.hasMoreElements()) {
  729. String name = (String) e.nextElement();
  730. String className = props.getProperty(name);
  731. AntTypeDefinition def = new AntTypeDefinition();
  732. def.setName(name);
  733. def.setClassName(className);
  734. def.setClassLoader(classLoader);
  735. antTypeTable.put(name, def);
  736. }
  737. }
  738. /**
  739. * Called for each component name, check if the
  740. * associated URI has been examined for antlibs.
  741. * @param componentName the name of the component, which should include a URI
  742. * prefix if it is in a namespace
  743. */
  744. private synchronized void checkNamespace(String componentName) {
  745. String uri = ProjectHelper.extractUriFromComponentName(componentName);
  746. if ("".equals(uri)) {
  747. uri = ProjectHelper.ANT_CORE_URI;
  748. }
  749. if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) {
  750. return; // namespace that does not contain antlib
  751. }
  752. if (checkedNamespaces.contains(uri)) {
  753. return; // Already processed
  754. }
  755. checkedNamespaces.add(uri);
  756. Typedef definer = new Typedef();
  757. definer.setProject(project);
  758. definer.init();
  759. definer.setURI(uri);
  760. //there to stop error messages being "null"
  761. definer.setTaskName(uri);
  762. //if this is left out, bad things happen. like all build files break
  763. //on the first element encountered.
  764. definer.setResource(Definer.makeResourceFromURI(uri));
  765. // a fishing expedition :- ignore errors if antlib not present
  766. definer.setOnError(new Typedef.OnError(Typedef.OnError.POLICY_IGNORE));
  767. definer.execute();
  768. }
  769. /**
  770. * Handler called to do decent diagnosis on instantiation failure.
  771. * @param componentName component name.
  772. * @param type component type, used in error messages
  773. * @return a string containing as much diagnostics info as possible.
  774. */
  775. public String diagnoseCreationFailure(String componentName, String type) {
  776. StringWriter errorText = new StringWriter();
  777. PrintWriter out = new PrintWriter(errorText);
  778. out.println("Problem: failed to create " + type + " " + componentName);
  779. //class of problem
  780. boolean lowlevel = false;
  781. boolean jars = false;
  782. boolean definitions = false;
  783. boolean antTask;
  784. String home = System.getProperty(Launcher.USER_HOMEDIR);
  785. File libDir = new File(home, Launcher.USER_LIBDIR);
  786. String antHomeLib;
  787. boolean probablyIDE = false;
  788. String anthome = System.getProperty(MagicNames.ANT_HOME);
  789. if (anthome != null) {
  790. File antHomeLibDir = new File(anthome, "lib");
  791. antHomeLib = antHomeLibDir.getAbsolutePath();
  792. } else {
  793. //running under an IDE that doesn't set ANT_HOME
  794. probablyIDE = true;
  795. antHomeLib = "ANT_HOME" + File.separatorChar + "lib";
  796. }
  797. StringBuffer dirListingText = new StringBuffer();
  798. final String tab = " -";
  799. dirListingText.append(tab);
  800. dirListingText.append(antHomeLib);
  801. dirListingText.append('\n');
  802. if (probablyIDE) {
  803. dirListingText.append(tab);
  804. dirListingText.append("the IDE Ant configuration dialogs");
  805. } else {
  806. dirListingText.append(tab);
  807. dirListingText.append(libDir);
  808. dirListingText.append('\n');
  809. dirListingText.append(tab);
  810. dirListingText.append("a directory added on the command line with the -lib argument");
  811. }
  812. String dirListing = dirListingText.toString();
  813. //look up the name
  814. AntTypeDefinition def = getDefinition(componentName);
  815. if (def == null) {
  816. //not a known type
  817. printUnknownDefinition(out, componentName, dirListing);
  818. definitions = true;
  819. } else {
  820. //we are defined, so it is an instantiation problem
  821. final String classname = def.getClassName();
  822. antTask = classname.startsWith("org.apache.tools.ant.");
  823. boolean optional = classname.startsWith("org.apache.tools.ant.taskdefs.optional");
  824. optional |= classname.startsWith("org.apache.tools.ant.types.optional");
  825. //start with instantiating the class.
  826. Class clazz = null;
  827. try {
  828. clazz = def.innerGetTypeClass();
  829. } catch (ClassNotFoundException e) {
  830. jars = true;
  831. if (!optional) {
  832. definitions = true;
  833. }
  834. printClassNotFound(out, classname, optional, dirListing);
  835. } catch (NoClassDefFoundError ncdfe) {
  836. jars = true;
  837. printNotLoadDependentClass(out, optional, ncdfe, dirListing);
  838. }
  839. //here we successfully loaded the class or failed.
  840. if (clazz != null) {
  841. //success: proceed with more steps
  842. try {
  843. def.innerCreateAndSet(clazz, project);
  844. //hey, there is nothing wrong with us
  845. out.println("The component could be instantiated.");
  846. } catch (NoSuchMethodException e) {
  847. lowlevel = true;
  848. out.println("Cause: The class " + classname
  849. + " has no compatible constructor.");
  850. } catch (InstantiationException e) {
  851. lowlevel = true;
  852. out.println("Cause: The class " + classname
  853. + " is abstract and cannot be instantiated.");
  854. } catch (IllegalAccessException e) {
  855. lowlevel = true;
  856. out.println("Cause: The constructor for " + classname
  857. + " is private and cannot be invoked.");
  858. } catch (InvocationTargetException ex) {
  859. lowlevel = true;
  860. Throwable t = ex.getTargetException();
  861. out.println("Cause: The constructor threw the exception");
  862. out.println(t.toString());
  863. t.printStackTrace(out);
  864. } catch (NoClassDefFoundError ncdfe) {
  865. jars = true;
  866. out.println("Cause: A class needed by class " + classname
  867. + " cannot be found: ");
  868. out.println(" " + ncdfe.getMessage());
  869. out.println("Action: Determine what extra JAR files are"
  870. + " needed, and place them in:");
  871. out.println(dirListing);
  872. }
  873. }
  874. out.println();
  875. out.println("Do not panic, this is a common problem.");
  876. if (definitions) {
  877. out.println("It may just be a typographical error in the build file "
  878. + "or the task/type declaration.");
  879. }
  880. if (jars) {
  881. out.println("The commonest cause is a missing JAR.");
  882. }
  883. if (lowlevel) {
  884. out.println("This is quite a low level problem, which may need "
  885. + "consultation with the author of the task.");
  886. if (antTask) {
  887. out.println("This may be the Ant team. Please file a "
  888. + "defect or contact the developer team.");
  889. } else {
  890. out.println("This does not appear to be a task bundled with Ant.");
  891. out.println("Please take it up with the supplier of the third-party " + type
  892. + ".");
  893. out.println("If you have written it yourself, you probably have a bug to fix.");
  894. }
  895. } else {
  896. out.println();
  897. out.println("This is not a bug; it is a configuration problem");
  898. }
  899. }
  900. out.flush();
  901. out.close();
  902. return errorText.toString();
  903. }
  904. /**
  905. * Print unknown definition.forking
  906. */
  907. private void printUnknownDefinition(PrintWriter out, String componentName, String dirListing) {
  908. boolean isAntlib = componentName.indexOf(MagicNames.ANTLIB_PREFIX) == 0;
  909. String uri = ProjectHelper.extractUriFromComponentName(componentName);
  910. out.println("Cause: The name is undefined.");
  911. out.println("Action: Check the spelling.");
  912. out.println("Action: Check that any custom tasks/types have been declared.");
  913. out.println("Action: Check that any <presetdef>/<macrodef>"
  914. + " declarations have taken place.");
  915. if (uri.length() > 0) {
  916. List matches = antTypeTable.findMatches(uri);
  917. if (matches.size() > 0) {
  918. out.println();
  919. out.println("The definitions in the namespace " + uri + " are:");
  920. for (Iterator it = matches.iterator(); it.hasNext();) {
  921. AntTypeDefinition def = (AntTypeDefinition) it.next();
  922. String local = ProjectHelper.extractNameFromComponentName(def.getName());
  923. out.println(" " + local);
  924. }
  925. } else {
  926. out.println("No types or tasks have been defined in this namespace yet");
  927. if (isAntlib) {
  928. out.println();
  929. out.println("This appears to be an antlib declaration. ");
  930. out.println("Action: Check that the implementing library exists in one of:");
  931. out.println(dirListing);
  932. }
  933. }
  934. }
  935. }
  936. /**
  937. * Print class not found.
  938. */
  939. private void printClassNotFound(PrintWriter out, String classname, boolean optional,
  940. String dirListing) {
  941. out.println("Cause: the class " + classname + " was not found.");
  942. if (optional) {
  943. out.println(" This looks like one of Ant's optional components.");
  944. out.println("Action: Check that the appropriate optional JAR exists in");
  945. out.println(dirListing);
  946. } else {
  947. out.println("Action: Check that the component has been correctly declared");
  948. out.println(" and that the implementing JAR is in one of:");
  949. out.println(dirListing);
  950. }
  951. }
  952. /**
  953. * Print could not load dependent class.
  954. */
  955. private void printNotLoadDependentClass(PrintWriter out, boolean optional,
  956. NoClassDefFoundError ncdfe, String dirListing) {
  957. out.println("Cause: Could not load a dependent class "
  958. + ncdfe.getMessage());
  959. if (optional) {
  960. out.println(" It is not enough to have Ant's optional JARs");
  961. out.println(" you need the JAR files that the" + " optional tasks depend upon.");
  962. out.println(" Ant's optional task dependencies are" + " listed in the manual.");
  963. } else {
  964. out.println(" This class may be in a separate JAR" + " that is not installed.");
  965. }
  966. out.println("Action: Determine what extra JAR files are"
  967. + " needed, and place them in one of:");
  968. out.println(dirListing);
  969. }
  970. /**
  971. * Map that contains the component definitions.
  972. */
  973. private static class AntTypeTable extends Hashtable {
  974. private static final long serialVersionUID = -3060442320477772028L;
  975. private Project project;
  976. AntTypeTable(Project project) {
  977. this.project = project;
  978. }
  979. AntTypeDefinition getDefinition(String key) {
  980. return (AntTypeDefinition) (super.get(key));
  981. }
  982. public Object get(Object key) {
  983. return getTypeClass((String) key);
  984. }
  985. Object create(String name) {
  986. AntTypeDefinition def = getDefinition(name);
  987. return (def == null) ? null : def.create(project);
  988. }
  989. Class getTypeClass(String name) {
  990. AntTypeDefinition def = getDefinition(name);
  991. return (def == null) ? null : def.getTypeClass(project);
  992. }
  993. Class getExposedClass(String name) {
  994. AntTypeDefinition def = getDefinition(name);
  995. return def == null ? null : def.getExposedClass(project);
  996. }
  997. public boolean contains(Object clazz) {
  998. boolean found = false;
  999. if (clazz instanceof Class) {
  1000. for (Iterator i = values().iterator(); i.hasNext() && !found;) {
  1001. found = (((AntTypeDefinition) (i.next())).getExposedClass(project) == clazz);
  1002. }
  1003. }
  1004. return found;
  1005. }
  1006. public boolean containsValue(Object value) {
  1007. return contains(value);
  1008. }
  1009. /**
  1010. * Create a list of all definitions that match a prefix, usually the URI
  1011. * of a library
  1012. * @param prefix prefix to match off
  1013. * @return the (possibly empty) list of definitions
  1014. */
  1015. public List/*<AntTypeDefinition>*/ findMatches(String prefix) {
  1016. ArrayList matches = new ArrayList();
  1017. for (Iterator i = values().iterator(); i.hasNext();) {
  1018. AntTypeDefinition def = (AntTypeDefinition) (i.next());
  1019. if (def.getName().startsWith(prefix)) {
  1020. matches.add(def);
  1021. }
  1022. }
  1023. return matches;
  1024. }
  1025. }
  1026. }