org.codehaus.mojo.javacc.ForkedJvm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javacc-maven-plugin Show documentation
Show all versions of javacc-maven-plugin Show documentation
Maven 3 Plugin for processing JavaCC grammar files.
package org.codehaus.mojo.javacc;
/*
* 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.
*/
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
import org.codehaus.plexus.util.cli.StreamConsumer;
/**
* Runs the main()
method of some tool in a forked JVM.
*
* @author Benjamin Bentmann
* @version $Id: ForkedJvm.java 7758 2008-09-29 20:06:33Z bentmann $
* @see java - The Java Application
* Launcher
*/
class ForkedJvm
{
/**
* The consumer for System.out
messages.
*/
private StreamConsumer systemOut;
/**
* The consumer for System.err
messages.
*/
private StreamConsumer systemErr;
/**
* The executable used to fork the JVM.
*/
private String executable;
/**
* The working directory for the forked JVM.
*/
private File workingDirectory;
/**
* The class path entries for the forked JVM, given as strings.
*/
private Set classPathEntries = new LinkedHashSet();
/**
* The qualified name of the class on which to invoke the main()
method.
*/
private String mainClass;
/**
* The command line arguments to pass to the main()
method, given as strings.
*/
private List cmdLineArgs = new ArrayList();
/**
* Creates a new configuration to fork a JVM.
*/
public ForkedJvm()
{
this.executable = getDefaultExecutable();
}
/**
* Gets the absolute path to the JVM executable.
*
* @return The absolute path to the JVM executable.
*/
private static String getDefaultExecutable()
{
return System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
}
/**
* Sets the working directory for the forked JVM.
*
* @param directory The working directory for the forked JVM, may be null
to inherit the working
* directory of the current JVM.
*/
public void setWorkingDirectory( File directory )
{
this.workingDirectory = directory;
}
/**
* Sets the stream consumer used to handle messages from System.out
.
*
* @param consumer The stream consumer, may be null
to discard the output.
*/
public void setSystemOut( StreamConsumer consumer )
{
this.systemOut = consumer;
}
/**
* Sets the stream consumer used to handle messages from System.err
.
*
* @param consumer The stream consumer, may be null
to discard the output.
*/
public void setSystemErr( StreamConsumer consumer )
{
this.systemErr = consumer;
}
/**
* Gets the class path for the forked JVM.
*
* @return The class path for the forked JVM.
*/
private String getClassPath()
{
return StringUtils.join( this.classPathEntries.iterator(), File.pathSeparator );
}
/**
* Adds the specified path to the class path of the forked JVM.
*
* @param path The path to add, may be null
.
*/
public void addClassPathEntry( String path )
{
if ( path != null )
{
this.classPathEntries.add( path );
}
}
/**
* Adds the specified path to the class path of the forked JVM.
*
* @param path The path to add, may be null
.
*/
public void addClassPathEntry( File path )
{
if ( path != null )
{
this.classPathEntries.add( path.getAbsolutePath() );
}
}
/**
* Adds the source JAR of the specified class/interface to the class path of the forked JVM.
*
* @param type The class/interface to add, may be null
.
*/
public void addClassPathEntry( Class type )
{
addClassPathEntry( getClassSource( type ) );
}
/**
* Gets the JAR file or directory that contains the specified class.
*
* @param type The class/interface to find, may be null
.
* @return The absolute path to the class source location or null
if unknown.
*/
private static File getClassSource( Class type )
{
if ( type != null )
{
String classResource = type.getName().replace( '.', '/' ) + ".class";
return getResourceSource( classResource, type.getClassLoader() );
}
return null;
}
/**
* Gets the JAR file or directory that contains the specified class.
*
* @param className The qualified name of the class/interface to find, may be null
.
* @return The absolute path to the class source location or null
if unknown.
*/
private static File getClassSource( String className )
{
if ( className != null )
{
String classResource = className.replace( '.', '/' ) + ".class";
return getResourceSource( classResource, Thread.currentThread().getContextClassLoader() );
}
return null;
}
/**
* Gets the JAR file or directory that contains the specified resource.
*
* @param resource The absolute name of the resource to find, may be null
.
* @param loader The class loader to use for searching the resource, may be null
.
* @return The absolute path to the resource location or null
if unknown.
*/
private static File getResourceSource( String resource, ClassLoader loader )
{
if ( resource != null )
{
URL url;
if ( loader != null )
{
url = loader.getResource( resource );
}
else
{
url = ClassLoader.getSystemResource( resource );
}
return UrlUtils.getResourceRoot( url, resource );
}
return null;
}
/**
* Sets the qualified name of the class on which to invoke the main()
method. The source of the
* specified class will automatically be added to the class path of the forked JVM.
*
* @param name The qualified name of the class on which to invoke the main()
method.
*/
public void setMainClass( String name )
{
this.mainClass = name;
addClassPathEntry( getClassSource( name ) );
}
/**
* Sets the class on which to invoke the main()
method. The source of the specified class will
* automatically be added to the class path of the forked JVM.
*
* @param type The class on which to invoke the main()
method, may be null
.
*/
public void setMainClass( Class type )
{
this.mainClass = ( type != null ) ? type.getName() : null;
addClassPathEntry( type );
}
/**
* Gets the command line arguments for the main()
method.
*
* @return The command line arguments for the main()
method.
*/
private String[] getArguments()
{
return (String[]) this.cmdLineArgs.toArray( new String[this.cmdLineArgs.size()] );
}
/**
* Adds the specified argument to the command line for the main()
method.
*
* @param argument The argument to add, may be null
.
*/
public void addArgument( String argument )
{
if ( argument != null )
{
this.cmdLineArgs.add( argument );
}
}
/**
* Adds the specified file path to the command line for the main()
method.
*
* @param argument The argument to add, may be null
.
*/
public void addArgument( File argument )
{
if ( argument != null )
{
this.cmdLineArgs.add( argument.getAbsolutePath() );
}
}
/**
* Adds the specified arguments to the command line for the main()
method.
*
* @param arguments The arguments to add, may be null
.
*/
public void addArguments( String[] arguments )
{
if ( arguments != null )
{
for ( int i = 0; i < arguments.length; i++ )
{
addArgument( arguments[i] );
}
}
}
/**
* Creates the command line for the new JVM based on the current configuration.
*
* @return The command line used to fork the JVM, never null
.
*/
private Commandline createCommandLine()
{
/*
* NOTE: This method is designed to work with plexus-utils:1.1 which is used by all Maven versions before 2.0.6
* regardless of our plugin dependency. Therefore, we use setWorkingDirectory(String) rather than
* setWorkingDirectory(File) and addArguments() rather than createArg().
*/
Commandline cli = new Commandline();
cli.setExecutable( this.executable );
if ( this.workingDirectory != null )
{
cli.setWorkingDirectory( this.workingDirectory.getAbsolutePath() );
}
String classPath = getClassPath();
if ( classPath != null && classPath.length() > 0 )
{
cli.addArguments( new String[] { "-cp", classPath } );
}
if ( this.mainClass != null && this.mainClass.length() > 0 )
{
cli.addArguments( new String[] { this.mainClass } );
}
cli.addArguments( getArguments() );
return cli;
}
/**
* Forks a JVM using the previously set parameters.
*
* @return The exit code of the forked JVM.
* @throws Exception If the JVM could not be forked.
*/
public int run()
throws Exception
{
return CommandLineUtils.executeCommandLine( createCommandLine(), this.systemOut, this.systemErr );
}
/**
* Gets a string representation of the command line arguments.
*
* @return A string representation of the command line arguments.
*/
public String toString()
{
return String.valueOf( createCommandLine() );
}
}