// Copyright FreeHEP, 2005-2006.
package org.freehep.maven.idlj;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
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.InclusionScanException;
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.FileUtils;
/**
* @goal generate
* @description Compiles IDL files using the idlj compiler.
* @phase generate-sources
* @author <a href="Mark.Donszelmann@slac.stanford.edu">Mark Donszelmann</a>
* @version $Id: IdljMojo.java 9121 2006-10-12 20:58:35Z duns $
*/
public class IdljMojo extends AbstractMojo {
/**
* Equivalent to "#define symbol" in IDL.
*
* @parameter
*/
private List defines;
/**
* Emit all types, including those found in #include files.
*
* @parameter expression="${idlj.emitAll}" default-value=false"
*/
private boolean emitAll;
/**
* Defines what bindings to emit: client, server, serverTIE, all or allTIE.
* Assumes client if none is specified.
*
* @parameter
*/
private List bindings;
/**
* Add include paths. By default the current directory is scanned.
*
* @parameter
*/
private List includePaths;
/**
* If a file to be generated already exists, do not overwrite it.
*
* @parameter expression="${idlj.keep}" default-value="false"
*/
private boolean keep;
/**
* Suppress warning messages.
*
* @parameter expression="${idlj.noWarn}" default-value="false"
*/
private boolean noWarn;
/**
* Generates skeletons compatible with pre-1.4 JDK ORBs.
*
* @parameter expression="${idlj.oldImplBase}" default-value="false"
*/
private boolean oldImplBase;
/**
* Wherever type is encountered at the file scope, prefix the generated Java package name
* with prefix for all files generated for that type. The type is the simple name of either
* a top-level module, or an IDL type defined outside the scope of any module.
*
* @parameter
*/
private List pkgPrefixes;
/**
* Whenever the module type is encountered in an identifier, replace it in the
* identifier with package for all files in the generated Java package. Note that
* pkfPrefixes changes are made first. Type is the simple name of either a top-level
* module, or an IDL type defined outside of any module, and must match the full
* apckage name exactly.
*
* @parameter
*/
private List pkgTranslates;
/**
* Use xxx%yyy as the pattern for naming the skeletons.
*
* @parameter
*/
private List skeletonNames;
/**
* The target directory into which to generate the output.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private String targetDirectory;
/**
* Use xxx%yyy as the pattern for naming the ties.
*
* @parameter
*/
private List tieNames;
/**
* The source directory.
*
* @parameter expression="${basedir}/src/main/idl"
* @required
*/
private String sourceDirectory;
/**
* The idl file.
*
* @parameter
* @required
*/
private String source;
/**
* The granularity in milliseconds of the last modification
* date for testing whether a source needs recompilation
*
* @parameter expression="${idlj.staleMillis}" default-value="0"
* @required
*/
private int staleMillis;
/**
* The directory to store the processed .idl files. Defaults to targetDirectory.
*
* @parameter
*/
private String timestampDirectory;
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
public void execute() throws MojoExecutionException {
if (!FileUtils.fileExists(targetDirectory)) {
FileUtils.mkdir( targetDirectory );
}
if (project != null) {
project.addCompileSourceRoot(targetDirectory);
}
if (!sourceDirectory.endsWith("/")) {
sourceDirectory = sourceDirectory+"/";
}
if (timestampDirectory == null) {
timestampDirectory = targetDirectory;
} else {
if (!FileUtils.fileExists(timestampDirectory)) {
FileUtils.mkdir( timestampDirectory );
}
}
File sourceFile = new File(sourceDirectory);
File targetFile = new File(timestampDirectory);
SourceInclusionScanner scanner = new StaleSourceScanner(staleMillis, Collections.singleton(source), Collections.EMPTY_SET);
SuffixMapping mapping = new SuffixMapping( ".idl", ".flag" );
scanner.addSourceMapping(mapping);
try {
Set files = scanner.getIncludedSources(sourceFile, targetFile);
if (!files.isEmpty()) {
getLog().info( "Running idlj compiler on "+source);
runCommand(generateCommandLine());
File flagFile = new File(timestampDirectory, FileUtils.basename(source, ".idl") + ".flag");
FileUtils.fileDelete(flagFile.getPath());
FileUtils.fileWrite(flagFile.getPath(), "");
}
} catch (InclusionScanException e) {
throw new MojoExecutionException( "IDLJ: Source scanning failed", e );
} catch (IOException e) {
throw new MojoExecutionException( "IDLJ: Creation of timestamp flag file failed", e );
}
}
private String[] generateCommandLine() throws MojoExecutionException {
List cmdLine = new ArrayList();
cmdLine.add("idlj");
if (defines != null) {
for (Iterator i = defines.iterator(); i.hasNext(); ) {
cmdLine.add("-d");
cmdLine.add((String)i.next());
}
}
if (emitAll) {
cmdLine.add("-emitAll");
}
if (bindings != null) {
for (Iterator i = bindings.iterator(); i.hasNext(); ) {
cmdLine.add("-f"+(String)i.next());
}
}
if (includePaths != null) {
for (Iterator i = includePaths.iterator(); i.hasNext(); ) {
cmdLine.add("-i");
cmdLine.add((String)i.next());
}
}
if (keep) {
cmdLine.add("-keep");
}
if (noWarn) {
cmdLine.add("-noWarn");
}
if (oldImplBase) {
cmdLine.add("-oldImplBase");
}
if (pkgPrefixes != null) {
for (Iterator i = pkgPrefixes.iterator(); i.hasNext(); ) {
addParamPair(cmdLine, "-pkgPrefix", i.next());
}
}
if (pkgTranslates != null) {
for (Iterator i = pkgTranslates.iterator(); i.hasNext(); ) {
addParamPair(cmdLine, "-pkgTranslate", i.next());
}
}
if (skeletonNames != null) {
for (Iterator i = skeletonNames.iterator(); i.hasNext(); ) {
cmdLine.add("-skeletonName");
cmdLine.add((String)i.next());
}
}
cmdLine.add("-td");
cmdLine.add(targetDirectory);
if (tieNames != null) {
for (Iterator i = tieNames.iterator(); i.hasNext(); ) {
cmdLine.add("-tieName");
cmdLine.add((String)i.next());
}
}
if (getLog().isDebugEnabled()) {
cmdLine.add("-verbose");
}
cmdLine.add(sourceDirectory+source);
getLog().debug(cmdLine.toString());
return (String[])cmdLine.toArray(new String[cmdLine.size()]);
}
private void addParamPair(List cmdLine, String option, Object obj) throws MojoExecutionException {
cmdLine.add(option);
String[] param = ((String)obj).split(" ", 2);
if (param.length != 2) throw new MojoExecutionException( "IDLJ: "+option+" takes 2 parameters");
cmdLine.add(param[0]);
cmdLine.add(param[1]);
}
private int runCommand(String[] cmdLine) throws MojoExecutionException {
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmdLine);
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), true);
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), false);
errorGobbler.start();
outputGobbler.start();
return process.waitFor();
} catch (Throwable e) {
throw new MojoExecutionException("Could not launch " + cmdLine[0], e);
}
}
class StreamGobbler extends Thread {
InputStream is;
boolean error;
StreamGobbler(InputStream is, boolean error) {
this.is = is;
this.error = error;
}
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = reader.readLine()) != null) {
if (error) {
getLog().error(line);
} else {
getLog().debug(line);
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}