diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Rmic.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Rmic.java | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Rmic.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Rmic.java new file mode 100644 index 00000000..6935f9e3 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Rmic.java @@ -0,0 +1,853 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs; + +import java.io.File; +import java.io.IOException; +import java.rmi.Remote; +import java.util.Vector; + +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.taskdefs.rmic.RmicAdapter; +import org.apache.tools.ant.taskdefs.rmic.RmicAdapterFactory; +import org.apache.tools.ant.types.FilterSetCollection; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.util.FileNameMapper; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.SourceFileScanner; +import org.apache.tools.ant.util.StringUtils; +import org.apache.tools.ant.util.facade.FacadeTaskHelper; + +/** + * <p>Runs the rmic compiler against classes.</p> + * + * <p>Rmic can be run on a single class (as specified with the classname + * attribute) or a number of classes at once (all classes below base that + * are neither _Stub nor _Skel classes). If you want to rmic a single + * class and this class is a class nested into another class, you have to + * specify the classname in the form <code>Outer$$Inner</code> instead of + * <code>Outer.Inner</code>.</p> + * + * <p>It is possible to refine the set of files that are being rmiced. This can + * be done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, + * <i>excludesfile</i> and <i>defaultexcludes</i> + * attributes. With the <i>includes</i> or <i>includesfile</i> attribute you + * specify the files you want to have included by using patterns. The + * <i>exclude</i> or <i>excludesfile</i> attribute is used to specify + * the files you want to have excluded. This is also done with patterns. And + * finally with the <i>defaultexcludes</i> attribute, you can specify whether + * you want to use default exclusions or not. See the section on + * directory based tasks, on how the + * inclusion/exclusion of files works, and how to write patterns.</p> + * + * <p>This task forms an implicit FileSet and + * supports all attributes of <code><fileset></code> + * (<code>dir</code> becomes <code>base</code>) as well as the nested + * <code><include></code>, <code><exclude></code> and + * <code><patternset></code> elements.</p> + * + * <p>It is possible to use different compilers. This can be selected + * with the "build.rmic" property or the <code>compiler</code> + * attribute. <a name="compilervalues">There are three choices</a>:</p> + * + * <ul> + * <li>sun (the standard compiler of the JDK)</li> + * <li>kaffe (the standard compiler of + * {@link <a href="http://www.kaffe.org">Kaffe</a>})</li> + * <li>weblogic</li> + * </ul> + * + * <p> The <a href="http://dione.zcu.cz/~toman40/miniRMI/">miniRMI</a> + * project contains a compiler implementation for this task as well, + * please consult miniRMI's documentation to learn how to use it.</p> + * + * @since Ant 1.1 + * + * @ant.task category="java" + */ + +public class Rmic extends MatchingTask { + + /** rmic failed message */ + public static final String ERROR_RMIC_FAILED + = "Rmic failed; see the compiler error output for details."; + + private File baseDir; + private File destDir; + private String classname; + private File sourceBase; + private String stubVersion; + private Path compileClasspath; + private Path extDirs; + private boolean verify = false; + private boolean filtering = false; + + private boolean iiop = false; + private String iiopOpts; + 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 AntClassLoader loader = null; + + private FacadeTaskHelper facade; + /** unable to verify message */ + public static final String ERROR_UNABLE_TO_VERIFY_CLASS = "Unable to verify class "; + /** could not be found message */ + public static final String ERROR_NOT_FOUND = ". It could not be found."; + /** not defined message */ + public static final String ERROR_NOT_DEFINED = ". It is not defined."; + /** loaded error message */ + public static final String ERROR_LOADING_CAUSED_EXCEPTION = ". Loading caused Exception: "; + /** base not exists message */ + public static final String ERROR_NO_BASE_EXISTS = "base or destdir does not exist: "; + /** base not a directory message */ + public static final String ERROR_NOT_A_DIR = "base or destdir is not a directory:"; + /** base attribute not set message */ + public static final String ERROR_BASE_NOT_SET = "base or destdir attribute must be set!"; + + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + private String executable = null; + + private boolean listFiles = false; + + private RmicAdapter nestedAdapter = null; + + /** + * Constructor for Rmic. + */ + public Rmic() { + facade = new FacadeTaskHelper(RmicAdapterFactory.DEFAULT_COMPILER); + } + + /** + * Sets the location to store the compiled files; required + * @param base the location to store the compiled files + */ + public void setBase(File base) { + this.baseDir = base; + } + + /** + * Sets the base directory to output the generated files. + * @param destdir the base directory to output the generated files. + * @since Ant 1.8.0 + */ + public void setDestdir(File destdir) { + this.destDir = destdir; + } + + /** + * Gets the base directory to output the generated files. + * @return the base directory to output the generated files. + * @since Ant 1.8.0 + */ + public File getDestdir() { + return this.destDir; + } + + /** + * Gets the base directory to output the generated files, + * favoring destdir if set, otherwise defaulting to basedir. + * @return the actual directory to output to (either destdir or basedir) + * @since Ant 1.8.0 + */ + public File getOutputDir() { + if (getDestdir() != null) { + return getDestdir(); + } + return getBase(); + } + + /** + * Gets the base directory to output generated class. + * @return the location of the compiled files + */ + public File getBase() { + return this.baseDir; + } + + /** + * Sets the class to run <code>rmic</code> against; + * optional + * @param classname the name of the class for rmic to create code for + */ + public void setClassname(String classname) { + this.classname = classname; + } + + /** + * Gets the class name to compile. + * @return the name of the class to compile + */ + public String getClassname() { + return classname; + } + + /** + * optional directory to save generated source files to. + * @param sourceBase the directory to save source files to. + */ + public void setSourceBase(File sourceBase) { + this.sourceBase = sourceBase; + } + + /** + * Gets the source dirs to find the source java files. + * @return sourceBase the directory containing the source files. + */ + public File getSourceBase() { + return sourceBase; + } + + /** + * Specify the JDK version for the generated stub code. + * Specify "1.1" to pass the "-v1.1" option to rmic. + * @param stubVersion the JDK version + */ + public void setStubVersion(String stubVersion) { + this.stubVersion = stubVersion; + } + + /** + * Gets the JDK version for the generated stub code. + * @return stubVersion + */ + public String getStubVersion() { + return stubVersion; + } + + /** + * Sets token filtering [optional], default=false + * @param filter turn on token filtering + */ + public void setFiltering(boolean filter) { + this.filtering = filter; + } + + /** + * Gets whether token filtering is set + * @return filtering + */ + public boolean getFiltering() { + return filtering; + } + + /** + * Generate debug info (passes -g to rmic); + * optional, defaults to false + * @param debug turn on debug info + */ + public void setDebug(boolean debug) { + this.debug = debug; + } + + /** + * Gets the debug flag. + * @return debug + */ + public boolean getDebug() { + return debug; + } + + /** + * Set the classpath to be used for this compilation. + * @param classpath the classpath used for this compilation + */ + public synchronized void setClasspath(Path classpath) { + if (compileClasspath == null) { + compileClasspath = classpath; + } else { + compileClasspath.append(classpath); + } + } + + /** + * Creates a nested classpath element. + * @return classpath + */ + public synchronized Path createClasspath() { + if (compileClasspath == null) { + compileClasspath = new Path(getProject()); + } + return compileClasspath.createPath(); + } + + /** + * Adds to the classpath a reference to + * a <path> defined elsewhere. + * @param pathRef the reference to add to the classpath + */ + public void setClasspathRef(Reference pathRef) { + createClasspath().setRefid(pathRef); + } + + /** + * Gets the classpath. + * @return the classpath + */ + public Path getClasspath() { + return compileClasspath; + } + + /** + * Flag to enable verification so that the classes + * found by the directory match are + * checked to see if they implement java.rmi.Remote. + * optional; This defaults to false if not set. + * @param verify turn on verification for classes + */ + public void setVerify(boolean verify) { + this.verify = verify; + } + + /** + * Get verify flag. + * @return verify + */ + public boolean getVerify() { + return verify; + } + + /** + * Indicates that IIOP compatible stubs should + * be generated; optional, defaults to false + * if not set. + * @param iiop generate IIOP compatible stubs + */ + public void setIiop(boolean iiop) { + this.iiop = iiop; + } + + /** + * Gets iiop flags. + * @return iiop + */ + public boolean getIiop() { + return iiop; + } + + /** + * Set additional arguments for iiop + * @param iiopOpts additional arguments for iiop + */ + public void setIiopopts(String iiopOpts) { + this.iiopOpts = iiopOpts; + } + + /** + * Gets additional arguments for iiop. + * @return iiopOpts + */ + public String getIiopopts() { + return iiopOpts; + } + + /** + * Indicates that IDL output should be + * generated. This defaults to false + * if not set. + * @param idl generate IDL output + */ + public void setIdl(boolean idl) { + this.idl = idl; + } + + /** + * Gets IDL flags. + * @return the idl flag + */ + public boolean getIdl() { + return idl; + } + + /** + * pass additional arguments for IDL compile + * @param idlOpts additional IDL arguments + */ + public void setIdlopts(String idlOpts) { + this.idlOpts = idlOpts; + } + + /** + * Gets additional arguments for idl compile. + * @return the idl options + */ + public String getIdlopts() { + return idlOpts; + } + + /** + * Gets file list to compile. + * @return the list of files to compile. + */ + public Vector getFileList() { + return compileList; + } + + /** + * Sets whether or not to include ant's own classpath in this task's + * classpath. + * Optional; default is <code>true</code>. + * @param include if true include ant'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. + * @return true if ant's classpath is to be included + */ + public boolean getIncludeantruntime() { + return includeAntRuntime; + } + + /** + * task's classpath. + * Enables or disables including the default run-time + * libraries from the executing VM; optional, + * defaults to false + * @param include if true include default run-time libraries + */ + public void setIncludejavaruntime(boolean include) { + includeJavaRuntime = include; + } + + /** + * Gets whether or not the java runtime should be included in this + * task's classpath. + * @return true if default run-time libraries are included + */ + public boolean getIncludejavaruntime() { + return includeJavaRuntime; + } + + /** + * Sets the extension directories that will be used during the + * compilation; optional. + * @param extDirs the extension directories to be used + */ + public synchronized void setExtdirs(Path extDirs) { + if (this.extDirs == null) { + this.extDirs = extDirs; + } else { + this.extDirs.append(extDirs); + } + } + + /** + * Maybe creates a nested extdirs element. + * @return path object to be configured with the extension directories + */ + public synchronized Path createExtdirs() { + if (extDirs == null) { + extDirs = new Path(getProject()); + } + return extDirs.createPath(); + } + + /** + * Gets the extension directories that will be used during the + * compilation. + * @return the extension directories to be used + */ + public Path getExtdirs() { + return extDirs; + } + + /** + * @return the compile list. + */ + public Vector getCompileList() { + return compileList; + } + + /** + * Sets the compiler implementation to use; optional, + * defaults to the value of the <code>build.rmic</code> property, + * or failing that, default compiler for the current VM + * @param compiler the compiler implementation to use + * @since Ant 1.5 + */ + public void setCompiler(String compiler) { + if (compiler.length() > 0) { + facade.setImplementation(compiler); + } + } + + /** + * get the name of the current compiler + * @return the name of the compiler + * @since Ant 1.5 + */ + public String getCompiler() { + facade.setMagicValue(getProject().getProperty("build.rmic")); + return facade.getImplementation(); + } + + /** + * Adds an implementation specific command line argument. + * @return an object to be configured with a command line argument + * @since Ant 1.5 + */ + public ImplementationSpecificArgument createCompilerArg() { + ImplementationSpecificArgument arg = new ImplementationSpecificArgument(); + facade.addImplementationArgument(arg); + return arg; + } + + /** + * Get the additional implementation specific command line arguments. + * @return array of command line arguments, guaranteed to be non-null. + * @since Ant 1.5 + */ + public String[] getCurrentCompilerArgs() { + getCompiler(); + return facade.getArgs(); + } + + /** + * Name of the executable to use when forking. + * + * @since Ant 1.8.0 + */ + public void setExecutable(String ex) { + executable = ex; + } + + /** + * Explicitly specified name of the executable to use when forking + * - if any. + * + * @since Ant 1.8.0 + */ + public String getExecutable() { + return executable; + } + + /** + * The classpath to use when loading the compiler implementation + * if it is not a built-in one. + * + * @since Ant 1.8.0 + */ + public Path createCompilerClasspath() { + return facade.getImplementationClasspath(getProject()); + } + + /** + * If true, list the source files being handed off to the compiler. + * @param list if true list the source files + * @since Ant 1.8.0 + */ + public void setListfiles(boolean list) { + listFiles = list; + } + + /** + * Set the compiler adapter explicitly. + * @since Ant 1.8.0 + */ + public void add(RmicAdapter adapter) { + if (nestedAdapter != null) { + throw new BuildException("Can't have more than one rmic adapter"); + } + nestedAdapter = adapter; + } + + /** + * execute by creating an instance of an implementation + * class and getting to do the work + * @throws org.apache.tools.ant.BuildException + * if there's a problem with baseDir or RMIC + */ + @Override + public void execute() throws BuildException { + try { + compileList.clear(); + + File outputDir = getOutputDir(); + if (outputDir == null) { + throw new BuildException(ERROR_BASE_NOT_SET, getLocation()); + } + if (!outputDir.exists()) { + throw new BuildException(ERROR_NO_BASE_EXISTS + outputDir, + getLocation()); + } + if (!outputDir.isDirectory()) { + throw new BuildException(ERROR_NOT_A_DIR + outputDir, getLocation()); + } + if (verify) { + log("Verify has been turned on.", Project.MSG_VERBOSE); + } + RmicAdapter adapter = + nestedAdapter != null ? nestedAdapter : + RmicAdapterFactory.getRmic(getCompiler(), this, + createCompilerClasspath()); + + // now we need to populate the compiler adapter + adapter.setRmic(this); + + Path classpath = adapter.getClasspath(); + loader = getProject().createClassLoader(classpath); + + // scan base dirs to build up compile lists only if a + // specific classname is not given + if (classname == null) { + DirectoryScanner ds = this.getDirectoryScanner(baseDir); + String[] files = ds.getIncludedFiles(); + scanDir(baseDir, files, adapter.getMapper()); + } else { + // otherwise perform a timestamp comparison - at least + String path = classname.replace('.', File.separatorChar) + + ".class"; + File f = new File(baseDir, path); + if (f.isFile()) { + scanDir(baseDir, new String[] {path}, adapter.getMapper()); + } else { + // Does not exist, so checking whether it is up to + // date makes no sense. Compilation will fail + // later anyway, but tests expect a certain + // output. + compileList.add(classname); + } + } + int fileCount = compileList.size(); + if (fileCount > 0) { + log("RMI Compiling " + fileCount + " class" + + (fileCount > 1 ? "es" : "") + " to " + + outputDir, Project.MSG_INFO); + + if (listFiles) { + for (int i = 0; i < fileCount; i++) { + log(compileList.get(i).toString()); + } + } + + // finally, lets execute the compiler!! + if (!adapter.execute()) { + throw new BuildException(ERROR_RMIC_FAILED, getLocation()); + } + } + /* + * Move the generated source file to the base directory. If + * base directory and sourcebase are the same, the generated + * sources are already in place. + */ + if (null != sourceBase && !outputDir.equals(sourceBase) + && fileCount > 0) { + if (idl) { + log("Cannot determine sourcefiles in idl mode, ", + Project.MSG_WARN); + log("sourcebase attribute will be ignored.", + Project.MSG_WARN); + } else { + for (int j = 0; j < fileCount; j++) { + moveGeneratedFile(outputDir, sourceBase, + (String) compileList.elementAt(j), + adapter); + } + } + } + } finally { + cleanup(); + } + } + + /** + * Cleans up resources. + * + * @since Ant 1.8.0 + */ + protected void cleanup() { + if (loader != null) { + loader.cleanup(); + loader = null; + } + } + + /** + * Move the generated source file(s) to the base directory + * + * @throws org.apache.tools.ant.BuildException When error + * copying/removing files. + */ + private void moveGeneratedFile(File baseDir, File sourceBaseFile, String classname, + RmicAdapter adapter) throws BuildException { + String classFileName = classname.replace('.', File.separatorChar) + + ".class"; + String[] generatedFiles = adapter.getMapper().mapFileName(classFileName); + + for (int i = 0; i < generatedFiles.length; i++) { + final String generatedFile = generatedFiles[i]; + if (!generatedFile.endsWith(".class")) { + // don't know how to handle that - a IDL file doesn't + // have a corresponding Java source for example. + continue; + } + String sourceFileName = StringUtils.removeSuffix(generatedFile, + ".class") + + ".java"; + + File oldFile = new File(baseDir, sourceFileName); + if (!oldFile.exists()) { + // no source file generated, nothing to move + continue; + } + + File newFile = new File(sourceBaseFile, sourceFileName); + try { + if (filtering) { + FILE_UTILS.copyFile(oldFile, newFile, + new FilterSetCollection(getProject() + .getGlobalFilterSet())); + } else { + FILE_UTILS.copyFile(oldFile, newFile); + } + oldFile.delete(); + } catch (IOException ioe) { + String msg = "Failed to copy " + oldFile + " to " + newFile + + " due to " + + ioe.getMessage(); + throw new BuildException(msg, ioe, getLocation()); + } + } + } + + /** + * Scans the directory looking for class files to be compiled. + * The result is returned in the class variable compileList. + * @param baseDir the base direction + * @param files the list of files to scan + * @param mapper the mapper of files to target files + */ + protected void scanDir(File baseDir, String[] files, FileNameMapper mapper) { + String[] newFiles = files; + if (idl) { + log("will leave uptodate test to rmic implementation in idl mode.", + Project.MSG_VERBOSE); + } else if (iiop && iiopOpts != null && iiopOpts.indexOf("-always") > -1) { + log("no uptodate test as -always option has been specified", + Project.MSG_VERBOSE); + } else { + SourceFileScanner sfs = new SourceFileScanner(this); + newFiles = sfs.restrict(files, baseDir, getOutputDir(), mapper); + } + for (int i = 0; i < newFiles.length; i++) { + String name = newFiles[i].replace(File.separatorChar, '.'); + name = name.substring(0, name.lastIndexOf(".class")); + compileList.addElement(name); + } + } + + /** + * Load named class and test whether it can be rmic'ed + * @param classname the name of the class to be tested + * @return true if the class can be rmic'ed + */ + public boolean isValidRmiRemote(String classname) { + try { + Class testClass = loader.loadClass(classname); + // One cannot RMIC an interface for "classic" RMI (JRMP) + if (testClass.isInterface() && !iiop && !idl) { + return false; + } + return isValidRmiRemote(testClass); + } catch (ClassNotFoundException e) { + log(ERROR_UNABLE_TO_VERIFY_CLASS + classname + ERROR_NOT_FOUND, + Project.MSG_WARN); + } catch (NoClassDefFoundError e) { + log(ERROR_UNABLE_TO_VERIFY_CLASS + classname + ERROR_NOT_DEFINED, + Project.MSG_WARN); + } catch (Throwable t) { + 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 + return false; + } + + /** + * Returns the topmost interface that extends Remote for a given + * class - if one exists. + * @param testClass the class to be tested + * @return the topmost interface that extends Remote, or null if there + * is none. + */ + public Class getRemoteInterface(Class testClass) { + if (Remote.class.isAssignableFrom(testClass)) { + Class [] interfaces = testClass.getInterfaces(); + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + if (Remote.class.isAssignableFrom(interfaces[i])) { + return interfaces[i]; + } + } + } + } + return null; + } + + /** + * Check to see if the class or (super)interfaces implement + * java.rmi.Remote. + */ + private boolean isValidRmiRemote (Class testClass) { + return getRemoteInterface(testClass) != null; + } + + /** + * Classloader for the user-specified classpath. + * @return the classloader + */ + public ClassLoader getLoader() { + return loader; + } + + /** + * Adds an "compiler" attribute to Commandline$Attribute used to + * filter command line attributes based on the current + * implementation. + */ + public class ImplementationSpecificArgument extends + org.apache.tools.ant.util.facade.ImplementationSpecificArgument { + /** + * Only pass the specified argument if the + * chosen compiler implementation matches the + * value of this attribute. Legal values are + * the same as those in the above list of + * valid compilers.) + * @param impl the compiler to be used. + */ + public void setCompiler(String impl) { + super.setImplementation(impl); + } + } +} |