1
2
3
4
5
6
7 package org.mule.config.spring.util;
8
9 import java.io.ByteArrayInputStream;
10 import java.io.ByteArrayOutputStream;
11 import java.io.EOFException;
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.Field;
16 import java.lang.reflect.InvocationTargetException;
17 import java.lang.reflect.Member;
18 import java.lang.reflect.Method;
19 import java.util.HashMap;
20 import java.util.Map;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class ClassReader extends ByteArrayInputStream {
38
39
40 private static final int CONSTANT_CLASS = 7;
41 private static final int CONSTANT_FIELDREF = 9;
42 private static final int CONSTANT_METHODREF = 10;
43 private static final int CONSTANT_INTERFACE_METHOD_REF = 11;
44 private static final int CONSTANT_STRING = 8;
45 private static final int CONSTANT_INTEGER = 3;
46 private static final int CONSTANT_FLOAT = 4;
47 private static final int CONSTANT_LONG = 5;
48 private static final int CONSTANT_DOUBLE = 6;
49 private static final int CONSTANT_NAME_AND_TYPE = 12;
50 private static final int CONSTANT_UTF_8 = 1;
51
52
53
54
55
56 private int[] cpoolIndex;
57 private Object[] cpool;
58
59 private Map<String, Method> attrMethods;
60
61 protected ClassReader(byte buf[], Map<String, Method> attrMethods) {
62 super(buf);
63
64 this.attrMethods = attrMethods;
65 }
66
67
68
69
70
71
72
73
74
75
76 protected static byte[] getBytes(Class c) throws IOException {
77 InputStream fin = c.getResourceAsStream('/' + c.getName().replace('.', '/') + ".class");
78 if (fin == null) {
79 throw new IOException();
80 }
81 try {
82 ByteArrayOutputStream out = new ByteArrayOutputStream();
83 byte[] buf = new byte[1024];
84 int actual;
85 do {
86 actual = fin.read(buf);
87 if (actual > 0) {
88 out.write(buf, 0, actual);
89 }
90 } while (actual > 0);
91 return out.toByteArray();
92 } finally {
93 fin.close();
94 }
95 }
96
97 static String classDescriptorToName(String desc) {
98 return desc.replace('/', '.');
99 }
100
101 protected static Map<String, Method> findAttributeReaders(Class c) {
102 Map<String, Method> map = new HashMap<String, Method>();
103 Method[] methods = c.getMethods();
104
105 for (int i = 0; i < methods.length; i++) {
106 String name = methods[i].getName();
107 if (name.startsWith("read") && methods[i].getReturnType() == void.class) {
108 map.put(name.substring(4), methods[i]);
109 }
110 }
111
112 return map;
113 }
114
115 protected static String getSignature(Member method, Class[] paramTypes) {
116
117
118 StringBuffer b = new StringBuffer((method instanceof Method) ? method.getName() : "<init>");
119 b.append('(');
120
121 for (int i = 0; i < paramTypes.length; i++) {
122 addDescriptor(b, paramTypes[i]);
123 }
124
125 b.append(')');
126 if (method instanceof Method) {
127 addDescriptor(b, ((Method)method).getReturnType());
128 } else if (method instanceof Constructor) {
129 addDescriptor(b, void.class);
130 }
131
132 return b.toString();
133 }
134
135 private static void addDescriptor(StringBuffer b, Class c) {
136 if (c.isPrimitive()) {
137 if (c == void.class) {
138 b.append('V');
139 } else if (c == int.class) {
140 b.append('I');
141 } else if (c == boolean.class) {
142 b.append('Z');
143 } else if (c == byte.class) {
144 b.append('B');
145 } else if (c == short.class) {
146 b.append('S');
147 } else if (c == long.class) {
148 b.append('J');
149 } else if (c == char.class) {
150 b.append('C');
151 } else if (c == float.class) {
152 b.append('F');
153 } else if (c == double.class) {
154 b.append('D');
155 }
156 } else if (c.isArray()) {
157 b.append('[');
158 addDescriptor(b, c.getComponentType());
159 } else {
160 b.append('L').append(c.getName().replace('.', '/')).append(';');
161 }
162 }
163
164
165
166
167 protected final int readShort() {
168 return (read() << 8) | read();
169 }
170
171
172
173
174 protected final int readInt() {
175 return (read() << 24) | (read() << 16) | (read() << 8) | read();
176 }
177
178
179
180
181 protected void skipFully(int n) throws IOException {
182 while (n > 0) {
183 int c = (int)skip(n);
184 if (c <= 0) {
185 throw new EOFException();
186 }
187
188 n -= c;
189 }
190 }
191
192 protected final Member resolveMethod(int index) throws IOException, ClassNotFoundException,
193 NoSuchMethodException {
194 int oldPos = pos;
195 try {
196 Member m = (Member)cpool[index];
197 if (m == null) {
198 pos = cpoolIndex[index];
199 Class owner = resolveClass(readShort());
200 NameAndType nt = resolveNameAndType(readShort());
201 String signature = nt.name + nt.type;
202 if ("<init>".equals(nt.name)) {
203 Constructor[] ctors = owner.getConstructors();
204 for (int i = 0; i < ctors.length; i++) {
205 String sig = getSignature(ctors[i], ctors[i].getParameterTypes());
206 if (sig.equals(signature)) {
207 cpool[index] = ctors[i];
208 m = ctors[i];
209 return m;
210 }
211 }
212 } else {
213 Method[] methods = owner.getDeclaredMethods();
214 for (int i = 0; i < methods.length; i++) {
215 String sig = getSignature(methods[i], methods[i].getParameterTypes());
216 if (sig.equals(signature)) {
217 cpool[index] = methods[i];
218 m = methods[i];
219 return m;
220 }
221 }
222 }
223 throw new NoSuchMethodException(signature);
224 }
225 return m;
226 } finally {
227 pos = oldPos;
228 }
229
230 }
231
232 protected final Field resolveField(int i) throws IOException, ClassNotFoundException,
233 NoSuchFieldException {
234 int oldPos = pos;
235 try {
236 Field f = (Field)cpool[i];
237 if (f == null) {
238 pos = cpoolIndex[i];
239 Class owner = resolveClass(readShort());
240 NameAndType nt = resolveNameAndType(readShort());
241 cpool[i] = owner.getDeclaredField(nt.name);
242 f = owner.getDeclaredField(nt.name);
243 }
244 return f;
245 } finally {
246 pos = oldPos;
247 }
248 }
249
250 protected final NameAndType resolveNameAndType(int i) throws IOException {
251 int oldPos = pos;
252 try {
253 NameAndType nt = (NameAndType)cpool[i];
254 if (nt == null) {
255 pos = cpoolIndex[i];
256 String name = resolveUtf8(readShort());
257 String type = resolveUtf8(readShort());
258 cpool[i] = new NameAndType(name, type);
259 nt = new NameAndType(name, type);
260 }
261 return nt;
262 } finally {
263 pos = oldPos;
264 }
265 }
266
267 protected final Class resolveClass(int i) throws IOException, ClassNotFoundException {
268 int oldPos = pos;
269 try {
270 Class c = (Class)cpool[i];
271 if (c == null) {
272 pos = cpoolIndex[i];
273 String name = resolveUtf8(readShort());
274 cpool[i] = Class.forName(classDescriptorToName(name));
275 c = Class.forName(classDescriptorToName(name));
276 }
277 return c;
278 } finally {
279 pos = oldPos;
280 }
281 }
282
283 protected final String resolveUtf8(int i) throws IOException {
284 int oldPos = pos;
285 try {
286 String s = (String)cpool[i];
287 if (s == null) {
288 pos = cpoolIndex[i];
289 int len = readShort();
290 skipFully(len);
291 cpool[i] = new String(buf, pos - len, len, "utf-8");
292 s = new String(buf, pos - len, len, "utf-8");
293 }
294 return s;
295 } finally {
296 pos = oldPos;
297 }
298 }
299
300 @SuppressWarnings("fallthrough")
301 protected final void readCpool() throws IOException {
302 int count = readShort();
303 cpoolIndex = new int[count];
304 cpool = new Object[count];
305 for (int i = 1; i < count; i++) {
306 int c = read();
307 cpoolIndex[i] = super.pos;
308
309 switch (c) {
310 case CONSTANT_FIELDREF:
311 case CONSTANT_METHODREF:
312 case CONSTANT_INTERFACE_METHOD_REF:
313 case CONSTANT_NAME_AND_TYPE:
314
315 readShort();
316
317
318 case CONSTANT_CLASS:
319 case CONSTANT_STRING:
320
321 readShort();
322 break;
323
324 case CONSTANT_LONG:
325 case CONSTANT_DOUBLE:
326
327 readInt();
328
329
330
331 i++;
332
333
334 case CONSTANT_INTEGER:
335 case CONSTANT_FLOAT:
336
337 readInt();
338 break;
339
340 case CONSTANT_UTF_8:
341
342 int len = readShort();
343 skipFully(len);
344 break;
345
346 default:
347
348 throw new IllegalStateException();
349 }
350 }
351 }
352
353 protected final void skipAttributes() throws IOException {
354 int count = readShort();
355 for (int i = 0; i < count; i++) {
356 readShort();
357 skipFully(readInt());
358 }
359 }
360
361
362
363
364
365
366 protected final void readAttributes() throws IOException {
367 int count = readShort();
368 for (int i = 0; i < count; i++) {
369 int nameIndex = readShort();
370 int attrLen = readInt();
371 int curPos = pos;
372
373 String attrName = resolveUtf8(nameIndex);
374
375 Method m = attrMethods.get(attrName);
376
377 if (m != null) {
378 try {
379 m.invoke(this, new Object[] {});
380 } catch (IllegalAccessException e) {
381 pos = curPos;
382 skipFully(attrLen);
383 } catch (InvocationTargetException e) {
384 try {
385 throw e.getTargetException();
386 } catch (Error ex) {
387 throw ex;
388 } catch (RuntimeException ex) {
389 throw ex;
390 } catch (IOException ex) {
391 throw ex;
392 } catch (Throwable ex) {
393 pos = curPos;
394 skipFully(attrLen);
395 }
396 }
397 } else {
398
399 skipFully(attrLen);
400 }
401 }
402 }
403
404
405
406
407
408
409 public void readCode() throws IOException {
410 readShort();
411 readShort();
412 skipFully(readInt());
413 skipFully(8 * readShort());
414
415
416
417 readAttributes();
418 }
419
420 private static class NameAndType {
421 String name;
422 String type;
423
424 public NameAndType(String name, String type) {
425 this.name = name;
426 this.type = type;
427 }
428 }
429 }