Package org.apache.tuscany.sca.interfacedef.java.jaxrs

Source Code of org.apache.tuscany.sca.interfacedef.java.jaxrs.RootResourceClassGenerator

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.tuscany.sca.interfacedef.java.jaxrs;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

public class RootResourceClassGenerator implements Opcodes {

    private static final String DELEGATE_FIELD = "delegate";

    public static Class<?> generateRootResourceClass(Class<?> interfaze, String path, String consumes, String produces)
        throws Exception {
        if (!interfaze.isInterface()) {
            throw new IllegalArgumentException(interfaze + " is not an interface.");
        }
        GeneratedClassLoader classLoader = new GeneratedClassLoader(interfaze.getClassLoader());
        String interfaceName = interfaze.getName();
        int index = interfaze.getName().lastIndexOf('.');
        String className =
            interfaceName.substring(0, index) + ".Generated" + interfaceName.substring(index + 1) + "Impl";

        final byte[] content = generate(interfaze, path, consumes, produces);
        Class<?> cls = classLoader.getGeneratedClass(className, content);
        return cls;
    }

    public static void injectProxy(Class<?> generatedResourceClass, Object proxy) throws Exception {
        Field field = generatedResourceClass.getField("delegate");
        field.set(null, proxy);
    }

    public static byte[] generate(Class<?> interfaze, String path, String consumes, String produces) throws Exception {
        String interfaceName = Type.getInternalName(interfaze);
        int index = interfaceName.lastIndexOf('/');
        String className =
            interfaceName.substring(0, index) + "/Generated" + interfaceName.substring(index + 1) + "Impl";

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

        declareClass(cw, interfaceName, className);

        annotatePath(cw, path);
        annotateContentTypes(cw, consumes, produces);
        declareField(cw, interfaceName);
        declareConstructor(cw, className);

        for (Method method : interfaze.getMethods()) {
            if (!(method.getDeclaringClass() == Object.class)) {
                generateMethod(cw, interfaceName, className, method, consumes, produces);
            }
        }
        cw.visitEnd();

        return cw.toByteArray();
    }

    // public <ReturnType> method(<Type0> arg0, ..., <TypeN> argN) throws <ExpectionType0>, ..., <ExceptionTypeK>
    private static void generateMethod(ClassWriter cw,
                                       String interfaceName,
                                       String className,
                                       Method method,
                                       String consumes,
                                       String produces) {
        String methodDescriptor = Type.getMethodDescriptor(method);

        MethodVisitor mv =
            cw.visitMethod(ACC_PUBLIC, method.getName(), methodDescriptor, null, getExceptionInternalNames(method));

        mv.visitCode();
        mv.visitFieldInsn(GETSTATIC, className, DELEGATE_FIELD, getSignature(interfaceName));
        Class<?>[] paramTypes = method.getParameterTypes();
        for (int i = 0; i < paramTypes.length; i++) {
            String signature = Type.getDescriptor(paramTypes[i]);
            mv.visitVarInsn(CodeGenerationHelper.getLoadOPCode(signature), i + 1);
        }
        mv.visitMethodInsn(INVOKEINTERFACE, interfaceName, method.getName(), methodDescriptor);

        Class<?> returnType = method.getReturnType();
        mv.visitInsn(CodeGenerationHelper.getReturnOPCode(Type.getDescriptor(returnType)));
        int size = paramTypes.length + 1;
        mv.visitMaxs(size, size);
        mv.visitEnd();
    }

    private static String[] getExceptionInternalNames(Method method) {
        Class<?>[] types = method.getExceptionTypes();
        if (types.length == 0) {
            return null;
        }
        String[] names = new String[types.length];
        for (int i = 0; i < types.length; i++) {
            names[i] = Type.getInternalName(types[i]);
        }
        return names;
    }

    private static String getSignature(String interfaceName) {
        return "L" + interfaceName + ";";
    }

    private static void declareConstructor(ClassWriter cw, String className) {
        MethodVisitor mv;
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        // mv.visitLineNumber(37, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", getSignature(className), null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    // public static <Interface> delegate;
    private static void declareField(ClassWriter cw, String interfaceName) {
        FieldVisitor fv =
            cw.visitField(ACC_PUBLIC + ACC_STATIC, DELEGATE_FIELD, getSignature(interfaceName), null, null);
        fv.visitEnd();
    }

    // public class _<Interface>Impl implements <Interface>
    private static void declareClass(ClassWriter cw, String interfaceName, String className) {
        cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[] {interfaceName});
    }

    // @Path(<path>)
    private static void annotatePath(ClassWriter cw, String path) {
        AnnotationVisitor av = cw.visitAnnotation("Ljavax/ws/rs/Path;", true);
        av.visit("value", path);
        av.visitEnd();
    }

    // @Consumes(<contentTypes>)
    // @Provides(<contentTypes>)
    private static void annotateContentTypes(ClassWriter cw, String consumes, String produces) {
        AnnotationVisitor av = null;
        if (consumes != null) {
            av = cw.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
            AnnotationVisitor av1 = av.visitArray("value");
            for (String s : consumes.split("(,| )")) {
                av1.visit(null, s.trim());
            }
            av1.visitEnd();
            av.visitEnd();
        }
        if (produces != null) {
            av = cw.visitAnnotation("Ljavax/ws/rs/Produces;", true);
            AnnotationVisitor av1 = av.visitArray("value");
            for (String s : produces.split("(,| )")) {
                av1.visit(null, s.trim());
            }
            av1.visitEnd();
            av.visitEnd();
        }
    }

    // @Consumes(<contentTypes>)
    // @Provides(<contentTypes>)
    private static void annotateContentTypes(MethodVisitor mv, String consumes, String produces) {
        AnnotationVisitor av = null;
        if (consumes != null) {
            av = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true);
            AnnotationVisitor av1 = av.visitArray("value");
            for (String s : consumes.split("(,| )")) {
                av1.visit(null, s.trim());
            }
            av1.visitEnd();
            av.visitEnd();
        }
        if (produces != null) {
            av = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true);
            AnnotationVisitor av1 = av.visitArray("value");
            for (String s : produces.split("(,| )")) {
                av1.visit(null, s.trim());
            }
            av1.visitEnd();
            av.visitEnd();
        }
    }
}
TOP

Related Classes of org.apache.tuscany.sca.interfacedef.java.jaxrs.RootResourceClassGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.