/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ant.tasks.retrocheck;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
* Ant task. Copied a bunch of shit from javac task
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
* @version $Revision: 24 $
*/
public class RetroCheck extends MatchingTask
{
private static String lSep = System.getProperty("line.separator");
private int maxSrc = 1000;
private Path classpath;
private Path compilerClasspath;
private Path compileSourcepath;
private File destDir;
private boolean verbose = false;
private boolean suppress = true;
private String maxmemory = null;
/**
* flag to control action on execution trouble
*/
protected boolean failOnError = true;
/**
* Set the verbose level of the compiler
*/
public void setVerbose(boolean i)
{
verbose = i;
}
public boolean getVerbose()
{
return verbose;
}
/**
* Set the verbose level of the compiler
*/
public void setSuppress(boolean i)
{
suppress = i;
}
public boolean getSupress()
{
return suppress;
}
/**
* Set the maxmemory of the Java task forked
*/
public void setMaxmemory(String maxmemory)
{
this.maxmemory = maxmemory;
}
public String getMaxmemory()
{
return maxmemory;
}
/**
* Whether or not the build should halt if compilation fails.
* Defaults to <code>true</code>.
*/
public void setFailonerror(boolean fail)
{
failOnError = fail;
}
/**
* Gets the failonerror flag.
*/
public boolean getFailonerror()
{
return failOnError;
}
/**
* Set the destination directory into which the Java source
* files should be compiled.
* @param destDir the destination director
*/
public void setDestdir(File destDir) {
this.destDir = destDir;
}
/**
* Gets the destination directory into which the java source files
* should be compiled.
* @return the destination directory
*/
public File getDestdir() {
return destDir;
}
/**
* Set the classpath to be used for this compilation.
*/
public void setClasspath(Path cp)
{
if (classpath == null)
{
classpath = cp;
}
else
{
classpath.append(cp);
}
}
public void setMaxSrc(int maxSrc)
{
this.maxSrc = maxSrc;
}
public int getMaxSrc()
{
return maxSrc;
}
/**
* Adds a path to the classpath.
*/
public Path createClasspath()
{
if (classpath == null)
{
classpath = new Path(getProject());
}
return classpath.createPath();
}
/**
* Adds a reference to a classpath defined elsewhere
*/
public void setClasspathRef(Reference r)
{
createClasspath().setRefid(r);
}
public Path getClasspath()
{
return classpath;
}
/**
* Adds a reference to a classpath defined elsewhere
*/
public void setCompilerClasspathRef(Reference r)
{
if (compilerClasspath == null)
compilerClasspath = new Path(getProject());
compilerClasspath.setRefid(r);
}
/**
* Set the classpath to be used to find this compiler adapter
*/
public void setCompilerclasspath(Path cp)
{
if (compilerClasspath == null)
{
compilerClasspath = cp;
}
else
{
compilerClasspath.append(cp);
}
}
/**
* get the classpath used to find the compiler adapter
*/
public Path getCompilerclasspath()
{
return compilerClasspath;
}
/**
* Support nested compiler classpath, used to locate compiler adapter
*/
public Path createCompilerclasspath()
{
if (compilerClasspath == null)
{
compilerClasspath = new Path(getProject());
}
return compilerClasspath.createPath();
}
/**
* Adds a path for source compilation.
*
* @return a nested src element.
*/
public Path createSrc()
{
if (compileSourcepath == null)
{
compileSourcepath = new Path(getProject());
}
return compileSourcepath.createPath();
}
public void execute() throws BuildException
{
CommandlineJava cmd = new CommandlineJava();
if (verbose)
cmd.createArgument().setValue("-verbose");
if (suppress)
cmd.createArgument().setValue("-suppress");
if (destDir != null)
{
cmd.createArgument().setValue("-destdir");
cmd.createArgument().setFile(destDir);
}
logAndAddFilesToCompile(cmd);
getProject().log("compileSourcepath: "+compileSourcepath, Project.MSG_DEBUG);
try
{
// Create an instance of the compiler, redirecting output to
// the project log
if (classpath == null)
throw new BuildException("No classpath");
classpath.append(compilerClasspath);
Java java = (Java) (getProject().createTask("java"));
if (getClasspath() != null)
{
getProject().log("using user supplied classpath: " + getClasspath(), Project.MSG_DEBUG);
java.setClasspath(getClasspath().concatSystemClasspath("ignore"));
}
else
{
Path classpath = new Path(getProject());
classpath = classpath.concatSystemClasspath("only");
getProject().log("using system classpath: " + classpath, Project.MSG_DEBUG);
java.setClasspath(classpath);
}
java.setDir(getProject().getBaseDir());
java.setClassname("org.jboss.ant.tasks.retrocheck.Checker");
//this is really irritating; we need a way to set stuff
String args[] = cmd.getJavaCommand().getArguments();
for (int i = 0; i < args.length; i++)
{
java.createArg().setValue(args[i]);
}
java.setFailonerror(getFailonerror());
//we are forking here to be sure that if JspC calls
//System.exit() it doesn't halt the build
java.setFork(true);
java.setTaskName("retrocheck");
if (maxmemory != null)
{
java.setMaxmemory(maxmemory);
}
java.execute();
}
catch (Exception ex)
{
if (ex instanceof BuildException)
{
throw (BuildException) ex;
}
else
{
throw new BuildException("Error running weaver: ", ex, getLocation());
}
}
}
protected void logAndAddFilesToCompile(CommandlineJava cmd)
{
// scan source directories and dest directory to build up
// compile lists
ArrayList compilingFiles = new ArrayList();
if (compileSourcepath != null)
{
String[] list = compileSourcepath.list();
for (int i = 0; i < list.length; i++)
{
File srcDir = getProject().resolveFile(list[i]);
if (!srcDir.exists())
{
throw new BuildException("srcdir \"" + srcDir.getPath() + "\" does not exist!", getLocation());
}
getProject().log("Adding classes from src: "+srcDir, Project.MSG_VERBOSE);
DirectoryScanner ds = this.getDirectoryScanner(srcDir);
String[] files = ds.getIncludedFiles();
for (int j = 0; j < files.length; j++)
{
if (files[j].endsWith(".class"))
{
File f = new File(srcDir, files[j]);
compilingFiles.add(f.getAbsolutePath());
getProject().log("Adding class: "+f, Project.MSG_DEBUG);
}
}
}
}
int length = 0;
for (int i = 0; i < compilingFiles.size(); i++)
{
//Add 1 to allow for the spaces between args
length += ((String) compilingFiles.get(i)).length() + 1;
if (length > maxSrc)
{
break;
}
}
if (length < maxSrc)
{
StringBuffer niceSourceList = new StringBuffer("Files\n");
for (int i = 0; i < compilingFiles.size(); i++)
{
String file = (String) compilingFiles.get(i);
cmd.createArgument().setValue(file);
niceSourceList.append(" " + file + lSep);
}
//getProject().log(niceSourceList.toString());
}
else
{
BufferedWriter writer = null;
try
{
File sourceFiles = File.createTempFile("src", ".tmp");
if (verbose)
{
System.out.println("[info] Total length of filenames to be compiled is greater than " + maxSrc
+ ", listing files in --SOURCEPATH: " + sourceFiles.getAbsolutePath());
}
sourceFiles.deleteOnExit();
writer = new BufferedWriter(new FileWriter(sourceFiles));
for (int i = 0; i < compilingFiles.size(); i++)
{
writer.write((String) compilingFiles.get(i));
writer.newLine();
}
writer.flush();
cmd.createArgument().setValue("--SOURCEPATH");
cmd.createArgument().setValue(sourceFiles.getAbsolutePath());
}
catch (IOException e)
{
if (writer != null)
{
try
{
writer.close();
}
catch (IOException e1)
{
}
}
throw new RuntimeException(e);
}
}
}
}