From 5cc29f61e6a8fbcf8cb8f0fe2f848955c41f486a Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Fri, 16 Mar 2001 12:57:16 +0000 Subject: [PATCH] Make a factory task just like already is. Support Kaffe's rmic. Submitted by: Takashi Okamoto Catch arbitrary Exceptions thrown when trying to verify a class. PR: 222 Support extdirs. PR: 893 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268852 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 8 + docs/manual/CoreTasks/rmic.html | 29 +- .../org/apache/tools/ant/taskdefs/Rmic.java | 387 ++++++++++-------- .../ant/taskdefs/rmic/DefaultRmicAdapter.java | 345 ++++++++++++++++ .../tools/ant/taskdefs/rmic/KaffeRmic.java | 111 +++++ .../tools/ant/taskdefs/rmic/RmicAdapter.java | 100 +++++ .../ant/taskdefs/rmic/RmicAdapterFactory.java | 144 +++++++ .../tools/ant/taskdefs/rmic/SunRmic.java | 105 +++++ 8 files changed, 1046 insertions(+), 183 deletions(-) create mode 100644 src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/rmic/KaffeRmic.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java diff --git a/WHATSNEW b/WHATSNEW index 5c7b55b3c..70b32e7d1 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -6,11 +6,19 @@ Changes that could break older environments: * Zip.setWhenempty() has changed its signature. +* is now implemented using a factory. This makes extending + rmic to use a new compiler a lot easier but may break custom + versions of this task that rely on the old implementation. + Other changes: -------------- * Ant now uses JAXP 1.1 +* rmic now supports Kaffe's version of rmic. + +* new magic property build.rmic to chose the rmic implementation + Fixed bugs: ----------- diff --git a/docs/manual/CoreTasks/rmic.html b/docs/manual/CoreTasks/rmic.html index 80f539587..6dda8619b 100644 --- a/docs/manual/CoreTasks/rmic.html +++ b/docs/manual/CoreTasks/rmic.html @@ -27,6 +27,12 @@ supports all attributes of <fileset> (dir becomes base) as well as the nested <include>, <exclude> and <patternset> elements.

+

It is possible to use different compilers. This can be selected with the +"build.rmic" property. There are two choices:

+
    +
  • sun (the standard compiler of the JDK)
  • +
  • kaffe (the standard compiler of Kaffe)
  • +

Parameters

@@ -133,12 +139,29 @@ supports all attributes of <fileset> + + + + + + + + + + + + + + +
generate debug info (passes -g to rmic). Defaults to false. No
includeAntRuntimewhether to include the Ant run-time libraries; + defaults to yes.No
includeJavaRuntimewhether to include the default run-time + libraries from the executing VM; defaults to no.No
extdirslocation of installed extensions.No

Parameters specified as nested elements

-

classpath

-

Rmic's classpath attribute is a classpath and extdirs +

Rmic's classpath and extdirs attributes are PATH like structure and can also be set via a nested -classpath elements.

+classpath and extdirs elements.

Examples

  <rmic classname="com.xyz.FooBar" base="${build}/classes"/>

runs the rmic compiler for the class com.xyz.FooBar. The diff --git a/src/main/org/apache/tools/ant/taskdefs/Rmic.java b/src/main/org/apache/tools/ant/taskdefs/Rmic.java index a020fd1d1..d01efad53 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Rmic.java +++ b/src/main/org/apache/tools/ant/taskdefs/Rmic.java @@ -58,15 +58,14 @@ import org.apache.tools.ant.AntClassLoader; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; -import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.taskdefs.rmic.*; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.util.*; -import java.io.*; -import java.util.StringTokenizer; +import java.io.File; +import java.io.IOException; import java.util.Vector; -import java.util.Date; /** * Task to compile RMI stubs and skeletons. This task can take the following @@ -81,6 +80,9 @@ import java.util.Date; *

  • iiopopts: Include IIOP options *
  • idl: Generate IDL output *
  • idlopts: Include IDL options + *
  • includeantruntime + *
  • includejavaruntime + *
  • extdirs * * Of these arguments, base is required. *

    @@ -92,15 +94,20 @@ import java.util.Date; * @author ludovic.claude@websitewatchers.co.uk * @author David Maclean david@cm.co.za * @author Stefan Bodewig + * @author Takashi Okamoto tokamoto@rd.nttdata.co.jp */ public class Rmic extends MatchingTask { + private static final String FAIL_MSG + = "Rmic failed, messages should have been provided."; + private File baseDir; private String classname; private File sourceBase; private String stubVersion; private Path compileClasspath; + private Path extdirs; private boolean verify = false; private boolean filtering = false; @@ -109,35 +116,70 @@ public class Rmic extends MatchingTask { private boolean idl = false; private String idlopts; private boolean debug = false; + private boolean includeAntRuntime = true; + private boolean includeJavaRuntime = false; private Vector compileList = new Vector(); private ClassLoader loader = null; + /** Sets the base directory to output generated class. */ public void setBase(File base) { this.baseDir = base; } + /** Gets the base directory to output generated class. */ + public File getBase() { + return this.baseDir; + } + + /** Sets the class name to compile. */ public void setClassname(String classname) { this.classname = classname; } + /** Gets the class name to compile. */ + public String getClassname() { + return classname; + } + + /** Sets the source dirs to find the source java files. */ public void setSourceBase(File sourceBase) { this.sourceBase = sourceBase; } + /** Gets the source dirs to find the source java files. */ + public File getSourceBase() { + return sourceBase; + } + + /** Sets the stub version. */ public void setStubVersion(String stubVersion) { this.stubVersion = stubVersion; } + public String getStubVersion() { + return stubVersion; + } + public void setFiltering(boolean filter) { filtering = filter; } + public boolean getFiltering() { + return filtering; + } + + /** Sets the debug flag. */ public void setDebug(boolean debug) { this.debug = debug; } + /** Gets the debug flag. */ + public boolean getDebug() { + return debug; + } + /** * Set the classpath to be used for this compilation. */ @@ -166,6 +208,13 @@ public class Rmic extends MatchingTask { createClasspath().setRefid(r); } + /** + * Gets the classpath. + */ + public Path getClasspath() { + return compileClasspath; + } + /** * Indicates that the classes found by the directory match should be * checked to see if they implement java.rmi.Remote. @@ -174,6 +223,11 @@ public class Rmic extends MatchingTask { this.verify = verify; } + /** Get verify flag. */ + public boolean getVerify() { + return verify; + } + /** * Indicates that IIOP compatible stubs should * be generated. This defaults to false @@ -183,6 +237,11 @@ public class Rmic extends MatchingTask { this.iiop = iiop; } + /** Gets iiop flags. */ + public boolean getIiop() { + return iiop; + } + /** * pass additional arguments for iiop */ @@ -190,6 +249,11 @@ public class Rmic extends MatchingTask { this.iiopopts = iiopopts; } + /** Gets additional arguments for iiop. */ + public String getIiopopts() { + return iiopopts; + } + /** * Indicates that IDL output should be * generated. This defaults to false @@ -199,6 +263,11 @@ public class Rmic extends MatchingTask { this.idl = idl; } + /* Gets IDL flags. */ + public boolean getIdl() { + return idl; + } + /** * pass additional arguments for idl compile */ @@ -206,6 +275,83 @@ public class Rmic extends MatchingTask { this.idlopts = idlopts; } + /** + * Gets additional arguments for idl compile. + */ + public String getIdlopts() { + return idlopts; + } + + /** Gets file list to compile. */ + public Vector getFileList() { + return compileList; + } + + /** + * Include ant's own classpath in this task's classpath? + */ + public void setIncludeantruntime( boolean include ) { + includeAntRuntime = include; + } + + /** + * Gets whether or not the ant classpath is to be included in the + * task's classpath. + */ + public boolean getIncludeantruntime() { + return includeAntRuntime; + } + + /** + * Sets whether or not to include the java runtime libraries to this + * task's classpath. + */ + public void setIncludejavaruntime( boolean include ) { + includeJavaRuntime = include; + } + + /** + * Gets whether or not the java runtime should be included in this + * task's classpath. + */ + public boolean getIncludejavaruntime() { + return includeJavaRuntime; + } + + /** + * Sets the extension directories that will be used during the + * compilation. + */ + public void setExtdirs(Path extdirs) { + if (this.extdirs == null) { + this.extdirs = extdirs; + } else { + this.extdirs.append(extdirs); + } + } + + /** + * Maybe creates a nested extdirs element. + */ + public Path createExtdirs() { + if (extdirs == null) { + extdirs = new Path(project); + } + return extdirs.createPath(); + } + + /** + * Gets the extension directories that will be used during the + * compilation. + */ + public Path getExtdirs() { + return extdirs; + } + + public Vector getCompileList() { + return compileList; + } + public void execute() throws BuildException { if (baseDir == null) { throw new BuildException("base attribute must be set!", location); @@ -217,20 +363,11 @@ public class Rmic extends MatchingTask { if (verify) { log("Verify has been turned on.", Project.MSG_INFO); } - if (iiop) { - log("IIOP has been turned on.", Project.MSG_INFO); - if( iiopopts != null ) { - log("IIOP Options: " + iiopopts, Project.MSG_INFO ); - } - } - if (idl) { - log("IDL has been turned on.", Project.MSG_INFO); - if( idlopts != null ) { - log("IDL Options: " + idlopts, Project.MSG_INFO ); - } - } - Path classpath = getCompileClasspath(baseDir); + String compiler = project.getProperty("build.rmic"); + RmicAdapter adapter = RmicAdapterFactory.getRmic(compiler, this ); + + Path classpath = adapter.getClasspath(); loader = new AntClassLoader(project, classpath); // scan base dirs to build up compile lists only if a @@ -238,61 +375,27 @@ public class Rmic extends MatchingTask { if (classname == null) { DirectoryScanner ds = this.getDirectoryScanner(baseDir); String[] files = ds.getIncludedFiles(); - scanDir(baseDir, files); + scanDir(baseDir, files, adapter.getMapper()); } else { // otherwise perform a timestamp comparison - at least scanDir(baseDir, - new String[] {classname.replace('.', File.separatorChar) + ".class"}); + new String[] {classname.replace('.', File.separatorChar) + ".class"}, + adapter.getMapper()); } - // XXX - // need to provide an input stream that we read in from! - - OutputStream logstr = new LogOutputStream(this, Project.MSG_WARN); - sun.rmi.rmic.Main compiler = new sun.rmi.rmic.Main(logstr, "rmic"); - Commandline cmd = new Commandline(); - - cmd.createArgument().setValue("-d"); - cmd.createArgument().setFile(baseDir); - cmd.createArgument().setValue("-classpath"); - cmd.createArgument().setPath(classpath); - if (null != stubVersion) { - if ("1.1".equals(stubVersion)) - cmd.createArgument().setValue("-v1.1"); - else if ("1.2".equals(stubVersion)) - cmd.createArgument().setValue("-v1.2"); - else - cmd.createArgument().setValue("-vcompat"); - } - if (null != sourceBase) - cmd.createArgument().setValue("-keepgenerated"); - - if( iiop ) { - cmd.createArgument().setValue("-iiop"); - if( iiopopts != null ) - cmd.createArgument().setValue(iiopopts); - } - - if( idl ) { - cmd.createArgument().setValue("-idl"); - if( idlopts != null ) - cmd.createArgument().setValue(idlopts); - } - if( debug ) { - cmd.createArgument().setValue("-g"); - } - int fileCount = compileList.size(); if (fileCount > 0) { log("RMI Compiling " + fileCount + " class"+ (fileCount > 1 ? "es" : "")+" to " + baseDir, Project.MSG_INFO); - for (int j = 0; j < fileCount; j++) { - cmd.createArgument().setValue((String) compileList.elementAt(j)); + // now we need to populate the compiler adapter + adapter.setRmic( this ); + + // finally, lets execute the compiler!! + if (!adapter.execute()) { + throw new BuildException(FAIL_MSG, location); } - log("Compilation args: " + cmd.toString(), Project.MSG_VERBOSE); - compiler.compile(cmd.getArguments()); } // Move the generated source file to the base directory @@ -310,7 +413,7 @@ public class Rmic extends MatchingTask { * @exception org.apache.tools.ant.BuildException When error copying/removing files. */ private void moveGeneratedFile (File baseDir, File sourceBaseFile, String classname) - throws BuildException { + throws BuildException { String stubFileName = classname.replace('.', File.separatorChar) + "_Stub.java"; File oldStubFile = new File(baseDir, stubFileName); File newStubFile = new File(sourceBaseFile, stubFileName); @@ -331,7 +434,7 @@ public class Rmic extends MatchingTask { oldSkelFile.delete(); } catch (IOException ioe) { String msg = "Failed to copy " + oldSkelFile + " to " + - newSkelFile + " due to " + ioe.getMessage(); + newSkelFile + " due to " + ioe.getMessage(); throw new BuildException(msg, ioe, location); } } @@ -341,144 +444,68 @@ public class Rmic extends MatchingTask { * Scans the directory looking for class files to be compiled. * The result is returned in the class variable compileList. */ - - protected void scanDir(File baseDir, String files[]) { + protected void scanDir(File baseDir, String files[], + FileNameMapper mapper) { SourceFileScanner sfs = new SourceFileScanner(this); - String[] newFiles = sfs.restrict(files, baseDir, baseDir, - new RmicFileNameMapper()); + String[] newFiles = sfs.restrict(files, baseDir, baseDir, mapper); for (int i = 0; i < newFiles.length; i++) { String classname = newFiles[i].replace(File.separatorChar, '.'); classname = classname.substring(0, classname.indexOf(".class")); compileList.addElement(classname); } } - + /** - * Builds the compilation classpath. + * Load named class and test whether it can be rmic'ed */ - - // XXX - // we need a way to not use the current classpath. - - private Path getCompileClasspath(File baseFile) { - // add dest dir to classpath so that previously compiled and - // untouched classes are on classpath - Path classpath = new Path(project, baseFile.getAbsolutePath()); - - // Combine the build classpath with the system classpath, in an - // order determined by the value of build.classpath - if (compileClasspath == null) { - classpath.addExisting(Path.systemClasspath); - } else { - classpath.addExisting(compileClasspath.concatSystemClasspath()); - } - - // in jdk 1.2, the system classes are not on the visible classpath. - if (Project.getJavaVersion().startsWith("1.2")) { - String bootcp = System.getProperty("sun.boot.class.path"); - if (bootcp != null) { - classpath.addExisting(new Path(project, bootcp)); + public boolean isValidRmiRemote(String classname) { + try { + Class testClass = loader.loadClass(classname); + // One cannot RMIC an interface + if (testClass.isInterface()) { + return false; } + return isValidRmiRemote(testClass); + } catch (ClassNotFoundException e) { + log("Unable to verify class " + classname + + ". It could not be found.", Project.MSG_WARN); + } catch (NoClassDefFoundError e) { + log("Unable to verify class " + classname + + ". It is not defined.", Project.MSG_WARN); + } catch (Throwable t) { + log("Unable to verify class " + classname + + ". Loading caused Exception: " + + t.getMessage(), Project.MSG_WARN); } - return classpath; + // we only get here if an exception has been thrown + return false; } /** - * Mapper that possibly returns two file names, *_Stub and *_Skel. + * Check to see if the class or (super)interfaces implement + * java.rmi.Remote. */ - private class RmicFileNameMapper implements FileNameMapper { - - private GlobPatternMapper stubMapper; - private GlobPatternMapper skelMapper; - - RmicFileNameMapper() { - stubMapper = new GlobPatternMapper(); - stubMapper.setFrom("*.class"); - stubMapper.setTo("*_Stub.class"); - - // no _Skel file in stub version 1.2 - if (!"1.2".equals(stubVersion)) { - skelMapper = new GlobPatternMapper(); - skelMapper.setFrom("*.class"); - skelMapper.setTo("*_Skel.class"); - } - } - - /** - * Empty implementation. - */ - public void setFrom(String s) {} - /** - * Empty implementation. - */ - public void setTo(String s) {} - - public String[] mapFileName(String name) { - String[] stubName = stubMapper.mapFileName(name); - - if (stubName == null || name.endsWith("_Stub.class") - || name.endsWith("_Skel.class")) { - // Not a .class file - return null; - } - - String classname = name.replace(File.separatorChar, '.'); - classname = classname.substring(0, classname.indexOf(".class")); - if (verify) { - try { - Class testClass = loader.loadClass(classname); - // One cannot RMIC an interface - if (testClass.isInterface() || - !isValidRmiRemote(testClass)) { - return null; - } - } catch (ClassNotFoundException e) { - log("Unable to verify class " + classname + - ". It could not be found.", Project.MSG_WARN); - } catch (NoClassDefFoundError e) { - log("Unable to verify class " + classname + - ". It is not defined.", Project.MSG_WARN); - } - } - - if (skelMapper != null) { - return new String[] { - stubName[0], - skelMapper.mapFileName(name)[0] - }; - } else { - return stubName; - } + private boolean isValidRmiRemote (Class testClass) { + Class rmiRemote = java.rmi.Remote.class; + + if (rmiRemote.equals(testClass)) { + // This class is java.rmi.Remote + return true; } - - /** - * Check to see if the class or superclasses/interfaces implement - * java.rmi.Remote. - */ - private boolean isValidRmiRemote (Class testClass) { - Class rmiRemote = java.rmi.Remote.class; - - if (rmiRemote.equals(testClass)) { - // This class is java.rmi.Remote - return true; - } - Class [] interfaces = testClass.getInterfaces(); - if (interfaces != null) { - for (int i = 0; i < interfaces.length; i++) { - if (rmiRemote.equals(interfaces[i])) { - // This class directly implements java.rmi.Remote - return true; - } - if (isValidRmiRemote(interfaces[i])) { - return true; - } + Class [] interfaces = testClass.getInterfaces(); + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + if (rmiRemote.equals(interfaces[i])) { + // This class directly implements java.rmi.Remote + return true; + } + if (isValidRmiRemote(interfaces[i])) { + return true; } } - return false; } - + return false; } - } diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java b/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java new file mode 100644 index 000000000..faad14e3f --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/DefaultRmicAdapter.java @@ -0,0 +1,345 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.rmic; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.taskdefs.*; +import org.apache.tools.ant.types.*; +import org.apache.tools.ant.util.*; + +import java.io.File; +import java.util.Vector; + +/** + * This is the default implementation for the RmicAdapter interface. + * Currently, this is a cut-and-paste of the original rmic task and + * DefaultCopmpilerAdapter. + * + * @author duncan@x180.com + * @author ludovic.claude@websitewatchers.co.uk + * @author David Maclean david@cm.co.za + * @author Stefan Bodewig + * @author Takashi Okamoto + */ +public abstract class DefaultRmicAdapter implements RmicAdapter { + + private Rmic attributes; + + public void setRmic( Rmic attributes ) { + this.attributes = attributes; + } + + public Rmic getRmic() { + return attributes; + } + + /** + * This implementation maps *.class to *_Stub.class and - if + * stubversion is not 1.2 - to _Skel.class. + */ + public FileNameMapper getMapper() { + return new RmicFileNameMapper(); + } + + /** + * The CLASSPATH this rmic process will use. + */ + public Path getClasspath() { + return getCompileClasspath(); + } + + /** + * Builds the compilation classpath. + */ + protected Path getCompileClasspath() { + // add dest dir to classpath so that previously compiled and + // untouched classes are on classpath + Path classpath = new Path(attributes.getProject()); + classpath.setLocation(attributes.getBase()); + + // Combine the build classpath with the system classpath, in an + // order determined by the value of build.classpath + + if (attributes.getClasspath() == null) { + if ( attributes.getIncludeantruntime() ) { + classpath.addExisting(Path.systemClasspath); + } + } else { + if ( attributes.getIncludeantruntime() ) { + classpath.addExisting(attributes.getClasspath().concatSystemClasspath("last")); + } else { + classpath.addExisting(attributes.getClasspath().concatSystemClasspath("ignore")); + } + } + + if (attributes.getIncludejavaruntime()) { + if (System.getProperty("java.vendor").toLowerCase().indexOf("microsoft") >= 0) { + // Pull in *.zip from packages directory + FileSet msZipFiles = new FileSet(); + msZipFiles.setDir(new File(System.getProperty("java.home") + File.separator + "Packages")); + msZipFiles.setIncludes("*.ZIP"); + classpath.addFileset(msZipFiles); + } else if (Project.getJavaVersion() == Project.JAVA_1_1) { + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator + "lib" + + File.separator + + "classes.zip")); + } else if(System.getProperty("java.vm.name").equals("Kaffe")) { + FileSet kaffeJarFiles = new FileSet(); + kaffeJarFiles.setDir(new File(System.getProperty("java.home") + + File.separator + "share" + + File.separator + "kaffe")); + + kaffeJarFiles.setIncludes("*.jar"); + classpath.addFileset(kaffeJarFiles); + } else { + // JDK > 1.1 seems to set java.home to the JRE directory. + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator + "lib" + + File.separator + "rt.jar")); + // Just keep the old version as well and let addExistingToPath + // sort it out. + classpath.addExisting(new Path(null, + System.getProperty("java.home") + + File.separator +"jre" + + File.separator + "lib" + + File.separator + "rt.jar")); + } + } + return classpath; + } + + /** + * setup rmic argument for rmic. + */ + protected Commandline setupRmicCommand() { + Commandline cmd = new Commandline(); + Path classpath = getCompileClasspath(); + + cmd.createArgument().setValue("-d"); + cmd.createArgument().setFile(attributes.getBase()); + + if (attributes.getExtdirs() != null) { + if (Project.getJavaVersion().startsWith("1.1")) { + /* + * XXX - This doesn't mix very well with build.systemclasspath, + */ + addExtdirsToClasspath(classpath); + } else { + cmd.createArgument().setValue("-extdirs"); + cmd.createArgument().setPath(attributes.getExtdirs()); + } + } + + cmd.createArgument().setValue("-classpath"); + cmd.createArgument().setPath(classpath); + + String stubVersion = attributes.getStubVersion(); + if (null != stubVersion) { + if ("1.1".equals(stubVersion)) + cmd.createArgument().setValue("-v1.1"); + else if ("1.2".equals(stubVersion)) + cmd.createArgument().setValue("-v1.2"); + else + cmd.createArgument().setValue("-vcompat"); + } + + if (null != attributes.getSourceBase()) { + cmd.createArgument().setValue("-keepgenerated"); + } + + if( attributes.getIiop() ) { + attributes.log("IIOP has been turned on.", Project.MSG_INFO); + cmd.createArgument().setValue("-iiop"); + if( attributes.getIiopopts() != null ) { + attributes.log("IIOP Options: " + attributes.getIiopopts(), + Project.MSG_INFO ); + cmd.createArgument().setValue(attributes.getIiopopts()); + } + } + + if( attributes.getIdl() ) { + cmd.createArgument().setValue("-idl"); + attributes.log("IDL has been turned on.", Project.MSG_INFO); + if( attributes.getIdlopts() != null ) { + cmd.createArgument().setValue(attributes.getIdlopts()); + attributes.log("IDL Options: " + attributes.getIdlopts(), + Project.MSG_INFO ); + } + } + + if( attributes.getDebug()) { + cmd.createArgument().setValue("-g"); + } + + logAndAddFilesToCompile(cmd); + return cmd; + } + + /** + * Logs the compilation parameters, adds the files to compile and logs the + * &qout;niceSourceList" + */ + protected void logAndAddFilesToCompile(Commandline cmd) { + Vector compileList = attributes.getCompileList(); + + attributes.log("Compilation args: " + cmd.toString(), + Project.MSG_VERBOSE); + + StringBuffer niceSourceList = new StringBuffer("File"); + if (compileList.size() != 1) { + niceSourceList.append("s"); + } + niceSourceList.append(" to be compiled:"); + + for (int i=0; i < compileList.size(); i++) { + String arg = (String)compileList.get(i); + cmd.createArgument().setValue(arg); + niceSourceList.append(" " + arg); + } + + attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE); + } + + /** + * Emulation of extdirs feature in java >= 1.2. + * This method adds all files in the given + * directories (but not in sub-directories!) to the classpath, + * so that you don't have to specify them all one by one. + * @param classpath - Path to append files to + */ + protected void addExtdirsToClasspath(Path classpath) { + Path extdirs = attributes.getExtdirs(); + if (extdirs == null) { + String extProp = System.getProperty("java.ext.dirs"); + if (extProp != null) { + extdirs = new Path(attributes.getProject(), extProp); + } else { + return; + } + } + + String[] dirs = extdirs.list(); + for (int i=0; i. + */ + +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.LogOutputStream; +import org.apache.tools.ant.types.Commandline; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * The implementation of the rmic for Kaffe + * + * @author Takashi Okamoto + */ +public class KaffeRmic extends DefaultRmicAdapter { + + public boolean execute() throws BuildException { + getRmic().log("Using Kaffe rmic", Project.MSG_VERBOSE); + Commandline cmd = setupRmicCommand(); + + PrintStream err = System.err; + PrintStream out = System.out; + + try { + // the project log + PrintStream logstr = + new PrintStream(new LogOutputStream(getRmic(), Project.MSG_WARN)); + System.setOut(logstr); + System.setErr(logstr); + + Class c = Class.forName("kaffe.rmi.rmic.RMIC"); + Constructor cons = c.getConstructor(new Class[] { String[].class }); + Object rmic = cons.newInstance(new Object[] { cmd.getArguments() }); + Method doRmic = c.getMethod("run", null); + String str[] = cmd.getArguments(); + Boolean ok = (Boolean)doRmic.invoke(rmic, null); + + return ok.booleanValue(); + } catch (ClassNotFoundException ex) { + throw new BuildException("Cannot use Kaffe rmic, as it is not available"+ + " A common solution is to set the environment variable"+ + " JAVA_HOME or CLASSPATH.", getRmic().getLocation() ); + } + catch (Exception ex) { + if (ex instanceof BuildException) { + throw (BuildException) ex; + } else { + throw new BuildException("Error starting Kaffe rmic: ", ex, getRmic().getLocation()); + } + } finally { + System.setErr(err); + System.setOut(out); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java new file mode 100644 index 000000000..7e044b032 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapter.java @@ -0,0 +1,100 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.rmic; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Rmic; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.FileNameMapper; + +/** + * The interface that all rmic adapters must adher to. + * + *

    A rmic adapter is an adapter that interprets the rmic's + * parameters in preperation to be passed off to the compiler this + * adapter represents. As all the necessary values are stored in the + * Rmic task itself, the only thing all adapters need is the rmic + * task, the execute command and a parameterless constructor (for + * reflection).

    + * + * @author Takashi Okamoto + * @author Stefan Bodewig + */ + +public interface RmicAdapter { + + /** + * Sets the rmic attributes, which are stored in the Rmic task. + */ + public void setRmic( Rmic attributes ); + + /** + * Executes the task. + * + * @return has the compilation been successful + */ + public boolean execute() throws BuildException; + + /** + * Maps source class files to the files generated by this rmic + * implementation. + */ + public FileNameMapper getMapper(); + + /** + * The CLASSPATH this rmic process will use. + */ + public Path getClasspath(); +} diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java new file mode 100644 index 000000000..e8dc4e586 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/RmicAdapterFactory.java @@ -0,0 +1,144 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.rmic; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.Project; + +/** + * Creates the necessary rmic adapter, given basic criteria. + * + * @author Takashi Okamoto + * @author J D Glanville + */ +public class RmicAdapterFactory { + + /** This is a singlton -- can't create instances!! */ + private RmicAdapterFactory() { + } + + /** + * Based on the parameter passed in, this method creates the necessary + * factory desired. + * + * The current mapping for rmic names are as follows: + *
    • sun = SUN's rmic + *
    • kaffe = Kaffe's rmic + *
    • a fully quallified classname = the name of a rmic + * adapter + *
    + * + * @param rmicType either the name of the desired rmic, or the + * full classname of the rmic's adapter. + * @param task a task to log through. + * @throws BuildException if the rmic type could not be resolved into + * a rmic adapter. + */ + public static RmicAdapter getRmic( String rmicType, Task task ) + throws BuildException { + if( rmicType == null){ + /* + * When not specified rmicType, search SUN's rmic and + * Kaffe's rmic. + */ + try { + Class.forName("sun.rmi.rmic.Main"); + rmicType = "sun"; + } catch (ClassNotFoundException cnfe) { + try { + Class.forName("kaffe.rmi.rmic.RMIC"); + Class.forName("kaffe.tools.compiler.Compiler"); + rmicType = "kaffe"; + } catch (ClassNotFoundException cnfk) { + throw new BuildException("Couldn\'t guess rmic implementation"); + } + } + } + + if ( rmicType.equalsIgnoreCase("sun") ) { + return new SunRmic(); + } if ( rmicType.equalsIgnoreCase("kaffe") ) { + return new KaffeRmic(); + } + return resolveClassName( rmicType ); + } + + /** + * Tries to resolve the given classname into a rmic adapter. + * Throws a fit if it can't. + * + * @param className The fully qualified classname to be created. + * @throws BuildException This is the fit that is thrown if className + * isn't an instance of RmicAdapter. + */ + private static RmicAdapter resolveClassName( String className ) + throws BuildException { + try { + Class c = Class.forName( className ); + Object o = c.newInstance(); + return (RmicAdapter) o; + } catch ( ClassNotFoundException cnfe ) { + throw new BuildException( className + " can\'t be found.", cnfe ); + } catch ( ClassCastException cce ) { + throw new BuildException(className + " isn\'t the classname of " + + "a rmic adapter.", cce); + } catch ( Throwable t ) { + // for all other possibilities + throw new BuildException(className + " caused an interesting " + + "exception.", t); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java new file mode 100644 index 000000000..9cb7aa87a --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/rmic/SunRmic.java @@ -0,0 +1,105 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +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.LogOutputStream; +import org.apache.tools.ant.types.Commandline; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * The implementation of the rmic for SUN's JDK. + * + * @author Takashi Okamoto + */ +public class SunRmic extends DefaultRmicAdapter { + + public boolean execute() throws BuildException { + getRmic().log("Using SUN rmic compiler", Project.MSG_VERBOSE); + Commandline cmd = setupRmicCommand(); + + try { + // Create an instance of the rmic, redirecting output to + // the project log + OutputStream logstr = new LogOutputStream(getRmic(), Project.MSG_WARN); + + Class c = Class.forName("sun.rmi.rmic.Main"); + Constructor cons = c.getConstructor(new Class[] + { OutputStream.class, String.class }); + Object rmic = cons.newInstance(new Object[] { logstr, "rmic" }); + + Method doRmic = c.getMethod("compile", + new Class [] { String[].class }); + Boolean ok = (Boolean)doRmic.invoke(rmic, + (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.", getRmic().getLocation() ); + } + catch (Exception ex) { + if (ex instanceof BuildException) { + throw (BuildException) ex; + } else { + throw new BuildException("Error starting SUN rmic: ", ex, getRmic().getLocation()); + } + } + } +}