001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon;
019:
020: import java.io.File;
021: import java.lang.reflect.Method;
022: import java.util.ArrayList;
023:
024: import spoon.processing.ProcessingManager;
025: import spoon.support.RuntimeProcessingManager;
026:
027: import com.martiansoftware.jsap.FlaggedOption;
028: import com.martiansoftware.jsap.JSAP;
029: import com.martiansoftware.jsap.JSAPException;
030:
031: /**
032: * This launcher can run a program within a special {@link SpoonClassLoader}
033: * that will process the used classes at load time. Actually this launcher
034: * accepts a list of processors that will be applied before the program is run,
035: * and another list of processors that will be applied at load-time (only once
036: * the classes are used and not before). You can then process bytecode at
037: * load-time by using this launcher with the decompile option. Launch with no
038: * arguments (see {@link #main(String[])}) for detailed usage.
039: */
040: public class LtLauncher extends Launcher {
041:
042: /**
043: * Starts a program with this launcher.
044: *
045: * @param args
046: * run with no args to print usage
047: * @throws JSAPException
048: * @throws Exception
049: * any untrapped exception
050: */
051: static public void main(String args[]) throws Exception {
052: new LtLauncher(args).run();
053: }
054:
055: /**
056: * Constructor with arguments.
057: */
058: public LtLauncher(String[] args) throws JSAPException {
059: super (args);
060: }
061:
062: /**
063: * Defines the arguments accepted by this launcher.
064: */
065: protected JSAP defineArgs() throws JSAPException {
066: JSAP jsap = super .defineArgs();
067:
068: // Processor qualified name
069: FlaggedOption opt2 = new FlaggedOption("ltprocessors");
070: opt2.setShortFlag('l');
071: opt2.setLongFlag("ltprocessors");
072: opt2.setHelp("List of load-time processors to use");
073: opt2.setStringParser(JSAP.STRING_PARSER);
074: opt2.setRequired(false);
075: jsap.registerParameter(opt2);
076:
077: opt2 = new FlaggedOption("sourcepath");
078: opt2.setLongFlag("sourcepath");
079: opt2.setHelp("Specify where to find input source files");
080: opt2.setStringParser(JSAP.STRING_PARSER);
081: opt2.setRequired(false);
082: jsap.registerParameter(opt2);
083:
084: return jsap;
085: }
086:
087: java.util.List<String> ltprocessors = new ArrayList<String>();
088:
089: /**
090: * Adds a processor.
091: */
092: @Override
093: public void addProcessor(String name) {
094: super .addProcessor(name);
095: ltprocessors.add(name);
096: }
097:
098: /**
099: * Gets the loadtime processor types.
100: */
101: protected java.util.List<String> getLtProcessorTypes() {
102: if (getArguments().getString("ltprocessors") != null) {
103: for (String processorName : getArguments().getString(
104: "ltprocessors").split(File.pathSeparator)) {
105: ltprocessors.add(processorName);
106: }
107: }
108: return ltprocessors;
109: }
110:
111: /**
112: * Processes the program within a {@link SpoonClassLoader}.
113: */
114: @Override
115: public void run() throws Exception {
116: getFactory().getEnvironment().debugMessage(
117: "loading command-line arguments...");
118: processArguments();
119:
120: getFactory().getEnvironment().debugMessage(
121: "start Processing...");
122:
123: long t = System.currentTimeMillis();
124: build();
125: getFactory().getEnvironment().debugMessage(
126: "model built in " + (System.currentTimeMillis() - t)
127: + " ms");
128: t = System.currentTimeMillis();
129: process();
130: getFactory().getEnvironment().debugMessage(
131: "model processed in "
132: + (System.currentTimeMillis() - t) + " ms");
133: t = System.currentTimeMillis();
134:
135: // Create a CompilingClassLoader
136: SpoonClassLoader ccl = new SpoonClassLoader();
137: ccl.setFactory(getFactory());
138: if (getArguments().getString("sourcepath") != null)
139: ccl.setSourcePath(new File(getArguments().getString(
140: "sourcepath")));
141:
142: // Create runtime processing manager
143: ProcessingManager pm = new RuntimeProcessingManager(
144: getFactory());
145: for (String s : getLtProcessorTypes())
146: pm.addProcessor(s);
147: ccl.setProcessingManager(pm);
148:
149: getFactory().getEnvironment().debugMessage("running...");
150: // Gets main class
151: String progClass = getArguments().getString("class");
152: String progArgs[] = getArguments().getStringArray("arguments");
153:
154: // Launch main class using reflection
155: Class<?> clas = ccl.loadClass(progClass);
156: Class<?> mainArgType[] = { (new String[0]).getClass() };
157: Method main = clas.getMethod("main", mainArgType);
158: Object argsArray[] = { progArgs };
159: main.invoke(null, argsArray);
160: }
161: }
|