ASF Bugzilla – Attachment 11563 Details for
Bug 28228
<classloader> task
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
modified diff (if also required), replaces attachment from 04/06/04 11:19
patch.txt (text/plain), 44.33 KB, created by
Rainer Noack
on 2004-05-15 10:42:38 UTC
(
hide
)
Description:
modified diff (if also required), replaces attachment from 04/06/04 11:19
Filename:
MIME Type:
Creator:
Rainer Noack
Created:
2004-05-15 10:42:38 UTC
Size:
44.33 KB
patch
obsolete
>? docs/manual/CoreTasks/classloader.html >? src/etc/testcases/taskdefs/classloader >? src/etc/testcases/taskdefs/classloader/path1 >? src/etc/testcases/taskdefs/classloader/path2 >? src/main/org/apache/tools/ant/taskdefs/classloader >? src/main/org/apache/tools/ant/taskdefs/classloader/AntClassLoaderAdapter.java >? src/main/org/apache/tools/ant/taskdefs/classloader/SimpleClassLoaderAdapter.java >? src/main/org/apache/tools/ant/taskdefs/classloader/URLClassLoaderAdapter.java >? src/main/org/apache/tools/ant/types/LoaderHandler.java >? src/main/org/apache/tools/ant/types/LoaderHandlerSet.java >? src/main/org/apache/tools/ant/types/URLPath.java >? src/main/org/apache/tools/ant/types/LoaderRef.java >? src/main/org/apache/tools/ant/types/LoaderParameters.java >? src/main/org/apache/tools/ant/types/AntLoaderParameters.java >? src/main/org/apache/tools/ant/util/URLUtils.java >? src/testcases/org/apache/tools/ant/taskdefs/ClassloaderTest.java >? src/testcases/org/apache/tools/ant/types/URLPathTest.java >? src/testcases/org/apache/tools/ant/util/URLUtilsTest.java >Index: CONTRIBUTORS >=================================================================== >RCS file: /home/cvspublic/ant/CONTRIBUTORS,v >retrieving revision 1.6 >diff -u -r1.6 CONTRIBUTORS >--- CONTRIBUTORS 1 Apr 2004 19:11:02 -0000 1.6 >+++ CONTRIBUTORS 4 Apr 2004 20:04:43 -0000 >@@ -150,6 +150,7 @@ > Pierre Dittgen > Raphael Pierquin > R Handerson >+Rainer Noack > Richard Evans > Rick Beton > Robert Anderson >Index: docs/manual/coretasklist.html >=================================================================== >RCS file: /home/cvspublic/ant/docs/manual/coretasklist.html,v >retrieving revision 1.53 >diff -u -r1.53 coretasklist.html >--- docs/manual/coretasklist.html 12 Mar 2004 15:11:35 -0000 1.53 >+++ docs/manual/coretasklist.html 4 Apr 2004 20:07:34 -0000 >@@ -26,6 +26,7 @@ > <a href="CoreTasks/pack.html">BZip2</a><br> > <a href="CoreTasks/checksum.html">Checksum</a><br> > <a href="CoreTasks/chmod.html">Chmod</a><br> >+<a href="CoreTasks/classloader.html">Classloader</a><br> > <a href="CoreTasks/concat.html">Concat</a><br> > <a href="CoreTasks/condition.html">Condition</a><br> > <a href="CoreTasks/conditions.html">Supported conditions</a><br> >Index: src/etc/testcases/taskdefs/classloader.xml >=================================================================== >RCS file: /home/cvspublic/ant/src/etc/testcases/taskdefs/classloader.xml,v >retrieving revision 1.2 >diff -u -r1.2 classloader.xml >--- src/etc/testcases/taskdefs/classloader.xml 24 Dec 2002 18:09:39 -0000 1.2 >+++ src/etc/testcases/taskdefs/classloader.xml 4 Apr 2004 20:12:19 -0000 >@@ -1,23 +1,119 @@ >-<project name="classloader-test" default="main" basedir="."> >+<project name="classloader-test" default="test-system2prop" basedir="."> > >- <target name="init"> >+ <target name="test.system2prop"> >+ <classloader loader="system" property="test.cl.system2prop" /> >+ <condition property="test.system2prop"> >+ <isset property="test.cl.system2prop"/> >+ </condition> >+ </target> >+ >+ <target name="test.report"> >+ <classloader report="true"/> >+ </target> > >- <path id="myJars" > >- <!-- both ant-junit.jar and junit.jar must be loaded from the same path --> >- <pathelement path="${ant.home}/lib/ant-junit.jar" /> >- <pathelement path="${junit.jar}" /> >- </path> >+ <target name="test.system2prop"> >+ <classloader loader="system" property="test.cl.system2prop" /> >+ <condition property="test.system2prop"> >+ <isset property="test.cl.system2prop"/> >+ </condition> >+ </target> > >- <classloader classpathRef="myJars" >- reverse="true" > >- >+ <target name="test.createURL"> >+ <classloader loader="test.cl.createURL"> >+ <classpath> >+ <urlpathelement location="http://my.domain/my.1st.jar"/> >+ <urlpathelement path="http://my.domain/my.2nd.jar;http://my.domain/my.3rd.jar"/> >+ </classpath> > </classloader> >- <junit /> >- >+ <classloader loader="test.cl.createURL" property="test.cl.createURL"/> >+ <condition property="test.createURL"> >+ <equals arg1="http://my.domain/my.1st.jar;http://my.domain/my.2nd.jar;http://my.domain/my.3rd.jar" >+ arg2="${test.cl.createURL}"/> >+ </condition> >+ >+ </target> >+ >+ <target name="test.updateURL"> >+ <classloader loader="test.cl.updateURL"> >+ <classpath> >+ <urlpathelement location="http://my.domain/my.1st.jar"/> >+ </classpath> >+ </classloader> >+ <classloader loader="test.cl.updateURL" property="test.cl.updateURL"> >+ <classpath> >+ <urlpathelement location="http://my.domain/my.2nd.jar"/> >+ </classpath> >+ </classloader> >+ <condition property="test.updateURL"> >+ <equals arg1="http://my.domain/my.1st.jar;http://my.domain/my.2nd.jar" >+ arg2="${test.cl.updateURL}"/> >+ </condition> >+ >+ </target> >+ >+ <target name="test.createAnt"> >+ <classloader loader="test.cl.createAnt"> >+ <classpath> >+ <pathelement location="classloader/path1"/> >+ </classpath> >+ <antparameters/> >+ </classloader> >+ <classloader loader="test.cl.createAnt" property="test.cl.createAnt"/> >+ <condition property="test.createAnt"> >+ <equals arg1="${basedir}${file.separator}classloader${file.separator}path1" >+ arg2="${test.cl.createAnt}"/> >+ </condition> >+ </target> >+ >+ <target name="test.updateAnt"> >+ <classloader loader="test.cl.updateAnt"> >+ <classpath> >+ <pathelement location="classloader/path1"/> >+ </classpath> >+ <antparameters/> >+ </classloader> >+ <classloader loader="test.cl.updateAnt" property="test.cl.updateAnt"> >+ <classpath> >+ <pathelement location="classloader/path2"/> >+ </classpath> >+ </classloader> >+ <condition property="test.updateAnt"> >+ <equals arg1="${basedir}${file.separator}classloader${file.separator}path1${path.separator}${basedir}${file.separator}classloader${file.separator}path2" >+ arg2="${test.cl.updateAnt}"/> >+ </condition> > </target> > >- <target name="main" depends="init"> >- <echo message="Found JUNIT" /> >+ <target name="test.updateSystem"> >+ <condition property="test.updateSystem.previous"> >+ <not> >+ <available resource="classloadertest.properties"/> >+ </not> >+ </condition> >+ <classloader loader="system"> >+ <classpath> >+ <pathelement location="classloader/path1"/> >+ </classpath> >+ <antparameters/> >+ </classloader> >+ <condition property="test.updateSystem"> >+ <and> >+ <available resource="classloadertest.properties"/> >+ <equals arg1="${test.updateSystem.previous}" arg2="true"/> >+ </and> >+ </condition> > </target> > >+ <target name="test.types" description="just checks whether buildIn types are available"> >+ <loaderhandler id="test.types.handler" loader="dummyloader" adapter="dummyadapter"/> >+ <loaderhandlerset id="test.types.handlerset"/> >+ <loaderparameters id="test.types.loaderparameters"/> >+ <antloaderparameters id="test.types.antloaderparameters"/> >+ <loaderref id="test.types.loaderref" loader="project"/> >+ <urlpath id="test.types.urlpath" location="http://ant.apache.org"/> >+ <property name="test.types" value="true"/> >+ </target> >+ >+ <!-- future use --> >+ <target name="cleanup"> >+ </target> > </project> >Index: src/main/org/apache/tools/ant/taskdefs/Classloader.java >=================================================================== >RCS file: /home/cvspublic/ant/src/main/org/apache/tools/ant/taskdefs/Classloader.java,v >retrieving revision 1.12 >diff -u -r1.12 Classloader.java >--- src/main/org/apache/tools/ant/taskdefs/Classloader.java 9 Mar 2004 16:48:04 -0000 1.12 >+++ src/main/org/apache/tools/ant/taskdefs/Classloader.java 4 Apr 2004 20:13:53 -0000 >@@ -17,33 +17,39 @@ > > package org.apache.tools.ant.taskdefs; > >+import java.io.PrintStream; >+import java.net.URL; >+import java.util.ArrayList; >+import java.util.Arrays; >+import java.util.HashMap; >+import java.util.Map; >+ >+import org.apache.tools.ant.AntTypeDefinition; >+import org.apache.tools.ant.ComponentHelper; >+import org.apache.tools.ant.Location; > import org.apache.tools.ant.Project; > import org.apache.tools.ant.Task; >-import org.apache.tools.ant.MagicNames; > import org.apache.tools.ant.BuildException; >-import org.apache.tools.ant.AntClassLoader; >+import org.apache.tools.ant.types.AntLoaderParameters; >+import org.apache.tools.ant.types.LoaderParameters; >+import org.apache.tools.ant.types.LoaderHandler; >+import org.apache.tools.ant.types.LoaderHandlerSet; >+import org.apache.tools.ant.types.LoaderRef; > import org.apache.tools.ant.types.Reference; >-import org.apache.tools.ant.types.Path; >+import org.apache.tools.ant.types.URLPath; > >-import java.io.File; >+import sun.misc.Launcher; >+import sun.misc.URLClassPath; > > /** >- * EXPERIMENTAL >- * Create or modifies ClassLoader. The required pathRef parameter >- * will be used to add classpath elements. >- * >- * The classpath is a regular path. Currently only file components are >- * supported (future extensions may allow URLs). >- * >- * You can modify the core loader by not specifying any name or using >- * "ant.coreLoader". (the core loader is used to load system ant >- * tasks and for taskdefs that don't specify an explicit path). >- * >- * Taskdef and typedef can use the loader you create if the name follows >- * the "ant.loader.NAME" pattern. NAME will be used as a pathref when >- * calling taskdef. >+ * Create or modifies ClassLoader. > * >- * This tasks will not modify the core loader if "build.sysclasspath=only" >+ * The classpath is a regular path. >+ * >+ * Taskdef and typedef can use the loader you create with the loaderRef attribute. >+ * >+ * This tasks will not modify the core loader, the project loader >+ * or the system loader if "build.sysclasspath=only" > * > * The typical use is: > * <pre> >@@ -53,170 +59,813 @@ > * </fileset> > * </path> > * >- * <classloader pathRef="ant.deps" /> >+ * <classloader loader="project" classpathRef="ant.deps" /> > * > * </pre> > * >+ * @since Ant 1.7 > */ > public class Classloader extends Task { >- /** @see MagicNames#SYSTEM_LOADER_REF */ >- public static final String SYSTEM_LOADER_REF = MagicNames.SYSTEM_LOADER_REF; >+ /** >+ * Actions for ClassLoaderAdapter. >+ */ >+ public static final class Action { >+ private static final int IDCREATE = 1; >+ private static final int IDAPPEND = 2; >+ private static final int IDGETPATH = 3; >+ private static final int IDREPORT = 4; >+ /** >+ * Append Path to an existing ClassLoader instance. >+ */ >+ public static final Action APPEND = new Action(IDAPPEND); >+ /** >+ * Create a new ClassLoader instance. >+ */ >+ public static final Action CREATE = new Action(IDCREATE); >+ /** >+ * Get the path of an existing ClassLoader instance. >+ */ >+ public static final Action GETPATH = new Action(IDGETPATH); >+ /** >+ * Get additional Report information. >+ */ >+ public static final Action REPORT = new Action(IDREPORT); >+ >+ private final int value; >+ private Action(int value) { >+ this.value = value; >+ } >+ } >+ /** >+ * ClassLoaderAdapter used to define classloader interaction. >+ */ >+ public static interface ClassLoaderAdapter { >+ /** >+ * add classloader to the report queue. >+ * the adapter should call task.addLoaderToReport to add a loader. >+ * @param task the calling Classloader-task. >+ * @param classloader the classloader to analyze. >+ * @param name the name of the classloader instance. >+ * @param loaderStack loaderStack to pass to Classloader.addLoaderToReport. >+ * @param loaderNames loaderNames to pass to Classloader.addLoaderToReport. >+ */ >+ void addReportable( >+ Classloader task, >+ ClassLoader classloader, >+ String name, >+ Map loaderStack, >+ Map loaderNames); >+ /** >+ * Appends a classpath to an existing classloader instance. >+ * @param task the calling Classloader-task. >+ * @param classloader the classloader instance to append the path to. >+ * @return The ClassLoader instance or null if an error occured. >+ */ >+ boolean appendClasspath(Classloader task, ClassLoader classloader); >+ /** >+ * Creates a classloader instance. >+ * @param task the calling Classloader-task. >+ * @return the newly created ClassLoader instance or null if an error occured. >+ */ >+ ClassLoader createClassLoader(Classloader task); >+ /** >+ * returns the actual classpath of a classloader instance. >+ * @param task the calling Classloader-task. >+ * @param classloader the classloader instance to get the path from. >+ * @param defaultToFile if true, returned url-elements with file protocol >+ * should trim the leading 'file:/' prefix. >+ * @return the path or null if an error occured >+ */ >+ String[] getClasspath( >+ Classloader task, >+ ClassLoader classloader, >+ boolean defaultToFile); >+ /** >+ * Checks whether the adapter supports an action. >+ * @param action the action to check. >+ * @return true, if action is supported. >+ */ >+ boolean isSupported(Action action); >+ /** >+ * performs additional reporting. >+ * @param to the Reporter Object to report to. >+ * @param task the calling Classloader-task. >+ * @param classloader the classloader instance to report about. >+ * @param name the name of the classloader instance. >+ */ >+ void report( >+ Reporter to, >+ Classloader task, >+ ClassLoader classloader, >+ String name); >+ } >+ /** >+ * Mandatory Interface for ClassLoaderParameters. >+ */ >+ public static interface ClassLoaderParameters { >+ /** >+ * returns the default handler for this descriptor. >+ * @return handler. >+ */ >+ LoaderHandler getDefaultHandler(); >+ /** >+ * returns the valuable parameter object which is either the instance itself >+ * or the resolved referenced parameters. >+ * @return parameters. >+ */ >+ ClassLoaderParameters getParameters(); >+ } >+ /** >+ * makes reporting destination transparent for reporting objects. >+ */ >+ public static class Reporter { >+ private PrintStream stream; >+ private Classloader task; >+ Reporter(Classloader task, PrintStream stream) { >+ this.task = task; >+ this.stream = stream; >+ } >+ /** >+ * writes a message line to the reporting dest. >+ * @param s the message line to report. >+ */ >+ public void report(String s) { >+ if (stream != null) { >+ stream.println(s); >+ } else { >+ task.log(s, Project.MSG_INFO); >+ } >+ } >+ } > >- private String name = null; >- private Path classpath; >+ private URLPath classpath = null; >+ private ClassLoaderParameters parameters = null; >+ private boolean failOnError; >+ private LoaderHandler handler = null; >+ private LoaderHandlerSet handlerSet = null; >+ private LoaderRef loader = null; >+ private String loaderName = null; >+ private LoaderRef parentLoader = null; >+ private String property = null; >+ private boolean report = false; >+ private boolean reportPackages = false; > private boolean reset = false; >- private boolean parentFirst = true; >- private String parentName = null; >- >+ private LoaderRef superLoader = null; > /** > * Default constructor > */ > public Classloader() { > } >- >- /** Name of the loader. If none, the default loader will be modified >- * >- * @param name the name of this loader >+ /** >+ * Sets a nested Descriptor element for an AntClassLoader. >+ * @param desc the parameters. > */ >- public void setName(String name) { >- this.name = name; >+ public void addAntParameters(AntLoaderParameters desc) { >+ parameters = desc; > } >- > /** >- * Reset the classloader, if it already exists. A new loader will >- * be created and all the references to the old one will be removed. >- * (it is not possible to remove paths from a loader). The new >- * path will be used. >- * >- * @param b true if the loader is to be reset. >+ * sets a nested LoaderHandler element. >+ * @param handler the loaderHandler. > */ >- public void setReset(boolean b) { >- this.reset = b; >+ public void addConfiguredHandler(LoaderHandler handler) { >+ handler.check(); >+ if (this.handler != null) { >+ throw new BuildException("nested element handler can only specified once"); >+ } >+ this.handler = handler; > } >- >- public void setReverse(boolean b) { >- this.parentFirst = !b; >+ /** >+ * sets a nested LoaderHandler element. >+ * @param handler the loaderHandler. >+ */ >+ public void setHandler(LoaderHandler handler) { >+ handler.check(); >+ this.handler = handler; >+ } >+ /** >+ * sets a nested ClassLoaderParameters element. >+ * @param desc the parameters. >+ */ >+ public void addParameters(LoaderParameters desc) { >+ parameters = desc; >+ } >+ /** >+ * sets a nested HandlerSet element. >+ * @param handlerSet the handlerSet >+ */ >+ public void addHandlerSet(LoaderHandlerSet handlerSet) { >+ if (this.handlerSet != null) { >+ throw new BuildException("nested element handlerSet may only specified once"); >+ } >+ this.handlerSet = handlerSet; >+ } >+ /** >+ * sets a HandlerSet ref. >+ * @param handlerSet the handlerSet >+ */ >+ public void setHandlerSet(LoaderHandlerSet handlerSet) { >+ this.handlerSet = handlerSet; > } >+ /** >+ * sets a nested loader element. >+ * @param x the loader definition. >+ */ >+ public void addLoader(LoaderRef x) { >+ if (x.isStandardLoader(LoaderRef.LoaderSpec.NONE)) { >+ throw new BuildException("nested element loader can not be 'none'"); >+ } >+ this.loader = x; >+ } >+ /** >+ * Callback method for ClassLoaderAdapters to add classloaders >+ * to the list of loaders to report. >+ * @param cl the classloader instance to add. >+ * @param name the name of the classloader instance. >+ * @param loaderStack a list of loader names by instance. >+ * @param loaderNames a list of loader instances by name. >+ * @return true, if successfully executed, false otherwise. >+ */ >+ public boolean addLoaderToReport( >+ ClassLoader cl, >+ String name, >+ Map loaderStack, >+ Map loaderNames) { >+ if (cl == null) { >+ Object old = loaderNames.put(name, null); >+ if (old != null) { >+ throw new BuildException("duplicate classloader name " + name); >+ } >+ } else { >+ Object old = loaderNames.put(name, cl); >+ if (old != null) { >+ throw new BuildException("duplicate classloader name " + name); >+ } >+ old = loaderStack.get(cl); >+ boolean isNew = (old == null); >+ if (old == null) { >+ old = new ArrayList(); >+ loaderStack.put(cl, old); >+ } >+ ((ArrayList) old).add(name); > >- public void setParentFirst(boolean b) { >- this.parentFirst = b; >+ if (isNew) { >+ addLoaderToReport( >+ cl.getParent(), >+ name + "->parent", >+ loaderStack, >+ loaderNames); >+ >+ LoaderHandlerSet handlerSet = getHandlerSet(); >+ if (handlerSet == null) { >+ return false; >+ } >+ LoaderHandler handler = >+ handlerSet.getHandler(this, cl, Action.REPORT); >+ if (handler == null) { >+ return false; >+ } >+ ClassLoaderAdapter adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ return false; >+ } >+ adapter.addReportable(this, cl, name, loaderStack, loaderNames); >+ } >+ } >+ return true; >+ } >+ /** >+ * sets the nested parentLoader element. >+ * @param x the parentLoader >+ */ >+ public void addParentLoader(LoaderRef x) { >+ this.parentLoader = x; > } >+ /** >+ * sets the nested superLoader element. >+ * @param x the superLoader. >+ */ >+ public void addSuperLoader(LoaderRef x) { >+ this.parentLoader = x; >+ } >+ /** >+ * creates a nested classpath element. >+ * @return the classpath. >+ */ >+ public URLPath createClasspath() { >+ if (this.classpath == null) { >+ this.classpath = new URLPath(getProject()); >+ } >+ return this.classpath.createUrlpath(); >+ } >+ /** >+ * executes this task. >+ */ >+ public void execute() { >+ if (report) { >+ executeReport(); >+ return; >+ } >+ if (loader == null) { >+ throw new BuildException("no loader specified"); >+ } >+ if (!executeCreateModify()) { >+ return; >+ } >+ if (property != null) { >+ this.executeProperty(); >+ } >+ } >+ private boolean executeCreateModify() { >+ URLPath cp = getClasspath(); >+ ClassLoader cl = null; >+ // Are any other references held ? Can we 'close' the loader >+ // so it removes the locks on jars ? >+ // Can we replace the system classloader by just changing the >+ // referenced object? >+ // however, is reset really useful? >+ if (!reset) { >+ cl = loader.getClassLoader(null, false, true); >+ } >+ >+ boolean create = (cl == null); >+ boolean modify = ((cl != null) && (cp != null)); >+ if (!(create || modify)) { >+ return true; >+ } > >- // TODO: add exceptions for delegation or reverse >+ // Gump friendly - don't mess with the core loader if only classpath >+ if ("only".equals(getProject().getProperty("build.sysclasspath")) >+ && loader.equalsSysLoader()) { >+ log("Changing " + loader.getName() + " is disabled " >+ + "by build.sysclasspath=only", >+ Project.MSG_WARN); >+ return true; >+ } > >- // TODO >- public void setParentName(String name) { >- this.parentName = name; >+ if (reset && !loader.isResetPossible()) { >+ this.handleError("reseting " + loader.getName() + " is not possible"); >+ return false; >+ } >+ if (create && !loader.isResetPossible()) { >+ this.handleError("creating " + loader.getName() + " is not possible"); >+ return false; >+ } >+ log( >+ "handling " >+ + this.getLoaderName() >+ + ": " >+ + ((cl == null) ? "not " : "") >+ + "found, cp=" >+ + this.getClasspath(), >+ Project.MSG_DEBUG); >+ LoaderHandlerSet handlerSet = null; >+ if (cl == null) { >+ LoaderHandler handler = getHandler(); >+ if (handler == null) { >+ throw new BuildException("internal error: handler is null"); >+ } >+ ClassLoaderAdapter adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ return false; >+ } >+ cl = adapter.createClassLoader(this); >+ if (cl == null) { >+ return false; >+ } >+ loader.setClassLoader(cl); >+ } else if (cp != null) { >+ handlerSet = getHandlerSet(); >+ if (handlerSet == null) { >+ throw new BuildException("internal error: handlerset is null"); >+ } >+ LoaderHandler handler = >+ handlerSet.getHandler(this, cl, Action.APPEND); >+ if (handler == null) { >+ log("NO HANDLER", Project.MSG_DEBUG); >+ return false; >+ } >+ ClassLoaderAdapter adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ log("NO ADAPTER", Project.MSG_DEBUG); >+ return false; >+ } >+ if (!adapter.appendClasspath(this, cl)) { >+ log("NO APPEND", Project.MSG_DEBUG); >+ return false; >+ } >+ } >+ return true; >+ } >+ private boolean executeProperty() { >+ ClassLoader cl = loader.getClassLoader(null); >+ LoaderHandlerSet handlerSet = getHandlerSet(); >+ if (handlerSet == null) { >+ throw new BuildException("internal error: handlerset is null"); >+ } >+ LoaderHandler handler = >+ handlerSet.getHandler(this, cl, Action.GETPATH); >+ if (handler == null) { >+ return false; >+ } >+ ClassLoaderAdapter adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ return false; >+ } >+ String[] propPath = adapter.getClasspath(this, cl, true); >+ if (propPath == null) { >+ return false; >+ } >+ StringBuffer propValue = new StringBuffer(); >+ if (propPath.length > 0) { >+ propValue.append(propPath[0]); >+ } >+ for (int i = 1; i < propPath.length; i++) { >+ propValue.append(';').append(propPath[i]); >+ } >+ getProject().setProperty(property, propValue.toString()); >+ return true; > } >+ private String formatIndex(int i) { >+ String x = String.valueOf(i + 1); >+ if (x.length() == 1) { >+ return " " + x; >+ } >+ return x; >+ } >+ /** >+ * gets the classpath to add to a classloader. >+ * @return the classpath. >+ */ >+ public URLPath getClasspath() { >+ return classpath; >+ } >+ /** >+ * gets the parameters for a newly created classloader. >+ * @return the parameters >+ */ >+ public ClassLoaderParameters getParameters() { >+ if (parameters == null) { >+ parameters = new LoaderParameters(getProject()); >+ } >+ return parameters; >+ } >+ /** >+ * gets the handler to create a new classloader. >+ * @return the handler >+ */ >+ public LoaderHandler getHandler() { >+ if (handler == null) { >+ handler = getParameters().getDefaultHandler(); >+ } >+ return handler; >+ } >+ /** >+ * gets the handlerset to analyze a given classloader with. >+ * @return the handlerset. >+ */ >+ public LoaderHandlerSet getHandlerSet() { >+ if (handlerSet == null) { >+ handlerSet = new LoaderHandlerSet(getProject()); >+ handlerSet.addConfiguredHandler(getHandler()); >+ } >+ return handlerSet; >+ } >+ /** >+ * gets the name of the described classloader for logging and report purposes. >+ * @return the name. >+ */ >+ public String getLoaderName() { >+ if (loaderName == null) { >+ loaderName = loader.getName(); >+ } >+ return loaderName; >+ } >+ /** >+ * gets the parent ClassLoader as defined via the parentLoader attribute. >+ * @return parent ClassLoader or null if not defined. >+ */ >+ public ClassLoader getParentLoader() { >+ if (parentLoader == null) { >+ return null; >+ } >+ return parentLoader.getClassLoader(null, failOnError, false); >+ } >+ /** >+ * gets the super classloader to create a new classloader with. >+ * @return the super loader. >+ */ >+ public ClassLoader getSuperLoader() { >+ if (superLoader == null) { >+ return getClass().getClassLoader(); >+ } >+ return superLoader.getClassLoader(null, failOnError, false); >+ } >+ /** >+ * indicates whether packages should been reported >+ * @return true, if packages should been reported, else false. >+ */ >+ public boolean isReportPackages() { >+ return reportPackages; >+ } >+ /** >+ * handles an error with respect to the failonerror attribute. >+ * @param msg error message. >+ */ >+ public void handleError(String msg) { >+ handleError(msg, null, null); >+ } >+ /** >+ * handles an error with respect to the failonerror attribute. >+ * @param msg error message. >+ * @param ex causing exception. >+ */ >+ public void handleError(String msg, Throwable ex) { >+ handleError(msg, ex, null); >+ } >+ /** >+ * handles an error with respect to the failonerror attribute. >+ * @param msg error message. >+ * @param ex causing exception. >+ * @param loc loaction. >+ */ >+ public void handleError(String msg, Throwable ex, Location loc) { >+ if (loc == null) { >+ loc = this.getLocation(); >+ } >+ if ((msg == null) && (ex != null)) { >+ msg = ex.getMessage(); >+ } >+ if (failOnError) { >+ throw new BuildException(msg, ex, loc); >+ } else { >+ log(loc + "Error: " + msg, Project.MSG_ERR); >+ } >+ } >+ /** >+ * handle the report. >+ */ >+ protected void executeReport() { >+ //let's hope, that no classloader implementation overrides >+ // equals/hashCode >+ //for 1.4 IdentityHashMap should be used for loaderStack >+ HashMap loaderStack = new HashMap(); >+ HashMap loaderNames = new HashMap(); >+ boolean addSuccess = true; >+ if (!addLoaderToReport( >+ ClassLoader.getSystemClassLoader(), >+ "1-SystemClassLoader", >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ if (!addLoaderToReport( >+ getProject().getClass().getClassLoader(), >+ "2-ProjectClassLoader", >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ if (!addLoaderToReport( >+ getClass().getClassLoader(), >+ "3-CurrentClassLoader", >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ if (!addLoaderToReport( >+ Thread.currentThread().getContextClassLoader(), >+ "4-ThreadContextClassLoader", >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ if (!addLoaderToReport( >+ getProject().getCoreLoader(), >+ "5-CoreLoader", >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ String[] rNames = >+ (String[]) getProject().getReferences().keySet().toArray( >+ new String[getProject().getReferences().size()]); >+ Arrays.sort(rNames); >+ for (int i = 0; i < rNames.length; i++) { >+ Object val = getProject().getReference(rNames[i]); >+ if (val instanceof ClassLoader) { >+ if (!addLoaderToReport( >+ (ClassLoader) val, >+ "6-id=" + rNames[i], >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ } >+ } >+ ComponentHelper ch = ComponentHelper.getComponentHelper(getProject()); >+ Map types = ch.getAntTypeTable(); >+ rNames = (String[]) types.keySet().toArray(new String[types.size()]); >+ Arrays.sort(rNames); >+ for (int i = 0; i < rNames.length; i++) { >+ AntTypeDefinition val = ch.getDefinition(rNames[i]); >+ if (val.getClassLoader() != null) { >+ if (!addLoaderToReport( >+ val.getClassLoader(), >+ "7-def=" + rNames[i], >+ loaderStack, >+ loaderNames)) { >+ addSuccess = false; >+ } >+ } >+ } >+ rNames = null; >+ String[] names = >+ (String[]) loaderNames.keySet().toArray( >+ new String[loaderNames.size()]); >+ Arrays.sort(names); >+ for (int i = names.length - 1; i >= 0; i--) { >+ Object cl = loaderNames.get(names[i]); >+ if (cl != null) { >+ loaderStack.put(cl, names[i]); >+ } >+ } >+ //fileoutput and xml-format to be implemented. >+ Reporter to = new Reporter(this, null); > >+ to.report("---------- ClassLoader Report ----------"); >+ if (!addSuccess) { >+ to.report("WARNING: As of missing Loaderhandlers, this report might not be complete."); >+ } >+ URLClassPath bscp = Launcher.getBootstrapClassPath(); >+ URL[] urls = bscp.getURLs(); >+ to.report(" "); >+ to.report(" 0. bootstrap classpath: " + urls.length + " elements"); >+ for (int i = 0; i < urls.length; i++) { >+ to.report(" > " + urls[i]); >+ } > >- /** Specify which path will be used. If the loader already exists >- * and is an AntClassLoader (or any other loader we can extend), >- * the path will be added to the loader. >+ for (int i = 0; i < names.length; i++) { >+ to.report(" "); >+ ClassLoader cl = (ClassLoader) loaderNames.get(names[i]); >+ if (cl == null) { >+ to.report( >+ formatIndex(i) >+ + ". " >+ + names[i].substring(2) >+ + " is not assigned."); >+ } else { >+ Object n = loaderStack.get(cl); >+ if (names[i].equals(n)) { >+ to.report(formatIndex(i) + ". " + names[i].substring(2)); >+ report(to, cl, names[i].substring(2)); >+ } else { >+ to.report( >+ formatIndex(i) >+ + ". " >+ + names[i].substring(2) >+ + " = " >+ + ((String) n).substring(2) >+ + ". (See above.)"); >+ } >+ } >+ } >+ to.report("---------- End Of ClassLoader Report ----------"); >+ } >+ /** >+ * handle the report for a single classloader >+ * @param to Reporter to report >+ * @param cl Classloader instance to report >+ * @param name name of the classloader instance. > */ >- public void setClasspathRef(Reference pathRef) throws BuildException { >- classpath = (Path) pathRef.getReferencedObject(getProject()); >+ public void report(Reporter to, ClassLoader cl, String name) { >+ to.report(" class: " + cl.getClass().getName()); >+ LoaderHandlerSet handlerSet = getHandlerSet(); >+ if (handlerSet == null) { >+ throw new BuildException("internal error: handlerset is null"); >+ } >+ LoaderHandler handler = handlerSet.getHandler(this, cl, Action.GETPATH); >+ ClassLoaderAdapter adapter; >+ if (handler == null) { >+ to.report(" path: - not investigatable (no Loaderhandler found) -"); >+ } else { >+ adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ to.report(" path: - not investigatable (Loaderhandler retrieves no adapter) -"); >+ } else { >+ String[] cp = adapter.getClasspath(this, cl, false); >+ if (cp == null) { >+ to.report(" path: - not investigatable (adapter retrieves no path) -"); >+ } else { >+ to.report(" path: " + cp.length + " elements"); >+ for (int i = 0; i < cp.length; i++) { >+ to.report(" > " + cp[i]); >+ } >+ } >+ } >+ } >+ handler = handlerSet.getHandler(this, cl, Action.REPORT); >+ if (handler == null) { >+ to.report(" - additional parameters not investigatable (no Loaderhandler found) -"); >+ return; >+ } >+ adapter = handler.getAdapter(this); >+ if (adapter == null) { >+ to.report(" - additional parameters not investigatable " >+ + "(Loaderhandler retrieves no adapter) -"); >+ return; >+ } >+ adapter.report(to, this, cl, name); > } > > /** >- * Set the classpath to be used when searching for component being defined >- * >+ * Specify which path will be used. If the loader already exists >+ * the path will be added to the loader. > * @param classpath an Ant Path object containing the classpath. > */ >- public void setClasspath(Path classpath) { >+ public void setClasspath(URLPath classpath) { > if (this.classpath == null) { > this.classpath = classpath; > } else { > this.classpath.append(classpath); > } > } >- >- public Path createClasspath() { >- if (this.classpath == null) { >- this.classpath = new Path(null); >+ /** >+ * Specify which path will be used. If the loader already exists >+ * the path will be added to the loader. >+ * @param pathRef reference to a path defined elsewhere >+ */ >+ public void setClasspathRef(Reference pathRef) { >+ createClasspath().addReference(pathRef); >+ } >+ /** >+ * sets the failonerror attribute >+ * @param onOff value >+ */ >+ public void setFailonerror(boolean onOff) { >+ this.failOnError = onOff; >+ } >+ /** >+ * sets the loader attribute >+ * @param x the loader >+ */ >+ public void setLoader(LoaderRef x) { >+ if (x.isStandardLoader(LoaderRef.LoaderSpec.NONE)) { >+ throw new BuildException("attribute loader can not be 'none'"); > } >- return this.classpath.createPath(); >+ this.loader = x; >+ } >+ /** >+ * sets the parameters attribute. >+ * @param desc the parameters. >+ */ >+ public void setParameters(LoaderParameters desc) { >+ parameters = desc; >+ } >+ /** >+ * sets the parentLoader attribute >+ * @param x the parent loader >+ */ >+ public void setParentLoader(LoaderRef x) { >+ this.parentLoader = x; >+ } >+ /** >+ * sets the property to put the ClassLoaders path into. >+ * @param property name of the property. >+ */ >+ public void setProperty(String property) { >+ this.property = property; >+ } >+ /** >+ * sets the report attribute. >+ * @param onOff indicates whether to generate a report or not. defaults to false. >+ */ >+ public void setReport(boolean onOff) { >+ report = onOff; >+ } >+ /** >+ * sets the reportPackages attribute. >+ * @param onOff indicates whether to generate a report or not. defaults to false. >+ */ >+ public void setReportpackages(boolean onOff) { >+ reportPackages = onOff; > } > >- >- public void execute() { >- try { >- // Gump friendly - don't mess with the core loader if only classpath >- if ("only".equals(getProject().getProperty("build.sysclasspath")) >- && (name == null || SYSTEM_LOADER_REF.equals(name))) { >- log("Changing the system loader is disabled " >- + "by build.sysclasspath=only", Project.MSG_WARN); >- return; >- } >- >- String loaderName = (name == null) ? SYSTEM_LOADER_REF : name; >- >- Object obj = getProject().getReference(loaderName); >- if (reset) { >- // Are any other references held ? Can we 'close' the loader >- // so it removes the locks on jars ? >- obj = null; // a new one will be created. >- } >- >- // XXX maybe use reflection to addPathElement (other patterns ?) >- if (obj != null && !(obj instanceof AntClassLoader)) { >- log("Referenced object is not an AntClassLoader", >- Project.MSG_ERR); >- return; >- } >- >- AntClassLoader acl = (AntClassLoader) obj; >- >- if (acl == null) { >- // Construct a new class loader >- Object parent = null; >- if (parentName != null) { >- parent = getProject().getReference(parentName); >- if (!(parent instanceof ClassLoader)) { >- parent = null; >- } >- } >- // TODO: allow user to request the system or no parent >- if (parent == null) { >- parent = this.getClass().getClassLoader(); >- } >- >- if (name == null) { >- // The core loader must be reverse >- //reverse=true; >- } >- getProject().log("Setting parent loader " + name + " " >- + parent + " " + parentFirst, Project.MSG_DEBUG); >- >- // The param is "parentFirst" >- acl = new AntClassLoader((ClassLoader) parent, >- getProject(), classpath, parentFirst); >- >- getProject().addReference(loaderName, acl); >- >- if (name == null) { >- // This allows the core loader to load optional tasks >- // without delegating >- acl.addLoaderPackageRoot("org.apache.tools.ant.taskdefs.optional"); >- getProject().setCoreLoader(acl); >- } >- } >- if (classpath != null) { >- String[] list = classpath.list(); >- for (int i = 0; i < list.length; i++) { >- File f = new File(list[i]); >- if (f.exists()) { >- acl.addPathElement(f.getAbsolutePath()); >- log("Adding to class loader " + acl + " " + f.getAbsolutePath(), >- Project.MSG_DEBUG); >- } >- } >- } >- >- // XXX add exceptions >- >- } catch (Exception ex) { >- ex.printStackTrace(); >- } >+ /** >+ * Reset the classloader, if it already exists. A new loader will >+ * be created and all the references to the old one will be removed. >+ * (it is not possible to remove paths from a loader). The new >+ * path will be used. >+ * >+ * @param b true if the loader is to be reset. >+ */ >+ public void setReset(boolean b) { >+ this.reset = b; >+ } >+ /** >+ * sets the superLoader attribute. >+ * @param x the superLoader. >+ */ >+ public void setSuperLoader(LoaderRef x) { >+ this.parentLoader = x; > } > } >Index: src/main/org/apache/tools/ant/types/defaults.properties >=================================================================== >RCS file: /home/cvspublic/ant/src/main/org/apache/tools/ant/types/defaults.properties,v >retrieving revision 1.23 >diff -u -r1.23 defaults.properties >--- src/main/org/apache/tools/ant/types/defaults.properties 27 Mar 2004 21:33:49 -0000 1.23 >+++ src/main/org/apache/tools/ant/types/defaults.properties 4 Apr 2004 20:17:05 -0000 >@@ -32,3 +32,9 @@ > propertyset=org.apache.tools.ant.types.PropertySet > assertions=org.apache.tools.ant.types.Assertions > concatfilter=org.apache.tools.ant.filters.ConcatFilter >+loaderhandler=org.apache.tools.ant.types.LoaderHandler >+loaderhandlerset=org.apache.tools.ant.types.LoaderHandlerSet >+loaderparameters=org.apache.tools.ant.types.LoaderParameters >+antloaderparameters=org.apache.tools.ant.types.AntLoaderParameters >+loaderref=org.apache.tools.ant.types.LoaderRef >+urlpath=org.apache.tools.ant.types.URLPath
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 28228
:
11152
|
11153
|
11178
|
11179
|
11562
| 11563