old: generic error message new: step by step diagnostics with instructions. The code treats ant tasks and ant optional tasks specially, based on package names. Also: moved some constants into the appropriate places. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277750 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -17,6 +17,9 @@ | |||||
| package org.apache.tools.ant; | package org.apache.tools.ant; | ||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.lang.reflect.Constructor; | |||||
| /** | /** | ||||
| * This class contains all the information | * This class contains all the information | ||||
| @@ -143,15 +146,8 @@ public class AntTypeDefinition { | |||||
| * @return the type of the definition. | * @return the type of the definition. | ||||
| */ | */ | ||||
| public Class getTypeClass(Project project) { | public Class getTypeClass(Project project) { | ||||
| if (clazz != null) { | |||||
| return clazz; | |||||
| } | |||||
| try { | try { | ||||
| if (classLoader == null) { | |||||
| clazz = Class.forName(className); | |||||
| } else { | |||||
| clazz = classLoader.loadClass(className); | |||||
| } | |||||
| return innerGetTypeClass(); | |||||
| } catch (NoClassDefFoundError ncdfe) { | } catch (NoClassDefFoundError ncdfe) { | ||||
| project.log("Could not load a dependent class (" | project.log("Could not load a dependent class (" | ||||
| + ncdfe.getMessage() + ") for type " | + ncdfe.getMessage() + ") for type " | ||||
| @@ -160,6 +156,24 @@ public class AntTypeDefinition { | |||||
| project.log("Could not load class (" + className | project.log("Could not load class (" + className | ||||
| + ") for type " + name, Project.MSG_DEBUG); | + ") for type " + name, Project.MSG_DEBUG); | ||||
| } | } | ||||
| return null; | |||||
| } | |||||
| /** | |||||
| * Try and load a class, with no attempt to catch any fault. | |||||
| * @return the class that implements this component | |||||
| * @throws ClassNotFoundException | |||||
| * @throws NoClassDefFoundError | |||||
| */ | |||||
| public Class innerGetTypeClass() throws ClassNotFoundException { | |||||
| if (clazz != null) { | |||||
| return clazz; | |||||
| } | |||||
| if (classLoader == null) { | |||||
| clazz = Class.forName(className); | |||||
| } else { | |||||
| clazz = classLoader.loadClass(className); | |||||
| } | |||||
| return clazz; | return clazz; | ||||
| } | } | ||||
| @@ -238,23 +252,9 @@ public class AntTypeDefinition { | |||||
| */ | */ | ||||
| private Object createAndSet(Project project, Class c) { | private Object createAndSet(Project project, Class c) { | ||||
| try { | try { | ||||
| java.lang.reflect.Constructor ctor = null; | |||||
| boolean noArg = false; | |||||
| // DataType can have a "no arg" constructor or take a single | |||||
| // Project argument. | |||||
| try { | |||||
| ctor = c.getConstructor(new Class[0]); | |||||
| noArg = true; | |||||
| } catch (NoSuchMethodException nse) { | |||||
| ctor = c.getConstructor(new Class[] {Project.class}); | |||||
| noArg = false; | |||||
| } | |||||
| Object o = ctor.newInstance( | |||||
| ((noArg) ? new Object[0] : new Object[] {project})); | |||||
| project.setProjectReference(o); | |||||
| Object o = innerCreateAndSet(c, project); | |||||
| return o; | return o; | ||||
| } catch (java.lang.reflect.InvocationTargetException ex) { | |||||
| } catch (InvocationTargetException ex) { | |||||
| Throwable t = ex.getTargetException(); | Throwable t = ex.getTargetException(); | ||||
| throw new BuildException( | throw new BuildException( | ||||
| "Could not create type " + name + " due to " + t, t); | "Could not create type " + name + " due to " + t, t); | ||||
| @@ -262,12 +262,60 @@ public class AntTypeDefinition { | |||||
| String msg = "Type " + name + ": A class needed by class " | String msg = "Type " + name + ": A class needed by class " | ||||
| + c + " cannot be found: " + ncdfe.getMessage(); | + c + " cannot be found: " + ncdfe.getMessage(); | ||||
| throw new BuildException(msg, ncdfe); | throw new BuildException(msg, ncdfe); | ||||
| } catch (Throwable t) { | |||||
| } catch (NoSuchMethodException nsme) { | |||||
| throw new BuildException("Could not create type " + name | |||||
| + " as the class " + c +" has no compatible constructor" ); | |||||
| } catch (InstantiationException nsme) { | |||||
| throw new BuildException("Could not create type " + | |||||
| name | |||||
| + " as the class " + c + " is abstract"); | |||||
| } catch(IllegalAccessException e) { | |||||
| throw new BuildException("Could not create type " + | |||||
| name | |||||
| + " as the constructor " + c + " is not accessible"); | |||||
| } catch (Throwable t) { | |||||
| throw new BuildException( | throw new BuildException( | ||||
| "Could not create type " + name + " due to " + t, t); | "Could not create type " + name + " due to " + t, t); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Inner implementation of the {@see #createAndSet} logic, with no | |||||
| * exception catching | |||||
| * @param newclass class to create | |||||
| * @param project | |||||
| * @return a newly constructed and bound instance. | |||||
| * @throws NoSuchMethodException | |||||
| * @throws InstantiationException | |||||
| * @throws IllegalAccessException | |||||
| * @throws InvocationTargetException | |||||
| */ | |||||
| public Object innerCreateAndSet(Class newclass, Project project) | |||||
| throws NoSuchMethodException, | |||||
| InstantiationException, | |||||
| IllegalAccessException, | |||||
| InvocationTargetException { | |||||
| Constructor ctor = null; | |||||
| boolean noArg = false; | |||||
| // DataType can have a "no arg" constructor or take a single | |||||
| // Project argument. | |||||
| try { | |||||
| ctor = newclass.getConstructor(new Class[0]); | |||||
| noArg = true; | |||||
| } catch (NoSuchMethodException nse) { | |||||
| //can throw the same exception, if there is no this(Project) ctor. | |||||
| ctor = newclass.getConstructor(new Class[] {Project.class}); | |||||
| noArg = false; | |||||
| } | |||||
| //now we instantiate | |||||
| Object o = ctor.newInstance( | |||||
| ((noArg) ? new Object[0] : new Object[] {project})); | |||||
| //set up project references. | |||||
| project.setProjectReference(o); | |||||
| return o; | |||||
| } | |||||
| /** | /** | ||||
| * Equality method for this definition (assumes the names are the same). | * Equality method for this definition (assumes the names are the same). | ||||
| * | * | ||||
| @@ -28,10 +28,15 @@ import java.util.Stack; | |||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.File; | |||||
| import java.io.StringWriter; | |||||
| import java.io.PrintWriter; | |||||
| import java.lang.ref.WeakReference; | import java.lang.ref.WeakReference; | ||||
| import java.lang.reflect.Modifier; | import java.lang.reflect.Modifier; | ||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import org.apache.tools.ant.taskdefs.Typedef; | import org.apache.tools.ant.taskdefs.Typedef; | ||||
| import org.apache.tools.ant.launch.Launcher; | |||||
| /** | /** | ||||
| * Component creation and configuration. | * Component creation and configuration. | ||||
| @@ -83,6 +88,9 @@ public class ComponentHelper { | |||||
| private ComponentHelper next; | private ComponentHelper next; | ||||
| private Project project; | private Project project; | ||||
| private static final String ERROR_NO_TASK_LIST_LOAD = "Can't load default task list"; | |||||
| private static final String ERROR_NO_TYPE_LIST_LOAD = "Can't load default type list"; | |||||
| public static final String COMPONENT_HELPER_REFERENCE = "ant.ComponentHelper"; | |||||
| /** | /** | ||||
| * Find a project component for a specific project, creating | * Find a project component for a specific project, creating | ||||
| @@ -93,14 +101,14 @@ public class ComponentHelper { | |||||
| public static ComponentHelper getComponentHelper(Project project) { | public static ComponentHelper getComponentHelper(Project project) { | ||||
| // Singleton for now, it may change ( per/classloader ) | // Singleton for now, it may change ( per/classloader ) | ||||
| ComponentHelper ph = (ComponentHelper) project.getReference( | ComponentHelper ph = (ComponentHelper) project.getReference( | ||||
| "ant.ComponentHelper"); | |||||
| COMPONENT_HELPER_REFERENCE); | |||||
| if (ph != null) { | if (ph != null) { | ||||
| return ph; | return ph; | ||||
| } | } | ||||
| ph = new ComponentHelper(); | ph = new ComponentHelper(); | ||||
| ph.setProject(project); | ph.setProject(project); | ||||
| project.addReference("ant.ComponentHelper", ph); | |||||
| project.addReference(COMPONENT_HELPER_REFERENCE, ph); | |||||
| return ph; | return ph; | ||||
| } | } | ||||
| @@ -654,14 +662,14 @@ public class ComponentHelper { | |||||
| && !("only".equals(project.getProperty("build.sysclasspath")))) { | && !("only".equals(project.getProperty("build.sysclasspath")))) { | ||||
| classLoader = project.getCoreLoader(); | classLoader = project.getCoreLoader(); | ||||
| } | } | ||||
| String dataDefs = "/org/apache/tools/ant/taskdefs/defaults.properties"; | |||||
| String dataDefs = MagicNames.TASKDEF_PROPERTIES_RESOURCE; | |||||
| InputStream in = null; | InputStream in = null; | ||||
| try { | try { | ||||
| Properties props = new Properties(); | Properties props = new Properties(); | ||||
| in = this.getClass().getResourceAsStream(dataDefs); | in = this.getClass().getResourceAsStream(dataDefs); | ||||
| if (in == null) { | if (in == null) { | ||||
| throw new BuildException("Can't load default task list"); | |||||
| throw new BuildException(ERROR_NO_TASK_LIST_LOAD); | |||||
| } | } | ||||
| props.load(in); | props.load(in); | ||||
| @@ -678,7 +686,7 @@ public class ComponentHelper { | |||||
| antTypeTable.put(name, def); | antTypeTable.put(name, def); | ||||
| } | } | ||||
| } catch (IOException ex) { | } catch (IOException ex) { | ||||
| throw new BuildException("Can't load default type list"); | |||||
| throw new BuildException(ERROR_NO_TASK_LIST_LOAD); | |||||
| } finally { | } finally { | ||||
| if (in != null) { | if (in != null) { | ||||
| try { | try { | ||||
| @@ -699,14 +707,14 @@ public class ComponentHelper { | |||||
| && !("only".equals(project.getProperty("build.sysclasspath")))) { | && !("only".equals(project.getProperty("build.sysclasspath")))) { | ||||
| classLoader = project.getCoreLoader(); | classLoader = project.getCoreLoader(); | ||||
| } | } | ||||
| String dataDefs = "/org/apache/tools/ant/types/defaults.properties"; | |||||
| String dataDefs = MagicNames.TYPEDEFS_PROPERTIES_RESOURCE; | |||||
| InputStream in = null; | InputStream in = null; | ||||
| try { | try { | ||||
| Properties props = new Properties(); | Properties props = new Properties(); | ||||
| in = this.getClass().getResourceAsStream(dataDefs); | in = this.getClass().getResourceAsStream(dataDefs); | ||||
| if (in == null) { | if (in == null) { | ||||
| throw new BuildException("Can't load default datatype list"); | |||||
| throw new BuildException(ERROR_NO_TYPE_LIST_LOAD); | |||||
| } | } | ||||
| props.load(in); | props.load(in); | ||||
| @@ -721,7 +729,7 @@ public class ComponentHelper { | |||||
| antTypeTable.put(name, def); | antTypeTable.put(name, def); | ||||
| } | } | ||||
| } catch (IOException ex) { | } catch (IOException ex) { | ||||
| throw new BuildException("Can't load default type list"); | |||||
| throw new BuildException(ERROR_NO_TYPE_LIST_LOAD); | |||||
| } finally { | } finally { | ||||
| if (in != null) { | if (in != null) { | ||||
| try { | try { | ||||
| @@ -761,6 +769,146 @@ public class ComponentHelper { | |||||
| definer.execute(); | definer.execute(); | ||||
| } | } | ||||
| /** | |||||
| * Handler called to do decent diagnosis on instantiation failure | |||||
| * @param componentName | |||||
| * @return a string containing as much diagnostics info as possible. | |||||
| */ | |||||
| public String diagnoseCreationFailure(String componentName,String type) { | |||||
| StringWriter errorText=new StringWriter(); | |||||
| PrintWriter out=new PrintWriter(errorText); | |||||
| out.println("Problem: failed to create "+ type +" "+componentName); | |||||
| //class of problem | |||||
| boolean lowlevel=false; | |||||
| boolean jars=false; | |||||
| boolean definitions=false; | |||||
| boolean antTask; | |||||
| //look up the name | |||||
| AntTypeDefinition def = getDefinition(componentName); | |||||
| if(def==null) { | |||||
| //not a known type | |||||
| out.println("Cause: The name is undefined."); | |||||
| out.println("Action: Check the spelling."); | |||||
| out.println("Action: Check that any custom tasks/types have been declared"); | |||||
| out.println("Action: Check that any <presetdef>/<macrodefs> declarations have taken place"); | |||||
| definitions=true; | |||||
| } else{ | |||||
| //we are defined, so it is an instantiation problem | |||||
| final String classname = def.getClassName(); | |||||
| antTask = classname.startsWith("org.apache.tools.ant."); | |||||
| boolean optional = classname.startsWith("org.apache.tools.ant.taskdefs.optional"); | |||||
| optional |= classname.startsWith("org.apache.tools.ant.types.optional"); | |||||
| String home = System.getProperty(Launcher.USER_HOMEDIR); | |||||
| File libDir = new File(home, | |||||
| Launcher.ANT_PRIVATEDIR + | |||||
| File.separator + | |||||
| Launcher.ANT_PRIVATELIB); | |||||
| //start with instantiating the class. | |||||
| Class clazz= null; | |||||
| try { | |||||
| clazz = def.innerGetTypeClass(); | |||||
| } catch (ClassNotFoundException e) { | |||||
| out.println("Cause: the class " + | |||||
| classname | |||||
| + " was not found"); | |||||
| jars = true; | |||||
| if (optional) { | |||||
| out.println(" This looks like one of Ant's optional components"); | |||||
| out.println("Action: check that the appropriate optional JAR exists " | |||||
| + "in ANT_HOME/lib or in "); | |||||
| out.println(" " + libDir); | |||||
| } else { | |||||
| out.println("Action: check that the component has been correctly declared"); | |||||
| out.println(" And that the implementing JAR is in ANT_HOME/lib or in"); | |||||
| out.println(" " + libDir); | |||||
| definitions = true; | |||||
| } | |||||
| } catch (NoClassDefFoundError ncdfe) { | |||||
| jars = true; | |||||
| out.println("Cause: Could not load a dependent class " | |||||
| + ncdfe.getMessage()); | |||||
| if(optional) { | |||||
| out.println(" It is not enough to have Ant's optional JAR, you need the JAR"); | |||||
| out.println(" files that it depends upon"); | |||||
| out.println("Ant's optional task dependencies are listed in the manual"); | |||||
| } else { | |||||
| out.println(" This class may be in a separate JAR, that is not installed."); | |||||
| } | |||||
| out.println("Action: determine what extra JAR files are needed, and place them"); | |||||
| out.println(" In ANT_HOME/lib or"); | |||||
| out.println(" in " + libDir ); | |||||
| } | |||||
| //here we successfully loaded the class or failed. | |||||
| if(clazz!=null) { | |||||
| //success: proceed with more steps | |||||
| try { | |||||
| def.innerCreateAndSet(clazz,project); | |||||
| //hey, there is nothing wrong with us | |||||
| out.println("The component could be instantiated"); | |||||
| } catch (NoSuchMethodException e) { | |||||
| lowlevel = true; | |||||
| out.println("Cause: The class " + classname | |||||
| + " has no compatible constructor"); | |||||
| } catch (InstantiationException e) { | |||||
| lowlevel = true; | |||||
| out.println("Cause: The class " + | |||||
| classname | |||||
| + " is abstract and cannot be instantiated"); | |||||
| } catch (IllegalAccessException e) { | |||||
| lowlevel = true; | |||||
| out.println("Cause: The constructor for " + | |||||
| classname | |||||
| + " is private and cannot be invoked"); | |||||
| } catch (InvocationTargetException ex) { | |||||
| lowlevel = true; | |||||
| Throwable t = ex.getTargetException(); | |||||
| out.println("Cause: The constructor threw the exception "); | |||||
| out.println(t.toString()); | |||||
| t.printStackTrace(out); | |||||
| } catch (NoClassDefFoundError ncdfe) { | |||||
| jars = true; | |||||
| out.println("Cause: A class needed by class " | |||||
| + classname + " cannot be found: "); | |||||
| out.println(" "+ ncdfe.getMessage()); | |||||
| out.println("Action: determine what extra JAR files are needed, and place them"); | |||||
| out.println(" In ANT_HOME/lib or"); | |||||
| out.println(" in " + libDir); | |||||
| } | |||||
| } | |||||
| out.println(); | |||||
| out.println("Do not panic, this is a common problem."); | |||||
| if(definitions) { | |||||
| out.println("It may just be a typing error in the build file " + | |||||
| "or the task/type declaration"); | |||||
| } | |||||
| if (jars) { | |||||
| out.println("The commonest cause is a missing JAR. "); | |||||
| } | |||||
| if (lowlevel) { | |||||
| out.println("This is quite a low level problem, which may need" + | |||||
| "consultation with the author of the task"); | |||||
| if(antTask) { | |||||
| out.println("This may be the Ant team. Please file a " + | |||||
| "defect or contact the developer team"); | |||||
| } else { | |||||
| out.println("This does not appear to be a task bundled with Ant"); | |||||
| out.println("Please take it up with the supplier of the third-party "+type); | |||||
| out.println("If you have written it yourself, you probably have a bug to fix"); | |||||
| } | |||||
| } else { | |||||
| out.println(); | |||||
| out.println("It is not an Ant bug; there is no need to file a bug" + | |||||
| " report or contact the developers"); | |||||
| } | |||||
| } | |||||
| out.flush(); | |||||
| out.close(); | |||||
| return errorText.toString(); | |||||
| } | |||||
| /** | /** | ||||
| * Map that contains the component definitions. | * Map that contains the component definitions. | ||||
| */ | */ | ||||
| @@ -72,7 +72,7 @@ public final class Diagnostics { | |||||
| public static void validateVersion() throws BuildException { | public static void validateVersion() throws BuildException { | ||||
| try { | try { | ||||
| Class optional | Class optional | ||||
| = Class.forName("org.apache.tools.ant.taskdefs.optional.Test"); | |||||
| = Class.forName(TEST_CLASS); | |||||
| String coreVersion = getImplementationVersion(Main.class); | String coreVersion = getImplementationVersion(Main.class); | ||||
| String optionalVersion = getImplementationVersion(optional); | String optionalVersion = getImplementationVersion(optional); | ||||
| @@ -94,7 +94,7 @@ public final class Diagnostics { | |||||
| * <tt>null</tt> if an error occurs. | * <tt>null</tt> if an error occurs. | ||||
| */ | */ | ||||
| public static File[] listLibraries() { | public static File[] listLibraries() { | ||||
| String home = System.getProperty("ant.home"); | |||||
| String home = System.getProperty(Launcher.ANTHOME_PROPERTY); | |||||
| if (home == null) { | if (home == null) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -211,8 +211,7 @@ public final class Diagnostics { | |||||
| Class optional = null; | Class optional = null; | ||||
| try { | try { | ||||
| optional = Class.forName( | |||||
| "org.apache.tools.ant.taskdefs.optional.Test"); | |||||
| optional = Class.forName(TEST_CLASS); | |||||
| out.println("optional tasks : " | out.println("optional tasks : " | ||||
| + getImplementationVersion(optional)); | + getImplementationVersion(optional)); | ||||
| } catch (ClassNotFoundException e) { | } catch (ClassNotFoundException e) { | ||||
| @@ -340,7 +339,7 @@ public final class Diagnostics { | |||||
| */ | */ | ||||
| private static void doReportTasksAvailability(PrintStream out) { | private static void doReportTasksAvailability(PrintStream out) { | ||||
| InputStream is = Main.class.getResourceAsStream( | InputStream is = Main.class.getResourceAsStream( | ||||
| "/org/apache/tools/ant/taskdefs/defaults.properties"); | |||||
| MagicNames.TASKDEF_PROPERTIES_RESOURCE); | |||||
| if (is == null) { | if (is == null) { | ||||
| out.println("None available"); | out.println("None available"); | ||||
| } else { | } else { | ||||
| @@ -24,11 +24,43 @@ package org.apache.tools.ant; | |||||
| * @since Ant 1.6 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public class MagicNames { | public class MagicNames { | ||||
| /** The name of the script repository used by the script repo task */ | |||||
| /** | |||||
| * The name of the script repository used by the script repo task | |||||
| * Value {@value} | |||||
| */ | |||||
| public static final String SCRIPT_REPOSITORY = "org.apache.ant.scriptrepo"; | public static final String SCRIPT_REPOSITORY = "org.apache.ant.scriptrepo"; | ||||
| /** The name of the reference to the System Class Loader */ | |||||
| /** | |||||
| * The name of the reference to the System Class Loader | |||||
| * Value {@value} | |||||
| **/ | |||||
| public static final String SYSTEM_LOADER_REF = "ant.coreLoader"; | public static final String SYSTEM_LOADER_REF = "ant.coreLoader"; | ||||
| /** | |||||
| * Name of the property which can provide an override of the repository dir | |||||
| * for the libraries task | |||||
| * Value {@value} | |||||
| */ | |||||
| public static final String REPOSITORY_DIR_PROPERTY = "ant.maven.repository.dir"; | |||||
| /** | |||||
| * Name of the property which can provide an override of the repository URL | |||||
| * for the libraries task | |||||
| * Value {@value} | |||||
| */ | |||||
| public static final String REPOSITORY_URL_PROPERTY = "ant.maven.repository.url"; | |||||
| /** | |||||
| * name of the resource that taskdefs are stored under | |||||
| * Value: {@value} | |||||
| */ | |||||
| public static final String TASKDEF_PROPERTIES_RESOURCE = | |||||
| "/org/apache/tools/ant/taskdefs/defaults.properties"; | |||||
| /** | |||||
| * name of the resource that typedefs are stored under | |||||
| * Value: {@value} | |||||
| */ | |||||
| public static final String TYPEDEFS_PROPERTIES_RESOURCE = | |||||
| "/org/apache/tools/ant/types/defaults.properties"; | |||||
| } | } | ||||
| @@ -463,45 +463,8 @@ public class UnknownElement extends Task { | |||||
| */ | */ | ||||
| protected BuildException getNotFoundException(String what, | protected BuildException getNotFoundException(String what, | ||||
| String elementName) { | String elementName) { | ||||
| String lSep = System.getProperty("line.separator"); | |||||
| String msg = "Could not create " + what + " of type: " + elementName | |||||
| + "." + lSep + lSep | |||||
| + "Ant could not find the task or a class this " | |||||
| + "task relies upon." + lSep + lSep | |||||
| + "This is common and has a number of causes; the usual " + lSep | |||||
| + "solutions are to read the manual pages then download and" + lSep | |||||
| + "install needed JAR files, or fix the build file: " + lSep | |||||
| + " - You have misspelt '" + elementName + "'." + lSep | |||||
| + " Fix: check your spelling." + lSep | |||||
| + " - The task needs an external JAR file to execute" + lSep | |||||
| + " and this is not found at the right place in the classpath." + lSep | |||||
| + " Fix: check the documentation for dependencies." + lSep | |||||
| + " Fix: declare the task." + lSep | |||||
| + " - The task is an Ant optional task and the JAR file and/or libraries" + lSep | |||||
| + " implementing the functionality were not found at the time you" + lSep | |||||
| + " yourself built your installation of Ant from the Ant sources." + lSep | |||||
| + " Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the" + lSep | |||||
| + " task and make sure it contains more than merely a META-INF/MANIFEST.MF." + lSep | |||||
| + " If all it contains is the manifest, then rebuild Ant with the needed" + lSep | |||||
| + " libraries present in ${ant.home}/lib/optional/ , or alternatively," + lSep | |||||
| + " download a pre-built release version from apache.org" + lSep | |||||
| + " - The build file was written for a later version of Ant" + lSep | |||||
| + " Fix: upgrade to at least the latest release version of Ant" + lSep | |||||
| + " - The task is not an Ant core or optional task " + lSep | |||||
| + " and needs to be declared using <taskdef>." + lSep | |||||
| + " - You are attempting to use a task defined using " + lSep | |||||
| + " <presetdef> or <macrodef> but have spelt wrong or not " + lSep | |||||
| + " defined it at the point of use" + lSep | |||||
| + lSep | |||||
| + "Remember that for JAR files to be visible to Ant tasks implemented" + lSep | |||||
| + "in ANT_HOME/lib, the files must be in the same directory or on the" + lSep | |||||
| + "classpath" + lSep | |||||
| + lSep | |||||
| + "Please neither file bug reports on this problem, nor email the" + lSep | |||||
| + "Ant mailing lists, until all of these causes have been explored," + lSep | |||||
| + "as this is not an Ant bug."; | |||||
| ComponentHelper helper = ComponentHelper.getComponentHelper(getProject()); | |||||
| String msg = helper.diagnoseCreationFailure(elementName, what); | |||||
| return new BuildException(msg, getLocation()); | return new BuildException(msg, getLocation()); | ||||
| } | } | ||||
| @@ -32,7 +32,10 @@ import java.util.Iterator; | |||||
| * @since Ant 1.6 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public class Launcher { | public class Launcher { | ||||
| /** The Ant Home property */ | |||||
| /** | |||||
| * Ant home directory | |||||
| * Value : {@value} | |||||
| */ | |||||
| public static final String ANTHOME_PROPERTY = "ant.home"; | public static final String ANTHOME_PROPERTY = "ant.home"; | ||||
| /** The Ant Library Directory property */ | /** The Ant Library Directory property */ | ||||