bsh
Class ClassGeneratorUtil

java.lang.Object
  extended bybsh.ClassGeneratorUtil

public class ClassGeneratorUtil
extends java.lang.Object

ClassGeneratorUtil utilizes the ASM (www.objectweb.org) bytecode generator by Eric Bruneton in order to generate class "stubs" for BeanShell at runtime.

Stub classes contain all of the fields of a BeanShell scripted class as well as two "callback" references to BeanShell namespaces: one for static methods and one for instance methods. Methods of the class are delegators which invoke corresponding methods on either the static or instance bsh object and then unpack and return the results. The static namespace utilizes a static import to delegate variable access to the class' static fields. The instance namespace utilizes a dynamic import (i.e. mixin) to delegate variable access to the class' instance variables.

Constructors for the class delegate to the static initInstance() method of ClassGeneratorUtil to initialize new instances of the object. initInstance() invokes the instance intializer code (init vars and instance blocks) and then delegates to the corresponding scripted constructor method in the instance namespace. Constructors contain special switch logic which allows the BeanShell to control the calling of alternate constructors (this() or super() references) at runtime.

Specially named superclass delegator methods are also generated in order to allow BeanShell to access overridden methods of the superclass (which reflection does not normally allow).

Author:
Pat Niemeyer

Nested Class Summary
static class ClassGeneratorUtil.ConstructorArgs
          A ConstructorArgs object holds evaluated arguments for a constructor call as well as the index of a possible alternate selector to invoke.
 
Field Summary
(package private) static java.lang.String BSHCONSTRUCTORS
          The bsh static namespace variable that holds the constructor methods
(package private) static java.lang.String BSHINIT
          The bsh static namespace variable name of the instance initializer
(package private) static java.lang.String BSHSTATIC
          The name of the static field holding the reference to the bsh static This (the callback namespace for static methods)
(package private) static java.lang.String BSHSUPER
          The prefix for the name of the super delegate methods.
(package private) static java.lang.String BSHTHIS
          The name of the instance field holding the reference to the bsh instance This (the callback namespace for instance methods)
(package private)  Modifiers classModifiers
           
(package private)  java.lang.String className
           
(package private)  NameSpace classStaticNameSpace
           
(package private)  DelayedEvalBshMethod[] constructors
           
(package private) static int DEFAULTCONSTRUCTOR
          The switch branch number for the default constructor.
(package private)  java.lang.String fqClassName
          fully qualified class name (with package) e.g.
(package private)  java.lang.Class[] interfaces
           
(package private)  boolean isInterface
           
(package private)  DelayedEvalBshMethod[] methods
           
(package private) static java.lang.String OBJECT
           
(package private)  java.lang.Class superClass
           
(package private)  java.lang.String superClassName
           
(package private)  java.lang.reflect.Constructor[] superConstructors
           
(package private)  Variable[] vars
           
 
Constructor Summary
ClassGeneratorUtil(Modifiers classModifiers, java.lang.String className, java.lang.String packageName, java.lang.Class superClass, java.lang.Class[] interfaces, Variable[] vars, DelayedEvalBshMethod[] bshmethods, NameSpace classStaticNameSpace, boolean isInterface)
           
 
Method Summary
(package private)  boolean classContainsMethod(java.lang.Class clas, java.lang.String methodName, java.lang.String[] paramTypes)
           
(package private) static void doSwitchBranch(int index, java.lang.String targetClassName, java.lang.String[] paramTypes, Label endLabel, Label[] labels, int consArgsVar, CodeVisitor cv)
           
 byte[] generateClass()
          Generate the class bytecode for this class.
(package private)  void generateConstructor(int index, java.lang.String[] paramTypes, int modifiers, ClassWriter cw)
          Generate a constructor.
(package private)  void generateConstructorSwitch(int consIndex, int argsVar, int consArgsVar, CodeVisitor cv)
          Generate a switch with a branch for each possible alternate constructor.
(package private) static void generateField(java.lang.String fieldName, java.lang.String type, int modifiers, ClassWriter cw)
          Generate a field - static or instance.
(package private) static void generateMethod(java.lang.String className, java.lang.String fqClassName, java.lang.String methodName, java.lang.String returnType, java.lang.String[] paramTypes, int modifiers, ClassWriter cw)
          Generate a delegate method - static or instance.
static void generateParameterReifierCode(java.lang.String[] paramTypes, boolean isStatic, CodeVisitor cv)
          Generates the code to reify the arguments of the given method.
(package private) static void generatePlainReturnCode(java.lang.String returnType, CodeVisitor cv)
          Generate return code for a normal bytecode
static void generateReturnCode(java.lang.String returnType, CodeVisitor cv)
          Generates the code to unreify the result of the given method.
(package private) static void generateSuperDelegateMethod(java.lang.Class superClass, java.lang.String superClassName, java.lang.String methodName, java.lang.String returnType, java.lang.String[] paramTypes, int modifiers, ClassWriter cw)
          Generate a superclass method delegate accessor method.
(package private) static int getASMModifiers(Modifiers modifiers)
          Translate bsh.Modifiers into ASM modifier bitflags.
(package private) static This getClassInstanceThis(java.lang.Object instance, java.lang.String className)
          Get the instance bsh namespace field from the object instance.
(package private) static This getClassStaticThis(java.lang.Class clas, java.lang.String className)
          Get the static bsh namespace field from the class.
static ClassGeneratorUtil.ConstructorArgs getConstructorArgs(java.lang.String superClassName, This classStaticThis, java.lang.Object[] consArgs, int index)
          Evaluate the arguments (if any) for the constructor specified by the constructor index.
(package private) static java.lang.String getMethodDescriptor(java.lang.String returnType, java.lang.String[] paramTypes)
           
(package private) static java.lang.String[] getTypeDescriptors(java.lang.Class[] cparams)
           
static void initInstance(java.lang.Object instance, java.lang.String className, java.lang.Object[] args)
          Initialize an instance of the class.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

BSHSTATIC

static final java.lang.String BSHSTATIC
The name of the static field holding the reference to the bsh static This (the callback namespace for static methods)

See Also:
Constant Field Values

BSHTHIS

static final java.lang.String BSHTHIS
The name of the instance field holding the reference to the bsh instance This (the callback namespace for instance methods)

See Also:
Constant Field Values

BSHSUPER

static final java.lang.String BSHSUPER
The prefix for the name of the super delegate methods. e.g. _bshSuperfoo() is equivalent to super.foo()

See Also:
Constant Field Values

BSHINIT

static final java.lang.String BSHINIT
The bsh static namespace variable name of the instance initializer

See Also:
Constant Field Values

BSHCONSTRUCTORS

static final java.lang.String BSHCONSTRUCTORS
The bsh static namespace variable that holds the constructor methods

See Also:
Constant Field Values

DEFAULTCONSTRUCTOR

static final int DEFAULTCONSTRUCTOR
The switch branch number for the default constructor. The value -1 will cause the default branch to be taken.

See Also:
Constant Field Values

OBJECT

static final java.lang.String OBJECT
See Also:
Constant Field Values

className

java.lang.String className

fqClassName

java.lang.String fqClassName
fully qualified class name (with package) e.g. foo/bar/Blah


superClass

java.lang.Class superClass

superClassName

java.lang.String superClassName

interfaces

java.lang.Class[] interfaces

vars

Variable[] vars

superConstructors

java.lang.reflect.Constructor[] superConstructors

constructors

DelayedEvalBshMethod[] constructors

methods

DelayedEvalBshMethod[] methods

classStaticNameSpace

NameSpace classStaticNameSpace

classModifiers

Modifiers classModifiers

isInterface

boolean isInterface
Constructor Detail

ClassGeneratorUtil

public ClassGeneratorUtil(Modifiers classModifiers,
                          java.lang.String className,
                          java.lang.String packageName,
                          java.lang.Class superClass,
                          java.lang.Class[] interfaces,
                          Variable[] vars,
                          DelayedEvalBshMethod[] bshmethods,
                          NameSpace classStaticNameSpace,
                          boolean isInterface)
Parameters:
packageName - e.g. "com.foo.bar"
Method Detail

generateClass

public byte[] generateClass()
Generate the class bytecode for this class.


getASMModifiers

static int getASMModifiers(Modifiers modifiers)
Translate bsh.Modifiers into ASM modifier bitflags.


generateField

static void generateField(java.lang.String fieldName,
                          java.lang.String type,
                          int modifiers,
                          ClassWriter cw)
Generate a field - static or instance.


generateMethod

static void generateMethod(java.lang.String className,
                           java.lang.String fqClassName,
                           java.lang.String methodName,
                           java.lang.String returnType,
                           java.lang.String[] paramTypes,
                           int modifiers,
                           ClassWriter cw)
Generate a delegate method - static or instance. The generated code packs the method arguments into an object array (wrapping primitive types in bsh.Primitive), invokes the static or instance namespace invokeMethod() method, and then unwraps / returns the result.


generateConstructor

void generateConstructor(int index,
                         java.lang.String[] paramTypes,
                         int modifiers,
                         ClassWriter cw)
Generate a constructor.


generateConstructorSwitch

void generateConstructorSwitch(int consIndex,
                               int argsVar,
                               int consArgsVar,
                               CodeVisitor cv)
Generate a switch with a branch for each possible alternate constructor. This includes all superclass constructors and all constructors of this class. The default branch of this switch is the default superclass constructor.

This method also generates the code to call the static ClassGeneratorUtil getConstructorArgs() method which inspects the scripted constructor to find the alternate constructor signature (if any) and evalute the arguments at runtime. The getConstructorArgs() method returns the actual arguments as well as the index of the constructor to call.


doSwitchBranch

static void doSwitchBranch(int index,
                           java.lang.String targetClassName,
                           java.lang.String[] paramTypes,
                           Label endLabel,
                           Label[] labels,
                           int consArgsVar,
                           CodeVisitor cv)

getMethodDescriptor

static java.lang.String getMethodDescriptor(java.lang.String returnType,
                                            java.lang.String[] paramTypes)

generateSuperDelegateMethod

static void generateSuperDelegateMethod(java.lang.Class superClass,
                                        java.lang.String superClassName,
                                        java.lang.String methodName,
                                        java.lang.String returnType,
                                        java.lang.String[] paramTypes,
                                        int modifiers,
                                        ClassWriter cw)
Generate a superclass method delegate accessor method. These methods are specially named methods which allow access to overridden methods of the superclass (which the Java reflection API normally does not allow).


classContainsMethod

boolean classContainsMethod(java.lang.Class clas,
                            java.lang.String methodName,
                            java.lang.String[] paramTypes)

generatePlainReturnCode

static void generatePlainReturnCode(java.lang.String returnType,
                                    CodeVisitor cv)
Generate return code for a normal bytecode


generateParameterReifierCode

public static void generateParameterReifierCode(java.lang.String[] paramTypes,
                                                boolean isStatic,
                                                CodeVisitor cv)
Generates the code to reify the arguments of the given method. For a method "int m (int i, String s)", this code is the bytecode corresponding to the "new Object[] { new bsh.Primitive(i), s }" expression.

Parameters:
cv - the code visitor to be used to generate the bytecode.
isStatic - the enclosing methods is static

generateReturnCode

public static void generateReturnCode(java.lang.String returnType,
                                      CodeVisitor cv)
Generates the code to unreify the result of the given method. For a method "int m (int i, String s)", this code is the bytecode corresponding to the "((Integer)...).intValue()" expression.

Parameters:
cv - the code visitor to be used to generate the bytecode.

getConstructorArgs

public static ClassGeneratorUtil.ConstructorArgs getConstructorArgs(java.lang.String superClassName,
                                                                    This classStaticThis,
                                                                    java.lang.Object[] consArgs,
                                                                    int index)
Evaluate the arguments (if any) for the constructor specified by the constructor index. Return the ConstructorArgs object which contains the actual arguments to the alternate constructor and also the index of that constructor for the constructor switch.

Returns:
the ConstructorArgs object containing a constructor selector and evaluated arguments for the alternate constructor

initInstance

public static void initInstance(java.lang.Object instance,
                                java.lang.String className,
                                java.lang.Object[] args)
Initialize an instance of the class. This method is called from the generated class constructor to evaluate the instance initializer and scripted constructor in the instance namespace.


getClassStaticThis

static This getClassStaticThis(java.lang.Class clas,
                               java.lang.String className)
Get the static bsh namespace field from the class.

Parameters:
className - may be the name of clas itself or a superclass of clas.

getClassInstanceThis

static This getClassInstanceThis(java.lang.Object instance,
                                 java.lang.String className)
Get the instance bsh namespace field from the object instance.

Returns:
the class instance This object or null if the object has not been initialized.

getTypeDescriptors

static java.lang.String[] getTypeDescriptors(java.lang.Class[] cparams)