diff --git a/docs/manual/CoreTasks/rmic.html b/docs/manual/CoreTasks/rmic.html index 9d1b2b9ca..32f67efae 100644 --- a/docs/manual/CoreTasks/rmic.html +++ b/docs/manual/CoreTasks/rmic.html @@ -37,6 +37,7 @@ attribute. There are three choices:

  • sun (the standard compiler of the JDK)
  • kaffe (the standard compiler of Kaffe)
  • weblogic
  • +
  • forking - the sun compiler forked into a separate process
  • The miniRMI diff --git a/src/etc/testcases/taskdefs/rmic/rmic.xml b/src/etc/testcases/taskdefs/rmic/rmic.xml new file mode 100644 index 000000000..42bb33416 --- /dev/null +++ b/src/etc/testcases/taskdefs/rmic/rmic.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java new file mode 100644 index 000000000..ecc0a9e7c --- /dev/null +++ b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java @@ -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 ; +} + diff --git a/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java new file mode 100644 index 000000000..837288d84 --- /dev/null +++ b/src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java @@ -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(); + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/Rmic.java b/src/main/org/apache/tools/ant/taskdefs/Rmic.java index da671f049..447e35e24 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Rmic.java +++ b/src/main/org/apache/tools/ant/taskdefs/Rmic.java @@ -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 diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java new file mode 100644 index 000000000..19cb695ec --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java @@ -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); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java index 0da3a7364..fad6a19e9 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java @@ -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; + } + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java index c60ff8a33..5fdde50af 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java @@ -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. * *

    A rmic adapter is an adapter that interprets the rmic's * parameters in preperation to be passed off to the compiler this 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 30513a787..73b6d129b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java @@ -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 { *

  • kaffe = Kaffe's rmic *
  • a fully quallified classname = the name of a rmic * adapter + *
  • weblogic = weblogic compiler + *
  • forking = Sun's RMIC by forking a new JVM * * * @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 " diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java index 2df1dd0c4..1ed994672 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java @@ -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 { diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java index d0077fba8..e3f1fc661 100644 --- a/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java @@ -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 { diff --git a/src/testcases/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java b/src/testcases/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java new file mode 100644 index 000000000..67a1acf65 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java @@ -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); + } +} + diff --git a/src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java b/src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java index a38a68029..96e785270 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java @@ -18,9 +18,9 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.Project; - import junit.framework.TestCase; + /** * Testcase for . * @@ -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); } - }