package org.codehaus.mojo.idlj;
/*
* 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.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.maven.plugin.MojoExecutionException;
/**
* This class implement the <code>CompilerTranslator</code> for the JacORB IDL compiler
*
* @author Anders Hessellund Jensen <ahj@trifork.com>
* @version $Id$
*/
public class JacorbTranslator
extends AbstractTranslator
implements CompilerTranslator
{
/**
* Default constructor
*/
public JacorbTranslator()
{
super();
}
/**
* Invoke the specified compiler with a set of arguments
*
* @param compilerClass the <code>Class</code> that implemtns the compiler
* @param args a <code>List</code> that contains the arguments to use for the compiler
* @throws MojoExecutionException if the compilation fail or the compiler crashes
*/
private void invokeCompiler( Class compilerClass, List args )
throws MojoExecutionException
{
// It would be great to use some 3rd party library for this stuff
boolean fork = true;
if ( !fork )
{
try
{
String arguments[] = (String[]) args.toArray( new String[args.size()] );
if ( isDebug() )
{
String command = "compile";
for ( int i = 0; i < arguments.length; i++ )
{
command += " " + arguments[i];
}
getLog().info( command );
}
Method compileMethod = compilerClass.getMethod( "compile", new Class[] { String[].class } );
compileMethod.invoke( compilerClass, arguments );
}
catch ( InvocationTargetException e )
{
throw new MojoExecutionException( "Compilation failed", e.getTargetException() );
}
catch ( Throwable t )
{
throw new MojoExecutionException( "Compilation failed", t );
}
}
else
{
// Forks a new java process.
// Get path to java binary
File javaHome = new File( System.getProperty( "java.home" ) );
File javaBin = new File( new File( javaHome, "bin" ), "java" );
// Get current class path
URLClassLoader cl = (URLClassLoader) this.getClass().getClassLoader();
URL[] classPathUrls = cl.getURLs();
// Construct list of arguments
List binArgs = new ArrayList();
// First argument is the java binary to run
binArgs.add( javaBin.getPath() );
// Add the classpath to argument list
binArgs.add( "-classpath" );
String classPath = "" + new File( classPathUrls[0].getPath().replaceAll( "%20", " " ) );
for ( int i = 1; i < classPathUrls.length; i++ )
{
classPath += File.pathSeparator + new File( classPathUrls[i].getPath().replaceAll( "%20", " " ) );
}
classPath += "";
binArgs.add( classPath );
// Add class containing main method to arg list
binArgs.add( compilerClass.getName() );
// Add java arguments
for ( Iterator it = args.iterator(); it.hasNext(); )
{
Object o = it.next();
binArgs.add( o.toString() );
}
// Convert arg list to array
String[] argArray = new String[binArgs.size()];
for ( int i = 0; i < argArray.length; i++ )
{
argArray[i] = binArgs.get( i ).toString();
}
if ( isDebug() )
{
String command = "";
for ( int i = 0; i < argArray.length; i++ )
{
command += " " + argArray[i];
}
getLog().info( command );
}
try
{
Process p = Runtime.getRuntime().exec( argArray );
redirectStream( p.getErrorStream(), System.err, "" );
redirectStream( p.getInputStream(), System.out, "" );
p.waitFor();
if ( isFailOnError() && p.exitValue() != 0 )
{
throw new MojoExecutionException( "IDL Compilation failure" );
}
}
catch ( IOException e )
{
throw new MojoExecutionException( "Error forking compiler", e );
}
catch ( InterruptedException e )
{
throw new MojoExecutionException( "Thread interrupted unexpectedly", e );
}
}
}
/**
* This method it's used to invoke the compiler
*
* @param sourceDirectory the path to the sources
* @param includeDirs the <code>File[]</code> of directories where to find the includes
* @param targetDirectory the path to the destination of the compilation
* @param idlFile the path to the file to compile
* @param source //TODO ???
* @throws MojoExecutionException the exeception is thrown whenever the compilation fails or crashes
* @see CompilerTranslator#invokeCompiler(String, List, String, String, Source)
*/
public void invokeCompiler( String sourceDirectory, File[] includeDirs, String targetDirectory, String idlFile,
Source source )
throws MojoExecutionException
{
List args = new ArrayList();
// TODO: This should be configurable
args.add( "-sloppy_names" );
args.add( "-I" + sourceDirectory );
// add idl files from other directories as well
if ( includeDirs != null && includeDirs.length > 0 )
{
for ( int i = 0; i < includeDirs.length; i++ )
{
args.add( "-I" + includeDirs[i] );
}
}
args.add( "-d" );
args.add( targetDirectory );
if ( source.emitSkeletons() != null && !source.emitSkeletons().booleanValue() )
{
args.add( "-noskel" );
}
if ( source.emitStubs() != null && !source.emitStubs().booleanValue() )
{
args.add( "-nostub" );
}
if ( source.getPackagePrefix() != null )
{
args.add( "-i2jpackage" );
args.add( ":" + source.getPackagePrefix() );
}
if ( source.getPackagePrefixes() != null )
{
for ( Iterator prefixes = source.getPackagePrefixes().iterator(); prefixes.hasNext(); )
{
PackagePrefix prefix = (PackagePrefix) prefixes.next();
args.add( "-i2jpackage" );
args.add( prefix.getType() + ":" + prefix.getPrefix() + "." + prefix.getType() );
}
}
if ( source.getDefines() != null )
{
for ( Iterator defs = source.getDefines().iterator(); defs.hasNext(); )
{
Define define = (Define) defs.next();
String arg = "-D" + define.getSymbol();
if ( define.getValue() != null )
{
arg += "=" + define.getValue();
}
args.add( arg );
}
}
if ( source.getAdditionalArguments() != null )
{
for ( Iterator it = source.getAdditionalArguments().iterator(); it.hasNext(); )
{
args.add( it.next() );
}
}
args.add( idlFile );
Class compilerClass;
try
{
compilerClass = Class.forName( "org.jacorb.idl.parser" );
}
catch ( ClassNotFoundException e )
{
throw new MojoExecutionException( "JacORB IDL compiler not found", e );
}
invokeCompiler( compilerClass, args );
}
/**
* This methos it's used to redirect an <code>InputeStream</code> to a <code>OutputStream</code>
*
* @param in the <code>InputStream</code> to read from
* @param out the <code>OutputStream</code> to write into
* @param streamName the name of Stream
*/
public static void redirectStream( final InputStream in, final OutputStream out, final String streamName )
{
Thread stdoutTransferThread = new Thread()
{
public void run()
{
PrintWriter pw = new PrintWriter( new OutputStreamWriter( out ), true );
try
{
BufferedReader reader = new BufferedReader( new InputStreamReader( in ) );
String line;
while ( ( line = reader.readLine() ) != null )
{
pw.println( line );
}
}
catch ( Throwable e )
{
e.printStackTrace();
}
}
};
stdoutTransferThread.start();
}
}