1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sf.jour;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Properties;
29 import java.util.Vector;
30
31 import javassist.ClassPool;
32 import javassist.CtClass;
33 import javassist.NotFoundException;
34 import net.sf.jour.instrumentor.Instrumentor;
35 import net.sf.jour.instrumentor.InstrumentorResults;
36 import net.sf.jour.instrumentor.InstrumentorResultsImpl;
37 import net.sf.jour.log.Logger;
38 import net.sf.jour.processor.DirectoryInputSource;
39 import net.sf.jour.processor.DirectoryOutputWriter;
40 import net.sf.jour.processor.Entry;
41 import net.sf.jour.processor.EntryHelper;
42 import net.sf.jour.processor.InputSource;
43 import net.sf.jour.processor.InstrumentedCreatedEntry;
44 import net.sf.jour.processor.InstrumentedEntry;
45 import net.sf.jour.processor.JarFileInputSource;
46 import net.sf.jour.processor.OutputWriter;
47 import net.sf.jour.util.BuildVersion;
48 import net.sf.jour.util.CmdArgs;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class PreProcessor {
65
66 protected static final Logger log = Logger.getLogger();
67
68 public long savedClasses;
69
70 public long countClasses;
71
72 private long countMethods;
73
74 private long countCounstructors;
75
76 private File input;
77
78 private File output;
79
80 private boolean copyClasses = false;
81
82 private boolean copyResources = false;
83
84 private boolean useSystemClassPath = false;
85
86 Config config;
87
88 ClassPool classPool;
89
90 public static void main(String[] args) {
91 Properties argsp = CmdArgs.load(args);
92 if ((args.length < 1) || argsp.getProperty("help") != null) {
93 StringBuffer usage = new StringBuffer();
94 usage.append("Usage:\n java ").append(PreProcessor.class.getName());
95 usage.append(" --config jour.xml --src classesDir|classes.jar --dst outDir\n");
96 usage.append(" (--classpath classpath) (--copy resource|classes|all) (--systempath)\n");
97 System.out.println(usage);
98 return;
99 }
100
101 try {
102 PreProcessor pp = new PreProcessor(argsp);
103 pp.process();
104
105 System.out.println("Processed Classes " + pp.countClasses);
106 System.out.println("Altered Counstructors " + pp.countCounstructors);
107 System.out.println("Altered Methods " + pp.countMethods);
108 System.out.println("Saved Classes " + pp.savedClasses);
109
110 } catch (Throwable e) {
111 e.printStackTrace();
112 throw new Error(e);
113 }
114 }
115
116 public PreProcessor(String[] args) throws NotFoundException {
117 this(CmdArgs.load(args));
118 }
119
120 public PreProcessor(Properties properties) throws NotFoundException {
121 String configFileName = properties.getProperty("config");
122 String out = properties.getProperty("dst");
123 String in = properties.getProperty("src");
124 if (out == null) {
125 out = in;
126 }
127 String copy = properties.getProperty("config");
128 if ("all".equalsIgnoreCase(copy)) {
129 setCopyClasses(true);
130 setCopyResources(true);
131 } else if ("classes".equalsIgnoreCase(copy)) {
132 setCopyClasses(true);
133 } else if ("resources".equalsIgnoreCase(copy)) {
134 setCopyResources(true);
135 }
136
137 this.useSystemClassPath = "true".equals(properties.getProperty("systempath"));
138
139 List classpath = new Vector();
140
141 Object cp = properties.get("cp");
142 if (cp != null) {
143 if (cp instanceof List) {
144 classpath.addAll((List) cp);
145 } else {
146 classpath.add(cp);
147 }
148 }
149 cp = properties.get("classpath");
150 if (cp != null) {
151 if (cp instanceof List) {
152 classpath.addAll((List) cp);
153 } else {
154 classpath.add(cp);
155 }
156 }
157
158 try {
159 init(configFileName, new File(in).getCanonicalFile(), new File(out).getCanonicalFile(), classpath);
160 } catch (IOException e) {
161 throw new Error("Can't configure input/output path", e);
162 }
163 }
164
165 public PreProcessor(String configFileName, File in, File out, List classpath) {
166 init(configFileName, in, out, classpath);
167 }
168
169 private void init(String configFileName, File in, File out, List classpath) {
170 if ((in == null) || (!in.exists())) {
171 throw new Error("Input jar or folder expected");
172 }
173 if (in.isFile() && (!in.getName().endsWith(".jar"))) {
174 throw new Error("Input file should be .jar");
175 }
176 log.debug("input " + in.getAbsolutePath());
177 log.debug("output " + out.getAbsolutePath());
178 this.input = in;
179 this.output = out;
180 this.config = new Config(configFileName);
181 this.classPool = new ClassPool();
182 try {
183 this.classPool.appendClassPath(this.input.getAbsolutePath());
184
185 if (classpath != null) {
186 for (Iterator i = classpath.iterator(); i.hasNext();) {
187 String path = (String) i.next();
188 log.debug("classPath " + path);
189 this.classPool.appendPathList(path);
190 }
191 }
192 } catch (NotFoundException e) {
193 log.error("Can't setup class path", e);
194 throw new ConfigException("Can't setup class path", e);
195 }
196 }
197
198 public void process() throws Exception {
199
200 log.info("Jour, version " + BuildVersion.getVersion());
201
202 if (this.useSystemClassPath) {
203 log.debug("useSystemClassPath");
204 this.classPool.appendSystemPath();
205 }
206
207 OutputWriter outputWriter;
208 if (!output.isFile()) {
209 outputWriter = new DirectoryOutputWriter(output);
210 } else {
211 throw new ConfigException("jar output not supported yet");
212 }
213
214 InputSource inputSource;
215 if (input.isDirectory()) {
216 inputSource = new DirectoryInputSource(input);
217 } else {
218 inputSource = new JarFileInputSource(input);
219 }
220
221 int countEntry = 0;
222 int countResources = 0;
223 int countNIClasses = 0;
224 try {
225
226 for (Enumeration en = inputSource.getEntries(); en.hasMoreElements();) {
227 Entry e = (Entry) en.nextElement();
228 log.debug(e.getName());
229 if (outputWriter.needUpdate(e)) {
230 if (!e.isClass()) {
231 if (isCopyResources()) {
232 outputWriter.write(e);
233 countResources++;
234 }
235 } else {
236 if (instrument(e, outputWriter) == InstrumentorResultsImpl.NOT_MODIFIED) {
237 if (isCopyClasses()) {
238 outputWriter.write(e);
239 countNIClasses++;
240 }
241 }
242 }
243 }
244 countEntry++;
245 }
246 } finally {
247 inputSource.close();
248 outputWriter.close();
249 }
250 log.debug("countEntry " + countEntry);
251
252 log.info("Processed Classes " + this.countClasses);
253 log.info("Altered Counstructors " + this.countCounstructors);
254 log.info("Altered Methods " + this.countMethods);
255 log.info("Saved Classes " + this.savedClasses);
256 if (isCopyClasses()) {
257 log.info("NotInstr Classes " + countNIClasses);
258 }
259 if (isCopyResources()) {
260 log.info("Resources " + countResources);
261 }
262 }
263
264 public InstrumentorResults instrument(Entry entry, OutputWriter outputWriter) throws IOException {
265 this.countClasses++;
266 String className = EntryHelper.getClassName(entry);
267 Instrumentor[] instrumentors = config.getInstrumentors(className);
268 if (instrumentors.length > 0) {
269 log.debug("intercepting class " + className);
270 Interceptor interceptor = new Interceptor(config, classPool, className, instrumentors);
271 CtClass ctClass = interceptor.instrument();
272 InstrumentorResults rc = interceptor.getInstrumentorResults();
273 log.debug("intercepted methods " + rc.getCountMethods());
274 if (rc.isModified()) {
275 this.savedClasses++;
276 this.countCounstructors += rc.getCountCounstructors();
277 this.countMethods += rc.getCountMethods();
278 outputWriter.write(new InstrumentedEntry(entry, ctClass));
279 if (rc.getCreatedClasses() != null) {
280 for (Iterator i = rc.getCreatedClasses().iterator(); i.hasNext();) {
281 outputWriter.write(new InstrumentedCreatedEntry(entry, ctClass, (CtClass) i.next()));
282 this.savedClasses++;
283 }
284 }
285 return rc;
286 }
287 }
288 return InstrumentorResultsImpl.NOT_MODIFIED;
289 }
290
291 public long getCountCounstructors() {
292 return countCounstructors;
293 }
294
295 public long getCountMethods() {
296 return countMethods;
297 }
298
299 public long getSavedClasses() {
300 return savedClasses;
301 }
302
303 public long getCountClasses() {
304 return countClasses;
305 }
306
307
308
309
310 public boolean isCopyClasses() {
311 return copyClasses;
312 }
313
314
315
316
317
318 public void setCopyClasses(boolean copyClasses) {
319 this.copyClasses = copyClasses;
320 }
321
322
323
324
325 public boolean isCopyResources() {
326 return copyResources;
327 }
328
329
330
331
332
333 public void setCopyResources(boolean copyResources) {
334 this.copyResources = copyResources;
335 }
336
337
338
339
340 public boolean isUseSystemClassPath() {
341 return useSystemClassPath;
342 }
343
344
345
346
347
348 public void setUseSystemClassPath(boolean useSystemClassPath) {
349 this.useSystemClassPath = useSystemClassPath;
350 }
351
352 }