@@ -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.
*/
*/