Browse Source

rmic gets a fork option.

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-ffa450edef68
master
Steve Loughran 21 years ago
parent
commit
fdf4bba148
13 changed files with 374 additions and 35 deletions
  1. +1
    -0
      docs/manual/CoreTasks/rmic.html
  2. +89
    -0
      src/etc/testcases/taskdefs/rmic/rmic.xml
  3. +10
    -0
      src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java
  4. +12
    -0
      src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java
  5. +21
    -15
      src/main/org/apache/tools/ant/taskdefs/Rmic.java
  6. +74
    -0
      src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java
  7. +16
    -1
      src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java
  8. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java
  9. +10
    -3
      src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java
  10. +18
    -6
      src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java
  11. +10
    -7
      src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java
  12. +98
    -0
      src/testcases/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java
  13. +14
    -2
      src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java

+ 1
- 0
docs/manual/CoreTasks/rmic.html View File

@@ -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>


+ 89
- 0
src/etc/testcases/taskdefs/rmic/rmic.xml View File

@@ -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>

+ 10
- 0
src/etc/testcases/taskdefs/rmic/src/RemoteTimestamp.java View File

@@ -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 ;
}


+ 12
- 0
src/etc/testcases/taskdefs/rmic/src/RemoteTimestampImpl.java View File

@@ -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();
}
}

+ 21
- 15
src/main/org/apache/tools/ant/taskdefs/Rmic.java View File

@@ -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


+ 74
- 0
src/main/org/apache/tools/ant/taskdefs/rmic/ForkingSunRmic.java View File

@@ -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);
}
}
}

+ 16
- 1
src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java View File

@@ -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;
}
}
}

+ 1
- 1
src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java View File

@@ -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


+ 10
- 3
src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java View File

@@ -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 "


+ 18
- 6
src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java View File

@@ -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 {


+ 10
- 7
src/main/org/apache/tools/ant/taskdefs/rmic/WLRmic.java View File

@@ -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 {


+ 98
- 0
src/testcases/org/apache/tools/ant/taskdefs/RmicAdvancedTest.java View File

@@ -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);
}
}


+ 14
- 2
src/testcases/org/apache/tools/ant/taskdefs/RmicTest.java View File

@@ -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);
}

}

Loading…
Cancel
Save