1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jdo.impl.enhancer.core;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.io.PrintWriter;
23 import java.io.DataInputStream;
24 import java.io.DataOutputStream;
25
26 import java.util.Properties;
27
28 import org.apache.jdo.impl.enhancer.ClassFileEnhancer;
29 import org.apache.jdo.impl.enhancer.EnhancerFatalError;
30 import org.apache.jdo.impl.enhancer.EnhancerUserException;
31 import org.apache.jdo.impl.enhancer.OutputStreamWrapper;
32 import org.apache.jdo.impl.enhancer.classfile.ClassFile;
33 import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData;
34 import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataUserException;
35 import org.apache.jdo.impl.enhancer.util.Support;
36
37
38
39
40
41
42
43 /***
44 * Provides a JDO byte-code enhancer.
45 */
46 public class EnhancerFilter
47 extends Support
48 implements ClassFileEnhancer
49 {
50 static public final String DO_TIMING_STATISTICS
51 = "Enhancer.doTimingStatistics";
52 static public final String DUMP_CLASS
53 = "Enhancer.dumpClass";
54 static public final String NO_AUGMENT
55 = "Enhancer.noAugment";
56 static public final String NO_ANNOTATE
57 = "Enhancer.noAnnotate";
58 static public final String VERBOSE_LEVEL
59 = "Enhancer.verboseLevel";
60 static public final String VERBOSE_LEVEL_QUIET
61 = "quiet";
62 static public final String VERBOSE_LEVEL_WARN
63 = "warn";
64 static public final String VERBOSE_LEVEL_VERBOSE
65 = "verbose";
66 static public final String VERBOSE_LEVEL_DEBUG
67 = "debug";
68
69
70
71 private Environment env = new Environment();
72
73 /***
74 * Initializes an instance of a JDO enhancer.
75 * @param metaData the JDO meta-data object
76 * @param settings enhancement properties
77 * @param out standard ouput stream for the enhancer
78 */
79 protected void init(EnhancerMetaData metaData,
80 Properties settings,
81 PrintWriter out,
82 PrintWriter err)
83 throws EnhancerUserException, EnhancerFatalError
84 {
85 if (metaData == null) {
86 throw new EnhancerFatalError(
87 getI18N("enhancer.internal_error",
88 "Illegal argument: metaData == null"));
89 }
90
91 env.setEnhancerMetaData(metaData);
92
93 final String doTiming
94 = (settings == null
95 ? null
96 : settings.getProperty(DO_TIMING_STATISTICS));
97 env.setDoTimingStatistics(Boolean.valueOf(doTiming).booleanValue());
98
99 final String dumpClass
100 = (settings == null
101 ? null
102 : settings.getProperty(DUMP_CLASS));
103 env.setDumpClass(Boolean.valueOf(dumpClass).booleanValue());
104
105 final String noAugment
106 = (settings == null
107 ? null
108 : settings.getProperty(NO_AUGMENT));
109 env.setNoAugment(Boolean.valueOf(noAugment).booleanValue());
110
111 final String noAnnotate
112 = (settings == null
113 ? null
114 : settings.getProperty(NO_ANNOTATE));
115 env.setNoAnnotate(Boolean.valueOf(noAnnotate).booleanValue());
116
117
118 if (err != null) {
119 env.setErrorWriter(err);
120 }
121 if (out != null) {
122 env.setOutputWriter(out);
123 }
124 final String verboseLevel
125 = (settings == null ? null : settings.getProperty(VERBOSE_LEVEL));
126 if (VERBOSE_LEVEL_QUIET.equals(verboseLevel)) {
127 env.setVerbose(false);
128 env.setQuiet(true);
129 } else if (VERBOSE_LEVEL_WARN.equals(verboseLevel)) {
130 env.setVerbose(false);
131 env.setQuiet(false);
132 } else if (VERBOSE_LEVEL_VERBOSE.equals(verboseLevel)) {
133 env.setVerbose(true);
134 env.setQuiet(false);
135 } else if (VERBOSE_LEVEL_DEBUG.equals(verboseLevel)) {
136 env.setVerbose(true);
137 env.setQuiet(false);
138 } else {
139 env.setVerbose(false);
140 env.setQuiet(false);
141 }
142 }
143
144 /***
145 * Creates an instance of a JDO enhancer.
146 * @param metaData the JDO meta-data object
147 * @param settings enhancement properties
148 * @param out standard ouput stream for the enhancer
149 */
150 public EnhancerFilter(EnhancerMetaData metaData,
151 Properties settings,
152 PrintWriter out,
153 PrintWriter err)
154 throws EnhancerUserException, EnhancerFatalError
155 {
156 init(metaData, settings, out, err);
157 }
158
159 /***
160 * Enhances a given class according to the JDO meta-data.
161 */
162 private boolean enhanceClassFile1(InputStream inClassFile,
163 OutputStreamWrapper outClassFile)
164 throws EnhancerUserException
165 {
166
167 affirm(inClassFile, "Illegal argument: inClassFile == null.");
168 affirm(outClassFile, "Illegal argument: outClassFile == null.");
169
170
171 final ClassFile cf;
172 final Controller cc;
173 try {
174
175 final DataInputStream dis = new DataInputStream(inClassFile);
176 final boolean allowJDK12ClassFiles = true;
177 cf = new ClassFile(dis, allowJDK12ClassFiles);
178
179
180
181
182 cc = new Controller(cf, env);
183
184
185 final String className = cf.classNameString();
186 } catch (ClassFormatError ex) {
187 throw new EnhancerUserException(
188 getI18N("enhancer.class_format_error"),
189 ex);
190 }
191
192
193 cc.enhanceClass();
194 if (env.errorCount() > 0) {
195
196 env.getErrorWriter().flush();
197
198 throw new EnhancerUserException(env.getLastErrorMessage());
199 }
200 affirm(env.errorCount() == 0);
201
202
203 boolean changed = cc.updated();
204 try {
205 if (changed) {
206 env.message("writing enhanced class " + cf.userClassName()
207 + " to output stream");
208 } else {
209 env.message("no changes to class " + cf.userClassName());
210 }
211 outClassFile.setClassName(cf.userClassName());
212 final DataOutputStream dos
213 = new DataOutputStream(outClassFile.getStream());
214 cf.write(dos);
215 dos.flush();
216 } catch (IOException ex) {
217 throw new EnhancerUserException(
218 getI18N("enhancer.io_error_while_writing_stream"),
219 ex);
220 }
221 return changed;
222 }
223
224 /***
225 * Enhances a given class according to the JDO meta-data.
226 */
227 public boolean enhanceClassFile(InputStream inClassFile,
228 OutputStreamWrapper outClassFile)
229 throws EnhancerUserException, EnhancerFatalError
230 {
231 env.verbose("---------------------------------------------------------------------------");
232 env.messageNL("Enhancer: enhancing classfile ...");
233
234
235 env.reset();
236
237
238 final boolean changed;
239 try {
240 changed = enhanceClassFile1(inClassFile, outClassFile);
241 } catch (EnhancerUserException ex) {
242
243 env.reset();
244 throw ex;
245 } catch (EnhancerMetaDataUserException ex) {
246
247
248
249 env.reset();
250 throw new EnhancerUserException(
251 getI18N("enhancer.error", ex.getMessage()),
252 ex);
253 } catch (RuntimeException ex) {
254
255 env.reset();
256 ex.printStackTrace ();
257 throw new EnhancerFatalError(
258 getI18N("enhancer.internal_error", ex.getMessage()),
259 ex);
260 }
261
262 env.messageNL(changed
263 ? "Enhancer: classfile enhanced successfully."
264 : "Enhancer: classfile not changed.");
265 return changed;
266 }
267
268 public boolean enhanceClassFile(InputStream in,
269 OutputStream out)
270 throws EnhancerUserException,
271 EnhancerFatalError
272 {
273 return enhanceClassFile(in, new OutputStreamWrapper(out));
274 }
275 }