Most of the changes here are actually adding tests, which was surprisingly hard work. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276755 13f79535-47bb-0310-9956-ffa450edef68master
@@ -37,6 +37,7 @@ attribute. <a name="compilervalues">There are three choices</a>:</p> | |||
<li>sun (the standard compiler of the JDK)</li> | |||
<li>kaffe (the standard compiler of <a href="http://www.kaffe.org" target="_top">Kaffe</a>)</li> | |||
<li>weblogic</li> | |||
<li>forking - the sun compiler forked into a separate process</li> | |||
</ul> | |||
<p>The <a href="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a> | |||
@@ -0,0 +1,89 @@ | |||
<?xml version="1.0"?> | |||
<project name="rmic" default="teardown" basedir="."> | |||
<property name="rmic.dir" location="." /> | |||
<property name="src.dir" location="${rmic.dir}/src"/> | |||
<property name="build.dir" location="${rmic.dir}/build"/> | |||
<target name="teardown"> | |||
<delete dir="${build.dir}"/> | |||
</target> | |||
<!-- init builds the java source --> | |||
<target name="init" depends="probe-rmic"> | |||
<mkdir dir="${build.dir}"/> | |||
<javac | |||
destdir="${build.dir}" | |||
srcdir="${src.dir}" > | |||
</javac> | |||
<presetdef name="base-rmic"> | |||
<rmic | |||
base="${build.dir}" | |||
verify="true" | |||
includes="**/*.class"/> | |||
</presetdef> | |||
</target> | |||
<target name="probe-rmic"> | |||
<available property="kaffe.present" classname="jkaffe.rmi.rmic.RMIC"/> | |||
<available property="rmic.present" classname="sun.rmi.rmic.Main"/> | |||
<available property="wlrmic.present" classname="weblogic.rmic"/> | |||
</target> | |||
<target name="testRmic" if="rmic.present" depends="init"> | |||
<base-rmic /> | |||
</target> | |||
<target name="testKaffe" if="kaffe.present" depends="init"> | |||
<base-rmic | |||
compiler="kaffe" | |||
/> | |||
</target> | |||
<target name="testWlrmic" if="wlrmic.present" depends="init"> | |||
<base-rmic | |||
compiler="wlrmic" | |||
/> | |||
</target> | |||
<target name="testForking" if="rmic.present" depends="init"> | |||
<base-rmic | |||
compiler="forking" | |||
/> | |||
</target> | |||
<target name="testBadName" if="rmic.present" depends="init"> | |||
<base-rmic | |||
compiler="no-such-compiler" | |||
/> | |||
</target> | |||
<target name="testWrongClass" if="rmic.present" depends="init"> | |||
<base-rmic | |||
compiler="org.apache.tools.ant.BuildException" | |||
/> | |||
</target> | |||
<target name="testNoBase" depends="init"> | |||
<rmic | |||
verify="true" | |||
includes="**/*.class"/> | |||
</target> | |||
<target name="testBaseDoesntExist" depends="init"> | |||
<rmic | |||
base="${build.dir}/classes" | |||
verify="true" | |||
includes="**/*.class"/> | |||
</target> | |||
<target name="testBaseIsntDir" depends="init"> | |||
<rmic | |||
base="${ant.file}" | |||
verify="true" | |||
includes="**/*.class"/> | |||
</target> | |||
</project> |
@@ -0,0 +1,10 @@ | |||
import java.rmi.Remote; | |||
import java.rmi.RemoteException; | |||
/** | |||
* this is the interface we remote | |||
*/ | |||
public interface RemoteTimestamp extends Remote { | |||
long when() throws RemoteException ; | |||
} | |||
@@ -0,0 +1,12 @@ | |||
import java.rmi.Remote; | |||
import java.rmi.RemoteException; | |||
/** | |||
* this is the implementation | |||
*/ | |||
public class RemoteTimestampImpl implements RemoteTimestamp { | |||
public long when() throws RemoteException { | |||
return System.currentTimeMillis(); | |||
} | |||
} |
@@ -26,6 +26,7 @@ import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.taskdefs.rmic.RmicAdapter; | |||
import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory; | |||
import org.apache.tools.ant.taskdefs.rmic.KaffeRmic; | |||
import org.apache.tools.ant.types.FilterSetCollection; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.Reference; | |||
@@ -106,14 +107,17 @@ public class Rmic extends MatchingTask { | |||
private FileUtils fileUtils = FileUtils.newFileUtils(); | |||
private FacadeTaskHelper facade; | |||
public static final String ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class "; | |||
public static final String ERROR_NOT_FOUND = ". It could not be found."; | |||
public static final String ERROR_NOT_DEFINED = ". It is not defined."; | |||
public static final String ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: "; | |||
public static final String ERROR_NO_BASE_EXISTS = "base does not exist: "; | |||
public static final String ERROR_NOT_A_DIR = "base is not a directory:"; | |||
public static final String ERROR_BASE_NOT_SET = "base attribute must be set!"; | |||
public Rmic() { | |||
try { | |||
Class.forName("kaffe.rmi.rmic.RMIC"); | |||
facade = new FacadeTaskHelper("kaffe"); | |||
} catch (ClassNotFoundException cnfe) { | |||
facade = new FacadeTaskHelper("sun"); | |||
} | |||
String facadeName=KaffeRmic.isAvailable()?"kaffe":"sun"; | |||
facade = new FacadeTaskHelper(facadeName); | |||
} | |||
/** | |||
@@ -433,12 +437,14 @@ public class Rmic extends MatchingTask { | |||
*/ | |||
public void execute() throws BuildException { | |||
if (baseDir == null) { | |||
throw new BuildException("base attribute must be set!", getLocation()); | |||
throw new BuildException(ERROR_BASE_NOT_SET, getLocation()); | |||
} | |||
if (!baseDir.exists()) { | |||
throw new BuildException("base does not exist!", getLocation()); | |||
throw new BuildException(ERROR_NO_BASE_EXISTS+baseDir, getLocation()); | |||
} | |||
if ( !baseDir.isDirectory() ) { | |||
throw new BuildException(ERROR_NOT_A_DIR+baseDir, getLocation()); | |||
} | |||
if (verify) { | |||
log("Verify has been turned on.", Project.MSG_VERBOSE); | |||
} | |||
@@ -595,14 +601,14 @@ public class Rmic extends MatchingTask { | |||
} | |||
return isValidRmiRemote(testClass); | |||
} catch (ClassNotFoundException e) { | |||
log("Unable to verify class " + classname | |||
+ ". It could not be found.", Project.MSG_WARN); | |||
log(ERROR_UNABLE_TO_VERIFY_CLASS + classname | |||
+ ERROR_NOT_FOUND, Project.MSG_WARN); | |||
} catch (NoClassDefFoundError e) { | |||
log("Unable to verify class " + classname | |||
+ ". It is not defined.", Project.MSG_WARN); | |||
log(ERROR_UNABLE_TO_VERIFY_CLASS + classname | |||
+ ERROR_NOT_DEFINED, Project.MSG_WARN); | |||
} catch (Throwable t) { | |||
log("Unable to verify class " + classname | |||
+ ". Loading caused Exception: " | |||
log(ERROR_UNABLE_TO_VERIFY_CLASS + classname | |||
+ ERROR_LOADING_CAUSED_EXCEPTION | |||
+ t.getMessage(), Project.MSG_WARN); | |||
} | |||
// we only get here if an exception has been thrown | |||
@@ -0,0 +1,74 @@ | |||
/** (C) Copyright 2004 Hewlett-Packard Development Company, LP | |||
This library is free software; you can redistribute it and/or | |||
modify it under the terms of the GNU Lesser General Public | |||
License as published by the Free Software Foundation; either | |||
version 2.1 of the License, or (at your option) any later version. | |||
This library is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public | |||
License along with this library; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
For more information: www.smartfrog.org | |||
*/ | |||
package org.apache.tools.ant.taskdefs.rmic; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.taskdefs.Rmic; | |||
import org.apache.tools.ant.taskdefs.Java; | |||
import org.apache.tools.ant.taskdefs.Execute; | |||
import org.apache.tools.ant.taskdefs.LogStreamHandler; | |||
import org.apache.tools.ant.types.Commandline; | |||
import java.io.IOException; | |||
/** | |||
* This is an extension of the sun rmic compiler, which forks rather than | |||
* executes it inline. Why so? Because rmic is dog slow, but if you fork the | |||
* compiler you can have multiple copies compiling different bits of your project | |||
* at the same time. Which, on a multi-cpu system results in significant speedups. | |||
* | |||
* @since ant1.7 | |||
*/ | |||
public class ForkingSunRmic extends DefaultRmicAdapter { | |||
/** | |||
* exec by creating a new command | |||
* @return | |||
* @throws BuildException | |||
*/ | |||
public boolean execute() throws BuildException { | |||
Rmic owner=getRmic(); | |||
Commandline cmd = setupRmicCommand(); | |||
Project project=owner.getProject(); | |||
//rely on RMIC being on the path | |||
cmd.setExecutable(SunRmic.RMIC_EXECUTABLE); | |||
//set up the args | |||
String[] args=cmd.getCommandline(); | |||
try { | |||
Execute exe = new Execute(new LogStreamHandler(owner, | |||
Project.MSG_INFO, | |||
Project.MSG_WARN)); | |||
exe.setAntRun(project); | |||
exe.setWorkingDirectory(project.getBaseDir()); | |||
exe.setCommandline(args); | |||
exe.execute(); | |||
return exe.getExitValue()==0; | |||
} catch (IOException exception) { | |||
throw new BuildException("Error running "+ SunRmic.RMIC_EXECUTABLE | |||
+" -maybe it is not on the path" , | |||
exception); | |||
} | |||
} | |||
} |
@@ -21,6 +21,7 @@ import java.lang.reflect.Constructor; | |||
import java.lang.reflect.Method; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.util.facade.FacadeTaskHelper; | |||
import org.apache.tools.ant.types.Commandline; | |||
/** | |||
@@ -29,6 +30,7 @@ import org.apache.tools.ant.types.Commandline; | |||
* @since Ant 1.4 | |||
*/ | |||
public class KaffeRmic extends DefaultRmicAdapter { | |||
public static final String RMIC_CLASSNAME = "kaffe.rmi.rmic.RMIC"; | |||
public boolean execute() throws BuildException { | |||
getRmic().log("Using Kaffe rmic", Project.MSG_VERBOSE); | |||
@@ -36,7 +38,7 @@ public class KaffeRmic extends DefaultRmicAdapter { | |||
try { | |||
Class c = Class.forName("kaffe.rmi.rmic.RMIC"); | |||
Class c = Class.forName(RMIC_CLASSNAME); | |||
Constructor cons = c.getConstructor(new Class[] {String[].class}); | |||
Object rmic = cons.newInstance(new Object[] {cmd.getArguments()}); | |||
Method doRmic = c.getMethod("run", null); | |||
@@ -58,4 +60,17 @@ public class KaffeRmic extends DefaultRmicAdapter { | |||
} | |||
} | |||
} | |||
/** | |||
* test for kaffe being on the system | |||
* @return | |||
*/ | |||
public static boolean isAvailable() { | |||
try { | |||
Class.forName(RMIC_CLASSNAME); | |||
return true; | |||
} catch (ClassNotFoundException cnfe) { | |||
return false; | |||
} | |||
} | |||
} |
@@ -23,7 +23,7 @@ import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.util.FileNameMapper; | |||
/** | |||
* The interface that all rmic adapters must adher to. | |||
* The interface that all rmic adapters must adhere to. | |||
* | |||
* <p>A rmic adapter is an adapter that interprets the rmic's | |||
* parameters in preperation to be passed off to the compiler this | |||
@@ -27,6 +27,8 @@ import org.apache.tools.ant.Task; | |||
* @since 1.4 | |||
*/ | |||
public class RmicAdapterFactory { | |||
public static final String ERROR_UNKNOWN_COMPILER = "Cannot find the compiler or class: "; | |||
public static final String ERROR_NOT_RMIC_ADAPTER = "Not an rmic adapter: "; | |||
/** This is a singleton -- can't create instances!! */ | |||
private RmicAdapterFactory() { | |||
@@ -41,6 +43,8 @@ public class RmicAdapterFactory { | |||
* <li>kaffe = Kaffe's rmic | |||
* <li><i>a fully quallified classname</i> = the name of a rmic | |||
* adapter | |||
* <li>weblogic = weblogic compiler | |||
* <li>forking = Sun's RMIC by forking a new JVM | |||
* </ul> | |||
* | |||
* @param rmicType either the name of the desired rmic, or the | |||
@@ -57,6 +61,8 @@ public class RmicAdapterFactory { | |||
return new KaffeRmic(); | |||
} else if (rmicType.equalsIgnoreCase("weblogic")) { | |||
return new WLRmic(); | |||
} else if (rmicType.equalsIgnoreCase("forking")) { | |||
return new ForkingSunRmic(); | |||
} | |||
return resolveClassName(rmicType); | |||
} | |||
@@ -76,10 +82,11 @@ public class RmicAdapterFactory { | |||
Object o = c.newInstance(); | |||
return (RmicAdapter) o; | |||
} catch (ClassNotFoundException cnfe) { | |||
throw new BuildException(className + " can\'t be found.", cnfe); | |||
throw new BuildException(ERROR_UNKNOWN_COMPILER+className, | |||
cnfe); | |||
} catch (ClassCastException cce) { | |||
throw new BuildException(className + " isn\'t the classname of " | |||
+ "a rmic adapter.", cce); | |||
throw new BuildException(ERROR_NOT_RMIC_ADAPTER+className, | |||
cce); | |||
} catch (Throwable t) { | |||
// for all other possibilities | |||
throw new BuildException(className + " caused an interesting " | |||
@@ -33,6 +33,21 @@ import org.apache.tools.ant.types.Commandline; | |||
*/ | |||
public class SunRmic extends DefaultRmicAdapter { | |||
/** | |||
* name of the class | |||
*/ | |||
public static final String RMIC_CLASSNAME = "sun.rmi.rmic.Main"; | |||
/** | |||
* name of the executable | |||
*/ | |||
public static final String RMIC_EXECUTABLE = "rmic"; | |||
public static final String ERROR_NO_RMIC_ON_CLASSPATH = "Cannot use SUN rmic, as it is not " | |||
+ "available. A common solution is to " | |||
+ "set the environment variable " | |||
+ "JAVA_HOME or CLASSPATH."; | |||
public static final String ERROR_RMIC_FAILED = "Error starting SUN rmic: "; | |||
public boolean execute() throws BuildException { | |||
getRmic().log("Using SUN rmic compiler", Project.MSG_VERBOSE); | |||
Commandline cmd = setupRmicCommand(); | |||
@@ -43,7 +58,7 @@ public class SunRmic extends DefaultRmicAdapter { | |||
Project.MSG_WARN); | |||
try { | |||
Class c = Class.forName("sun.rmi.rmic.Main"); | |||
Class c = Class.forName(RMIC_CLASSNAME); | |||
Constructor cons | |||
= c.getConstructor(new Class[] {OutputStream.class, String.class}); | |||
Object rmic = cons.newInstance(new Object[] {logstr, "rmic"}); | |||
@@ -55,16 +70,13 @@ public class SunRmic extends DefaultRmicAdapter { | |||
(new Object[] {cmd.getArguments()})); | |||
return ok.booleanValue(); | |||
} catch (ClassNotFoundException ex) { | |||
throw new BuildException("Cannot use SUN rmic, as it is not " | |||
+ "available. A common solution is to " | |||
+ "set the environment variable " | |||
+ "JAVA_HOME or CLASSPATH.", | |||
throw new BuildException(ERROR_NO_RMIC_ON_CLASSPATH, | |||
getRmic().getLocation()); | |||
} catch (Exception ex) { | |||
if (ex instanceof BuildException) { | |||
throw (BuildException) ex; | |||
} else { | |||
throw new BuildException("Error starting SUN rmic: ", | |||
throw new BuildException(ERROR_RMIC_FAILED, | |||
ex, getRmic().getLocation()); | |||
} | |||
} finally { | |||
@@ -29,6 +29,12 @@ import org.apache.tools.ant.types.Commandline; | |||
* @since Ant 1.4 | |||
*/ | |||
public class WLRmic extends DefaultRmicAdapter { | |||
public static final String WLRMIC_CLASSNAME = "weblogic.rmic"; | |||
public static final String ERROR_NO_WLRMIC_ON_CLASSPATH = "Cannot use WebLogic rmic, as it is not " | |||
+ "available. A common solution is to " | |||
+ "set the environment variable " | |||
+ "CLASSPATH."; | |||
public static final String ERROR_WLRMIC_FAILED = "Error starting WebLogic rmic: "; | |||
public boolean execute() throws BuildException { | |||
getRmic().log("Using WebLogic rmic", Project.MSG_VERBOSE); | |||
@@ -39,26 +45,23 @@ public class WLRmic extends DefaultRmicAdapter { | |||
// Create an instance of the rmic | |||
Class c = null; | |||
if (getRmic().getClasspath() == null) { | |||
c = Class.forName("weblogic.rmic"); | |||
c = Class.forName(WLRMIC_CLASSNAME); | |||
} else { | |||
loader | |||
= getRmic().getProject().createClassLoader(getRmic().getClasspath()); | |||
c = Class.forName("weblogic.rmic", true, loader); | |||
c = Class.forName(WLRMIC_CLASSNAME, true, loader); | |||
} | |||
Method doRmic = c.getMethod("main", | |||
new Class [] {String[].class}); | |||
doRmic.invoke(null, new Object[] {cmd.getArguments()}); | |||
return true; | |||
} catch (ClassNotFoundException ex) { | |||
throw new BuildException("Cannot use WebLogic rmic, as it is not " | |||
+ "available. A common solution is to " | |||
+ "set the environment variable " | |||
+ "CLASSPATH.", getRmic().getLocation()); | |||
throw new BuildException(ERROR_NO_WLRMIC_ON_CLASSPATH, getRmic().getLocation()); | |||
} catch (Exception ex) { | |||
if (ex instanceof BuildException) { | |||
throw (BuildException) ex; | |||
} else { | |||
throw new BuildException("Error starting WebLogic rmic: ", ex, | |||
throw new BuildException(ERROR_WLRMIC_FAILED, ex, | |||
getRmic().getLocation()); | |||
} | |||
} finally { | |||
@@ -0,0 +1,98 @@ | |||
/** (C) Copyright 2004 Hewlett-Packard Development Company, LP | |||
This library is free software; you can redistribute it and/or | |||
modify it under the terms of the GNU Lesser General Public | |||
License as published by the Free Software Foundation; either | |||
version 2.1 of the License, or (at your option) any later version. | |||
This library is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public | |||
License along with this library; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
For more information: www.smartfrog.org | |||
*/ | |||
package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.BuildFileTest; | |||
import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory; | |||
/** | |||
* Date: 04-Aug-2004 | |||
* Time: 22:15:46 | |||
*/ | |||
public class RmicAdvancedTest extends BuildFileTest { | |||
public RmicAdvancedTest(String name) { | |||
super(name); | |||
} | |||
private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/rmic/"; | |||
/** | |||
* The JUnit setup method | |||
*/ | |||
public void setUp() { | |||
configureProject(TASKDEFS_DIR + "rmic.xml"); | |||
} | |||
/** | |||
* The teardown method for JUnit | |||
*/ | |||
public void tearDown() { | |||
executeTarget("teardown"); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testRmic() throws Exception { | |||
executeTarget("testRmic"); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testKaffe() throws Exception { | |||
executeTarget("testKaffe"); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testWlrmic() throws Exception { | |||
executeTarget("testWlrmic"); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testForking() throws Exception { | |||
executeTarget("testForking"); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testBadName() throws Exception { | |||
expectBuildExceptionContaining("testBadName", | |||
"compiler not known", | |||
RmicAdapterFactory.ERROR_UNKNOWN_COMPILER); | |||
} | |||
/** | |||
* A unit test for JUnit | |||
*/ | |||
public void testWrongClass() throws Exception { | |||
expectBuildExceptionContaining("testWrongClass", | |||
"class not an RMIC adapter", | |||
RmicAdapterFactory.ERROR_NOT_RMIC_ADAPTER); | |||
} | |||
} | |||
@@ -18,9 +18,9 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.Project; | |||
import junit.framework.TestCase; | |||
/** | |||
* Testcase for <rmic>. | |||
* | |||
@@ -43,6 +43,19 @@ public class RmicTest extends TestCase { | |||
rmic.setProject(project); | |||
} | |||
/** | |||
* test for a compiler class existing | |||
* @param compilerClass | |||
* @return | |||
*/ | |||
private boolean hasCompiler(String compilerClass) { | |||
try { | |||
Class.forName(compilerClass); | |||
return true; | |||
} catch (ClassNotFoundException cnfe) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Test nested compiler args. | |||
*/ | |||
@@ -99,5 +112,4 @@ public class RmicTest extends TestCase { | |||
assertNotNull(compiler); | |||
assertEquals("kaffe", compiler); | |||
} | |||
} |