01: /*
02: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
03: * Distributed under the terms of either:
04: * - the common development and distribution license (CDDL), v1.0; or
05: * - the GNU Lesser General Public License, v2.1 or later
06: * $Id: ContinuationsBytecodeTransformer.java 3811 2007-06-25 15:06:16Z gbevin $
07: */
08: package com.uwyn.rife.continuations.instrument;
09:
10: import com.uwyn.rife.asm.ClassReader;
11: import com.uwyn.rife.asm.ClassVisitor;
12: import com.uwyn.rife.asm.ClassWriter;
13: import com.uwyn.rife.continuations.ContinuationConfigInstrument;
14: import com.uwyn.rife.continuations.instrument.ContinuationDebug;
15: import com.uwyn.rife.continuations.instrument.MetricsClassVisitor;
16: import com.uwyn.rife.continuations.instrument.ResumableClassAdapter;
17: import com.uwyn.rife.continuations.instrument.TypesClassVisitor;
18: import java.util.logging.Level;
19:
20: /**
21: * Abstract class that transforms the bytecode of regular classes so that
22: * they support continuations functionalities.
23: *
24: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
25: * @version $Revision: 3811 $
26: * @since 1.6
27: */
28: public abstract class ContinuationsBytecodeTransformer {
29: /**
30: * Perform the class transformation.
31: * <p>If the class doesn't implement the marker interface that is setup
32: * in the instrumentation config, the original bytes will be returned.
33: *
34: * @param configInstrument the configuration for the instrumentation
35: * @param rawBytes the raw bytes of the class to instrument
36: * @param classname the name of the class to instrument
37: * @return a byte array with the instrumented bytecode; or
38: * <p>the original raw byte array if the class didn't need to be
39: * instrumented
40: * @throws ClassNotFoundException when an error occurs during the
41: * inspection or transformation
42: * @since 1.6
43: */
44: public static byte[] transformIntoResumableBytes(
45: ContinuationConfigInstrument configInstrument,
46: byte[] rawBytes, String classname)
47: throws ClassNotFoundException {
48: // adapts the class on the fly
49: byte[] resumable_bytes = null;
50: boolean skip_debug = false;
51: try {
52: ContinuationDebug.LOGGER.finest("METRICS:");
53: ClassReader metrics_reader = new ClassReader(rawBytes);
54: MetricsClassVisitor metrics_visitor = new MetricsClassVisitor(
55: configInstrument, classname);
56: metrics_reader.accept(metrics_visitor, skip_debug);
57: ContinuationDebug.LOGGER.finest("\n");
58:
59: if (metrics_visitor.makeResumable()) {
60: ContinuationDebug.LOGGER.finest("TYPES:");
61: ClassReader types_reader = new ClassReader(rawBytes);
62: TypesClassVisitor types_visitor = new TypesClassVisitor(
63: configInstrument, metrics_visitor, classname);
64: types_reader.accept(types_visitor, skip_debug);
65: ContinuationDebug.LOGGER.finest("\n");
66:
67: ContinuationDebug.LOGGER.finest("SOURCE:");
68: ClassReader resumable_reader = new ClassReader(rawBytes);
69: ClassWriter resumable_writer = new ClassWriter(true);
70: ClassVisitor resumable_visitor = new ResumableClassAdapter(
71: configInstrument, metrics_visitor,
72: types_visitor, classname, resumable_writer);
73: resumable_reader.accept(resumable_visitor, skip_debug);
74: resumable_bytes = resumable_writer.toByteArray();
75: ContinuationDebug.LOGGER.finest("\n");
76:
77: ///CLOVER:OFF
78: if (ContinuationDebug.LOGGER.isLoggable(Level.FINEST)) {
79: ContinuationDebug.LOGGER.finest("RESULT:");
80: ClassReader reporting_reader = new ClassReader(
81: resumable_bytes);
82: ClassVisitor reporting_visitor = new ResumableClassAdapter(
83: configInstrument, null, null, classname,
84: null);
85: reporting_reader.accept(reporting_visitor,
86: skip_debug);
87: }
88: ///CLOVER:ON
89: }
90: } catch (Exception e) {
91: throw new ClassNotFoundException(classname, e);
92: }
93:
94: return resumable_bytes;
95: }
96: }
|