package edu.neu.ccs.demeter.tools.daj;
import edu.neu.ccs.demeter.dj.*;
import java.io.*;
import java.util.*;
/** The main DAJ functionality. */
public class DAJ {
// There's no need to instantiate this class.
DAJ() { }
/** Compile a DAJ project, then exit the VM.
@param args command line arguments
*/
public static void main(String args[]) {
if (args.length == 0) {
CommandLine.printUsage();
System.exit(-1);
}
System.exit(compile(args));
}
/** Compile a DAJ project.
@param args command line arguments
@return the exit code
*/
public static int compile(String args[]) {
// parse the command line so that we can process this compilation
CommandLine cmdLine;
try {
cmdLine = new CommandLine(args);
} catch (CommandLineException e) {
System.out.println("Error: " + e.getMessage());
return -1;
}
return compile(cmdLine);
}
static int compile(CommandLine cmdLine) {
// generate some stubs for traversal generation compilation
if (!generateStubs(cmdLine))
return -1;
if (cmdLine.isTraversalGenerationOption())
return 0;
// run the ajc compiler to compile the code
// to generate the traversals
if (!compileStubs(cmdLine))
return -1;
if (cmdLine.isTraversalGenerationCompilationOption())
return 0;
// run traversalj to generate the traversal files
if (!generateTraversals(cmdLine))
return -1;
if (cmdLine.isTraversalCompilationOption())
return 0;
// compile the generated traversal code with original
if (!compileTraversals(cmdLine))
return -1;
return 0;
}
static boolean generateStubs(CommandLine cmdLine) {
return generateStubs(cmdLine.getTraversalFiles(),
cmdLine.getTraversalDestinationOption());
}
/** Generate a stub aspect file to the current directory
for each traversal file.
@param traversalFiles a list of .trv
files
@return false if there are any errors
*/
public static boolean generateStubs(List traversalFiles) {
return generateStubs(traversalFiles, null);
}
/** Generate a stub aspect file for each traversal file.
@param traversalFiles a list of .trv
files
@param destinationDirectory the output directory for the stubs
@return false if there are any errors
*/
public static boolean generateStubs(List traversalFiles,
File destinationDirectory) {
boolean returnVal = true;
System.out.println("\n%I - Generating Stubs");
for (Iterator it = traversalFiles.iterator(); it.hasNext();) {
File f = (File) it.next();
try {
Reader in = new BufferedReader(new FileReader(f));
TraversalAspectList tal = TraversalAspectList.parse(in);
returnVal = tal.generateStubs(destinationDirectory, getRootName(f))
&& returnVal;
} catch (Exception e) {
System.out.println(e);
returnVal = false;
}
}
return returnVal;
}
static boolean compileStubs(CommandLine cmdLine) {
return compileStubs(cmdLine.getAJC(),
cmdLine.getTraversalFiles(),
cmdLine.getTraversalDestinationOption(),
cmdLine.getJavaFiles(),
cmdLine.getAJCOptions(),
cmdLine.getTempFileDirOption());
}
/** Compile the generated stub aspects along with the source aspects.
@param ajc the aspect compiler executable, or null to invoke ajc on the
class path
@param traversalFiles a list of .trv
files
@param stubsDirectory the directory the stubs were generated into
@param aspectFiles a list of aspect source files
@param AJCOptions a list of options for the aspect compiler
@param destinationDirectory the output directory for the class files
*/
public static boolean compileStubs(String ajc,
List traversalFiles,
File stubsDirectory,
List aspectFiles,
List AJCOptions,
File destinationDirectory)
{
List args = new ArrayList();
if (destinationDirectory != null) {
args.add("-d");
args.add(destinationDirectory);
}
if (AJCOptions != null) args.addAll(AJCOptions);
if (aspectFiles != null) args.addAll(aspectFiles);
args.addAll(getGeneratedFiles(traversalFiles, stubsDirectory));
System.out.println("\n%I - traversal generation compilation\n"
+ (ajc == null ? "ajc" : ajc) + " "
+ toStringWithSpaces(args));
return compileAspects(ajc, args);
}
static boolean generateTraversals(CommandLine cmdLine) {
return generateTraversals(cmdLine.getTraversalFiles(),
cmdLine.getTempFileDirOption(),
cmdLine.getGeneratePrintingAdviceOption(),
cmdLine.getGenerationClassPathOption(),
cmdLine.getTraversalDestinationOption());
}
/** Generate a traversal aspect file for each traversal file.
@param traversalFiles a list of .trv
files
@param stubClassesDirectory the directory the stubs were compiled into
@param generatePrintingAdvice should printing advice be generated?
@param classPath the class path to be used for invoking DJ
@param destinationDirectory the output directory for the traversal aspects
*/
public static boolean generateTraversals(List traversalFiles,
File stubClassesDirectory,
boolean generatePrintingAdvice,
String classPath,
File destinationDirectory)
{
if (stubClassesDirectory != null) {
if (classPath == null) classPath = System.getProperty("java.class.path");
classPath = stubClassesDirectory + File.pathSeparator + classPath;
}
List args = new ArrayList();
if (generatePrintingAdvice)
args.add("-gpa");
if (destinationDirectory != null) {
args.add("-d");
args.add(destinationDirectory);
}
args.addAll(traversalFiles);
// return generateTraversals(classPath, args);
return generateTraversalsExec(classPath, args);
}
// This doesn't work, because the current ClassLoader ignores the new
// class path.
static boolean generateTraversals(String classPath, List args) {
System.out.println("\n%I - traversal generation");
if (classPath != null) {
System.out.println("CLASSPATH = " + classPath);
System.setProperty("java.class.path", classPath);
}
System.out.println("CreateClassGraph "
+ toStringWithSpaces(args));
CreateClassGraph.main(toStringArray(args));
return true;
}
static boolean generateTraversalsExec(String classPath, List args) {
List cmd = new ArrayList();
cmd.add("java");
if (classPath != null) {
cmd.add("-cp");
cmd.add(classPath);
}
cmd.add("edu.neu.ccs.demeter.tools.daj.CreateClassGraph");
cmd.addAll(args);
System.out.println("\n%I - traversal generation\n"
+ toStringWithSpaces(cmd));
return executeCommand(cmd);
}
static boolean compileTraversals(CommandLine cmdLine) {
return compileTraversals(cmdLine.getAJC(),
cmdLine.getTraversalFiles(),
cmdLine.getTraversalDestinationOption(),
cmdLine.getJavaFiles(),
cmdLine.getAJCOptions(),
cmdLine.getTempFileDirOption());
}
/** Compile the generated traversal aspects along with the source aspects.
@param ajc the aspect compiler executable, or null to invoke ajc on the
class path
@param traversalFiles a list of .trv
files
@param traversalsDirectory the directory the traversal aspects were
generated into
@param aspectFiles a list of aspect source files
@param AJCOptions a list of options for the aspect compiler
@param destinationDirectory the output directory for the class files
*/
public static boolean compileTraversals(String ajc,
List traversalFiles,
File traversalsDirectory,
List aspectFiles,
List AJCOptions,
File destinationDirectory)
{
List args = new ArrayList();
if (destinationDirectory != null) {
args.add("-d");
args.add(destinationDirectory);
}
if (AJCOptions != null) args.addAll(AJCOptions);
if (aspectFiles != null) args.addAll(aspectFiles);
args.addAll(getGeneratedFiles(traversalFiles, traversalsDirectory));
System.out.println("\n%I - traversal compilation\n"
+ (ajc == null ? "ajc" : ajc) + " "
+ toStringWithSpaces(args));
return compileAspects(ajc, args);
}
/** Compile a list of aspects.
@param ajc the aspect compiler executable, or null to invoke ajc on the
class path
@param argList the command line arguments to the aspect compiler
@return false if there are any errors
*/
public static boolean compileAspects(String ajc, List argList) {
if (ajc == null) {
String args[] = toStringArray(argList);
return (new org.aspectj.tools.ajc.Main().compile(args) == 0);
}
List cmd = new ArrayList();
cmd.add(ajc);
cmd.addAll(argList);
return executeCommand(cmd);
}
static boolean executeCommand(List cmdList) {
return executeCommand(toStringArray(cmdList));
}
static boolean executeCommand(String cmd[]) {
Process cmdProc = null;
try {
cmdProc = Runtime.getRuntime().exec(cmd);
InputStream err = cmdProc.getErrorStream();
//forwardOutputStream(System.out, err);
InputStream in = cmdProc.getInputStream();
//forwardOutputStream(System.out, in);
StreamFunnel sf = new StreamFunnel(err, in, System.out);
sf.run();
cmdProc.waitFor();
// System.out.println("exit value = " + cmdProc.exitValue());
if (cmdProc.exitValue() != 0) {
System.out.println("Error executing command: "
+ toStringWithSpaces(cmd));
}
cmdProc.destroy();
} catch (IllegalThreadStateException e) {
e.printStackTrace(System.out);
cmdProc.destroy();
return false;
} catch (java.io.IOException e) {
System.out.print("%ERROR : ");
System.out.println(e);
System.out.println("\n%Information : \n "
+ "You might need to specify -ajc ajc.bat or some other\n"
+ "string as the command to execute the AspectJ Compiler.\n"
+ "DAJ is not smart enough to know that you're using windows\n"
+ "and need to have ajc.bat instead of ajc.");
return false;
} catch (Exception e) {
System.out.println(e);
e.printStackTrace(System.out);
return false;
}
return true;
}
static void forwardOutputStream(OutputStream out, InputStream in) throws IOException{
int read = in.read();
while (read > 0) {
out.write((byte) read);
read = in.read();
}
}
/** A list of generated aspect files.
@param traversalFiles a list of .trv
files
@param destinationDirectory the directory the aspects are generated into
*/
public static List getGeneratedFiles(List traversalFiles,
File destinationDirectory)
{
List files = new ArrayList();
Iterator it = traversalFiles.iterator();
while (it.hasNext()) {
File f = (File) it.next();
files.add(new File(destinationDirectory, getRootName(f) + ".java"));
}
return files;
}
/** The file name without its final ".xxx" extension. */
static String getRootName(File f) {
return getRootName(f.getName());
}
/** The file name without its final ".xxx" extension. */
static String getRootName(String fname) {
return fname.substring(0, fname.lastIndexOf("."));
}
static String[] toStringArray(List list) {
String array[] = new String[list.size()];
int i = 0;
for (Iterator it = list.iterator(); it.hasNext(); i++)
array[i] = it.next().toString();
return array;
}
static String toStringWithSpaces(Object x[]) {
return toStringWithSpaces(Arrays.asList(x));
}
static String toStringWithSpaces(List x) {
String s = "";
Iterator it = x.iterator();
while (it.hasNext()) {
s += it.next();
if (it.hasNext()) s += " ";
}
return s;
}
}