/*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.tools.ant;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.compilers.CompilerAdapter;
import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.GlobPatternMapper;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.apache.tools.ant.util.SourceFileScanner;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* VisageAntTask
*
* @author Brian Goetz
*/
public class VisageAntTask extends Javac {
public Path compilerClassPath;
public String profile;
private static final String FAIL_MSG
= "Visage compile failed; see the compiler error output for details.";
public static final String VISAGE_ENTRY_POINT = "org.visage.tools.Main";
public VisageAntTask() {
super();
super.setCompiler(VisageCompilerAdapter.class.getName());
super.setIncludeantruntime(true);
}
@Override
protected void scanDir(File srcDir, File destDir, String[] files) {
GlobPatternMapper m = new GlobPatternMapper();
m.setFrom("*.visage");
m.setTo("*.class");
SourceFileScanner sfs = new SourceFileScanner(this);
File[] newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
if (newFiles.length > 0) {
File[] newCompileList
= new File[compileList.length + newFiles.length];
System.arraycopy(compileList, 0, newCompileList, 0, compileList.length);
System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length);
compileList = newCompileList;
}
}
/**
* Workaround for classloader bug in CompilerAdapterFactory
*/
@Override
protected void compile() {
if (compileList.length > 0) {
log("Compiling " + compileList.length + " source file"
+ (compileList.length == 1 ? "" : "s")
+ (getDestdir() != null ? " to " + getDestdir() : ""));
if (listFiles) {
for (int i = 0; i < compileList.length; i++) {
String filename = compileList[i].getAbsolutePath();
log(filename);
}
}
CompilerAdapter adapter = new VisageCompilerAdapter();
// now we need to populate the compiler adapter
adapter.setJavac(this);
// finally, lets execute the compiler!!
if (!adapter.execute()) {
if (failOnError) {
throw new BuildException(FAIL_MSG, getLocation());
} else {
log(FAIL_MSG, Project.MSG_ERR);
}
}
}
}
public void setCompilerClassPath(Path p) {
compilerClassPath = p;
}
public void setCompilerClassPathRef(Reference r) {
setCompilerClassPath((Path) r.getReferencedObject());
}
private URL[] pathAsURLs() throws java.net.MalformedURLException {
Path p = compilerClassPath != null ? compilerClassPath : new Path(getProject());
java.util.ArrayList<URL> urls = new java.util.ArrayList<URL>();
for (String s : p.list()) {
urls.add(new File(s).toURI().toURL());
}
return urls.toArray(new URL[0]);
}
public void setProfile(String s) {
profile = s;
}
@Override
public String getCompiler() {
return "extJavac";
}
@Override
protected void checkParameters() throws BuildException {
super.checkParameters();
if (super.getExecutable() == null && compilerClassPath == null) {
throw new BuildException("visagec: executable or compilerclasspath must be set", getLocation());
}
}
public static class VisageCompilerAdapter extends DefaultCompilerAdapter {
public boolean execute() throws BuildException {
try {
if (getJavac().isForkedJavac())
return forkeExecute();
else {
Commandline cmd = setupModernJavacCommand();
URL[] jars = ((VisageAntTask) getJavac()).pathAsURLs();
URLClassLoader loader = new URLClassLoader(jars) {
@Override
protected Class loadClass(String n, boolean r) throws ClassNotFoundException {
if (n.indexOf("sun.tools") >= 0 || n.startsWith("com.sun.source")) {
Class c = findLoadedClass(n);
if (c != null) {
getJavac().log("found loaded class: " + n);
return c;
}
c = findClass(n);
if (c == null) {
getJavac().log("didn't find class: " + n);
return super.loadClass(n, r);
}
if (r)
resolveClass(c);
return c;
}
return super.loadClass(n, r);
}
};
Class c = Class.forName(VISAGE_ENTRY_POINT, true, loader);
Object compiler = c.newInstance();
Method compile = c.getMethod("compile", String[].class);
Object[] args = cmd.getArguments();
int result = (Integer) compile.invoke(compiler, new Object[]{args});
return (result == 0); // zero errors
}
} catch (Exception ex) {
getJavac().log(ex.toString());
if (ex instanceof ClassNotFoundException ||
ex instanceof java.lang.reflect.InvocationTargetException) {
throw new BuildException(ex);
}
if (ex instanceof BuildException) {
throw (BuildException) ex;
} else {
throw new BuildException("Error starting Visage compiler",
ex, location);
}
}
}
public boolean forkeExecute() throws Exception {
Commandline cmd = new Commandline();
String executable = getJavac().getExecutable();
if (executable != null) {
cmd.setExecutable(executable);
if (((VisageAntTask) getJavac()).compilerClassPath != null) {
getJavac().log("Ignoring attribute compilerclasspath, because executable is set.", Project.MSG_WARN);
}
} else {
cmd.setExecutable(JavaEnvUtils.getJdkExecutable("java"));
if (memoryInitialSize != null) {
cmd.createArgument().setValue("-Xms" + memoryInitialSize);
memoryInitialSize = null; // don't include it in setupJavacCommandlineSwitches()
}
if (memoryMaximumSize != null) {
cmd.createArgument().setValue("-Xmx" + memoryMaximumSize);
memoryMaximumSize = null; // don't include it in setupJavacCommandlineSwitches()
}
String cp = "-Xbootclasspath/p:" +
((VisageAntTask) getJavac()).compilerClassPath.toString();
cmd.createArgument().setValue(cp);
cmd.createArgument().setValue(VISAGE_ENTRY_POINT);
}
String profile = ((VisageAntTask) getJavac()).profile;
if (profile != null) {
cmd.createArgument().setLine("-profile " + profile);
}
setupJavacCommandlineSwitches(cmd, true);
int firstFileName = cmd.size();
logAndAddFilesToCompile(cmd);
return executeExternalCompile(cmd.getCommandline(), firstFileName, true) == 0;
}
}
}