diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java index cfa53a791..78ea07a80 100644 --- a/src/main/org/apache/tools/ant/Main.java +++ b/src/main/org/apache/tools/ant/Main.java @@ -29,6 +29,7 @@ import java.util.Vector; import org.apache.tools.ant.input.DefaultInputHandler; import org.apache.tools.ant.input.InputHandler; import org.apache.tools.ant.launch.AntMain; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.FileUtils; @@ -698,17 +699,13 @@ public class Main implements AntMain { for (int i = 0; i < listeners.size(); i++) { String className = (String) listeners.elementAt(i); - try { - BuildListener listener = - (BuildListener) Class.forName(className).newInstance(); - if (project != null) { - project.setProjectReference(listener); - } - project.addBuildListener(listener); - } catch (Throwable exc) { - throw new BuildException("Unable to instantiate listener " - + className, exc); + BuildListener listener = + (BuildListener) ClasspathUtils.newInstance(className, + Main.class.getClassLoader(), BuildListener.class); + if (project != null) { + project.setProjectReference(listener); } + project.addBuildListener(listener); } } @@ -725,22 +722,11 @@ public class Main implements AntMain { if (inputHandlerClassname == null) { handler = new DefaultInputHandler(); } else { - try { - handler = (InputHandler) - (Class.forName(inputHandlerClassname).newInstance()); - if (project != null) { - project.setProjectReference(handler); - } - } catch (ClassCastException e) { - String msg = "The specified input handler class " - + inputHandlerClassname - + " does not implement the InputHandler interface"; - throw new BuildException(msg); - } catch (Exception e) { - String msg = "Unable to instantiate specified input handler " - + "class " + inputHandlerClassname + " : " - + e.getClass().getName(); - throw new BuildException(msg); + handler = (InputHandler) ClasspathUtils.newInstance( + inputHandlerClassname, Main.class.getClassLoader(), + InputHandler.class); + if (project != null) { + project.setProjectReference(handler); } } project.setInputHandler(handler); @@ -760,17 +746,13 @@ public class Main implements AntMain { BuildLogger logger = null; if (loggerClassname != null) { try { - Class loggerClass = Class.forName(loggerClassname); - logger = (BuildLogger) (loggerClass.newInstance()); - } catch (ClassCastException e) { + logger = (BuildLogger) ClasspathUtils.newInstance( + loggerClassname, Main.class.getClassLoader(), + BuildLogger.class); + } catch (BuildException e) { System.err.println("The specified logger class " + loggerClassname - + " does not implement the BuildLogger interface"); - throw new RuntimeException(); - } catch (Exception e) { - System.err.println("Unable to instantiate specified logger " - + "class " + loggerClassname + " : " - + e.getClass().getName()); + + " could not be used because " + e.getMessage()); throw new RuntimeException(); } } else { diff --git a/src/main/org/apache/tools/ant/listener/MailLogger.java b/src/main/org/apache/tools/ant/listener/MailLogger.java index 4a534592d..4fc12f599 100644 --- a/src/main/org/apache/tools/ant/listener/MailLogger.java +++ b/src/main/org/apache/tools/ant/listener/MailLogger.java @@ -27,11 +27,13 @@ import java.util.Enumeration; import java.util.StringTokenizer; import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.email.EmailAddress; import org.apache.tools.ant.taskdefs.email.Message; import org.apache.tools.ant.taskdefs.email.Mailer; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.DateUtils; import org.apache.tools.ant.util.StringUtils; import org.apache.tools.mail.MailMessage; @@ -239,14 +241,15 @@ public class MailLogger extends DefaultLogger { String message) { // convert the replyTo string into a vector of emailaddresses Mailer mailer = null; - try { - mailer = - (Mailer) Class.forName("org.apache.tools.ant.taskdefs.email.MimeMailer") - .newInstance(); - } catch (Throwable e) { - log("Failed to initialise MIME mail: " + e.getMessage()); - return; - } + try { + mailer = (Mailer) ClasspathUtils.newInstance( + "org.apache.tools.ant.taskdefs.email.MimeMailer", + MailLogger.class.getClassLoader(), Mailer.class); + } catch (BuildException e) { + Throwable t = e.getCause() == null ? e : e.getCause(); + log("Failed to initialise MIME mail: " + t.getMessage()); + return; + } Vector replyToList = vectorizeEmailAddresses(replyToString); mailer.setHost(host); mailer.setPort(port); diff --git a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java index 37397180a..9acac7192 100644 --- a/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/compilers/CompilerAdapterFactory.java @@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs.compilers; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.JavaEnvUtils; /** @@ -162,21 +163,9 @@ public final class CompilerAdapterFactory { */ private static CompilerAdapter resolveClassName(String className) throws BuildException { - try { - Class c = Class.forName(className); - Object o = c.newInstance(); - return (CompilerAdapter) o; - } catch (ClassNotFoundException cnfe) { - throw new BuildException("Compiler Adapter '" + className - + "' can\'t be found.", cnfe); - } catch (ClassCastException cce) { - throw new BuildException(className + " isn\'t the classname of " - + "a compiler adapter.", cce); - } catch (Throwable t) { - // for all other possibilities - throw new BuildException("Compiler Adapter " + className - + " caused an interesting exception.", t); - } + return (CompilerAdapter) ClasspathUtils.newInstance(className, + CompilerAdapterFactory.class.getClassLoader(), + CompilerAdapter.class); } } diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java index c7995435e..9c4b84b19 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java @@ -25,8 +25,10 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; +import org.apache.tools.ant.listener.MailLogger; import org.apache.tools.ant.types.EnumeratedAttribute; import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.util.ClasspathUtils; /** * A task to send SMTP email. This is a refactoring of the SendMail and @@ -399,14 +401,16 @@ public class EmailTask extends Task { if (encoding.equals(MIME) || (encoding.equals(AUTO) && !autoFound)) { try { - mailer = (Mailer) Class.forName( - "org.apache.tools.ant.taskdefs.email.MimeMailer") - .newInstance(); + mailer = (Mailer) ClasspathUtils.newInstance( + "org.apache.tools.ant.taskdefs.email.MimeMailer", + EmailTask.class.getClassLoader(), Mailer.class); autoFound = true; log("Using MIME mail", Project.MSG_VERBOSE); - } catch (Throwable e) { - log("Failed to initialise MIME mail: " - + e.getMessage(), Project.MSG_WARN); + } catch (BuildException e) { + Throwable t = e.getCause() == null ? e : e.getCause(); + log("Failed to initialise MIME mail: " + t.getMessage(), + Project.MSG_WARN); + return; } } // SMTP auth only allowed with MIME mail @@ -423,13 +427,16 @@ public class EmailTask extends Task { if (encoding.equals(UU) || (encoding.equals(AUTO) && !autoFound)) { try { - mailer = - (Mailer) Class.forName("org.apache.tools.ant.taskdefs.email.UUMailer") - .newInstance(); + mailer = (Mailer) ClasspathUtils.newInstance( + "org.apache.tools.ant.taskdefs.email.UUMailer", + EmailTask.class.getClassLoader(), Mailer.class); autoFound = true; log("Using UU mail", Project.MSG_VERBOSE); - } catch (Throwable e) { - log("Failed to initialise UU mail", Project.MSG_WARN); + } catch (BuildException e) { + Throwable t = e.getCause() == null ? e : e.getCause(); + log("Failed to initialise UU mail: " + t.getMessage(), + Project.MSG_WARN); + return; } } // try plain format diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java index 4ee013ee6..451bd1a46 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/javah/JavahAdapterFactory.java @@ -18,6 +18,7 @@ package org.apache.tools.ant.taskdefs.optional.javah; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.JavaEnvUtils; /** @@ -77,20 +78,8 @@ public class JavahAdapterFactory { * isn't an instance of JavahAdapter. */ private static JavahAdapter resolveClassName(String className) - throws BuildException { - try { - Class c = Class.forName(className); - Object o = c.newInstance(); - return (JavahAdapter) o; - } catch (ClassNotFoundException cnfe) { - throw new BuildException("Can't load " + className, cnfe); - } catch (ClassCastException cce) { - throw new BuildException(className - + " is not a Javah adapter", cce); - } catch (Throwable t) { - // for all other possibilities - throw new BuildException(className + " caused an interesting " - + "exception.", t); - } + throws BuildException { + return (JavahAdapter) ClasspathUtils.newInstance(className, + JavahAdapterFactory.class.getClassLoader(), JavahAdapter.class); } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java index c477ed087..b3e1c7141 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/native2ascii/Native2AsciiAdapterFactory.java @@ -18,6 +18,7 @@ package org.apache.tools.ant.taskdefs.optional.native2ascii; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.JavaEnvUtils; /** @@ -77,20 +78,10 @@ public class Native2AsciiAdapterFactory { * isn't an instance of Native2AsciiAdapter. */ private static Native2AsciiAdapter resolveClassName(String className) - throws BuildException { - try { - Class c = Class.forName(className); - Object o = c.newInstance(); - return (Native2AsciiAdapter) o; - } catch (ClassNotFoundException cnfe) { - throw new BuildException("Can't load " + className, cnfe); - } catch (ClassCastException cce) { - throw new BuildException(className - + " is not a Native2Ascii adapter", cce); - } catch (Throwable t) { - // for all other possibilities - throw new BuildException(className + " caused an interesting " - + "exception.", t); - } + throws BuildException + { + return (Native2AsciiAdapter) ClasspathUtils.newInstance(className, + Native2AsciiAdapterFactory.class.getClassLoader(), + Native2AsciiAdapter.class); } } \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java index f11d89339..95b73ecdb 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java @@ -34,6 +34,7 @@ import java.util.Set; import java.util.HashSet; import java.io.File; +import org.apache.tools.ant.util.ClasspathUtils; import org.apache.tools.ant.util.ScriptRunner; /** @@ -272,27 +273,13 @@ public class ScriptDef extends DefBase { */ ClassLoader loader = createLoader(); - Class instanceClass = null; - try { - instanceClass = Class.forName(classname, true, loader); - } catch (Throwable e) { - // try normal method - try { - instanceClass = Class.forName(classname); - } catch (Throwable e2) { - throw new BuildException("scriptdef: Unable to load " - + "class " + classname + " for nested element <" - + elementName + ">", e2); - } + try + { + instance = ClasspathUtils.newInstance(classname, loader); + } catch (BuildException e) { + instance = ClasspathUtils.newInstance(classname, ScriptDef.class.getClassLoader()); } - try { - instance = instanceClass.newInstance(); - } catch (Throwable e) { - throw new BuildException("scriptdef: Unable to create " - + "element of class " + classname + " for nested " - + "element <" + elementName + ">", e); - } getProject().setProjectReference(instance); } diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java index 259cfda32..ad8365fe2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java @@ -19,6 +19,7 @@ package org.apache.tools.ant.taskdefs.rmic; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; +import org.apache.tools.ant.util.ClasspathUtils; /** @@ -28,10 +29,10 @@ import org.apache.tools.ant.Task; */ public final class RmicAdapterFactory { /** The error message to be used when the compiler cannot be found. */ - public static final String ERROR_UNKNOWN_COMPILER = "Cannot find the compiler or class: "; + public static final String ERROR_UNKNOWN_COMPILER = "Class not found: "; /** The error message to be used when the class is not an rmic adapter. */ - public static final String ERROR_NOT_RMIC_ADAPTER = "Not an rmic adapter: "; + public static final String ERROR_NOT_RMIC_ADAPTER = "Class of unexpected Type: "; /** If the compiler has this name use a default compiler. */ public static final String DEFAULT_COMPILER = "default"; @@ -93,20 +94,7 @@ public final class RmicAdapterFactory { */ private static RmicAdapter resolveClassName(String className) throws BuildException { - try { - Class c = Class.forName(className); - Object o = c.newInstance(); - return (RmicAdapter) o; - } catch (ClassNotFoundException cnfe) { - throw new BuildException(ERROR_UNKNOWN_COMPILER + className, - cnfe); - } catch (ClassCastException cce) { - throw new BuildException(ERROR_NOT_RMIC_ADAPTER + className, - cce); - } catch (Throwable t) { - // for all other possibilities - throw new BuildException(className + " caused an interesting " - + "exception.", t); - } + return (RmicAdapter) ClasspathUtils.newInstance(className, + RmicAdapterFactory.class.getClassLoader(), RmicAdapter.class); } } diff --git a/src/main/org/apache/tools/ant/util/ClasspathUtils.java b/src/main/org/apache/tools/ant/util/ClasspathUtils.java index 6b79e3309..e001cdf67 100644 --- a/src/main/org/apache/tools/ant/util/ClasspathUtils.java +++ b/src/main/org/apache/tools/ant/util/ClasspathUtils.java @@ -235,18 +235,50 @@ public class ClasspathUtils { * @return The fresh object instance * @throws BuildException when loading or instantiation failed. */ + public static Object newInstance( + String className, + ClassLoader userDefinedLoader) { + return newInstance(className, userDefinedLoader, Object.class); + } + + + + /** + * Creates a fresh object instance of the specified classname. + * + *
This uses the userDefinedLoader to load the specified class, + * and then makes an instance using the default no-argument constructor. + *
+ * + * @param className the full qualified class name to load. + * @param userDefinedLoader the classloader to use. + * @param expectedType the Class that the result should be assignment + * compatible with. (No ClassCastException will be thrown in case + * the result of this method is casted to the expectedType) + * @return The fresh object instance + * @throws BuildException when loading or instantiation failed. + * @since Ant 1.7 + */ public static Object newInstance( String className, - ClassLoader userDefinedLoader) { + ClassLoader userDefinedLoader, + Class expectedType) { try { - Class clazz = userDefinedLoader.loadClass(className); + Class clazz = Class.forName(className, true, userDefinedLoader); Object o = clazz.newInstance(); + if (!expectedType.isInstance(o)) + { + throw new BuildException( + "Class of unexpected Type: " + + className + + " expected :" + + expectedType); + } return o; } catch (ClassNotFoundException e) { throw new BuildException( - "Class " - + className - + " not found by the specific classLoader.", + "Class not found: " + + className, e); } catch (InstantiationException e) { throw new BuildException( @@ -262,9 +294,32 @@ public class ClasspathUtils { + ". Specified class should have a " + "public constructor.", e); + } catch (LinkageError e) { + throw new BuildException( + "Class " + + className + + " could not be loaded because of an invalid dependency.", + e); } } + /** + * Creates a fresh object instance of the specified classname. + * + *This uses the userDefinedLoader to load the specified class, + * and then makes an instance using the default no-argument constructor. + *
+ * + * @param className the full qualified class name to load. + * @param userDefinedLoader the classloader to use. + * @param expectedType the Class that the result should be assignment + * compatible with. (No ClassCastException will be thrown in case + * the result of this method is casted to the expectedType) + * @return The fresh object instance + * @throws BuildException when loading or instantiation failed. + */ + + /** * Obtains a delegate that helps out with classic classpath configuration. * diff --git a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java index 6d4f7d287..53aea6445 100644 --- a/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java +++ b/src/main/org/apache/tools/ant/util/regexp/RegexpMatcherFactory.java @@ -19,6 +19,7 @@ package org.apache.tools.ant.util.regexp; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; +import org.apache.tools.ant.util.ClasspathUtils; /** * Simple Factory Class that produces an implementation of @@ -99,13 +100,10 @@ public class RegexpMatcherFactory { * @exception BuildException if an error occurs */ protected RegexpMatcher createInstance(String className) - throws BuildException { - try { - Class implClass = Class.forName(className); - return (RegexpMatcher) implClass.newInstance(); - } catch (Throwable t) { - throw new BuildException(t); - } + throws BuildException + { + return (RegexpMatcher) ClasspathUtils.newInstance(className, + RegexpMatcherFactory.class.getClassLoader(), RegexpMatcher .class); } /**