static Class make()

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;

    }