CompileCommand.java
/* *******************************************************************
* Copyright (c) 2003 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* Wes Isberg initial implementation
* Helen Hawkins Converted to new interface (bug 148190)
* ******************************************************************/
package org.aspectj.testing.ajde;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.aspectj.ajde.core.AjCompiler;
import org.aspectj.ajde.core.IBuildMessageHandler;
import org.aspectj.ajde.core.IBuildProgressMonitor;
import org.aspectj.ajde.core.ICompilerConfiguration;
import org.aspectj.ajde.core.IOutputLocationManager;
import org.aspectj.ajde.core.JavaOptions;
import org.aspectj.bridge.AbortException;
import org.aspectj.bridge.ICommand;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessage.Kind;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.MessageHandler;
import org.aspectj.testing.harness.bridge.Globals;
import org.aspectj.util.FileUtil;
/**
* This re-uses the same config file to setup ajde so that recompiles appear to be of the same configuration.
*
* @since Java 1.3 (uses dynamic proxies)
*/
public class CompileCommand implements ICommand {
// time out waiting for build at three minutes
long MAX_TIME = 180 * 1000;
// this proxy ignores calls
InvocationHandler proxy = new VoidInvocationHandler();
InvocationHandler loggingProxy = new LoggingInvocationHandler();
MyMessageHandler myHandler = new MyMessageHandler();
long endTime;
boolean buildNextFresh;
File tempDir;
private AjCompiler compiler;
/**
* Clients call this before repeatCommand as a one-shot request for a full rebuild of the same configuration. (Requires a
* downcast from ICommand to CompileCommand.)
*/
public void buildNextFresh() {
buildNextFresh = true;
}
// --------- ICommand interface
public boolean runCommand(String[] args, IMessageHandler handler) {
setup(args);
myHandler.start();
long startTime = System.currentTimeMillis();
try {
compiler.buildFresh();
} finally {
runCommandCleanup();
}
return !myHandler.hasError();
}
public boolean repeatCommand(IMessageHandler handler) {
myHandler.start();
long startTime = System.currentTimeMillis();
// System.err.println("recompiling...");
if (buildNextFresh) {
buildNextFresh = false;
compiler.buildFresh();
} else {
compiler.build();
}
return !myHandler.hasError();
}
void runCommandCleanup() {
if (null != tempDir) {
FileUtil.deleteContents(tempDir);
tempDir.delete();
}
}
// set by build progress monitor when done
void setEndTime(long endTime) {
this.endTime = endTime;
}
private void setup(String[] args) {
File config = writeConfig(args);
if (null == config) {
throw new Error("unable to write config file");
}
IBuildProgressMonitor buildProgressMonitor = new MyBuildProgressMonitor();
String classesDir = "../testing/bin/classes";
for (int i = 0; i < args.length; i++) {
if ("-d".equals(args[i]) && ((1 + i) < args.length)) {
classesDir = args[1 + i];
break;
}
}
MyCompilerConfig compilerConfig = new MyCompilerConfig();
compiler = new AjCompiler("blah", compilerConfig, buildProgressMonitor, myHandler);
}
private File writeConfig(String[] args) {
tempDir = FileUtil.getTempDir("CompileCommand");
File result = new File(tempDir, "config.lst");
OutputStream out = null;
try {
out = new FileOutputStream(result);
PrintStream outs = new PrintStream(out, true);
for (String arg : args) {
outs.println(arg);
}
return result;
} catch (IOException e) {
return null;
} finally {
try {
out.close();
} catch (IOException e) {
}
}
}
// private Object makeLoggingProxy(Class interfac) {
// return Proxy.newProxyInstance(
// interfac.getClassLoader(),
// new Class[] { interfac },
// loggingProxy);
// }
private Object makeProxy(Class interfac) {
return Proxy.newProxyInstance(interfac.getClassLoader(), new Class[] { interfac }, proxy);
}
}
class MyMessageHandler implements IBuildMessageHandler {
boolean hasError;
boolean hasWarning;
private MessageHandler messageHandler = new MessageHandler(false);
public boolean handleMessage(IMessage message) throws AbortException {
maintainHasWarning(message.getKind());
return messageHandler.handleMessage(message);
}
private void maintainHasWarning(IMessage.Kind kind) {
if (!hasError) {
if (IMessage.ERROR.isSameOrLessThan(kind)) {
hasError = true;
hasWarning = true;
}
}
if (!hasWarning && IMessage.WARNING.isSameOrLessThan(kind)) {
hasWarning = true;
}
}
public boolean hasWarning() {
return hasWarning;
}
public boolean hasError() {
return hasError;
}
public void start() {
hasWarning = false;
hasError = false;
messageHandler.init(true);
}
public void dontIgnore(Kind kind) {
messageHandler.dontIgnore(kind);
}
public void ignore(Kind kind) {
messageHandler.ignore(kind);
}
public boolean isIgnoring(Kind kind) {
return messageHandler.isIgnoring(kind);
}
}
class MyBuildProgressMonitor implements IBuildProgressMonitor {
public void begin() {
}
public void finish(boolean wasFullBuild) {
}
public boolean isCancelRequested() {
return false;
}
public void setProgress(double percentDone) {
}
public void setProgressText(String text) {
}
}
class VoidInvocationHandler implements InvocationHandler {
public Object invoke(Object me, Method method, Object[] args) throws Throwable {
// System.err.println("Proxying"
// // don't call toString on self b/c proxied
// // + " me=" + me.getClass().getName()
// + " method=" + method
// + " args=" + (LangUtil.isEmpty(args)
// ? "[]" : Arrays.asList(args).toString()));
return null;
}
}
class LoggingInvocationHandler implements InvocationHandler {
public Object invoke(Object me, Method method, Object[] args) throws Throwable {
System.err.println("Proxying " + render(method, args));
return null;
}
public static String render(Class c) {
if (null == c) {
return "(Class) null";
}
String result = c.getName();
if (result.startsWith("java")) {
int loc = result.lastIndexOf(".");
if (-1 != loc) {
result = result.substring(loc + 1);
}
}
return result;
}
public static String render(Method method, Object[] args) {
StringBuilder sb = new StringBuilder();
sb.append(render(method.getReturnType()));
sb.append(" ");
sb.append(method.getName());
sb.append("(");
Class[] parmTypes = method.getParameterTypes();
int parmTypesLength = (null == parmTypes ? 0 : parmTypes.length);
int argsLength = (null == args ? 0 : args.length);
boolean doType = (parmTypesLength == argsLength);
for (int i = 0; i < argsLength; i++) {
if (i > 0) {
sb.append(", ");
}
if (doType) {
sb.append("(");
sb.append(render(parmTypes[i]));
sb.append(") ");
}
if (null == args[i]) {
sb.append("null");
} else { // also don't recurse into proxied toString?
sb.append(args[i].toString());
}
}
sb.append(")");
return sb.toString();
}
}
class MyCompilerConfig implements ICompilerConfiguration {
private Set inpath;
private Set aspectPath;
private String outJar;
private IOutputLocationManager locationMgr;
public Set getAspectPath() {
return aspectPath;
}
public void setAspectPath(Set path) {
aspectPath = path;
}
public String getClasspath() {
return Globals.S_aspectjrt_jar;
}
public Set getInpath() {
return inpath;
}
public void setInpath(Set input) {
inpath = input;
}
public Map getJavaOptionsMap() {
return JavaOptions.getDefaultJavaOptions();
}
public List getProjectXmlConfigFiles() {
return Collections.EMPTY_LIST;
}
public String getOutJar() {
return outJar;
}
public void configurationRead() {
}
public void setOutJar(String input) {
outJar = input;
}
public IOutputLocationManager getOutputLocationManager() {
if (locationMgr == null) {
locationMgr = new MyOutputLocationManager();
}
return locationMgr;
}
public String getNonStandardOptions() {
return null;
}
public List getProjectSourceFiles() {
return null;
}
public List getProjectSourceFilesChanged() {
return null;
}
public Map getSourcePathResources() {
return null;
}
public int getConfigurationChanges() {
return ICompilerConfiguration.EVERYTHING;
}
public List getClasspathElementsWithModifiedContents() {
return null;
}
public String getProjectEncoding() {
return null;
}
public String getProcessor() {
return null;
}
public String getProcessorPath() {
return null;
}
@Override
public String getModulepath() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getModuleSourcepath() {
// TODO Auto-generated method stub
return null;
}
}
class MyOutputLocationManager implements IOutputLocationManager {
public List getAllOutputLocations() {
return null;
}
public File getDefaultOutputLocation() {
return null;
}
public File getOutputLocationForClass(File compilationUnit) {
return null;
}
public File getOutputLocationForResource(File resource) {
return null;
}
public String getUniqueIdentifier() {
return null;
}
public Map getInpathMap() {
return Collections.EMPTY_MAP;
}
public String getSourceFolderForFile(File sourceFile) {
return null;
}
public void reportFileWrite(String outputfile, int filetype) {
}
public void reportFileRemove(String outputfile, int filetype) {
}
public int discoverChangesSince(File dir, long buildtime) {
return 0;
}
public String getProjectEncoding() {
return null;
}
}