KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > capability > OptimizedMBeanDispatcher


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.capability;
23
24 import org.apache.bcel.Constants;
25 import org.apache.bcel.classfile.JavaClass;
26 import org.apache.bcel.generic.*;
27 import org.jboss.mx.metadata.AttributeOperationResolver;
28 import org.jboss.mx.server.ServerConstants;
29
30 import javax.management.MBeanException JavaDoc;
31 import javax.management.MBeanInfo JavaDoc;
32 import javax.management.MBeanOperationInfo JavaDoc;
33 import javax.management.MBeanParameterInfo JavaDoc;
34 import javax.management.ReflectionException JavaDoc;
35 import java.io.BufferedOutputStream JavaDoc;
36 import java.io.ByteArrayOutputStream JavaDoc;
37 import java.lang.reflect.Constructor JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.HashMap JavaDoc;
40 import java.util.Iterator JavaDoc;
41
42
43 /**
44  * Byte code optimized dispatcher for Standard MBeans. This dispatcher generates
45  * an invoke implementation that handles the operation dispatching without
46  * Java reflection.<p>
47  *
48  * The use of this dispatcher may be controlled by setting a
49  * {@link org.jboss.mx.server.ServerConstants#OPTIMIZE_REFLECTED_DISPATCHER OPTIMIZE_REFLECTED_DISPATCHER}
50  * property to either <tt>"true"</tt> or <tt>"false"</tt> string value.
51  *
52  * @see org.jboss.mx.capability.ReflectedMBeanDispatcher
53  * @see org.jboss.mx.capability.DispatchClassLoader
54  *
55  * @author <a HREF="mailto:juha@jboss.org">Juha Lindfors</a>.
56  * @version $Revision: 45810 $
57  *
58  */

59 public class OptimizedMBeanDispatcher implements ServerConstants
60 {
61    // Constants -----------------------------------------------------
62
final static Class JavaDoc SUPER_CLASS = ReflectedMBeanDispatcher.class;
63
64
65    // Static --------------------------------------------------------
66
public static ReflectedMBeanDispatcher create(MBeanInfo JavaDoc info, Object JavaDoc resource)
67    {
68       try
69       {
70          // construct class template
71
String JavaDoc className = resource.getClass().getName().replace('.', '_') + "_Dispatcher";
72          String JavaDoc superClass = SUPER_CLASS.getName();
73          String JavaDoc fileName = className + ".class";
74          int modifiers = Constants.ACC_PUBLIC;
75          String JavaDoc[] interfaces = new String JavaDoc[0];
76
77          ClassGen clazz = new ClassGen(className, superClass, fileName, modifiers, interfaces);
78          ConstantPoolGen cp = clazz.getConstantPool();
79
80          clazz.addMethod(createConstructor(cp, className).getMethod());
81          clazz.addMethod(createInvoke(cp, info, className, resource.getClass().getName()).getMethod());
82          clazz.update();
83
84          JavaClass c = clazz.getJavaClass();
85
86          ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc(2000);
87          BufferedOutputStream JavaDoc bos = new BufferedOutputStream JavaDoc(baos);
88          c.dump(bos);
89          
90          // FIXME: what about ctx cl?
91
// FIXME: also I dont know if the parent is right here, have to check later
92
ClassLoader JavaDoc ocl = new DispatchClassLoader(resource.getClass().getClassLoader(), className, baos.toByteArray());
93
94          Class JavaDoc dispatcherClass = ocl.loadClass(className);
95          Constructor JavaDoc constr = dispatcherClass.getConstructor(
96                new Class JavaDoc[] { MBeanInfo JavaDoc.class, AttributeOperationResolver.class, Object JavaDoc.class }
97          );
98
99          Object JavaDoc o = constr.newInstance(new Object JavaDoc[] { info, new AttributeOperationResolver(info), resource });
100
101          return (ReflectedMBeanDispatcher)o;
102       }
103       catch (Exception JavaDoc e)
104       {
105          e.printStackTrace();
106          throw new Error JavaDoc();
107       }
108    }
109
110    /**
111     * Returns the signature of a MBean operation using the grammar required by
112     * the class file format, excluding the method name. <p>
113     *
114     * <h4>The Java Virtual Machine Specification: 4.3.3 Method Descriptors</h4>
115     *
116     * A method descriptor represents the parameters that the method takes and the value that it returns: <br><i><pre>
117     *
118     * MethodDescriptor:
119     * ( ParameterDescriptor* ) ReturnDescriptor
120     * </pre></i>
121     *
122     * A parameter descriptor represents a parameter passed to a method: <br><i><pre>
123     *
124     * ParameterDescriptor:
125     * FieldType
126     * </pre></i>
127     *
128     * A return descriptor represents the type of the value returned from a method. It is a series of characters generated by the grammar: <br><i><pre>
129     *
130     * ReturnDescriptor:
131     * FieldType
132     * V
133     * </pre></i>
134     *
135     * The character V indicates that the method returns no value (its return type is void). <p>
136     *
137     * For example, the method descriptor for the method <br>
138     *
139     * <pre> Object mymethod(int i, double d, Thread t) </pre>
140     *
141     * is <br>
142     *
143     * <b><pre> (IDLjava/lang/Thread;)Ljava/lang/Object; </pre></b>
144     *
145     * Note that internal forms of the fully qualified names of Thread and Object are used in the method descriptor.
146     */

147    public static String JavaDoc getMethodDescriptor(MBeanParameterInfo JavaDoc[] signature, String JavaDoc returnType)
148    {
149
150       StringBuffer JavaDoc sign = new StringBuffer JavaDoc(256);
151       sign.append("(");
152
153       for (int i = 0; i < signature.length; ++i)
154          sign.append(getDescriptorForType(signature[i].getName()));
155
156       sign.append(")" + getDescriptorForType(returnType));
157
158       return sign.toString();
159    }
160
161    /**
162    * Returns a descriptor for a given Java type. See {@link java.lang.Class#getName() Class.getName()}
163    * for details on the grammar for arrays and primitive types. Note that the internal form of the fully
164    * qualified name for class Object is used, so for example, the returned descriptor for
165    * <tt>java.lang.Object</tt> is
166    *
167    * <b><pre>Ljava/lang/Object;</pre></b>
168    *
169    * See JVM spec 4.2 and 4.3 for detailed description of the internal class name format and grammar notation.
170    *
171    * @param name fully qualified name of the Java type
172    * @return descriptor string using the JVM grammar
173    */

174    public static String JavaDoc getDescriptorForType(String JavaDoc name)
175    {
176       if (name.equals(Byte.TYPE.getName())) return "B";
177       else if (name.equals(Character.TYPE.getName())) return "C";
178       else if (name.equals(Double.TYPE.getName())) return "D";
179       else if (name.equals(Float.TYPE.getName())) return "F";
180       else if (name.equals(Integer.TYPE.getName())) return "I";
181       else if (name.equals(Long.TYPE.getName())) return "J";
182       else if (name.equals(Short.TYPE.getName())) return "S";
183       else if (name.equals(Boolean.TYPE.getName())) return "Z";
184       else if (name.equals(Void.TYPE.getName())) return "V";
185       else if (name.startsWith("[")) return name.replace('.', '/');
186       else return "L" + name.replace('.', '/') + ";";
187    }
188
189    /**
190     * Checks if a given name matches the <tt>TYPE</tt> name of a primitive wrapper class.
191     *
192     * @see java.lang.Integer#TYPE
193     *
194     * @param name TYPE.getName()
195     * @return true if is a primitive type name; false otherwise
196     */

197    public static boolean isPrimitive(String JavaDoc name)
198    {
199       if (name.equals(Byte.TYPE.getName()) ||
200           name.equals(Character.TYPE.getName()) ||
201           name.equals(Double.TYPE.getName()) ||
202           name.equals(Float.TYPE.getName()) ||
203           name.equals(Integer.TYPE.getName()) ||
204           name.equals(Long.TYPE.getName()) ||
205           name.equals(Short.TYPE.getName()) ||
206           name.equals(Boolean.TYPE.getName()))
207
208                return true;
209
210       return false;
211    }
212
213
214
215    // Protected -----------------------------------------------------
216

217    /**
218     * creates constructor <tt>&lt;init&gt;(MBeanInfo info, AttributeOperationResolver resolver, Object resource)</tt>
219     * that calls <tt>super(info, resolver, resource)</tt> in its implementation
220     *
221     * @param cp constant pool
222     * @param className name of the class being generated
223     */

224    protected static MethodGen createConstructor(ConstantPoolGen cp, String JavaDoc className)
225    {
226       InstructionList constrInstructions = new InstructionList();
227
228       int constrRefIndex = cp.addMethodref(
229             SUPER_CLASS.getName(),
230             "<init>",
231             "(" + getDescriptorForType(MBeanInfo JavaDoc.class.getName())
232                 + getDescriptorForType(AttributeOperationResolver.class.getName())
233                 + getDescriptorForType(Object JavaDoc.class.getName())
234                 + ")V"
235       );
236
237       constrInstructions.append(new ALOAD(0)); // Stack: => ..., this
238
constrInstructions.append(new ALOAD(1)); // Stack: => ..., this, arg1 [MBeanInfo]
239
constrInstructions.append(new ALOAD(2)); // Stack: => ..., this, arg1 [MBeanInfo], arg2 [AttributeOperationResolver]
240
constrInstructions.append(new ALOAD(3)); // Stack: => ..., this, arg1 [MBeanInfo], arg2 [AttributeOperationResolver], arg3 [Object]
241
constrInstructions.append(new INVOKESPECIAL(constrRefIndex)); // Stack: => ...
242
constrInstructions.append(new RETURN()); // Stack: => <empty>
243

244       MethodGen constrMethod = new MethodGen(
245             Constants.ACC_PUBLIC,
246             Type.VOID,
247             new Type[] {
248                   new ObjectType(MBeanInfo JavaDoc.class.getName()),
249                   new ObjectType(AttributeOperationResolver.class.getName()),
250                   new ObjectType(Object JavaDoc.class.getName()) },
251             new String JavaDoc[] { "info", "resolver", "resource" },
252             "<init>",
253             className, constrInstructions, cp
254       );
255       constrMethod.setMaxStack(4);
256
257       return constrMethod;
258    }
259
260    /**
261     * Creates the implementation of the <tt>invoke(String actionName, Object[] args, String[] signature)</tt>
262     * method. This implementation currently handles all non overloaded MBean operation invocations.
263     * Overloaded operations still fall back to the default reflected invocations. <p>
264     *
265     * The Java equivalent of the implementation looks roughly as follows:<br><pre>
266     *
267     * public void invoke(String actionName, Object[] args, String[] signature)
268     * {
269     * if (actionName != null)
270     * {
271     * try
272     * {
273     * if (actionName.equals(&lt;operName1&gt;))
274     * return ((&lt;resource type&gt;)super.getResourceObject()).&lt;operName1&gt;((&lt;arg1 type&gt;)arg1, (&lt;arg2 type&gt;)arg2, ...);
275     * else if (actionName.equals(&lt;operName2&gt;))
276     * return ((&lt;resource type&gt;)super.getResourceObject()).&lt;operName2&gt;((&lt;arg1 type&gt;)arg1, (&lt;arg2 type&gt;)arg2, ...);
277     *
278     * ...
279     *
280     * else
281     * super.invoke(actionName, args, signature);
282     * }
283     * catch (Throwable t)
284     * {
285     * super.invoke(actionName, args, signature);
286     * }
287     * }
288     * }
289     * </pre>
290     *
291     * @param cp constant pool of the class being generated
292     * @param info metadata of the MBean
293     * @param className name of the class being generated
294     * @param resourceClassName name of the resource class being invoked
295     */

296    protected static MethodGen createInvoke(ConstantPoolGen cp, MBeanInfo JavaDoc info, String JavaDoc className, String JavaDoc resourceClassName)
297    {
298       InstructionList invokeInstructions = new InstructionList();
299       MethodEntry[] operations = getOperations(info);
300
301       // load operation name strings and methods to constant pool
302
for (int i = 0; i < operations.length; ++i) {
303          operations[i].nameIndexInCP = cp.addString(operations[i].getName());
304          operations[i].methodIndexInCP = cp.addMethodref(
305                   resourceClassName,
306                   operations[i].getName(),
307                   operations[i].methodDescriptor
308          );
309       }
310
311
312       int invokeIndex = cp.addMethodref(
313             SUPER_CLASS.getName(),
314             "invoke",
315             "(" + getDescriptorForType(String JavaDoc.class.getName())
316                 + getDescriptorForType(Object JavaDoc[].class.getName())
317                 + getDescriptorForType(String JavaDoc[].class.getName())
318                 +
319             ")" + getDescriptorForType(Object JavaDoc.class.getName())
320       );
321
322       int getResourceObjectIndex = cp.addMethodref(
323             SUPER_CLASS.getName(),
324             "getResourceObject",
325             "()Ljava/lang/Object;"
326       );
327
328       int strEqualsIndex = cp.addMethodref(
329             String JavaDoc.class.getName(),
330             "equals",
331             "(Ljava/lang/Object;)Z"
332       );
333
334       InstructionHandle beginTryBlock = null;
335       InstructionHandle endTryBlock = null;
336
337       IFNULL ifOperationEqualsNull = new IFNULL(null);
338       IFEQ operationElseIfBranch = null;
339
340       if (operations.length > 0)
341       {
342          //
343
// if (actionName != null)
344
//
345
invokeInstructions.append(new ALOAD(1)); // Stack: => ..., arg1 [String]
346

347          beginTryBlock =
348             invokeInstructions.append(ifOperationEqualsNull); // Stack: => ...
349

350          for (int i = 0; i < operations.length; ++i)
351          {
352             //
353
// if (actionName.equals(operations[i].getName());
354
//
355
InstructionHandle jumpToNextElse =
356                   invokeInstructions.append(new ALOAD(1)); // Stack: => ..., arg1 [String]
357
invokeInstructions.append(new LDC(operations[i].nameIndexInCP)); // Stack: => ..., opName [String]
358
invokeInstructions.append(new INVOKEVIRTUAL(strEqualsIndex)); // Stack: => ..., 0 | 1 [boolean]
359

360             // set the jump target for previous else if branch
361
if (operationElseIfBranch != null)
362                operationElseIfBranch.setTarget(jumpToNextElse);
363
364             operationElseIfBranch = new IFEQ(null);
365             invokeInstructions.append(operationElseIfBranch); // Stack: => ...
366

367             invokeInstructions.append(new ALOAD(0)); // Stack: => ..., this
368
invokeInstructions.append(new INVOKEVIRTUAL(getResourceObjectIndex)); // Stack: => ..., resource [Object]
369

370             int x = cp.addClass(resourceClassName);
371             invokeInstructions.append(new CHECKCAST(x)); // Stack: => ..., resource [<resource object type>]
372

373             // if invocation has args, we need to push them into stack
374
if (operations[i].getSignature().length > 0)
375             {
376
377                for (int arrayIndex = 0; arrayIndex < operations[i].getSignature().length; ++arrayIndex)
378                {
379                   invokeInstructions.append(new ALOAD(2)); // Stack: => ..., resource [<type>], arg2 [Object[]]
380
invokeInstructions.append(new PUSH(cp, arrayIndex)); // Stack: => ..., resource [<type>], arg2 [Object[]], array index [int]
381
invokeInstructions.append(new AALOAD()); // Stack: => ..., resource [<type>], array[index] [Object]
382

383                   // Args come in as objects. If signature has a primitive type
384
// we need to convert the arg before we can invoke the operation
385
String JavaDoc type = operations[i].getSignature() [arrayIndex].getName();
386
387                   if (isPrimitive(type))
388                      invokeInstructions.append(convertObjectToPrimitive(cp, type)); // Stack: => ..., resource[<type>], value [<primitive>]
389

390                   else
391                   {
392                      x = cp.addClass(type);
393                      invokeInstructions.append(new CHECKCAST(x)); // Stack: => ..., resource[<type>], value [<reference>]
394
}
395                }
396             }
397
398             //
399
// resource.<operation>(<arg 1, ... arg n>)
400
//
401
x = operations[i].methodIndexInCP;
402             invokeInstructions.append(new INVOKEVIRTUAL(x)); // Stack: => ..., returnvalue
403

404             // Wrap primitive return values into their corresponding wrapper objects
405
String JavaDoc type = operations[i].getReturnType();
406
407             if (isPrimitive(type))
408             {
409                invokeInstructions.append(convertPrimitiveToObject(cp, type)); // Stack: => ..., objectref [wrapper]
410
invokeInstructions.append(new ARETURN()); // Stack: => <empty>
411
}
412             else if (type.equals(Void.TYPE.getName()))
413             {
414                invokeInstructions.append(new ACONST_NULL()); // Stack: => ..., null
415
invokeInstructions.append(new ARETURN()); // Stack: => <empty>
416
}
417             else
418             {
419                invokeInstructions.append(new ARETURN()); // Stack: => <empty>
420
}
421          }
422       }
423
424       //
425
// super.invoke(actionName, args, signature) if no match was found
426
//
427
InstructionHandle jumpToSuperInvoke =
428             invokeInstructions.append(new ALOAD(0)); // Stack: => ..., this
429
invokeInstructions.append(new ALOAD(1)); // Stack: => ..., this, arg1 [String]
430
invokeInstructions.append(new ALOAD(2)); // Stack: => ..., this, arg1 [String], arg2 [Object[]]
431
invokeInstructions.append(new ALOAD(3)); // Stack: => ..., this, arg1 [String], arg2 [Object[]], arg3 [String[]]
432
invokeInstructions.append(new INVOKESPECIAL(invokeIndex)); // Stack: => ..., reference [Object]
433
invokeInstructions.append(new ARETURN()); // Stack: => <empty>
434

435       // set the jump targets
436
ifOperationEqualsNull.setTarget(jumpToSuperInvoke);
437
438       if (operations.length > 0)
439       {
440          // set the last else branch to call super.invoke
441
if (operationElseIfBranch != null)
442             operationElseIfBranch.setTarget(jumpToSuperInvoke);
443
444          // set the try catch block limits
445
beginTryBlock = beginTryBlock.getNext();
446          endTryBlock = jumpToSuperInvoke.getPrev();
447       }
448
449
450       // exception handler (it's a cheap shot -- if there is any exception, re-invoke
451
// on super class and let it handle all exceptions)
452
InstructionHandle exceptionHandlerCode =
453             invokeInstructions.append(new ALOAD(0));
454       invokeInstructions.append(new ALOAD(1));
455       invokeInstructions.append(new ALOAD(2));
456       invokeInstructions.append(new ALOAD(3));
457       invokeInstructions.append(new INVOKESPECIAL(invokeIndex));
458       invokeInstructions.append(new ARETURN());
459
460       MethodGen invokeMethod = new MethodGen(
461             Constants.ACC_PUBLIC,
462             Type.OBJECT,
463             new Type[] {
464                   Type.STRING,
465                   new ArrayType(Object JavaDoc.class.getName(), 1),
466                   new ArrayType(String JavaDoc.class.getName(), 1)
467             },
468             new String JavaDoc[] {
469                   "operationName",
470                   "args",
471                   "signature"
472             },
473             "invoke",
474             className, invokeInstructions, cp
475       );
476       invokeMethod.setMaxLocals(7);
477       invokeMethod.setMaxStack(calculateMaxStackSize(info));
478
479       invokeMethod.addException(ReflectionException JavaDoc.class.getName());
480       invokeMethod.addException(MBeanException JavaDoc.class.getName());
481
482       if (operations.length > 0) {
483          invokeMethod.addExceptionHandler(beginTryBlock, endTryBlock, exceptionHandlerCode, new ObjectType("java.lang.Throwable"));
484       }
485
486       return invokeMethod;
487    }
488
489    private static int calculateMaxStackSize(MBeanInfo JavaDoc info)
490    {
491       MBeanOperationInfo JavaDoc[] operations = info.getOperations();
492       int maxSize = 7;
493
494       for (int i = 0; i < operations.length; ++i)
495       {
496          if (operations[i].getSignature().length > maxSize + 2)
497             maxSize = operations[i].getSignature().length + 2;
498       }
499
500       return maxSize;
501    }
502
503    /**
504     * Converts a reference of a primitve wrapper object into a primite value type.
505     * This method assumes that the wrapper object reference is already loaded at the
506     * top of the operand stack. The stack is modified so that the object reference
507     * to a primitive wrapper is replaced by the corresponding value in the stack.
508     *
509     * @param cp constant pool
510     * @param type class name of the primitive wrapper object to convert
511     * @return an instruction list that replaces an object reference of a primitive
512     * wrapper object to its corresponding value in the operand stack
513     */

514    protected static InstructionList convertObjectToPrimitive(ConstantPoolGen cp, String JavaDoc type)
515    {
516       InstructionList il = new InstructionList();
517
518       int intValueIndex = cp.addMethodref(Integer JavaDoc.class.getName(), "intValue", "()I");
519       int byteValueIndex = cp.addMethodref(Byte JavaDoc.class.getName(), "byteValue", "()B");
520       int charValueIndex = cp.addMethodref(Character JavaDoc.class.getName(), "charValue", "()C");
521       int doubleValueIndex = cp.addMethodref(Double JavaDoc.class.getName(), "doubleValue", "()D");
522       int floatValueIndex = cp.addMethodref(Float JavaDoc.class.getName(), "floatValue", "()F");
523       int longValueIndex = cp.addMethodref(Long JavaDoc.class.getName(), "longValue", "()J");
524       int shortValueIndex = cp.addMethodref(Short JavaDoc.class.getName(), "shortValue", "()S");
525       int booleanValueIndex = cp.addMethodref(Boolean JavaDoc.class.getName(), "booleanValue", "()Z");
526
527       //
528
// Assumes the wrapper object reference is on top of the stack
529
//
530

531       if (type.equals(Integer.TYPE.getName()))
532       {
533          int x = cp.addClass("java.lang.Integer");
534          il.append(new CHECKCAST(x)); // Stack: => ..., type [Integer]
535
il.append(new INVOKEVIRTUAL(intValueIndex)); // Stack: => ..., value [int]
536
}
537
538       else if (type.equals(Byte.TYPE.getName()))
539       {
540          int x = cp.addClass("java.lang.Byte");
541          il.append(new CHECKCAST(x)); // Stack: => ..., type [Boolean]
542
il.append(new INVOKEVIRTUAL(byteValueIndex)); // Stack: => ..., 0 | 1 [boolean]
543
}
544
545       else if (type.equals(Character.TYPE.getName()))
546       {
547          int x = cp.addClass("java.lang.Character");
548          il.append(new CHECKCAST(x)); // Stack: => ..., type [Character]
549
il.append(new INVOKEVIRTUAL(charValueIndex)); // Stack: => ..., value [char]
550
}
551
552       else if (type.equals(Double.TYPE.getName()))
553       {
554          int x = cp.addClass("java.lang.Double");
555          il.append(new CHECKCAST(x)); // Stack: => ..., type [Double]
556
il.append(new INVOKEVIRTUAL(doubleValueIndex)); // Stack: => ..., value [double]
557
}
558
559       else if (type.equals(Float.TYPE.getName()))
560       {
561          int x = cp.addClass("java.lang.Float");
562          il.append(new CHECKCAST(x)); // Stack: => ..., type [Float]
563
il.append(new INVOKEVIRTUAL(floatValueIndex)); // Stack: => ..., value [float]
564
}
565
566       else if (type.equals(Long.TYPE.getName()))
567       {
568          int x = cp.addClass("java.lang.Long");
569          il.append(new CHECKCAST(x)); // Stack: => ..., type [Long]
570
il.append(new INVOKEVIRTUAL(longValueIndex)); // Stack: => ..., value [long]
571
}
572
573       else if (type.equals(Short.TYPE.getName()))
574       {
575          int x = cp.addClass("java.lang.Short");
576          il.append(new CHECKCAST(x)); // Stack: => ..., type [Short]
577
il.append(new INVOKEVIRTUAL(shortValueIndex)); // Stack: => ..., value [short]
578
}
579
580       else if (type.equals(Boolean.TYPE.getName()))
581       {
582          int x = cp.addClass("java.lang.Boolean");
583          il.append(new CHECKCAST(x)); // Stack: => ..., type [Boolean]
584
il.append(new INVOKEVIRTUAL(booleanValueIndex)); // Stack: => ..., value [boolean]
585
}
586
587       return il;
588    }
589
590
591    /**
592     * Converts a primitive into its corresponding object wrapper reference.
593     * This method assumes the primitve is already pushed to the top of the operand
594     * stack. The stack is modified so that the primitive value is replaced
595     * by a reference to its corresponding wrapper object that has been
596     * initialized to contain the same value.
597     *
598     * @param cp constant pool
599     * @param type type string of the primitive, for example {@link java.lang.Integer#TYPE Integer.TYPE.getName()}
600     * @return an instruction list that replaces the primitive type at the top of
601     * the operand stack with its corresponding, initialized, wrapper object
602     */

603    protected static InstructionList convertPrimitiveToObject(ConstantPoolGen cp, String JavaDoc type)
604    {
605       InstructionList il = new InstructionList();
606
607       if (type.equals(Boolean.TYPE.getName()))
608       {
609          int x = cp.addClass("java.lang.Boolean");
610          int constrIndex = cp.addMethodref("java.lang.Boolean", "<init>", "(B)V");
611
612          il.append(new ISTORE(4));
613          il.append(new NEW(x));
614          il.append(new ASTORE(5));
615          il.append(new ALOAD(5));
616          il.append(new ILOAD(4));
617          il.append(new INVOKESPECIAL(constrIndex));
618          il.append(new ALOAD(5));
619       }
620
621       else if (type.equals(Short.TYPE.getName()))
622       {
623          int x = cp.addClass("java.lang.Short");
624          int constrIndex = cp.addMethodref("java.lang.Short", "<init>", "(S)V");
625
626          il.append(new ISTORE(4));
627          il.append(new NEW(x));
628          il.append(new ASTORE(5));
629          il.append(new ALOAD(5));
630          il.append(new ILOAD(4));
631          il.append(new INVOKESPECIAL(constrIndex));
632          il.append(new ALOAD(5));
633       }
634
635       else if (type.equals(Long.TYPE.getName()))
636       {
637          int x = cp.addClass("java.lang.Long");
638          int constrIndex = cp.addMethodref("java.lang.Long", "<init>", "(J)V");
639
640          il.append(new LSTORE(4));
641          il.append(new NEW(x));
642          il.append(new ASTORE(6));
643          il.append(new ALOAD(6));
644          il.append(new LLOAD(4));
645          il.append(new INVOKESPECIAL(constrIndex));
646          il.append(new ALOAD(6));
647       }
648
649       else if (type.equals(Integer.TYPE.getName()))
650       {
651          int x = cp.addClass("java.lang.Integer");
652          int constrIndex = cp.addMethodref("java.lang.Integer", "<init>", "(I)V");
653
654          il.append(new ISTORE(4));
655          il.append(new NEW(x));
656          il.append(new ASTORE(5));
657          il.append(new ALOAD(5));
658          il.append(new ILOAD(4));
659          il.append(new INVOKESPECIAL(constrIndex));
660          il.append(new ALOAD(5));
661       }
662
663       else if (type.equals(Float.TYPE.getName()))
664       {
665          int x = cp.addClass("java.lang.Float");
666          int constrIndex = cp.addMethodref("java.lang.Float", "<init>", "(F)V");
667
668          il.append(new FSTORE(4));
669          il.append(new NEW(x));
670          il.append(new ASTORE(5));
671          il.append(new ALOAD(5));
672          il.append(new FLOAD(4));
673          il.append(new INVOKESPECIAL(constrIndex));
674          il.append(new ALOAD(5));
675       }
676
677       else if (type.equals(Double.TYPE.getName()))
678       {
679          int x = cp.addClass("java.lang.Double");
680          int constrIndex = cp.addMethodref("java.lang.Double", "<init>", "(D)V");
681
682          il.append(new DSTORE(4));
683          il.append(new NEW(x));
684          il.append(new ASTORE(6));
685          il.append(new ALOAD(6));
686          il.append(new DLOAD(4));
687          il.append(new INVOKESPECIAL(constrIndex));
688          il.append(new ALOAD(6));
689       }
690
691       else if (type.equals(Character.TYPE.getName()))
692       {
693          int x = cp.addClass("java.lang.Character");
694          int constrIndex = cp.addMethodref("java.lang.Character", "<init>", "(C)V");
695
696          il.append(new ISTORE(4));
697          il.append(new NEW(x));
698          il.append(new ASTORE(5));
699          il.append(new ALOAD(5));
700          il.append(new ILOAD(4));
701          il.append(new INVOKESPECIAL(constrIndex));
702          il.append(new ALOAD(5));
703       }
704
705       else if (type.equals(Byte.TYPE.getName()))
706       {
707          int x = cp.addClass("java.lang.Byte");
708          int constrIndex = cp.addMethodref("java.lang.Byte", "<init>", "(B)V");
709
710          il.append(new ISTORE(4));
711          il.append(new NEW(x));
712          il.append(new ASTORE(5));
713          il.append(new ALOAD(5));
714          il.append(new ILOAD(4));
715          il.append(new INVOKESPECIAL(constrIndex));
716          il.append(new ALOAD(5));
717       }
718
719       return il;
720    }
721
722
723    /**
724     * Returns a subset of MBean's operations. Overloaded operations are not supported yet,
725     * so they're left out of the list and their invocations are delegated to the reflection
726     * based super class. <p>
727     *
728     * Overloaded operations that differ in their arg list length may be able to gain in
729     * performance if implemented directly with byte code. Overloaded operations with
730     * equal arg list length may not show much difference compared to ternary search tree
731     * based resolver.
732     */

733    protected static MethodEntry[] getOperations(MBeanInfo JavaDoc info)
734    {
735       HashMap JavaDoc operationMap = new HashMap JavaDoc();
736       ArrayList JavaDoc overloadList = new ArrayList JavaDoc();
737       MBeanOperationInfo JavaDoc[] operations = info.getOperations();
738
739       for (int i = 0; i < operations.length; ++i)
740       {
741          String JavaDoc methodName = operations[i].getName();
742
743          if (operationMap.containsKey(methodName))
744             overloadList.add(methodName);
745          else
746             operationMap.put(methodName, new MethodEntry(operations[i]));
747       }
748
749       // method overloading not supported yet
750
Iterator JavaDoc it = overloadList.iterator();
751       while (it.hasNext())
752          operationMap.remove(it.next());
753
754       return (MethodEntry[])operationMap.values().toArray(new MethodEntry[0]);
755    }
756
757
758    // Inner classes -------------------------------------------------
759
private static class MethodEntry extends MBeanOperationInfo JavaDoc
760    {
761       private static final long serialVersionUID = 1792631947840418314L;
762       String JavaDoc methodDescriptor = null;
763       int nameIndexInCP = -1;
764       int methodIndexInCP = -1;
765
766       public MethodEntry(MBeanOperationInfo JavaDoc info)
767       {
768          super(info.getName(), info.getDescription(), info.getSignature(), info.getReturnType(), info.getImpact());
769
770          this.methodDescriptor = getMethodDescriptor(info.getSignature(), info.getReturnType());
771       }
772    }
773
774
775 }
776
777
778
779
780
Popular Tags