KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mx4j > server > BCELMBeanInvoker


1 /*
2  * Copyright (C) MX4J.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the MX4J License version 1.0.
6  * See the terms of the MX4J License in the documentation provided with this software.
7  */

8
9 package mx4j.server;
10
11 import java.lang.reflect.Method JavaDoc;
12 import java.security.AccessController JavaDoc;
13 import java.security.PrivilegedActionException JavaDoc;
14 import java.security.PrivilegedExceptionAction JavaDoc;
15 import java.security.SecureClassLoader JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Arrays JavaDoc;
18 import java.util.List JavaDoc;
19
20 import mx4j.log.Log;
21 import mx4j.log.Logger;
22 import org.apache.bcel.Constants;
23 import org.apache.bcel.generic.ARRAYLENGTH;
24 import org.apache.bcel.generic.ArrayType;
25 import org.apache.bcel.generic.BranchInstruction;
26 import org.apache.bcel.generic.ClassGen;
27 import org.apache.bcel.generic.InstructionConstants;
28 import org.apache.bcel.generic.InstructionFactory;
29 import org.apache.bcel.generic.InstructionHandle;
30 import org.apache.bcel.generic.InstructionList;
31 import org.apache.bcel.generic.LocalVariableGen;
32 import org.apache.bcel.generic.MethodGen;
33 import org.apache.bcel.generic.ObjectType;
34 import org.apache.bcel.generic.PUSH;
35 import org.apache.bcel.generic.ReferenceType;
36 import org.apache.bcel.generic.Type;
37
38 /**
39  * MBeanInvoker that generates on-the-fly implementations to call standard MBeans directly, instead of using reflection.
40  * <br />
41  * It uses the <a HREF="http://jakarta.apache.org/bcel">BCEL</a> to generate the required bytecode on-the-fly.
42  * The generated class is named "mx4j.server.BCELMBeanInvokerGenerated", and it's loaded into the JVM by a different
43  * classloader for each MBean. This classloader has the MBean classloader as parent. <br>
44  * Below is an example of the generated code; beware that the management interface and all parameter's classes must be
45  * public, otherwise an IllegalAccessError is thrown and the invocation falls back to use reflection (but with a significant
46  * overhead - throwing an exception is expensive).
47  * <pre>
48  * public interface ServiceMBean
49  * {
50  * public void start();
51  * public Collection getServices(ServiceSelector selector);
52  * }
53  *
54  * public class BCELMBeanInvokerGenerated extends BCELMBeanInvoker
55  * {
56  * protected Object invokeImpl(MBeanMetaData metadata, String method, String[] signature, Object[] args)
57  * throws Throwable
58  * {
59  * if (method.equals("start") && args.length == 0)
60  * {
61  * try
62  * {
63  * ((ServiceMBean)metadata.mbean).start();
64  * return null;
65  * }
66  * catch (ClassCastException x) {}
67  * catch (IllegalAccessError x) {}
68  * }
69  * else if (method.equals("getServices") && args.length == 1)
70  * {
71  * try
72  * {
73  * return ((ServiceMBean)metadata.mbean).getServices((ServiceSelector)args[0]);
74  * }
75  * catch (ClassCastException x) {}
76  * catch (IllegalAccessError x) {}
77  * }
78  * return super.invokeImpl(metadata, method, signature, args);
79  * }
80  * }
81  * </pre>
82  *
83  * @author <a HREF="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
84  * @version $Revision: 1.12 $
85  */

86 public class BCELMBeanInvoker extends CachingReflectionMBeanInvoker
87 {
88    private static final String JavaDoc LOGGER_CATEGORY = BCELMBeanInvoker.class.getName();
89 /*
90     public static void main(String[] args) throws Exception
91     {
92         MBeanMetaData metadata = new MBeanMetaData();
93         metadata.classloader = ClassLoader.getSystemClassLoader();
94         metadata.management = Object.class;
95         Object generated = create(metadata);
96         System.out.println("generated = " + generated);
97     }
98
99    private static void dump(ClassGen classGen)
100    {
101       try
102       {
103          java.io.FileOutputStream fos = new java.io.FileOutputStream(new java.io.File("C:\\Simon\\OpenSource\\mx4j\\mx4j\\classes\\core\\mx4j\\server\\BCELMBeanInvokerGenerated.class"));
104          classGen.getJavaClass().dump(fos);
105          fos.close();
106       }
107       catch (java.io.IOException x)
108       {
109          x.printStackTrace();
110       }
111    }
112 */

113    protected BCELMBeanInvoker()
114    {
115    }
116
117    /**
118     * Creates a new MBeanInvoker created on-the-fly by using BCEL.
119     * It must be synchronized since BCEL is not thread safe, and uses static variables
120     * (refer to org.apache.bcel.generic.Type.getArgumentTypes(...) for further details)
121     */

122    public synchronized static MBeanInvoker create(final MBeanMetaData metadata)
123    {
124       String JavaDoc parentName = BCELMBeanInvoker.class.getName();
125       final String JavaDoc name = parentName + "Generated";
126       ClassGen classGen = new ClassGen(name, // Qualified class name
127
parentName, // Qualified superclass name
128
"<generated-on-the-fly>", // File name
129
Constants.ACC_PUBLIC | Constants.ACC_FINAL | Constants.ACC_SUPER, // Modifiers
130
null); // Implemented interfaces
131

132       classGen.addEmptyConstructor(Constants.ACC_PUBLIC);
133       classGen.addMethod(createInvokeImpl(metadata, classGen, name));
134
135       // For debug purposes only
136
// dump(classGen);
137

138       final byte[] bytes = classGen.getJavaClass().getBytes();
139
140       try
141       {
142          // Must shield clients, since creating a new classloader requires a permission
143
return (BCELMBeanInvoker)AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
144          {
145             public Object JavaDoc run() throws Exception JavaDoc
146             {
147                Class JavaDoc cls = new BCELClassLoader(metadata.getClassLoader(), bytes).loadClass(name);
148                return cls.newInstance();
149             }
150          });
151       }
152       catch (Throwable JavaDoc x)
153       {
154          Logger logger = Log.getLogger(LOGGER_CATEGORY);
155          if (logger.isEnabledFor(Logger.INFO)) logger.info("Cannot create on-the-fly MBeanInvoker class, going with reflection MBeanInvoker", x);
156          return new CachingReflectionMBeanInvoker();
157       }
158    }
159
160    private static org.apache.bcel.classfile.Method createInvokeImpl(MBeanMetaData metadata, ClassGen classGen, String JavaDoc clsName)
161    {
162       InstructionList implementation = new InstructionList();
163
164       ObjectType metadataType = new ObjectType(MBeanMetaData.class.getName());
165       Type[] signature = new Type[]{metadataType, Type.STRING, new ArrayType(Type.STRING, 1), new ArrayType(Type.OBJECT, 1)};
166
167       // Method definition
168
MethodGen mthd = new MethodGen(Constants.ACC_PROTECTED, // Modifiers
169
Type.OBJECT, // Return type
170
signature, // Signature
171
new String JavaDoc[]{"metadata", "method", "params", "args"}, // Parameter names
172
"invokeImpl", // Method name
173
clsName, // Class name
174
implementation, // Implementation
175
classGen.getConstantPool()); // Pool
176
mthd.addException("java.lang.Throwable");
177
178       // Now I should create the implementation
179
InstructionFactory factory = new InstructionFactory(classGen);
180
181       Method JavaDoc[] methods = metadata.getMBeanInterface().getMethods();
182       List JavaDoc tests = new ArrayList JavaDoc();
183       List JavaDoc catches = new ArrayList JavaDoc();
184       for (int i = 0; i < methods.length; ++i)
185       {
186          Method JavaDoc method = methods[i];
187          catches.addAll(generateDirectInvokeBranch(classGen, mthd, implementation, factory, metadata.getMBeanInterface().getName(), method, tests));
188       }
189
190       // To close the last branch, I must jump to super.invokeImpl(), so I need its first instruction here
191
InstructionHandle invokeSuper = implementation.append(factory.createThis());
192       for (int i = 0; i < tests.size(); ++i)
193       {
194          BranchInstruction branch = (BranchInstruction)tests.get(i);
195          branch.setTarget(invokeSuper);
196       }
197       tests.clear();
198       for (int i = 0; i < catches.size(); ++i)
199       {
200          BranchInstruction branch = (BranchInstruction)catches.get(i);
201          branch.setTarget(invokeSuper);
202       }
203       catches.clear();
204
205       //
206
// return super.invokeImpl(metadata, method, params, args);
207
//
208
// Again, it's invokeImpl(super, args) instead of super.invokeImpl(args)
209
// Use 'this' as first argument, and invokespecial instead of invokevirtual to call super
210
// 'this' is created above, to close the last branch
211
implementation.append(factory.createLoad(metadataType, 1));
212       implementation.append(factory.createLoad(Type.STRING, 2));
213       implementation.append(factory.createLoad(new ArrayType(Type.STRING, 1), 3));
214       implementation.append(factory.createLoad(new ArrayType(Type.OBJECT, 1), 4));
215       implementation.append(factory.createInvoke(BCELMBeanInvoker.class.getName(), "invokeImpl", Type.OBJECT, signature, Constants.INVOKESPECIAL));
216       implementation.append(factory.createReturn(Type.OBJECT));
217
218       mthd.setMaxStack();
219
220       org.apache.bcel.classfile.Method method = mthd.getMethod();
221
222       // Reuse instruction handles
223
implementation.dispose();
224
225       return method;
226    }
227
228    private static List JavaDoc generateDirectInvokeBranch(ClassGen classGen, MethodGen methodGen, InstructionList implementation, InstructionFactory factory, String JavaDoc management, Method JavaDoc method, List JavaDoc tests)
229    {
230       ArrayList JavaDoc catches = new ArrayList JavaDoc();
231
232       //
233
// if (method.equals("<operation>") && args.length == <num>)
234
//
235
// The first instruction, will be where I should go if the previous branch fails
236
InstructionHandle startTest = implementation.append(factory.createLoad(Type.STRING, 2));
237
238       // The first time it will be empty, the second time will be the first time's uninitialized jump instructions
239
for (int i = 0; i < tests.size(); ++i)
240       {
241          BranchInstruction branch = (BranchInstruction)tests.get(i);
242          // Initialize previous jump instruction to jump to the next branch
243
branch.setTarget(startTest);
244       }
245       tests.clear();
246
247       implementation.append(new PUSH(classGen.getConstantPool(), method.getName()));
248       implementation.append(factory.createInvoke(String JavaDoc.class.getName(), "equals", Type.BOOLEAN, new Type[]{Type.OBJECT}, Constants.INVOKEVIRTUAL));
249       // IFEQ compares the stack with 0, which means "if the previous comparison is false, ..."
250
BranchInstruction test1 = factory.createBranchInstruction(Constants.IFEQ, null);
251       tests.add(test1);
252       implementation.append(test1);
253
254       implementation.append(factory.createLoad(new ArrayType(Type.OBJECT, 1), 4));
255       implementation.append(new ARRAYLENGTH());
256       implementation.append(new PUSH(classGen.getConstantPool(), method.getParameterTypes().length));
257       // Here I should test if args.length == <num>, if not equal then go to the next branch
258
// Create branch instructions with no offset, since it cannot be handled now, see above
259
BranchInstruction test2 = factory.createBranchInstruction(Constants.IF_ICMPNE, null);
260       tests.add(test2);
261       implementation.append(test2);
262
263       // Here I am on the right method, unless someone created 2 methods with same names and same number of
264
// parameters but of different type. In this last case if we're lucky it's the right method and we go
265
// via direct call, otherwise we will have a class cast exception and go via reflection
266

267       // Cast and invoke
268
// Put the metadata on the stack, to access its 'mbean' field, that will be put on the stack
269
// It's also the start of the try block
270
InstructionHandle tryStart = implementation.append(factory.createLoad(new ObjectType(MBeanMetaData.class.getName()), 1));
271       implementation.append(factory.createInvoke(MBeanMetaData.class.getName(), "getMBean", Type.OBJECT, new Type[0], Constants.INVOKEVIRTUAL));
272       // Cast the 'mbean' field to the proper type, the stack will contain the casted mbean
273
implementation.append(factory.createCheckCast(new ObjectType(management)));
274
275       // Now add all the arguments to the stack
276
Class JavaDoc[] signature = method.getParameterTypes();
277       Type[] invokeSignature = new Type[signature.length];
278       for (int i = 0; i < signature.length; ++i)
279       {
280          Class JavaDoc param = signature[i];
281
282          // Load all args on the stack
283
implementation.append(factory.createLoad(new ArrayType(Type.OBJECT, 1), 4));
284          // I want index 'i'
285
implementation.append(new PUSH(classGen.getConstantPool(), i));
286          // Now on the stack there is args[i]
287
implementation.append(factory.createArrayLoad(Type.OBJECT));
288
289          // Save the signature for the invocation
290
invokeSignature[i] = convertClassToType(param);
291
292          if (param.isPrimitive())
293          {
294             // On the stack I have the wrapper object, I have to convert them to primitive
295
replaceObjectWithPrimitive(param, implementation, factory);
296          }
297          else if (param.isArray())
298          {
299             // Cast args[i] to the proper class
300
implementation.append(factory.createCheckCast((ReferenceType)invokeSignature[i]));
301          }
302          else
303          {
304             // Cast args[i] to the proper class
305
implementation.append(factory.createCheckCast((ReferenceType)invokeSignature[i]));
306          }
307       }
308
309       Class JavaDoc returnClass = method.getReturnType();
310       Type returnType = convertClassToType(returnClass);
311
312       // On the stack we now have the casted mbean and all the casted arguments, invoke
313
implementation.append(factory.createInvoke(management, method.getName(), returnType, invokeSignature, Constants.INVOKEINTERFACE));
314
315       if (returnClass == Void.TYPE)
316       {
317          implementation.append(InstructionConstants.ACONST_NULL);
318       }
319       else if (returnClass.isArray())
320       {
321          // Thanks to the fact that we can assign any array to Object, we do nothing here
322
}
323       else if (returnClass.isPrimitive())
324       {
325          replacePrimitiveWithObject(returnClass, methodGen, implementation, factory);
326       }
327
328       InstructionHandle tryEnd = implementation.append(factory.createReturn(Type.OBJECT));
329
330       // In case of class cast exception, eat the exception and call super (hence using reflection)
331
// catch (ClassCastException x) {/* do nothing */}
332
// On the stack there is the exception, we assign it to local variable 'x'
333
ObjectType exceptionTypeCCE = new ObjectType("java.lang.ClassCastException");
334       LocalVariableGen x = methodGen.addLocalVariable("x", exceptionTypeCCE, null, null);
335       InstructionHandle handler = implementation.append(factory.createStore(exceptionTypeCCE, x.getIndex()));
336       x.setStart(handler);
337       x.setEnd(handler);
338       methodGen.addExceptionHandler(tryStart, tryEnd, handler, exceptionTypeCCE);
339       // This catch block is followed by another one, and I don't exit with a throw or a return
340
BranchInstruction skip = factory.createBranchInstruction(Constants.GOTO, null);
341       catches.add(skip);
342       implementation.append(skip);
343
344       // An IllegalAccessError is thrown if the MBean interface or a parameter class is not public
345
// We eat it and fall back to call super (hence using reflection)
346
// catch (IllegalAccessError x) {/* do nothing */}
347
ObjectType errorTypeIAE = new ObjectType("java.lang.IllegalAccessError");
348       x = methodGen.addLocalVariable("x", errorTypeIAE, null, null);
349       handler = implementation.append(factory.createStore(errorTypeIAE, x.getIndex()));
350       x.setStart(handler);
351       x.setEnd(handler);
352       methodGen.addExceptionHandler(tryStart, tryEnd, handler, errorTypeIAE);
353       // This catch block is followed by another one, and I don't exit with a throw or a return,
354
skip = factory.createBranchInstruction(Constants.GOTO, null);
355       catches.add(skip);
356       implementation.append(skip);
357
358       return catches;
359    }
360
361    private static Type convertClassToType(Class JavaDoc cls)
362    {
363       if (cls == void.class) return Type.VOID;
364       if (cls == boolean.class) return Type.BOOLEAN;
365       if (cls == byte.class) return Type.BYTE;
366       if (cls == char.class) return Type.CHAR;
367       if (cls == short.class) return Type.SHORT;
368       if (cls == int.class) return Type.INT;
369       if (cls == long.class) return Type.LONG;
370       if (cls == float.class) return Type.FLOAT;
371       if (cls == double.class) return Type.DOUBLE;
372       if (cls == Object JavaDoc.class) return Type.OBJECT;
373       if (cls == String JavaDoc.class) return Type.STRING;
374       if (cls.isArray())
375       {
376          int dimensions = 0;
377          Class JavaDoc c = null;
378          while ((c = cls.getComponentType()) != null)
379          {
380             ++dimensions;
381             cls = c;
382          }
383          Type t = convertClassToType(cls);
384          return new ArrayType(t, dimensions);
385       }
386       return new ObjectType(cls.getName());
387    }
388
389    private static void replaceObjectWithPrimitive(Class JavaDoc type, InstructionList implementation, InstructionFactory factory)
390    {
391       // Put as first the most common ones
392
if (type == int.class)
393       {
394          // Cast the operand in the stack and get the value
395
implementation.append(factory.createCheckCast(new ObjectType(Integer JavaDoc.class.getName())));
396          implementation.append(factory.createInvoke(Integer JavaDoc.class.getName(), "intValue", Type.INT, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
397       }
398       else if (type == boolean.class)
399       {
400          // Cast the operand in the stack and get the value
401
implementation.append(factory.createCheckCast(new ObjectType(Boolean JavaDoc.class.getName())));
402          implementation.append(factory.createInvoke(Boolean JavaDoc.class.getName(), "booleanValue", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
403       }
404       else if (type == long.class)
405       {
406          // Cast the operand in the stack and get the value
407
implementation.append(factory.createCheckCast(new ObjectType(Long JavaDoc.class.getName())));
408          implementation.append(factory.createInvoke(Long JavaDoc.class.getName(), "longValue", Type.LONG, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
409       }
410       else if (type == byte.class)
411       {
412          // Cast the operand in the stack and get the value
413
implementation.append(factory.createCheckCast(new ObjectType(Byte JavaDoc.class.getName())));
414          implementation.append(factory.createInvoke(Byte JavaDoc.class.getName(), "byteValue", Type.BYTE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
415       }
416       else if (type == char.class)
417       {
418          // Cast the operand in the stack and get the value
419
implementation.append(factory.createCheckCast(new ObjectType(Character JavaDoc.class.getName())));
420          implementation.append(factory.createInvoke(Character JavaDoc.class.getName(), "charValue", Type.CHAR, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
421       }
422       else if (type == short.class)
423       {
424          // Cast the operand in the stack and get the value
425
implementation.append(factory.createCheckCast(new ObjectType(Short JavaDoc.class.getName())));
426          implementation.append(factory.createInvoke(Short JavaDoc.class.getName(), "shortValue", Type.SHORT, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
427       }
428       else if (type == float.class)
429       {
430          // Cast the operand in the stack and get the value
431
implementation.append(factory.createCheckCast(new ObjectType(Float JavaDoc.class.getName())));
432          implementation.append(factory.createInvoke(Float JavaDoc.class.getName(), "floatValue", Type.FLOAT, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
433       }
434       else
435       {
436          // Cast the operand in the stack and get the value
437
implementation.append(factory.createCheckCast(new ObjectType(Double JavaDoc.class.getName())));
438          implementation.append(factory.createInvoke(Double JavaDoc.class.getName(), "doubleValue", Type.DOUBLE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
439       }
440    }
441
442    private static void replacePrimitiveWithObject(Class JavaDoc type, MethodGen methodGen, InstructionList implementation, InstructionFactory factory)
443    {
444       // Put as first the most common ones
445
if (type == int.class)
446       {
447          // Create a new instance of the wrapper
448
LocalVariableGen i = methodGen.addLocalVariable("i", Type.INT, null, null);
449          i.setStart(implementation.append(factory.createStore(Type.INT, i.getIndex())));
450          implementation.append(factory.createNew(new ObjectType(Integer JavaDoc.class.getName())));
451          implementation.append(InstructionConstants.DUP);
452          implementation.append(factory.createLoad(Type.INT, i.getIndex()));
453          i.setEnd(implementation.append(factory.createInvoke(Integer JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.INT}, Constants.INVOKESPECIAL)));
454       }
455       else if (type == boolean.class)
456       {
457          // Create a new instance of the wrapper
458
LocalVariableGen b = methodGen.addLocalVariable("b", Type.BOOLEAN, null, null);
459          b.setStart(implementation.append(factory.createStore(Type.BOOLEAN, b.getIndex())));
460          implementation.append(factory.createNew(new ObjectType(Boolean JavaDoc.class.getName())));
461          implementation.append(InstructionConstants.DUP);
462          implementation.append(factory.createLoad(Type.BOOLEAN, b.getIndex()));
463          b.setEnd(implementation.append(factory.createInvoke(Boolean JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.BOOLEAN}, Constants.INVOKESPECIAL)));
464       }
465       else if (type == long.class)
466       {
467          // Create a new instance of the wrapper
468
LocalVariableGen l = methodGen.addLocalVariable("l", Type.LONG, null, null);
469          l.setStart(implementation.append(factory.createStore(Type.LONG, l.getIndex())));
470          implementation.append(factory.createNew(new ObjectType(Long JavaDoc.class.getName())));
471          implementation.append(InstructionConstants.DUP);
472          implementation.append(factory.createLoad(Type.LONG, l.getIndex()));
473          l.setEnd(implementation.append(factory.createInvoke(Long JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.LONG}, Constants.INVOKESPECIAL)));
474       }
475       else if (type == byte.class)
476       {
477          // Create a new instance of the wrapper
478
LocalVariableGen b = methodGen.addLocalVariable("b", Type.BYTE, null, null);
479          b.setStart(implementation.append(factory.createStore(Type.BYTE, b.getIndex())));
480          implementation.append(factory.createNew(new ObjectType(Byte JavaDoc.class.getName())));
481          implementation.append(InstructionConstants.DUP);
482          implementation.append(factory.createLoad(Type.BYTE, b.getIndex()));
483          b.setEnd(implementation.append(factory.createInvoke(Byte JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.BYTE}, Constants.INVOKESPECIAL)));
484       }
485       else if (type == char.class)
486       {
487          // Create a new instance of the wrapper
488
LocalVariableGen c = methodGen.addLocalVariable("c", Type.CHAR, null, null);
489          c.setStart(implementation.append(factory.createStore(Type.CHAR, c.getIndex())));
490          implementation.append(factory.createNew(new ObjectType(Character JavaDoc.class.getName())));
491          implementation.append(InstructionConstants.DUP);
492          implementation.append(factory.createLoad(Type.CHAR, c.getIndex()));
493          c.setEnd(implementation.append(factory.createInvoke(Character JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.CHAR}, Constants.INVOKESPECIAL)));
494       }
495       else if (type == short.class)
496       {
497          // Create a new instance of the wrapper
498
LocalVariableGen s = methodGen.addLocalVariable("s", Type.SHORT, null, null);
499          s.setStart(implementation.append(factory.createStore(Type.SHORT, s.getIndex())));
500          implementation.append(factory.createNew(new ObjectType(Short JavaDoc.class.getName())));
501          implementation.append(InstructionConstants.DUP);
502          implementation.append(factory.createLoad(Type.SHORT, s.getIndex()));
503          s.setEnd(implementation.append(factory.createInvoke(Short JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.SHORT}, Constants.INVOKESPECIAL)));
504       }
505       else if (type == float.class)
506       {
507          // Create a new instance of the wrapper
508
LocalVariableGen f = methodGen.addLocalVariable("f", Type.FLOAT, null, null);
509          f.setStart(implementation.append(factory.createStore(Type.FLOAT, f.getIndex())));
510          implementation.append(factory.createNew(new ObjectType(Float JavaDoc.class.getName())));
511          implementation.append(InstructionConstants.DUP);
512          implementation.append(factory.createLoad(Type.FLOAT, f.getIndex()));
513          f.setEnd(implementation.append(factory.createInvoke(Float JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.FLOAT}, Constants.INVOKESPECIAL)));
514       }
515       else
516       {
517          // Create a new instance of the wrapper
518
LocalVariableGen d = methodGen.addLocalVariable("d", Type.DOUBLE, null, null);
519          d.setStart(implementation.append(factory.createStore(Type.DOUBLE, d.getIndex())));
520          implementation.append(factory.createNew(new ObjectType(Double JavaDoc.class.getName())));
521          implementation.append(InstructionConstants.DUP);
522          implementation.append(factory.createLoad(Type.DOUBLE, d.getIndex()));
523          d.setEnd(implementation.append(factory.createInvoke(Double JavaDoc.class.getName(), "<init>", Type.VOID, new Type[]{Type.DOUBLE}, Constants.INVOKESPECIAL)));
524       }
525    }
526
527    private Logger getLogger()
528    {
529       return Log.getLogger(LOGGER_CATEGORY);
530    }
531
532    protected Object JavaDoc invokeImpl(MBeanMetaData metadata, String JavaDoc method, String JavaDoc[] signature, Object JavaDoc[] args) throws Throwable JavaDoc
533    {
534       Logger logger = getLogger();
535       if (logger.isEnabledFor(Logger.INFO))
536       {
537          logger.info("BCEL invocation failed for method " + method + "" + Arrays.asList(signature) + ", using reflection");
538       }
539       return super.invokeImpl(metadata, method, signature, args);
540    }
541
542    private static class BCELClassLoader extends SecureClassLoader JavaDoc
543    {
544       private byte[] m_bytes;
545
546       private BCELClassLoader(ClassLoader JavaDoc parent, byte[] bytecode)
547       {
548          super(parent);
549          m_bytes = bytecode;
550       }
551
552       protected Class JavaDoc findClass(final String JavaDoc name) throws ClassNotFoundException JavaDoc
553       {
554          try
555          {
556             return (Class JavaDoc)AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
557             {
558                public Object JavaDoc run() throws ClassNotFoundException JavaDoc
559                {
560                   try
561                   {
562                      return defineClass(name, m_bytes, 0, m_bytes.length, BCELClassLoader.this.getClass().getProtectionDomain());
563                   }
564                   catch (ClassFormatError JavaDoc x)
565                   {
566                      throw new ClassNotFoundException JavaDoc("Class Format Error", x);
567                   }
568                }
569             }, null);
570          }
571          catch (PrivilegedActionException JavaDoc x)
572          {
573             throw (ClassNotFoundException JavaDoc)x.getException();
574          }
575       }
576    }
577 }
578
Popular Tags