package org.codehaus.mojo.rmic; /* * Copyright (c) 2004, Codehaus.org * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.File; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner; import org.codehaus.plexus.compiler.util.scan.StaleSourceScanner; import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping; import org.codehaus.plexus.util.StringUtils; /** * Generic super class of rmi compiler mojos. * * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> * @version $Id$ */ public abstract class AbstractRmiMojo extends AbstractMojo implements RmicConfig { // ---------------------------------------------------------------------- // Configurable parameters // ---------------------------------------------------------------------- /** * A list of inclusions when searching for classes to compile. * * @parameter */ protected Set includes; /** * A list of exclusions when searching for classes to compile. * * @parameter */ protected Set excludes; /** * The id of the rmi compiler to use. * * @parameter default-value="sun" */ protected String compilerId; /** * The version of the rmi protocol to which the stubs should be compiled. Valid values include 1.1, 1.2, compat. See * the rmic documentation for more information. If nothing is specified the underlying rmi compiler will * choose the default value. For example, in sun jdk 1.5 the default is 1.2. * * @parameter */ private String version; /** * Create stubs for IIOP. * * @parameter default-value="false" */ private boolean iiop; /** * Do not create stubs optimized for same process. * * @parameter */ private boolean noLocalStubs; /** * Create IDL. * * @parameter default-value="false" */ private boolean idl; /** * Do not generate methods for valuetypes. * * @parameter */ private boolean noValueMethods; /** * Do not delete intermediate generated source files. * * @parameter default-value="false" */ private boolean keep; /** * Turn off rmic warnings. * * @parameter */ private boolean nowarn; /** * Enable verbose rmic output. * * @parameter */ private boolean verbose; /** * Time in milliseconds between automatic recompilations. A value of 0 means that up to date rmic output classes * will not be recompiled until the source classes change. * * @parameter default-value=0 */ private int staleMillis; // ---------------------------------------------------------------------- // Constant parameters // ---------------------------------------------------------------------- /** * @component org.apache.maven.plugin.rmic.RmiCompilerManager */ private RmiCompilerManager rmiCompilerManager; /** * The maven project. * * @parameter expression="${project}" * @readonly */ protected MavenProject project; /** * Get the list of elements to add to the classpath of rmic * * @return list of classpath elements */ public abstract List getProjectClasspathElements(); /** * Get the directory where rmic generated class files are written. * * @return the directory */ public abstract File getOutputDirectory(); /** * Get the directory where Remote impl classes are located. * * @return path to compiled classes */ public abstract File getClassesDirectory(); /** * Main mojo execution. * * @throws MojoExecutionException if there is a problem executing the mojo. */ public void execute() throws MojoExecutionException { if ( this.includes == null ) { this.includes = Collections.singleton( "**/*" ); } if ( this.excludes == null ) { this.excludes = new HashSet(); } // Exclude _Stub files from being recompiled by rmic. excludes.add( "**/*_Stub.class" ); RmiCompiler rmiCompiler; try { rmiCompiler = rmiCompilerManager.getRmiCompiler( compilerId ); } catch ( NoSuchRmiCompilerException e ) { throw new MojoExecutionException( "No such RMI compiler installed '" + compilerId + "'." ); } if ( !getOutputDirectory().isDirectory() ) { if ( !getOutputDirectory().mkdirs() ) { throw new MojoExecutionException( "Could not make output directory: " + "'" + getOutputDirectory().getAbsolutePath() + "'." ); } } try { // Get the list of classes to compile List remoteClassesToCompile = scanForRemoteClasses(); if ( remoteClassesToCompile.size() == 0 ) { getLog().info( "No out of date rmi classes to process." ); return; } getLog().info( "Compiling " + remoteClassesToCompile.size() + " remote classes" ); rmiCompiler.execute( this, remoteClassesToCompile ); } catch ( RmiCompilerException e ) { throw new MojoExecutionException( "Error while executing the RMI compiler.", e ); } } /** * Get the list of elements to add to the classpath of rmic * * @return list of classpath elements */ public List getRmicClasspathElements() { List classpathElements = getProjectClasspathElements(); if ( !classpathElements.contains( getClassesDirectory().getAbsolutePath() ) ) { classpathElements.add( getClassesDirectory().getAbsolutePath() ); } return classpathElements; } /** * Search the input directory for classes to compile. * * @return a list of class names to rmic */ public List scanForRemoteClasses() { List remoteClasses = new ArrayList(); try { // Set up the classloader List classpathList = generateUrlCompileClasspath(); URL[] classpathUrls = new URL[classpathList.size()]; classpathUrls[0] = getClassesDirectory().toURL(); classpathUrls = (URL[]) classpathList.toArray( classpathUrls ); URLClassLoader loader = new URLClassLoader( classpathUrls ); // Scan for remote classes SourceInclusionScanner scanner = new StaleSourceScanner( staleMillis, this.includes, this.excludes ); scanner.addSourceMapping( new SuffixMapping( ".class", "_Stub.class" ) ); Collection staleRemoteClasses = scanner.getIncludedSources( getClassesDirectory(), getOutputDirectory() ); for ( Iterator iter = staleRemoteClasses.iterator(); iter.hasNext(); ) { // Get the classname and load the class File remoteClassFile = (File) iter.next(); URI relativeURI = getClassesDirectory().toURI().relativize( remoteClassFile.toURI() ); String className = StringUtils.replace( StringUtils.replace( relativeURI.toString(), ".class", "" ), "/", "." ); Class remoteClass = loader.loadClass( className ); // Check that each class implements java.rmi.Remote, ignore interfaces unless in IIOP mode if ( java.rmi.Remote.class.isAssignableFrom( remoteClass ) && ( !remoteClass.isInterface() || isIiop() ) ) { remoteClasses.add( className ); } } // Check for classes in a classpath jar for ( Iterator iter = includes.iterator(); iter.hasNext(); ) { String include = (String) iter.next(); File includeFile = new File( getClassesDirectory(), include ); if ( ( include.indexOf( "*" ) != -1 ) || includeFile.exists() ) { continue; } // We have found a class that is not in the classes dir. String fqClassName = StringUtils.replace( StringUtils.replace( include, ".class", "" ), "/", "." ); remoteClasses.add( fqClassName ); } } catch ( Exception e ) { getLog().warn( "Problem while scanning for classes: " + e ); } return remoteClasses; } /** * Returns a list of URL objects that represent the classpath elements. This is useful for using a URLClassLoader * * @return list of url classpath elements */ protected List generateUrlCompileClasspath() throws MojoExecutionException { List rmiCompileClasspath = new ArrayList(); try { rmiCompileClasspath.add( getClassesDirectory().toURL() ); Iterator iter = getRmicClasspathElements().iterator(); while ( iter.hasNext() ) { URL pathUrl = new File( (String) iter.next() ).toURL(); rmiCompileClasspath.add( pathUrl ); } } catch ( Exception e ) { e.printStackTrace(); throw new MojoExecutionException( "Problem while generating classpath: " + e.getMessage() ); } return rmiCompileClasspath; } public String getCompilerId() { return compilerId; } public boolean isIiop() { return iiop; } public boolean isIdl() { return idl; } public boolean isKeep() { return keep; } public String getVersion() { return version; } public boolean isNowarn() { return nowarn; } public boolean isVerbose() { return verbose; } public boolean isNoLocalStubs() { return noLocalStubs; } public boolean isNoValueMethods() { return noValueMethods; } }