vinayc 2003/08/28 11:40:12
Added: tools/src/java/org/apache/altrmi/tools/generator
AbstractProxyGenerator.java
BCELProxyGeneratorImpl.java ProxyGeneratorImpl.java
Log:
Refactorize (includes modularize,mavenize & rest of the nice's)
Revision Changes Path
1.1
incubator-altrmi/tools/src/java/org/apache/altrmi/tools/generator/AbstractProxyGenerator.java
Index: AbstractProxyGenerator.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 1997-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software
* itself, if and wherever such third-party acknowledgments
* normally appear.
*
* 4. The names "Incubator", "AltRMI", and "Apache Software Foundation"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.altrmi.tools.generator;
import org.apache.altrmi.server.ProxyGenerator;
import org.apache.altrmi.server.ProxyGenerationException;
import org.apache.altrmi.server.PublicationDescriptionItem;
import java.lang.reflect.Method;
/**
* Abstract parent for Proxy Generators
*
* @author Paul Hammant
* @version $Revision: 1.1 $*
*
*/
public abstract class AbstractProxyGenerator
implements ProxyGenerator
{
private String m_classGenDir;
private String m_genName;
private String m_srcGenDir;
private String m_classpath;
private boolean m_verbose;
private PublicationDescriptionItem[] m_additionalFacades;
private PublicationDescriptionItem[] m_callbackFacades;
private PublicationDescriptionItem[] m_interfacesToExpose;
/**
* Get the directory name of the class generation directory.
*
* @return the dir name.
*/
public String getClassGenDir()
{
return m_classGenDir;
}
/**
* Get the generation name of the class
*
* @return the name.
*/
public String getGenName()
{
return m_genName;
}
/**
* Get the source directory name
*
* @return the dir name.
*/
public String getSrcGenDir()
{
return m_srcGenDir;
}
/**
* Get the m_classpath used during creation
*
* @return m_classpath
*/
public String getClasspath()
{
return m_classpath;
}
/**
* Is verbose debugging level
*
* @return verbose or not
*/
public boolean isVerbose()
{
return m_verbose;
}
/**
* Get the additional facades
*
* @return the additional facades
*/
public PublicationDescriptionItem[] getAdditionalFacades()
{
return m_additionalFacades;
}
public PublicationDescriptionItem[] getCallbackFacades()
{
return m_callbackFacades;
}
/**
* Get the interfaces to expose.
*
* @return the interfaces
*/
public PublicationDescriptionItem[] getInterfacesToExpose()
{
return m_interfacesToExpose;
}
/**
* Set the verbose logging level for class generation.
*
*
* @param trueFalse set the verbose level
*
*/
public void verbose( boolean trueFalse )
{
m_verbose = trueFalse;
}
/**
* Set the interfaces to expose.
*
*
* @param interfacesToExpose the interfaces.
*
*/
public void setInterfacesToExpose( PublicationDescriptionItem[]
interfacesToExpose )
{
m_interfacesToExpose = interfacesToExpose;
}
/**
* Set the additional facades
*
*
*
* @param additionalFacades the facades.
*
*/
public void setAdditionalFacades( PublicationDescriptionItem[]
additionalFacades )
{
m_additionalFacades = additionalFacades;
}
public void setCallbackFacades(PublicationDescriptionItem[]
callbackFacades)
{
this.m_callbackFacades = callbackFacades;
}
/**
* Set the clas generation dorectory
*
*
* @param classGenDir the dir.
*
*/
public void setClassGenDir( String classGenDir )
{
m_classGenDir = classGenDir;
}
/**
* Set the generation name
*
*
* @param genName the name
*
*/
public void setGenName( String genName )
{
this.m_genName = genName;
}
/**
* Set the source generation directory.
*
*
* @param srcGenDir the dir name.
*
*/
public void setSrcGenDir( String srcGenDir )
{
m_srcGenDir = srcGenDir;
}
/**
* Set the m_classpath to generate with
*
*
* @param classpath the m_classpath.
*
*/
public void setClasspath( String classpath )
{
m_classpath = classpath;
}
/**
* Is the param one of the additional facades?
*
*
* @param clazz the class
* @return true if the class is one of the designated facades
*
*/
protected boolean isAdditionalFacade( Class clazz )
{
if( m_additionalFacades == null )
{
return false;
}
for( int p = 0; p < m_additionalFacades.length; p++ )
{
if( clazz.getName().equals( m_additionalFacades[ p
].getFacadeClass().getName() ) )
{
return true;
}
else if( clazz.getName().equals( "[L" + m_additionalFacades[ p
].getFacadeClass().getName() + ";" ) )
{
return true;
}
}
return false;
}
/**
* Creates the Java-Source type of the string.
*
* @param rClass the class to get a type for
* @return the class type
*/
protected String getClassType( Class rClass )
{
String cn = rClass.getName();
if( rClass.getName().startsWith( "[L" ) )
{
return cn.substring( 2, cn.length() - 1 ) + "[]";
}
else
{
return cn;
}
}
/**
* Gernerate the source for the proxy class.
*
* @param classLoader the classloader to use while making the source.
* @throws ProxyGenerationException if an error during generation
*
*/
public void generateSrc( ClassLoader classLoader ) throws
ProxyGenerationException
{
// default impl
}
/**
* Generate the deferred classes.
*
*/
public void generateDeferredClasses()
{
// default impl
}
/**
*
* @param publicationDescriptionItemses
* @return
*/
protected boolean needsAsyncBehavior(PublicationDescriptionItem[]
publicationDescriptionItemses)
{
for (int i = 0; i < publicationDescriptionItemses.length; i++)
{
PublicationDescriptionItem publicationDescriptionItem =
publicationDescriptionItemses[i];
if (publicationDescriptionItem.hasAsyncBehavior())
{
return true;
}
}
return false;
}
protected Method[] getGeneratableMethods(Class clazz) {
Method[] methods = null;
try
{
Method ts = Object.class.getMethod("toString", new Class[0]);
Method hc = Object.class.getMethod("hashCode", new Class[0]);
Method[] interfaceMethods = clazz.getMethods();
methods = new Method[interfaceMethods.length +2];
System.arraycopy(interfaceMethods,0,methods,
0,interfaceMethods.length);
methods[interfaceMethods.length] = ts;
methods[interfaceMethods.length+1] = hc;
}
catch (NoSuchMethodException e)
{
// never!
}
return methods;
}
}
1.1
incubator-altrmi/tools/src/java/org/apache/altrmi/tools/generator/BCELProxyGeneratorImpl.java
Index: BCELProxyGeneratorImpl.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 1997-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software
* itself, if and wherever such third-party acknowledgments
* normally appear.
*
* 4. The names "Incubator", "AltRMI", and "Apache Software Foundation"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.altrmi.tools.generator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.ArrayType;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.INSTANCEOF;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.Type;
import org.apache.altrmi.server.PublicationDescriptionItem;
import org.apache.altrmi.common.MethodNameHelper;
/**
* Class BCElProxyGeneratorImpl
* This class generates AltRMI stubs using Jakarta BCEL library.
*
* HOWTO: Use 'javap' to read the bytecodes of the stubs generated
* by using the original stub-generator(which generates pure java code).
*
* @author <a href="mailto:[EMAIL PROTECTED]">Vinay Chandran</a>
* @version $Revision: 1.1 $
*/
public class BCELProxyGeneratorImpl
extends AbstractProxyGenerator {
//bcel
private static final String STUB_PREFIX = "AltrmiGenerated";
private InstructionFactory m_factory;
private ConstantPoolGen m_constantsPool;
private ClassGen m_classGen;
private ArrayList m_internalFieldRepresentingClasses;
/**
* Generate the class.
*
* @param classLoader the classloader to use during generation.
* @see org.apache.altrmi.common.ProxyGenerator#generateClass(ClassLoader)
*/
public void generateClass(ClassLoader classLoader) {
//create the Main Stubs:
generateProxyClass(STUB_PREFIX + getGenName() + "_Main",
getInterfacesToExpose());
//Create the Additional Facades
if (getAdditionalFacades() != null) {
for (int i = 0; i < getAdditionalFacades().length; i++) {
String encodedClassName =
MethodNameHelper.encodeClassName(getAdditionalFacades()[i].getFacadeClass());
generateProxyClass(
STUB_PREFIX + getGenName() + "_" + encodedClassName,
new
PublicationDescriptionItem[]{getAdditionalFacades()[i]});
}
}
}
/**
* Method generateProxyClass.
* Create Proxy Implementation with all interface methods
* Generating AltrmiGeneratedGENNAME_Main class
* @param mGeneratedClassName the name of the class to generate.
* @param interfacesToStubify the interfaces to stubify.
*/
protected void generateProxyClass(
String mGeneratedClassName,
PublicationDescriptionItem[] interfacesToStubify) {
//Start creating class
createNewClassDeclaration(mGeneratedClassName, interfacesToStubify);
/******** CONSTRUCTOR **************/
//create constructor that takes ProxyHelper
createConstructor(mGeneratedClassName);
/******** FIELDS *************/
//create fields
createFields();
/******** METHODS *************/
//create fields
createGetReferenceIDMethod(mGeneratedClassName);
createHelperMethodForDotClassCalls(mGeneratedClassName);
createInterfaceMethods(mGeneratedClassName, interfacesToStubify);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(getClassGenDir() + "/" +
mGeneratedClassName + ".class");
m_classGen.getJavaClass().dump(fos);
fos.close();
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
//<BCEL> <!-- Enter the BCEL Arena -->
/**
* Method createAndInitializeClass.
* This method starts creating the class.
* @param generatedClassName the bean class name
*/
protected void createNewClassDeclaration(String generatedClassName,
PublicationDescriptionItem[] interfacesToStubify) {
String[] interfaces = new String[interfacesToStubify.length + 1];
for (int i = 0; i < interfacesToStubify.length; i++) {
PublicationDescriptionItem publicationDescriptionItem =
interfacesToStubify[i];
interfaces[i] =
publicationDescriptionItem.getFacadeClass().getName();
}
interfaces[interfacesToStubify.length] =
"org.apache.altrmi.client.Proxy";
m_classGen =
new ClassGen(
generatedClassName,
"java.lang.Object",
generatedClassName + ".java",
Constants.ACC_PUBLIC | Constants.ACC_SUPER |
Constants.ACC_FINAL,
interfaces);
m_constantsPool = m_classGen.getConstantPool();
m_factory = new InstructionFactory(m_classGen, m_constantsPool);
m_internalFieldRepresentingClasses = new ArrayList();
}
/**
* Method createConstructor.
* This method adds a constructor that takes in a ProxyHelper Instance
* @param generatedClassName the bean class name
*/
protected void createConstructor(String generatedClassName) {
InstructionList il = new InstructionList();
MethodGen method =
new MethodGen(
Constants.ACC_PUBLIC,
Type.VOID,
new Type[]{new
ObjectType("org.apache.altrmi.client.ProxyHelper")},
new String[]{"arg0"},
"<init>",
generatedClassName,
il,
m_constantsPool);
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(
m_factory.createInvoke(
"java.lang.Object",
"<init>",
Type.VOID,
Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(m_factory.createLoad(Type.OBJECT, 1));
il.append(
m_factory.createFieldAccess(
generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.PUTFIELD));
il.append(m_factory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
m_classGen.addMethod(method.getMethod());
il.dispose();
}
/**
* Method createFields.
* =================adding===============
* private transient org.apache.altrmi.client.ProxyHelper m_proxyHelper;
* =================adding===============
* Add
*/
protected void createFields() {
FieldGen field;
field =
new FieldGen(
Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT,
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
"m_proxyHelper",
m_constantsPool);
m_classGen.addField(field.getField());
}
/**
* Method createGetReferenceIDMethod.
* =================adding=====================================
* public Long altrmiGetReferenceID(Object factoryThatIsAsking) {
* return m_proxyHelper.getReferenceID(factoryThatIsAsking);
* }
* =================adding=====================================
*
* @param generatedClassName the generated class name
*
*/
protected void createGetReferenceIDMethod(String generatedClassName) {
InstructionList il = new InstructionList();
MethodGen method =
new MethodGen(
Constants.ACC_PUBLIC,
new ObjectType("java.lang.Long"),
new Type[]{Type.OBJECT},
new String[]{"arg0"},
"altrmiGetReferenceID",
generatedClassName,
il,
m_constantsPool);
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(
m_factory.createFieldAccess(
generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.GETFIELD));
il.append(m_factory.createLoad(Type.OBJECT, 1));
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"getReferenceID",
new ObjectType("java.lang.Long"),
new Type[]{Type.OBJECT},
Constants.INVOKEINTERFACE));
il.append(m_factory.createReturn(Type.OBJECT));
method.setMaxStack();
method.setMaxLocals();
m_classGen.addMethod(method.getMethod());
il.dispose();
}
/**
* Method createHelperMethodForDotClassCalls.
* This class creates a method class$(String) which is used
* during SomeClass.class instruction
*
* @param generatedClassName the bean class name
*/
protected void createHelperMethodForDotClassCalls(String
generatedClassName) {
InstructionList il = new InstructionList();
MethodGen method =
new MethodGen(
Constants.ACC_STATIC,
new ObjectType("java.lang.Class"),
new Type[]{Type.STRING},
new String[]{"arg0"},
"class$",
generatedClassName,
il,
m_constantsPool);
InstructionHandle ih0 = il.append(m_factory.createLoad(Type.OBJECT,
0));
il.append(
m_factory.createInvoke(
"java.lang.Class",
"forName",
new ObjectType("java.lang.Class"),
new Type[]{Type.STRING},
Constants.INVOKESTATIC));
InstructionHandle ih4 =
il.append(m_factory.createReturn(Type.OBJECT));
InstructionHandle ih5 = il.append(m_factory.createStore(Type.OBJECT,
1));
il.append(m_factory.createNew("java.lang.NoClassDefFoundError"));
il.append(InstructionConstants.DUP);
il.append(m_factory.createLoad(Type.OBJECT, 1));
il.append(
m_factory.createInvoke(
"java.lang.Throwable",
"getMessage",
Type.STRING,
Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
il.append(
m_factory.createInvoke(
"java.lang.NoClassDefFoundError",
"<init>",
Type.VOID,
new Type[]{Type.STRING},
Constants.INVOKESPECIAL));
il.append(InstructionConstants.ATHROW);
method.addExceptionHandler(
ih0,
ih4,
ih5,
new ObjectType("java.lang.ClassNotFoundException"));
method.setMaxStack();
method.setMaxLocals();
m_classGen.addMethod(method.getMethod());
il.dispose();
}
/**
* Method createInterfaceMethods.
* This methods shall iterate through the set of methods
* of the interface creating equivalent methods for the
* stubs in the process.
*
* @param generatedClassName the generated class name
* @param interfacesToStubify the interfaces to make stubs for.
*/
protected void createInterfaceMethods(
String generatedClassName,
PublicationDescriptionItem[] interfacesToStubify) {
for (int x = 0; x < interfacesToStubify.length; x++) {
Class clazz = interfacesToStubify[x].getFacadeClass();
if (isVerbose()) {
System.out.println("ProxyGen: Processing interface: " +
clazz.getName());
}
Method[] methods = getGeneratableMethods(clazz);
generateEqualsMethod(generatedClassName);
for (int i = 0; i < methods.length; i++) {
createInterfaceMethod(generatedClassName,
methods[i],interfacesToStubify[x]);
}
}
}
/**
* Method createInterfaceMethod.
* Add the java.lang.reflect.Method wrapper into the stub
* @param generatedClassName the bean class name
* @param mth the method
*/
protected void createInterfaceMethod(String generatedClassName, Method
mth,PublicationDescriptionItem interfaceToStubify) {
InstructionList il = new InstructionList();
MethodGen method =
new MethodGen(
Constants.ACC_PUBLIC,
getReturnType(mth),
getArguments(mth),
getArgumentNames(mth),
mth.getName(),
generatedClassName,
il,
m_constantsPool);
//debug(getArguments(m));
// **** TO Insert TEST Bytecode Inside the stub ,uncomment the
subsequent lines
//if (m_verbose)
// createTestMethod(il, "calling " + mth.getName());
/*
* Declaration of Arrays
* =======================
* Object[] args = new Object[__number__of__arguments];
* Class[] argClasses = new Class[__number__of__arguments];
*/
int variableIndex, numberOfArguments;
Class[] paramTypes = mth.getParameterTypes();
numberOfArguments = paramTypes.length;
variableIndex = getFreeIndexToStart(paramTypes);
il.append(new PUSH(m_constantsPool, numberOfArguments));
il.append(m_factory.createNewArray(Type.OBJECT, (short) 1));
il.append(m_factory.createStore(Type.OBJECT, ++variableIndex));
il.append(new PUSH(m_constantsPool, numberOfArguments));
il.append(m_factory.createNewArray(
new ObjectType("java.lang.Class"),
(short) 1));
il.append(m_factory.createStore(Type.OBJECT, ++variableIndex));
/*
* Assigning parameter into Object[] and Class[] Array
* ====================================================
* args[0] = v0;
* argClasses[0]=v0Class.class
*/
//Used for adjustment of double/long datatype:
createInterfaceMethodArgs(numberOfArguments, il, variableIndex,
paramTypes, generatedClassName);
//check if its a rollback method
InstructionHandle ih_rollback =null;
InstructionHandle catchHandler=null;
BranchInstruction gotoCall =null;
InstructionHandle ih_tryEnd =null;
if(interfaceToStubify.isRollback(mth))
{
ih_rollback =
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(
m_factory.createFieldAccess(
generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.GETFIELD));
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"rollbackAsyncRequests",
Type.VOID,
Type.NO_ARGS,
Constants.INVOKEINTERFACE));
gotoCall =
m_factory.createBranchInstruction(Constants.GOTO,
null);
ih_tryEnd = il.append(gotoCall);
catchHandler =
il.append(m_factory.createStore(Type.OBJECT, ++variableIndex));
il.append(m_factory.createLoad(Type.OBJECT,
variableIndex));
injectCommonExceptionCatchBlock(il,method,variableIndex);
--variableIndex;
//createTestMethod(il,"after rollback");
}
/* Within the stub put the
* Call processObjectRequest on the instance ProxyHelper held within
the stub
* Thus,
* Injecting the following
* ================================================
* try
* {
* Object retVal = m_proxyHelper.processObjectRequest("foo1(int,
* float, java.lang.String,
java.lang.Integer)",args,argClasses);
* return (java.lang.String) retVal;
* }
* catch (Throwable t)
* {
* if (t instanceof RuntimeException)
* {
* throw (RuntimeException) t;
* }
* else if (t instanceof Error)
* {
* throw (Error) t;
* }
* else
* {
* t.printStackTrace();
* throw new org.apache.altrmi.client.
* InvocationException("Should never get here:"
+t.getMessage());
* }
* }
* ================================================
*/
InstructionHandle ihe1 = il.append(m_factory.createLoad(Type.OBJECT,
0));
if(interfaceToStubify.isRollback(mth))
{
gotoCall.setTarget(ihe1);
method.addExceptionHandler( ih_rollback,
ih_tryEnd,
catchHandler,
new ObjectType("java.lang.Throwable"));
}
il.append(
m_factory.createFieldAccess(
generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.GETFIELD));
// **** Check if the return type is facade ***
Class returnClass = mth.getReturnType();
if (returnClass.isArray()) {
returnClass = returnClass.getComponentType();
}
if (isAdditionalFacade(mth.getReturnType())) {
String encodedReturnClassName = "class$" +
MethodNameHelper.encodeClassName(returnClass);
addField(encodedReturnClassName);
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedReturnClassName,
new ObjectType("java.lang.Class"),
Constants.GETSTATIC));
BranchInstruction ifnullReturnClass =
m_factory.createBranchInstruction(Constants.IFNULL, null);
il.append(ifnullReturnClass);
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedReturnClassName,
new ObjectType("java.lang.Class"),
Constants.GETSTATIC));
BranchInstruction gotoReturnClass =
m_factory.createBranchInstruction(Constants.GOTO, null);
il.append(gotoReturnClass);
InstructionHandle ihPushMethodName =
il.append(new PUSH(m_constantsPool,
returnClass.getName()));
ifnullReturnClass.setTarget(ihPushMethodName);
il.append(
m_factory.createInvoke(
generatedClassName,
"class$",
new ObjectType("java.lang.Class"),
new Type[]{Type.STRING},
Constants.INVOKESTATIC));
il.append(InstructionConstants.DUP);
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedReturnClassName,
new ObjectType("java.lang.Class"),
Constants.PUTSTATIC));
InstructionHandle ihPushSignature =
il.append(new PUSH(m_constantsPool,
MethodNameHelper.getMethodSignature(mth)));
gotoReturnClass.setTarget(ihPushSignature);
il.append(m_factory.createLoad(Type.OBJECT, variableIndex - 1));
il.append(new PUSH(m_constantsPool,
MethodNameHelper.encodeClassName(getClassType(returnClass))));
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"processObjectRequestGettingFacade",
Type.OBJECT,
new Type[]{
new ObjectType("java.lang.Class"),
Type.STRING,
new ArrayType(Type.OBJECT, 1),
Type.STRING},
Constants.INVOKEINTERFACE));
} else {
//method signature = METHODNAME(arguments....)
il.append(new PUSH(m_constantsPool,
MethodNameHelper.getMethodSignature(mth)));
variableIndex -= 2;
il.append(m_factory.createLoad(Type.OBJECT, ++variableIndex));
il.append(m_factory.createLoad(Type.OBJECT, ++variableIndex));
//Check for async methods
if( interfaceToStubify.isAsync(mth) )
{
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"queueAsyncRequest",
Type.VOID,
new Type[]{
Type.STRING,
new ArrayType(Type.OBJECT, 1),
new ArrayType(new
ObjectType("java.lang.Class"), 1)},
Constants.INVOKEINTERFACE));
}
else
{
if(getBCELPrimitiveType(mth.getReturnType().getName()) == Type.VOID )
{
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"processVoidRequest",
Type.VOID,
new Type[]{
Type.STRING,
new ArrayType(Type.OBJECT, 1),
new ArrayType(new
ObjectType("java.lang.Class"), 1)},
Constants.INVOKEINTERFACE));
}
else
{
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"processObjectRequest",
Type.OBJECT,
new Type[]{
Type.STRING,
new ArrayType(Type.OBJECT, 1),
new ArrayType(new
ObjectType("java.lang.Class"), 1)},
Constants.INVOKEINTERFACE));
il.append(m_factory.createStore(Type.OBJECT,
++variableIndex));
il.append(m_factory.createLoad(Type.OBJECT,
variableIndex));
}
}
}
//createTestMethod(il,"after remote call");
InstructionHandle ihe2;
if(interfaceToStubify.isCommit(mth))
{
gotoCall =
m_factory.createBranchInstruction(Constants.GOTO,
null);
ihe2 = il.append(gotoCall);
variableIndex++;
}
else
{
if (mth.getReturnType().isPrimitive()) {
if (getBCELPrimitiveType(mth.getReturnType().getName()) ==
Type.VOID) {
ihe2 = il.append(m_factory.createReturn(Type.VOID));
} else {
il.append(
m_factory.createCheckCast(
new
ObjectType(getJavaWrapperClass(mth.getReturnType().getName()))));
il.append(
m_factory.createInvoke(
getJavaWrapperClass(mth.getReturnType().getName()),
mth.getReturnType().getName() + "Value",
getBCELPrimitiveType(mth.getReturnType().getName()),
Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
ihe2 = il.append(
m_factory.createReturn(getBCELPrimitiveType(mth.getReturnType().getName())));
}
} else {
il.append(
m_factory.createCheckCast(new
ObjectType(mth.getReturnType().getName())));
ihe2 = il.append(m_factory.createReturn(Type.OBJECT));
}
}
InstructionHandle ihe3 =
il.append(m_factory.createStore(Type.OBJECT, variableIndex));
//add custom exceptionHandling here
Class[] exceptionClasses = mth.getExceptionTypes();
InstructionHandle customHandler = null;
BranchInstruction ifCustomExceptionBranch = null;
for (int i = 0; i < exceptionClasses.length; i++) {
customHandler = il.append(m_factory.createLoad(Type.OBJECT,
variableIndex));
//create the series of custom exception handlers for the classes
if (ifCustomExceptionBranch != null) {
ifCustomExceptionBranch.setTarget(customHandler);
}
il.append(
new INSTANCEOF(
m_constantsPool.addClass(new
ObjectType(exceptionClasses[i].getName()))));
ifCustomExceptionBranch =
m_factory.createBranchInstruction(Constants.IFEQ, null);
il.append(ifCustomExceptionBranch);
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(
m_factory.createCheckCast(new
ObjectType(exceptionClasses[i].getName())));
il.append(InstructionConstants.ATHROW);
}
InstructionHandle defaultExceptionHandler =
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
if (customHandler != null) {
ifCustomExceptionBranch.setTarget(defaultExceptionHandler);
}
//add standard exception handling routine which handles any
//other exception generated during the remote call
injectCommonExceptionCatchBlock(il,method,variableIndex);
method.addExceptionHandler(
ihe1,
ihe2,
ihe3,
new ObjectType("java.lang.Throwable"));
//check if its a commit method
if(interfaceToStubify.isCommit(mth))
{
InstructionHandle ih_commit=
il.append(m_factory.createLoad(Type.OBJECT, 0));
gotoCall.setTarget(ih_commit);
il.append(
m_factory.createFieldAccess(
generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.GETFIELD));
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.ProxyHelper",
"commitAsyncRequests",
Type.VOID,
Type.NO_ARGS,
Constants.INVOKEINTERFACE));
InstructionHandle ih_return =
il.append(m_factory.createReturn(Type.VOID));
catchHandler =
il.append(m_factory.createStore(Type.OBJECT, variableIndex));
il.append(m_factory.createLoad(Type.OBJECT,
variableIndex));
injectCommonExceptionCatchBlock(il,method,variableIndex);
method.addExceptionHandler(ih_commit,ih_return,catchHandler,new
ObjectType("java.lang.Throwable"));
}
method.setMaxStack();
method.setMaxLocals();
m_classGen.addMethod(method.getMethod());
il.dispose();
}
private void generateEqualsMethod(String generatedClassName) {
/* public boolean equals(Object o) {
* return m_proxyHelper.isEquals(this,o);
* }
*/
InstructionList il = new InstructionList();
MethodGen method = new
MethodGen(Constants.ACC_PUBLIC, Type.BOOLEAN, new
Type[]{
Type.OBJECT}, new String[]{"arg0"},
"equals", generatedClassName, il, m_constantsPool);
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(m_factory.createFieldAccess(generatedClassName,
"m_proxyHelper",
new
ObjectType("org.apache.altrmi.client.ProxyHelper"),
Constants.GETFIELD));
il.append(m_factory.createLoad(Type.OBJECT, 0));
il.append(m_factory.createLoad(Type.OBJECT, 1));
il.append(m_factory.createInvoke("org.apache.altrmi.client.ProxyHelper",
"isEquals",
Type.BOOLEAN, new Type[]{Type.OBJECT,
Type.OBJECT},
Constants.INVOKEINTERFACE));
il.append(m_factory.createReturn(Type.INT));
method.setMaxStack();
method.setMaxLocals();
m_classGen.addMethod(method.getMethod());
il.dispose();
}
/**
* Create interface method's args.
*
* @param numberOfArguments the number of arguments.
* @param il an instruction list
* @param variableIndex a varible index.
* @param paramTypes parameter types
* @param generatedClassName the generated class name.
*/
private void createInterfaceMethodArgs(int numberOfArguments,
InstructionList il, int variableIndex,
Class[] paramTypes, String
generatedClassName) {
Type previousType = null;
int loadIndex = 0;
for (int i = 0; i < numberOfArguments; i++) {
// assigning the obj ref's
il.append(m_factory.createLoad(Type.OBJECT, variableIndex - 1));
il.append(new PUSH(m_constantsPool, i));
String className = paramTypes[i].getName();
//adjust for any previous wider datatype (double/long)
if (previousType != null
&& (previousType == Type.DOUBLE || previousType ==
Type.LONG)) {
++loadIndex;
}
if (paramTypes[i].isPrimitive()) {
il.append(m_factory.createNew(getJavaWrapperClass(className)));
il.append(InstructionConstants.DUP);
il.append(m_factory.createLoad(getBCELPrimitiveType(className), ++loadIndex));
il.append(
m_factory.createInvoke(
getJavaWrapperClass(className),
"<init>",
Type.VOID,
new Type[]{getBCELPrimitiveType(className)},
Constants.INVOKESPECIAL));
il.append(InstructionConstants.AASTORE);
} else {
//create the static fields for enabling .class calls
String encodedFieldName;
if (paramTypes[i].isArray()) {
int index = className.lastIndexOf('[');
if (className.charAt(index + 1) == 'L') {
encodedFieldName =
"array$" + className.substring(1 + index,
className.length() - 1).replace('.',
'$');
} else {
encodedFieldName =
"array$" + className.substring(1 + index,
className.length());
}
} else {
encodedFieldName = "class$" + className.replace('.', '$');
}
addField(encodedFieldName);
// ******** TODO assign the obj reference
il.append(m_factory.createLoad(Type.OBJECT, variableIndex -
1));
il.append(new PUSH(m_constantsPool, i));
il.append(m_factory.createLoad(Type.OBJECT, ++loadIndex));
il.append(InstructionConstants.AASTORE);
// *********TODO assign the class ref's
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(new PUSH(m_constantsPool, i));
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedFieldName,
new ObjectType("java.lang.Class"),
Constants.GETSTATIC));
BranchInstruction ifnull =
m_factory.createBranchInstruction(Constants.IFNULL,
null);
il.append(ifnull);
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedFieldName,
new ObjectType("java.lang.Class"),
Constants.GETSTATIC));
BranchInstruction goHeadToStoreRef =
m_factory.createBranchInstruction(Constants.GOTO,
null);
il.append(goHeadToStoreRef);
InstructionHandle ifnullStartHere =
il.append(new PUSH(m_constantsPool, className));
ifnull.setTarget(ifnullStartHere);
il.append(
m_factory.createInvoke(
generatedClassName,
"class$",
new ObjectType("java.lang.Class"),
new Type[]{Type.STRING},
Constants.INVOKESTATIC));
il.append(InstructionConstants.DUP);
il.append(
m_factory.createFieldAccess(
generatedClassName,
encodedFieldName,
new ObjectType("java.lang.Class"),
Constants.PUTSTATIC));
InstructionHandle storeClassRef =
il.append(InstructionConstants.AASTORE);
goHeadToStoreRef.setTarget(storeClassRef);
}
previousType = getBCELPrimitiveType(className);
}
}
/**
* Inject common exception catch blocks
*/
public void injectCommonExceptionCatchBlock(InstructionList
il,MethodGen method,int variableIndex)
{
il.append(
new INSTANCEOF(
m_constantsPool.addClass(new
ObjectType("java.lang.RuntimeException"))));
BranchInstruction b1 =
m_factory.createBranchInstruction(Constants.IFEQ, null);
il.append(b1);
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(
m_factory.createCheckCast(new
ObjectType("java.lang.RuntimeException")));
il.append(InstructionConstants.ATHROW);
InstructionHandle ih1 =
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(
new INSTANCEOF(m_constantsPool.addClass(new
ObjectType("java.lang.Error"))));
BranchInstruction b2 =
m_factory.createBranchInstruction(Constants.IFEQ, null);
il.append(b2);
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(m_factory.createCheckCast(new
ObjectType("java.lang.Error")));
il.append(InstructionConstants.ATHROW);
InstructionHandle ih2 =
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(
m_factory.createInvoke(
"java.lang.Throwable",
"printStackTrace",
Type.VOID,
Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
il.append(
m_factory.createNew(
"org.apache.altrmi.client.InvocationException"));
il.append(InstructionConstants.DUP);
il.append(m_factory.createNew("java.lang.StringBuffer"));
il.append(InstructionConstants.DUP);
il.append(new PUSH(m_constantsPool, "Should never get here: "));
il.append(
m_factory.createInvoke(
"java.lang.StringBuffer",
"<init>",
Type.VOID,
new Type[]{Type.STRING},
Constants.INVOKESPECIAL));
il.append(m_factory.createLoad(Type.OBJECT, variableIndex));
il.append(
m_factory.createInvoke(
"java.lang.Throwable",
"getMessage",
Type.STRING,
Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
il.append(
m_factory.createInvoke(
"java.lang.StringBuffer",
"append",
Type.STRINGBUFFER,
new Type[]{Type.STRING},
Constants.INVOKEVIRTUAL));
il.append(
m_factory.createInvoke(
"java.lang.StringBuffer",
"toString",
Type.STRING,
Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
il.append(
m_factory.createInvoke(
"org.apache.altrmi.client.InvocationException",
"<init>",
Type.VOID,
new Type[]{Type.STRING},
Constants.INVOKESPECIAL));
il.append(InstructionConstants.ATHROW);
b1.setTarget(ih1);
b2.setTarget(ih2);
}
/**
* Method getFreeIndexToStart.
* Returns the index to start allocating the subsequent stack
variables
* @param classes the classes
* @return int the index
*/
protected int getFreeIndexToStart(Class[] classes) {
int index = 0;
for (int i = 0; i < classes.length; i++) {
if (getBCELType(classes[i]) == Type.DOUBLE ||
getBCELType(classes[i]) == Type.LONG) {
index += 2;
}
index += 1;
}
return index;
}
/**
* Method getArguments.
* Convert the arguments of the method
* into equivalent BCEL datatypes
* @param method the method for which arguments are needed.
* @return Type[] an array of types
*/
protected Type[] getArguments(Method method) {
Class[] classes = method.getParameterTypes();
if (classes.length == 0) {
return Type.NO_ARGS;
}
Type[] types = new Type[classes.length];
for (int i = 0; i < classes.length; i++) {
types[i] = getBCELType(classes[i]);
}
return types;
}
/**
* Method getReturnType.
* Convert the returnType of the method into BCEL datatype
* @param method the method
* @return Type the type
*/
protected Type getReturnType(Method method) {
return getBCELType(method.getReturnType());
}
/**
* Method getArgumentNames.
* The arguments are arg0,arg1,.....
* @param method the method
* @return String[]
*/
protected String[] getArgumentNames(Method method) {
Class[] classes = method.getParameterTypes();
String[] args = new String[classes.length];
for (int i = 0; i < classes.length; i++) {
args[i] = "arg" + i;
}
return args;
}
/**
* Method getBCELType.
* Maps the java datatype and the BCEL datatype
* @param clazz the class
* @return Type the type
*/
protected Type getBCELType(Class clazz) {
if (clazz.isPrimitive()) {
return getBCELPrimitiveType(clazz.getName());
} else if (!clazz.isArray()) {
return new ObjectType(clazz.getName());
} else {
String className = clazz.getName();
int index = className.lastIndexOf('[');
int arrayDepth = className.indexOf('[') -
className.lastIndexOf('[') + 1;
if (className.charAt(index + 1) == 'L') {
return new ArrayType(
new ObjectType(clazz.getComponentType().getName()),
arrayDepth);
}
return new ArrayType(
getBCELPrimitiveType(className.substring(arrayDepth)),
arrayDepth);
}
}
/**
* Method getBCELPrimitiveType.
* Returns the BCEL Type given the Class Name
* @param javaDataType the java data type
* @return Type the BCEL type
*/
protected Type getBCELPrimitiveType(String javaDataType) {
switch (javaDataType.charAt(0)) {
case 'b':
if (javaDataType.toString().charAt(1) == 'o') {
return Type.BOOLEAN;
} else {
return Type.BYTE;
}
case 'c':
case 'C':
return Type.CHAR;
case 's':
case 'S':
return Type.SHORT;
case 'i':
case 'I':
return Type.INT;
case 'l':
case 'L':
return Type.LONG;
case 'f':
case 'F':
return Type.FLOAT;
case 'd':
case 'D':
return Type.DOUBLE;
//boolean array appears in this format
case 'Z':
return Type.BOOLEAN;
case 'B':
return Type.BYTE;
case 'v':
case 'V':
return Type.VOID;
}
return null;
}
/**
* Method getJavaWrapperClass.
* Returns the String representing the Wrapper class given the
* primitive datatype
* @param javaDataType the java data type
* @return String the JavaSource type.
*/
protected String getJavaWrapperClass(String javaDataType) {
switch (javaDataType.charAt(0)) {
case 'b':
if (javaDataType.charAt(1) == 'o') {
return "java.lang.Boolean";
} else {
return "java.lang.Byte";
}
case 'c':
case 'C':
return "java.lang.Character";
case 's':
case 'S':
return "java.lang.Short";
case 'i':
case 'I':
return "java.lang.Integer";
case 'l':
case 'L':
return "java.lang.Long";
case 'f':
case 'F':
return "java.lang.Float";
case 'd':
case 'D':
return "java.lang.Double";
case 'B':
return "java.lang.Byte";
case 'Z':
return "java.lang.Boolean";
case 'v':
case 'V':
return "java.lang.Void";
case '[':
return getJavaWrapperClass(javaDataType.substring(1));
}
return null; //never occurs;
}
/**
*
* @param encodedFieldName the encoded field name
*/
protected void addField(String encodedFieldName) {
if (!m_internalFieldRepresentingClasses.contains(encodedFieldName)) {
//System.out.println("method."+method.getName()+".addingfield["
// + _encodedFieldName + "]");
FieldGen field =
new FieldGen(
Constants.ACC_STATIC,
new ObjectType("java.lang.Class"),
encodedFieldName,
m_constantsPool);
m_classGen.addField(field.getField());
m_internalFieldRepresentingClasses.add(encodedFieldName);
}
}
/**
*
* @param il the instruction list
* @param msg the message
*/
protected void createTestMethod(InstructionList il, String msg) {
il.append(
m_factory.createFieldAccess(
"java.lang.System",
"out",
new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC));
il.append(new PUSH(m_constantsPool, msg));
il.append(
m_factory.createInvoke(
"java.io.PrintStream",
"println",
Type.VOID,
new Type[]{Type.STRING},
Constants.INVOKEVIRTUAL));
}
/**
* A debugging method
*
* @param prefix the prefix to print
* @param objArray the object array to print.
*/
protected void debug(String prefix, Object[] objArray) {
System.out.print(prefix);
for (int i = 0; i < objArray.length; i++) {
System.out.print(objArray[i] + ":");
}
System.out.println();
}
/**
* Get a class for a generated class name.
*
*
* @param generatedClassName the generated class name
* @return the class
*/
public Class getGeneratedClass(String generatedClassName) {
return getProxyClass(generatedClassName);
}
/**
* Method getProxyClass.
* This get the Class definition from the bytes
* @param className the clas name
* @return Class the class
*/
protected Class getProxyClass(String className) {
/*
FromJavaClassClassLoader fromJavaClassClassLoader =
new FromJavaClassClassLoader();
Class clazz =
fromJavaClassClassLoader.getClassFromJavaClass(m_classGen.getJavaClass());
*/
Class clazz = null;
try {
URLClassLoader urlCL =
new URLClassLoader(
new URL[]{
new URL("file:/" + new
File(getClassGenDir()).getCanonicalPath() + "/")},
//
this.getClass().getClassLoader());
clazz = urlCL.loadClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
// this is OK, as null will be passed back.
}
return clazz;
}
//++++++++++++++++++testing
//</BCEL>
}
1.1
incubator-altrmi/tools/src/java/org/apache/altrmi/tools/generator/ProxyGeneratorImpl.java
Index: ProxyGeneratorImpl.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 1997-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software
* itself, if and wherever such third-party acknowledgments
* normally appear.
*
* 4. The names "Incubator", "AltRMI", and "Apache Software Foundation"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.altrmi.tools.generator;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Vector;
import org.apache.altrmi.server.ProxyGenerationException;
import org.apache.altrmi.common.MethodNameHelper;
import org.apache.altrmi.tools.javacompiler.JavaCompiler;
import org.apache.altrmi.server.PublicationDescriptionItem;
/**
* Class ProxyGeneratorImpl
*
*
* @author Paul Hammant
* @author Mike Miller of www.gac.com
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Royal</a>
* @version $Revision: 1.1 $
*/
public class ProxyGeneratorImpl extends AbstractProxyGenerator
{
/**
* Method generate
*
*
* @param classLoader the class loader to use.
* @throws ProxyGenerationException if a problem during generation.
*
*/
public void generateSrc( ClassLoader classLoader ) throws
ProxyGenerationException
{
// The lookupable service class source.
makeSource( classLoader, "Main", getInterfacesToExpose() );
if( getAdditionalFacades() != null )
{
for( int i = 0; i < getAdditionalFacades().length; i++ )
{
PublicationDescriptionItem facade = getAdditionalFacades()[ i
];
makeSource( classLoader, MethodNameHelper.encodeClassName(
facade.getFacadeClass() ), new PublicationDescriptionItem[]{facade} );
}
}
}
/**
* Method generateClass
*
*
* @param classLoader the class loader to use.
*
*/
public void generateClass( ClassLoader classLoader )
{
JavaCompiler jc = JavaCompiler.getDefaultCompiler();
jc.setOutputDir( getClassGenDir() );
//jc.setM_compilerPath();
jc.addClassPath( getClassGenDir() );
jc.addClassPath( getClasspath() );
jc.addDefaultClassPath();
jc.doCompile( getSrcGenDir() + File.separator + "AltrmiGenerated"
+ getGenName() + "_Main.java" );
System.out.println( jc.getCompilerMessage() );
if( getAdditionalFacades() != null )
{
for( int i = 0; i < getAdditionalFacades().length; i++ )
{
String classname = MethodNameHelper.encodeClassName(
getAdditionalFacades()[ i ].getFacadeClass() );
jc.doCompile( getSrcGenDir() + File.separator +
"AltrmiGenerated"
+ getGenName() + "_" + classname + ".java" );
}
}
}
/**
* Method generateDeferredClasses
*
*
*/
public void generateDeferredClasses()
{
JavaCompiler jc = JavaCompiler.getDefaultCompiler();
jc.setOutputDir( getClassGenDir() );
jc.setCompilerPath( getSrcGenDir() );
jc.addClassPath( getClassGenDir() );
jc.addClassPath( getClasspath() );
jc.addDefaultClassPath();
jc.doCompile( "*.java" );
System.out.println( jc.getCompilerMessage() );
}
/**
* Method makeSource
*
*
* @param classloader the classloader to use
* @param name the name of the source file.
* @param interfacesToExpose the interfaces to expose.
*
* @throws ProxyGenerationException if generation not possible.
*
*/
public void makeSource( ClassLoader classloader, String name,
PublicationDescriptionItem[] interfacesToExpose )
throws ProxyGenerationException
{
// methdos could be in more than one interface.
Vector methodsDone = new Vector();
String filename = getSrcGenDir() + File.separator + "AltrmiGenerated"
+ getGenName() + "_" + name + ".java";
PrintWriter classSource = null;
try
{
classSource = new PrintWriter( new FileOutputStream( filename ) );
}
catch( FileNotFoundException e )
{
throw new ProxyGenerationException( "Cannot make source output
file '"
+ filename + "'" );
}
classSource.print( "public final class AltrmiGenerated" +
getGenName() + "_" + name );
classSource.println( " implements org.apache.altrmi.client.Proxy, " );
generateInterfaceList( classSource, interfacesToExpose );
classSource.println( " { " );
classSource.println(
" private transient org.apache.altrmi.client.ProxyHelper
m_proxyHelper;" );
// Generate Constructor
classSource.println(
" public AltrmiGenerated" + getGenName() + "_" + name
+ " (org.apache.altrmi.client.ProxyHelper proxyHelper) {" );
classSource.println( " m_proxyHelper = proxyHelper;" );
classSource.println( " }" );
// helper method for the m_factory.
// from Proxy interface
classSource
.println( " public Long altrmiGetReferenceID(Object
factoryThatIsAsking) {" );
classSource
.println( " return
m_proxyHelper.getReferenceID(factoryThatIsAsking);" );
classSource.println( " }" );
makeSourceInterfaces(classSource, interfacesToExpose, methodsDone);
classSource.print( "}" );
classSource.close();
}
private void makeSourceInterfaces(PrintWriter classSource,
PublicationDescriptionItem[] interfacesToExpose,
Vector methodsDone) throws ProxyGenerationException
{
// TODO DefaultProxyHelper altrmiGetProxyHelper();
generateEqualsMethod(classSource);
methodsDone.add("equals(java.lang.Object)");
for( int x = 0; x < interfacesToExpose.length; x++ )
{
PublicationDescriptionItem interfaceToExpose =
interfacesToExpose[ x ];
Class clazz = interfaceToExpose.getFacadeClass();
if( isVerbose() )
{
System.out.println( "ProxyGen: Processing interface: " +
clazz.getName() );
}
Method[] methods = getGeneratableMethods(clazz);
for( int y = 0; y < methods.length; y++ )
{
Method method = methods[ y ];
String methodSignature = MethodNameHelper.getMethodSignature(
method );
if( isVerbose() )
{
System.out.println( "ProxyGen: Processing method: " +
methodSignature );
}
if( !methodsDone.contains( methodSignature ))
{
makeSourceInterfacesMethodsNotDone(
classSource,
methodsDone,
methodSignature,
method,
interfaceToExpose.isAsync(method),
interfaceToExpose.isCommit(method),
interfaceToExpose.isRollback(method)
);
}
}
}
}
private void generateEqualsMethod(PrintWriter classSource)
{
classSource.println( " public boolean equals(Object o) {" );
classSource.println( " return m_proxyHelper.isEquals(this,o);" );
classSource.println( " }" );
}
private void makeSourceInterfacesMethodsNotDone(PrintWriter classSource,
Vector methodsDone,
String methodSignature, Method method,
boolean async, boolean commit, boolean rollback)
throws ProxyGenerationException
{
methodsDone.add( methodSignature );
Class rClass = method.getReturnType();
if( !( method.getReturnType() instanceof Serializable ) )
{
throw new ProxyGenerationException( "Return type " + rClass
+ " must be serializable" );
}
String mName = method.getName();
classSource.print( " public " + generateReturnValue( rClass ) + " "
+ mName
+ " (" );
Class[] argTypes = method.getParameterTypes();
for( int i = 0; i < argTypes.length; i++ )
{
String cn = ( argTypes[ i ].isArray()
? argTypes[ i ].getComponentType().getName()
: argTypes[ i ].getName() );
if( !( argTypes[ i ] instanceof Serializable ) )
{
throw new ProxyGenerationException( "Argument type " + cn
+ " must be serializable"
);
}
generateParameter( classSource, argTypes[ i ], i );
}
classSource.print( ") " );
Class[] throwsTypes = method.getExceptionTypes();
for( int i = 0; i < throwsTypes.length; i++ )
{
generateThrows( classSource, i, throwsTypes );
}
classSource.println( "{" );
if (async)
{
generateAsyncMethodBody(classSource, argTypes, rClass,
methodSignature, method);
}
else if (commit)
{
generateAsyncMethodBody(classSource, argTypes, rClass,
methodSignature, method);
generateAsyncCommitMethodBody(classSource);
}
else if (rollback)
{
generateAsyncRollbackMethodBody(classSource);
generateNonAsyncMethodBody(classSource, argTypes, rClass,
methodSignature, method);
}
else
{
generateNonAsyncMethodBody(classSource, argTypes, rClass,
methodSignature, method);
}
classSource.println( " " +
"" +
"" +
"}" );
}
private void generateNonAsyncMethodBody(PrintWriter classSource, Class[]
argTypes, Class rClass, String methodSignature, Method method) {
generateMethodBody(classSource, argTypes, rClass, methodSignature,
method, "processVoidRequest");
}
private void generateAsyncMethodBody(PrintWriter classSource, Class[]
argTypes, Class rClass, String methodSignature, Method method) {
generateMethodBody(classSource, argTypes, rClass, methodSignature,
method, "queueAsyncRequest");
}
private void generateMethodBody(PrintWriter classSource, Class[] argTypes,
Class rClass, String methodSignature,
Method method, String proxyMethodName)
{
Class[] throwsTypes;
generateMethodArgs(classSource, argTypes);
classSource.println( " try {" );
if( rClass.toString().equals( "void" ) )
{
classSource.println( " m_proxyHelper." + proxyMethodName +
"(\""
+ methodSignature + "\",args,argClasses);"
);
}
else
{
makeSourceInterfacesMethodsNotDoneNotVoid(classSource, method,
rClass, methodSignature);
}
classSource.println( " } catch (Throwable t) {" );
throwsTypes = method.getExceptionTypes();
for( int i = 0; i < throwsTypes.length; i++ )
{
generateThrowHandler( classSource, i, throwsTypes );
}
classSource.println( " if (t instanceof RuntimeException) { " );
classSource.println( " throw (RuntimeException) t;" );
classSource.println( " } else if (t instanceof Error) { " );
classSource.println( " throw (Error) t;" );
classSource.println( " } else { " );
classSource.println( " t.printStackTrace(); " );
classSource.println(
" throw new org.apache.altrmi.client."
+ "InvocationException(\"Should never get here: \"
+t.getMessage());");
classSource.println( " }" );
classSource.println( " }" );
}
private void generateMethodArgs(PrintWriter classSource, Class[] argTypes)
{
classSource.println( " Object[] args = new Object[" +
argTypes.length
+ "];" );
classSource.println( " Class[] argClasses = new Class[" +
argTypes.length
+ "];" );
for( int i = 0; i < argTypes.length; i++ )
{
generateAssignLine( classSource, argTypes[ i ], i );
}
}
private void generateAsyncCommitMethodBody(PrintWriter classSource)
{
classSource.println( " try {" );
classSource.println( " m_proxyHelper.commitAsyncRequests();" );
classSource.println( " } catch (Throwable t) {" );
classSource.println( " if (t instanceof RuntimeException) { " );
classSource.println( " throw (RuntimeException) t;" );
classSource.println( " } else if (t instanceof Error) { " );
classSource.println( " throw (Error) t;" );
classSource.println( " } else { " );
classSource.println( " t.printStackTrace(); " );
classSource.println(
" throw new org.apache.altrmi.client."
+ "InvocationException(\"Should never get here: \"
+t.getMessage());");
classSource.println( " }" );
classSource.println( " }" );
}
private void generateAsyncRollbackMethodBody(PrintWriter classSource)
{
Vector v = new Vector();
v.removeAllElements();
classSource.println( " try {" );
classSource.println( " m_proxyHelper.rollbackAsyncRequests();" );
classSource.println( " } catch (Throwable t) {" );
classSource.println( " if (t instanceof RuntimeException) { " );
classSource.println( " throw (RuntimeException) t;" );
classSource.println( " } else if (t instanceof Error) { " );
classSource.println( " throw (Error) t;" );
classSource.println( " } else { " );
classSource.println( " t.printStackTrace(); " );
classSource.println(
" throw new org.apache.altrmi.client."
+ "InvocationException(\"Should never get here: \"
+t.getMessage());");
classSource.println( " }" );
classSource.println( " }" );
}
private void makeSourceInterfacesMethodsNotDoneNotVoid(PrintWriter
classSource, Method method,
Class rClass, String methodSignature)
{
boolean isFacadeRetVal = isAdditionalFacade( method.getReturnType() );
if( isFacadeRetVal )
{
Class retClassType = rClass;
if( rClass.isArray() )
{
retClassType = rClass.getComponentType();
}
classSource.println(
" Object retVal =
m_proxyHelper.processObjectRequestGettingFacade("
+ retClassType.getName() + ".class , \""
+ methodSignature + "\",args,\""
+ MethodNameHelper.encodeClassName( getClassType( rClass ) )
+ "\");" );
classSource.println( " return (" + getClassType( rClass )
+ ") retVal;" );
}
else
{
classSource.println(
" Object retVal = m_proxyHelper.processObjectRequest(\""
+ methodSignature + "\",args,argClasses);" );
generateReturnLine( classSource, rClass );
}
}
private void generateThrowHandler(PrintWriter classSource, int i, Class[]
throwsTypes )
{
if( i == 0 )
{
classSource.println(
" if (t instanceof " + throwsTypes[ i ].getName() +
") { " );
}
else
{
classSource.println( " } else if (t instanceof " +
throwsTypes[ i ].getName()
+ ") { " );
}
classSource.println( " throw (" + throwsTypes[ i ].getName() +
") t;" );
if( i + 1 == throwsTypes.length )
{
classSource.print( " } else" );
}
}
private void generateThrows(PrintWriter classSource, int i, Class[]
throwsTypes )
{
if( i == 0 )
{
classSource.print( "throws " );
}
classSource.print( throwsTypes[ i ].getName() );
if( i + 1 < throwsTypes.length )
{
classSource.print( ", " );
}
}
private void generateInterfaceList(PrintWriter classSource,
PublicationDescriptionItem[] interfacesToExpose )
{
for( int x = 0; x < interfacesToExpose.length; x++ )
{
classSource.print( interfacesToExpose[ x
].getFacadeClass().getName() );
if( x + 1 < interfacesToExpose.length )
{
classSource.print( ", " );
}
}
}
private void generateParameter(PrintWriter classSource, Class cl, int i )
{
if( i > 0 )
{
classSource.print( ", " );
}
if( cl.isArray() )
{
classSource.print( cl.getComponentType().getName() + "[]" );
}
else
{
classSource.print( cl.getName() );
}
classSource.print( " v" + i );
}
private void generateAssignLine( PrintWriter classSource, Class clazz,
int i )
{
String cn = clazz.getName();
if( cn.equals( "int" ) )
{
classSource.println( " args[" + i + "] = new Integer(v" + i +
");" );
}
else if( cn.equals( "short" ) )
{
classSource.println( " args[" + i + "] = new Short(v" + i +
");" );
}
else if( cn.equals( "float" ) )
{
classSource.println( " args[" + i + "] = new Float(v" + i +
");" );
}
else if( cn.equals( "double" ) )
{
classSource.println( " args[" + i + "] = new Double(v" + i +
");" );
}
else if( cn.equals( "long" ) )
{
classSource.println( " args[" + i + "] = new Long(v" + i +
");" );
}
else if( cn.equals( "char" ) )
{
classSource.println( " args[" + i + "] = new Character(v" + i
+ ");" );
}
else if( cn.equals( "boolean" ) )
{
classSource.println( " args[" + i + "] = new Boolean(v" + i +
");" );
}
else if( cn.equals( "byte" ) )
{
classSource.println( " args[" + i + "] = new Byte(v" + i +
");" );
}
else
{
classSource.println( " args[" + i + "] = v" + i + ";" );
classSource.println( " argClasses[" + i + "] = "
+ generateReturnValue( clazz ) + ".class;" );
}
}
private void generateReturnLine( PrintWriter classSource, Class rClass )
{
String cn = rClass.getName();
if( cn.equals( "boolean" ) )
{
classSource.println( " return ((Boolean)
retVal).booleanValue();" );
}
else if( cn.equals( "int" ) )
{
classSource.println( " return ((Integer)
retVal).intValue();" );
}
else if( cn.equals( "short" ) )
{
classSource.println( " return ((Short)
retVal).shortValue();" );
}
else if( cn.equals( "float" ) )
{
classSource.println( " return ((Float)
retVal).floatValue();" );
}
else if( cn.equals( "double" ) )
{
classSource.println( " return ((Double)
retVal).doubleValue();" );
}
else if( cn.equals( "long" ) )
{
classSource.println( " return ((Long) retVal).longValue();"
);
}
else if( cn.equals( "char" ) )
{
classSource.println( " return ((Character)
retVal).charValue();" );
}
else if( cn.equals( "void" ) )
{
classSource.println( " return;" );
}
else if( cn.equals( "byte" ) )
{
classSource.println( " return ((Byte) retVal).byteValue();"
);
}
else if( cn.equals( "[B" ) )
{
classSource.println( " return (byte[]) retVal;" );
}
else if( cn.equals( "[C" ) )
{
classSource.println( " return (char[]) retVal;" );
}
else if( cn.equals( "[D" ) )
{
classSource.println( " return (double[]) retVal;" );
}
else if( cn.equals( "[F" ) )
{
classSource.println( " return (float[]) retVal;" );
}
else if( cn.equals( "[I" ) )
{
classSource.println( " return (int[]) retVal;" );
}
else if( cn.equals( "[J" ) )
{
classSource.println( " return (long[]) retVal;" );
}
else if( cn.equals( "[S" ) )
{
classSource.println( " return (short[]) retVal;" );
}
else if( cn.equals( "[Z" ) )
{
classSource.println( " return (boolean[]) retVal;" );
}
else if( rClass.getName().startsWith( "[L" ) )
{
classSource.println( " return (" + cn.substring( 2,
cn.length() - 1 )
+ "[]) retVal;" );
}
else
{
classSource.println( " return (" + cn + ") retVal;" );
}
}
private String generateReturnValue( Class rClass )
{
String cn = rClass.getName();
if( cn.equals( "[B" ) )
{
return "byte[]";
}
else if( cn.equals( "[C" ) )
{
return "char[]";
}
else if( cn.equals( "[D" ) )
{
return "double[]";
}
else if( cn.equals( "[F" ) )
{
return "float[]";
}
else if( cn.equals( "[I" ) )
{
return "int[]";
}
else if( cn.equals( "[J" ) )
{
return "long[]";
}
else if( cn.equals( "[S" ) )
{
return "short[]";
}
else if( cn.equals( "[Z" ) )
{
return "boolean[]";
}
else if( cn.startsWith( "[L" ) )
{
return cn.substring( 2, cn.length() - 1 ) + "[]";
}
else
{
return cn;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]