org.sadun.util.codegen
Class ObjectWrapperGenerator

java.lang.Object
  extended byorg.sadun.util.codegen.ObjectWrapperGenerator

public class ObjectWrapperGenerator
extends java.lang.Object

This class generates wrapper classes for existing classes, in both source and compiled form. tools.jar must be in classpath if Class compilation is required.

The wrapper class source code is produced in a working directory (by default, the temporary directory) and compiled on the fly. The resulting class will implement the same interfaces as the wrapped object.

Wrapping is performed in two phases: preparation and code/class generation.

The preparation phase starts by invoking beginWrap() (or overloads) which declares which class to wrap. The wrapper class will have a method for each public method exposed by the original wrapped class. static methods will simply invoke the corresponding method of the wrapped class.

Further methods can be added programmatically by addMethod() (or overloads), defining signature and body. An incorrect body will generate compilation errors if an attempt to produce a Class object is executed later.

The standard implementation for the wrapper object methods consists in simply invoking corresponding methods in the wrapped object. However, prologue or epilogue code (occurring before or after the wrapped object method invocation) can be added by using the setPrologue() and setEpilogue() methods (in various overloads). Prologue/epilogue code may have a set of thrown exceptions attached.

Prologue and epilogue code can contain references to the some values depending on the current method, as of the following table, expressed by the syntax $(symbol name).

Unless declared otherwise when invoking beginWrap(), the generated wrappers implement the Wrapper interface.

SymbolDescription
$(methodName)the name of the method
$(returnType)the return type of the method
$(paramNames)the parameter types of the method
$(paramTypes)the parameter types of the method

For example, the following code is valid in prologue/epilogue: System.out.println("Invoking wrapped $(methodName)");

endWrap() terminates the preparation phase.

At this point, either createCode(), createClass() or wrap() may be invoked to produce either the source code, a compiled Class object or a wrapper object instance.

Here's an example of typical inteface-based usage:

  // Create a generator
  ObjectWrapperGenerator gen = new ObjectWrapperGenerator();
  // Define the class to wrap
  Class cls = ArrayList.class;
  gen.beginWrap(cls, "ListWrapper");
  // Add a prologue to all methods
  gen.setPrologue(
	  cls.getMethods(),
	  "System.out.println(\"Wrapped call to \\\"$(methodName)\\\"\");",
	  new Class[] { RuntimeException.class });
  // End the preparation phase
  gen.endWrap();

  // Create a wrapped object instance and cast to the List interface
  List l = (List) gen.wrap(new ArrayList());
  // Use the wrapped object
  l.add(new String("Hello"));
  // Use the Wrapper interface
  System.out.println("Wrapping "+((Wrapper)l).getWrappedObject().getClass());
 

Author:
Cristiano Sadun

Constructor Summary
ObjectWrapperGenerator()
           
 
Method Summary
 void addInterface(java.lang.Class interfaceCls)
          Add an interface and a corresponding implementing object to the wrapped object.
 void addInterface(java.lang.Class interfaceCls, java.lang.reflect.Method method, java.lang.String code)
           
 void addInterface(java.lang.Class interfaceCls, java.lang.String name, java.lang.Class[] paramTypes, java.lang.String[] paramNames, java.lang.Class returnType, java.lang.String code)
           
 void addMethod(java.lang.String name, java.lang.Class[] paramTypes, java.lang.Class returnType, java.lang.String bodyCode)
          Add a public method specification to the wrapper class.
 void addMethod(java.lang.String name, java.lang.Class[] paramTypes, java.lang.Class returnType, java.lang.String bodyCode, int modifiers)
          Add a method specification to the wrapper class.
 void addMethod(java.lang.String name, java.lang.Class[] paramTypes, java.lang.String[] paramNames, java.lang.Class returnType, java.lang.String bodyCode)
          Add a public method specification to the wrapper class.
 void addMethod(java.lang.String name, java.lang.Class[] paramTypes, java.lang.String[] paramNames, java.lang.Class returnType, java.lang.String bodyCode, int modifiers)
          Add a method specification to the wrapper class.
 void beginWrap(java.lang.Class cls)
          Begin the preparation phase, setting which class is to be wrapped.
 void beginWrap(java.lang.Class cls, boolean implementWrapperInterface)
          Begin the preparation phase, setting which class is to be wrapped.
 void beginWrap(java.lang.Class cls, java.lang.String wrapperClassName)
          Begin the preparation phase, setting which class is to be wrapped and the fully qualified name of the wrapper class.
 void beginWrap(java.lang.Class cls, java.lang.String wrapperClassName, boolean implementWrapperInterface)
          Begin the preparation phase, setting which class is to be wrapped and the name of the wrapper class.
 java.lang.Class createClass()
          Return a wrapper class as a Class Object.
 java.lang.String createCode()
          Create the source code for the class.
 void endWrap()
          Terminate the preparation phase.
 java.lang.String getWorkingDirectory()
          Get the working directory, where source and class files are stored.
 boolean isVerbose()
          Return true if the generator is in verbose mode, otherwise false.
static java.lang.String[] makeParamNames(java.lang.String methodName, java.lang.Class[] paramTypes)
           
 void setEpilogue(java.lang.reflect.Method[] methods, java.lang.String epilogueCode)
          Set epilogue code for a set of wrapped method.
 void setEpilogue(java.lang.reflect.Method[] methods, java.lang.String prologueCode, java.lang.Class[] throwedExceptions)
          Set epilogue code for a set of wrapped method.
 void setEpilogue(java.lang.reflect.Method m, java.lang.String epilogueCode)
          Set epilogue code for a wrapped method.
 void setEpilogue(java.lang.reflect.Method m, java.lang.String epilogueCode, java.lang.Class[] throwedExceptions)
          Set epilogue code for a wrapped method.
 void setEpilogue(java.lang.String methodName, java.lang.Class[] paramTypes, java.lang.String prologueCode)
          Set epilogue code for a wrapped method, defined by name and parameter types.
 void setPrologue(java.lang.reflect.Method[] methods, java.lang.String prologueCode)
          Set prologue code for a set of methods.
 void setPrologue(java.lang.reflect.Method[] methods, java.lang.String prologueCode, java.lang.Class[] throwedExceptions)
          Set prologue code for a set of methods.
 void setPrologue(java.lang.reflect.Method m, java.lang.String prologueCode)
          Set prologue code for a wrapped method, defined by name and parameter types.
 void setPrologue(java.lang.reflect.Method m, java.lang.String prologueCode, java.lang.Class[] throwedExceptions)
          Set prologue code for a wrapped method, defined by name and parameter types.
 void setPrologue(java.lang.String methodName, java.lang.Class[] paramTypes, java.lang.String prologueCode)
          Set prologue code for a wrapped method, defined by name and parameter types.
 void setVerbose(boolean verbose)
          Set the verbose mode, which provides information on the generator's actions on standard error
 void setWorkingDirectory(java.lang.String workingDirectory)
          Set the working directory, where source and class files are stored.
 java.lang.Object wrap(java.lang.Object obj)
          Return an instance of the wrapper object for the given object (when no other implementors are necessary).
 java.lang.Object wrap(java.lang.Object[] obj)
          Return an instance of the wrapper object for the given object.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ObjectWrapperGenerator

public ObjectWrapperGenerator()
Method Detail

makeParamNames

public static java.lang.String[] makeParamNames(java.lang.String methodName,
                                                java.lang.Class[] paramTypes)

beginWrap

public void beginWrap(java.lang.Class cls,
                      boolean implementWrapperInterface)
Begin the preparation phase, setting which class is to be wrapped. The wrapper class will live in the same package as the wrapped class and have the same name concatenated with the Wrapped postfix.

For example, the wrapper for a class MyClass will be named MyClassWrapper.

Parameters:
cls - the class to be wrapped
implementWrapperInterface - if true, the wrapper object will implement the Wrapper interface

beginWrap

public void beginWrap(java.lang.Class cls)
Begin the preparation phase, setting which class is to be wrapped. The wrapper class will live in the same package as the wrapped class and have the same name concatenated with the Wrapped postfix.

For example, the wrapper for a class MyClass will be named MyClassWrapper.

Parameters:
cls - the class to be wrapped

beginWrap

public void beginWrap(java.lang.Class cls,
                      java.lang.String wrapperClassName)
Begin the preparation phase, setting which class is to be wrapped and the fully qualified name of the wrapper class. A getter for the wrapped object is automatically added and the wrapper object will implement the Wrapper interface.

Parameters:
cls - the class to be wrapped
wrapperClassName - the fully qualified name of the wrapper class

beginWrap

public void beginWrap(java.lang.Class cls,
                      java.lang.String wrapperClassName,
                      boolean implementWrapperInterface)
Begin the preparation phase, setting which class is to be wrapped and the name of the wrapper class.

Parameters:
cls - the class to be wrapped
wrapperClassName - the fully qualified name of the wrapper class
implementWrapperInterface - if true, the wrapper object will implement the Wrapper interface

addInterface

public void addInterface(java.lang.Class interfaceCls)
Add an interface and a corresponding implementing object to the wrapped object.

Parameters:
interfaceCls -

addInterface

public void addInterface(java.lang.Class interfaceCls,
                         java.lang.String name,
                         java.lang.Class[] paramTypes,
                         java.lang.String[] paramNames,
                         java.lang.Class returnType,
                         java.lang.String code)

addInterface

public void addInterface(java.lang.Class interfaceCls,
                         java.lang.reflect.Method method,
                         java.lang.String code)

setPrologue

public void setPrologue(java.lang.reflect.Method m,
                        java.lang.String prologueCode)
Set prologue code for a wrapped method, defined by name and parameter types.

The prloogue code is executed before the invocation of the wrapped object method occurs. The prologue code can contain refereneces to symbols (see class description).

If the code throws any checked exception, use the setPrologue() with exceptions overload.

Parameters:
m - the wrapped method
prologueCode - the code

setPrologue

public void setPrologue(java.lang.reflect.Method m,
                        java.lang.String prologueCode,
                        java.lang.Class[] throwedExceptions)
Set prologue code for a wrapped method, defined by name and parameter types.

The prloogue code is executed before the invocation of the wrapped object method occurs. The prologue code can contain refereneces to symbols (see class description).

Parameters:
m -
prologueCode -
throwedExceptions -

setPrologue

public void setPrologue(java.lang.reflect.Method[] methods,
                        java.lang.String prologueCode,
                        java.lang.Class[] throwedExceptions)
Set prologue code for a set of methods.

The prologue code is executed before the invocation of the wrapped object method occurs. The prologue code can contain refereneces to symbols (see class description).

Parameters:
methods - the set of wrapped method with the same prologue
prologueCode - the code
throwedExceptions - the exception thrown by the code.

setPrologue

public void setPrologue(java.lang.reflect.Method[] methods,
                        java.lang.String prologueCode)
Set prologue code for a set of methods.

The prloogue code is executed before the invocation of the wrapped object method occurs. The prologue code can contain refereneces to symbols (see class description).

If the code throws any checked exception, use the setPrologue() with exceptions overload.

Parameters:
methods - the set of wrapped method with the same prologue
prologueCode - the code

setPrologue

public void setPrologue(java.lang.String methodName,
                        java.lang.Class[] paramTypes,
                        java.lang.String prologueCode)
Set prologue code for a wrapped method, defined by name and parameter types.

The prloogue code is executed before the invocation of the wrapped object method occurs. The prologue code can contain refereneces to symbols (see class description).

Parameters:
methodName - the name of the wrapped method
paramTypes - the parameter types of the wrapped method
prologueCode - the code

setEpilogue

public void setEpilogue(java.lang.String methodName,
                        java.lang.Class[] paramTypes,
                        java.lang.String prologueCode)
Set epilogue code for a wrapped method, defined by name and parameter types.

The epilogue code is executed after the invocation of the wrapped object method occurs. The epilogue code can contain refereneces to symbols (see class description).

If the code throws any checked exception, use the setEpilogue() with exceptions overload.

Parameters:
methodName - the name of the wrapped method
paramTypes - the parameters of the wrapped method
prologueCode - the code

setEpilogue

public void setEpilogue(java.lang.reflect.Method m,
                        java.lang.String epilogueCode)
Set epilogue code for a wrapped method.

The epilogue code is executed after the invocation of the wrapped object method occurs. The epilogue code can contain refereneces to symbols (see class description).

If the code throws any checked exception, use the setEpilogue() with exceptions overload.

Parameters:
m - the wrapped method
epilogueCode - the code

setEpilogue

public void setEpilogue(java.lang.reflect.Method m,
                        java.lang.String epilogueCode,
                        java.lang.Class[] throwedExceptions)
Set epilogue code for a wrapped method.

The epilogue code is executed after the invocation of the wrapped object method occurs. The epilogue code can contain refereneces to symbols (see class description).

Parameters:
m - the wrapped method
epilogueCode - the code
throwedExceptions - the exceptions thrown by the code

setEpilogue

public void setEpilogue(java.lang.reflect.Method[] methods,
                        java.lang.String prologueCode,
                        java.lang.Class[] throwedExceptions)
Set epilogue code for a set of wrapped method.

The epilogue code is executed after the invocation of the wrapped object method occurs. The epilogue code can contain refereneces to symbols (see class description).

Parameters:
methods - the methods to wrap
throwedExceptions - the exceptions thrown by the code

setEpilogue

public void setEpilogue(java.lang.reflect.Method[] methods,
                        java.lang.String epilogueCode)
Set epilogue code for a set of wrapped method.

The epilogue code is executed after the invocation of the wrapped object method occurs. The epilogue code can contain refereneces to symbols (see class description).

If the code throws any checked exception, use the setEpilogue() with exceptions overload.

Parameters:
methods - the methods to wrap
epilogueCode - the code

addMethod

public void addMethod(java.lang.String name,
                      java.lang.Class[] paramTypes,
                      java.lang.String[] paramNames,
                      java.lang.Class returnType,
                      java.lang.String bodyCode,
                      int modifiers)
Add a method specification to the wrapper class. The method must be either new or a valid overload not already existing. The method body source code is specified directly in a String object.

Parameters:
name - the method name
paramTypes - the types of the parameters
paramNames - the names of the parameters
returnType - the return type
bodyCode - the Java source code of the method body
modifiers - the modifiers for the method

addMethod

public void addMethod(java.lang.String name,
                      java.lang.Class[] paramTypes,
                      java.lang.Class returnType,
                      java.lang.String bodyCode,
                      int modifiers)
Add a method specification to the wrapper class. The method must be either new or a valid overload not already existing. The method body source code is specified directly in a String object.

The names of the parameters are automatically generated by using a VariableNameGenerator object and following the rules defined therein.

Parameters:
name - the method name
paramTypes - the types of the parameters
returnType - the return type
bodyCode - the Java source code of the method body
modifiers - the modifiers for the method

addMethod

public void addMethod(java.lang.String name,
                      java.lang.Class[] paramTypes,
                      java.lang.String[] paramNames,
                      java.lang.Class returnType,
                      java.lang.String bodyCode)
Add a public method specification to the wrapper class. The method must be either new or a valid overload not already existing. The method body source code is specified directly in a String object.

Parameters:
name - the method name
paramTypes - the types of the parameters
paramNames - the names of the parameters
returnType - the return type
bodyCode - the Java source code of the method body

addMethod

public void addMethod(java.lang.String name,
                      java.lang.Class[] paramTypes,
                      java.lang.Class returnType,
                      java.lang.String bodyCode)
Add a public method specification to the wrapper class. The method must be either new or a valid overload not already existing. The method body source code is specified directly in a String object.

The names of the parameters are automatically generated by using a VariableNameGenerator object and following the rules defined therein.

Parameters:
name - the method name
paramTypes - the types of the parameters
returnType - the return type
bodyCode - the Java source code of the method body

endWrap

public void endWrap()
Terminate the preparation phase. As a result, the generator is ready for generating either source or compiled code.


createCode

public java.lang.String createCode()
Create the source code for the class. No syntax check is performed.

Returns:
the source code for the wrapper object

createClass

public java.lang.Class createClass()
                            throws ObjectWrapperGeneratorException
Return a wrapper class as a Class Object.

Returns:
Throws:
java.io.IOException
ObjectWrapperGeneratorException

wrap

public java.lang.Object wrap(java.lang.Object obj)
                      throws ObjectWrapperGeneratorException
Return an instance of the wrapper object for the given object (when no other implementors are necessary).

Parameters:
obj -
Returns:
Throws:
java.io.IOException
ObjectWrapperGeneratorException

wrap

public java.lang.Object wrap(java.lang.Object[] obj)
                      throws ObjectWrapperGeneratorException
Return an instance of the wrapper object for the given object. All the objects in the array are used.

Parameters:
obj -
Returns:
Throws:
java.io.IOException
ObjectWrapperGeneratorException

getWorkingDirectory

public java.lang.String getWorkingDirectory()
Get the working directory, where source and class files are stored.

Returns:
the working directory, where source and class files are stored.

setWorkingDirectory

public void setWorkingDirectory(java.lang.String workingDirectory)
Set the working directory, where source and class files are stored.

Parameters:
workingDirectory - the directory where source and class files are stored.

isVerbose

public boolean isVerbose()
Return true if the generator is in verbose mode, otherwise false.

Returns:
true if the generator is in verbose mode, otherwise false.

setVerbose

public void setVerbose(boolean verbose)
Set the verbose mode, which provides information on the generator's actions on standard error

Parameters:
verbose - true or false to enable/disable the verbose mode