in yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/stub/BCELClassBuilder.java [62:219]
static Class make(ClassLoader loader, Class superClass, Class[] interfaces,
MethodRef[] methods, MethodRef[] superMethodRefs, Object[] data,
MethodRef handlerMethodRef, String className,
StubInitializer initializer)
throws IllegalAccessException, InstantiationException,
IllegalArgumentException {
String superClassName = superClass.getName();
String[] interfaceNames = new String[interfaces.length + 1];
for (int i = 0; i < interfaces.length; i++)
interfaceNames[i] = interfaces[i].getName();
interfaceNames[interfaces.length] = Stub.class.getName();
ClassGen newStubClass = new ClassGen(className, superClassName,
"generated", // file name
Constants.ACC_PUBLIC | Constants.ACC_FINAL, interfaceNames);
ConstantPoolGen cp = newStubClass.getConstantPool();
if (handlerMethodRef == null)
throw new IllegalArgumentException("handler method is null");
//
// Check that the handler method is valid
//
Class[] paramTypes = handlerMethodRef.getParameterTypes();
if (paramTypes.length != 3) {
throw new IllegalArgumentException(
"handler method must have three arguments");
}
if (!paramTypes[0].isAssignableFrom(superClass)) {
throw new IllegalArgumentException(
"Handler's 1st argument must be super-type for "
+ superClass);
}
// the type of data fields
Type typeOfDataFields = translate(paramTypes[1]);
if (Object[].class != paramTypes[2]) {
throw new IllegalArgumentException(
"Handler's 3rd argument must be Object[]");
}
//
// Construct field for the handler reference
//
Class handlerClass = handlerMethodRef.getDeclaringClass();
FieldGen handlerFieldGen = new FieldGen(Constants.ACC_PRIVATE
| Constants.ACC_FINAL, translate(handlerClass), Util
.handlerFieldName(), cp);
newStubClass.addField(handlerFieldGen.getField());
//
// Construct the method that gets the stub handler.
//
generateHandlerGetter(newStubClass, handlerFieldGen);
//
// construct the field that holds the initializer
//
FieldGen initializerFieldGen = new FieldGen(Constants.ACC_PRIVATE
| Constants.ACC_STATIC, translate(StubInitializer.class), Util
.initializerFieldName(), cp);
newStubClass.addField(initializerFieldGen.getField());
//
// Emit constructor
//
emitInitializerConstructor(newStubClass, handlerFieldGen,
initializerFieldGen);
//
// Construct data fields
//
FieldGen[] dataFieldGens = new FieldGen[methods.length];
for (int i = 0; i < methods.length; i++) {
MethodRef method = methods[i];
dataFieldGens[i] = new FieldGen(Constants.ACC_PRIVATE
| Constants.ACC_STATIC, typeOfDataFields, Util
.methodFieldName(i), cp);
newStubClass.addField(dataFieldGens[i].getField());
}
//
// Construct method stubs
//
for (int i = 0; i < methods.length; i++) {
generate(newStubClass, methods[i], dataFieldGens[i],
handlerFieldGen, handlerMethodRef);
}
//
// Construct super-method trampolines
//
for (int i = 0; i < superMethodRefs.length; i++) {
generateSuperMethod(newStubClass, superMethodRefs[i]);
}
JavaClass javaClass = newStubClass.getJavaClass();
byte[] classData = javaClass.getBytes();
try {
if (Boolean.getBoolean("org.apache.yoko.rmi.util.stub.debug")) {
java.io.File out = new java.io.File(className + ".class");
// System.out.println ("dumping to file "+out);
javaClass.dump(out);
}
} catch (java.io.IOException ex) {
logger.log(Level.WARNING, "", ex);
}
Class proxyClass = Util.defineClass(loader, className, classData, 0,
classData.length);
// initialize the static data fields
for (int i = 0; i < methods.length; i++) {
try {
java.lang.reflect.Field f = proxyClass
.getDeclaredField(dataFieldGens[i].getName());
f.setAccessible(true);
f.set(null, data[i]);
f.setAccessible(false);
} catch (NoSuchFieldException ex) {
logger
.log(
Level.WARNING,
"cannot find field "
+ dataFieldGens[i].getName()
+ " for stub class "
+ className
+ " extends: "
+ superClassName
+ "implements: "
+ interfaceNames[0]
+ (interfaceNames.length > 2 ? " (among others) "
: ""), ex);
throw new Error("internal error!", ex);
}
}
// set the initializer
try {
java.lang.reflect.Field f = proxyClass.getDeclaredField(Util
.initializerFieldName());
f.setAccessible(true);
f.set(null, initializer);
} catch (NoSuchFieldException ex) {
throw new Error("internal error!", ex);
}
return proxyClass;
}