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

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