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

Source Code of org.apache.tuscany.sca.interfacedef.java.jaxws.BaseBeanGenerator

/*
* 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.jaxws;

import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint;
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;

public abstract class BaseBeanGenerator implements Opcodes {
    private static final Map<String, String> COLLECTION_CLASSES = new HashMap<String, String>();
    static {
        COLLECTION_CLASSES.put("Ljava/util/Collection;", "java/util/ArrayList");
        COLLECTION_CLASSES.put("Ljava/util/List;", "java/util/ArrayList");
        COLLECTION_CLASSES.put("Ljava/util/Set;", "java/util/HashSet");
        COLLECTION_CLASSES.put("Ljava/util/Queue;", "java/util/LinkedList");
    }
    protected static final Map<Object, Class<?>> generatedClasses =
        Collections.synchronizedMap(new WeakHashMap<Object, Class<?>>());

    protected XMLAdapterExtensionPoint xmlAdapters;

    public byte[] defineClass(ClassWriter cw,
                              String classDescriptor,
                              String classSignature,
                              String namespace,
                              String name,
                              BeanProperty[] properties) {
        // Declare the class
        declareClass(cw, classDescriptor);

        // Compute the propOrder
        String[] propOrder = null;
        if (properties != null && properties.length > 0) {
            int size = properties.length;
            propOrder = new String[size];
            for (int i = 0; i < size; i++) {
                propOrder[i] = getFieldName(properties[i].getName());
            }
        }
        // Annotate the class
        annotateClass(cw, name, namespace, propOrder);

        // Decalre the default constructor
        declareConstructor(cw, classSignature);
        if (properties != null) {
            for (BeanProperty p : properties) {
                boolean isMap = Map.class.isAssignableFrom(p.getType());
                String xmlAdapterClassSignature = null;
                if (xmlAdapters != null) {
                    Class<?> adapterClass = xmlAdapters.getAdapter(p.getType());
                    if (adapterClass != null) {
                        xmlAdapterClassSignature = CodeGenerationHelper.getSignature(adapterClass);
                    }
                }
                declareProperty(cw, classDescriptor, classSignature, p.getName(), p.getSignature(), p
                    .getGenericSignature(), isMap, xmlAdapterClassSignature);
            }
        }

        // Close the generation
        cw.visitEnd();
        return cw.toByteArray();
    }

    protected void declareProperty(ClassWriter cw,
                                   String classDescriptor,
                                   String classSignature,
                                   String propName,
                                   String propClassSignature,
                                   String propTypeSignature,
                                   boolean isMap,
                                   String xmlAdapterClassSignature) {
        if (propClassSignature.equals(propTypeSignature)) {
            propTypeSignature = null;
        }
        declareField(cw, propName, propClassSignature, propTypeSignature, isMap, xmlAdapterClassSignature);
        decalreGetter(cw, classDescriptor, classSignature, propName, propClassSignature, propTypeSignature);
        declareSetter(cw, classDescriptor, classSignature, propName, propClassSignature, propTypeSignature);
    }

    protected String getFieldName(String propName) {
        if ("return".equals(propName)) {
            return "_return";
        } else {
            return propName;
        }
    }

    protected void declareField(ClassWriter cw,
                                String propName,
                                String propClassSignature,
                                String propTypeSignature,
                                boolean isMap,
                                String xmlAdapterClassSignature) {
        FieldVisitor fv;
        AnnotationVisitor av0;
        fv = cw.visitField(ACC_PROTECTED, getFieldName(propName), propClassSignature, propTypeSignature, null);

        // For Map property, we cannot have the XmlElement annotation
        if (!isMap) {
            av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlElement;", true);
            av0.visit("name", propName);
            av0.visit("namespace", "");
            av0.visitEnd();
        }

        if (xmlAdapterClassSignature != null) {
            av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/adapters/XmlJavaTypeAdapter;", true);
            av0.visit("value", org.objectweb.asm.Type.getType(xmlAdapterClassSignature));
            av0.visitEnd();
        }

        fv.visitEnd();
    }

    protected void declareSetter(ClassWriter cw,
                                 String classDescriptor,
                                 String classSignature,
                                 String propName,
                                 String propClassSignature,
                                 String propTypeSignature) {
        if ("Ljava/util/List;".equals(propClassSignature)) {
            return;
        }
        MethodVisitor mv =
            cw.visitMethod(ACC_PUBLIC,
                           "set" + capitalize(propName),
                           "(" + propClassSignature + ")V",
                           propTypeSignature == null ? null : "(" + propTypeSignature + ")V",
                           null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        // mv.visitLineNumber(57, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(CodeGenerationHelper.getLoadOPCode(propClassSignature), 1);
        mv.visitFieldInsn(PUTFIELD, classDescriptor, getFieldName(propName), propClassSignature);
        Label l1 = new Label();
        mv.visitLabel(l1);
        // mv.visitLineNumber(58, l1);
        mv.visitInsn(RETURN);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLocalVariable("this", classSignature, null, l0, l2, 0);
        mv.visitLocalVariable(getFieldName(propName), propClassSignature, propTypeSignature, l0, l2, 1);
        mv.visitMaxs(3, 3);
        mv.visitEnd();

    }

    protected void decalreGetter(ClassWriter cw,
                                 String classDescriptor,
                                 String classSignature,
                                 String propName,
                                 String propClassSignature,
                                 String propTypeSignature) {
        String collectionImplClass = COLLECTION_CLASSES.get(propClassSignature);
        if (collectionImplClass != null) {
            decalreCollectionGetter(cw,
                                    classDescriptor,
                                    classSignature,
                                    propName,
                                    propClassSignature,
                                    propTypeSignature,
                                    collectionImplClass);
            return;
        }

        String getterName = ("Z".equals(propClassSignature) ? "is" : "get") + capitalize(propName);
        MethodVisitor mv =
            cw.visitMethod(ACC_PUBLIC, getterName, "()" + propClassSignature, propTypeSignature == null ? null
                : "()" + propTypeSignature, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        // mv.visitLineNumber(48, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classDescriptor, getFieldName(propName), propClassSignature);
        mv.visitInsn(CodeGenerationHelper.getReturnOPCode(propClassSignature));
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", classSignature, null, l0, l1, 0);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    }

    protected void decalreCollectionGetter(ClassWriter cw,
                                           String classDescriptor,
                                           String classSignature,
                                           String propName,
                                           String propClassSignature,
                                           String propTypeSignature,
                                           String collectionImplClass) {
        String getterName = "get" + capitalize(propName);
        String fieldName = getFieldName(propName);
        MethodVisitor mv =
            cw.visitMethod(ACC_PUBLIC, getterName, "()" + propClassSignature, propTypeSignature == null ? null
                : "()" + propTypeSignature, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitLineNumber(63, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classDescriptor, fieldName, propClassSignature);
        Label l1 = new Label();
        mv.visitJumpInsn(IFNONNULL, l1);
        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitLineNumber(64, l2);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitTypeInsn(NEW, collectionImplClass);
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, collectionImplClass, "<init>", "()V");
        mv.visitFieldInsn(PUTFIELD, classDescriptor, fieldName, propClassSignature);
        mv.visitLabel(l1);
        mv.visitLineNumber(66, l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, classDescriptor, fieldName, propClassSignature);
        mv.visitInsn(ARETURN);
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLocalVariable("this", classSignature, null, l0, l3, 0);
        mv.visitMaxs(3, 1);
        mv.visitEnd();
    }

    protected static String capitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        } else {
            return Character.toUpperCase(name.charAt(0)) + name.substring(1);
        }
    }

    protected void declareConstructor(ClassWriter cw, String classSignature) {
        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", classSignature, null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    protected void declareClass(ClassWriter cw, String classDescriptor) {
        cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, classDescriptor, null, "java/lang/Object", null);
    }

    protected void annotateClass(ClassWriter cw, String name, String namespace, String[] propOrder) {
        AnnotationVisitor av0;
        // @XmlRootElement
        av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlRootElement;", true);
        av0.visit("name", name);
        av0.visit("namespace", namespace);
        av0.visitEnd();
        // @XmlAccessorType
        av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlAccessorType;", true);
        av0.visitEnum("value", "Ljavax/xml/bind/annotation/XmlAccessType;", "FIELD");
        av0.visitEnd();
        // @XmlType
        av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlType;", true);
        av0.visit("name", name);
        av0.visit("namespace", namespace);
        if (propOrder != null) {
            AnnotationVisitor pv = av0.visitArray("propOrder");
            for (String p : propOrder) {
                pv.visit(null, p);
            }
            pv.visitEnd();
        }
        av0.visitEnd();
    }

    public Class<?> generate(String classDescriptor,
                             String classSignature,
                             String namespace,
                             String name,
                             BeanProperty[] properties,
                             GeneratedClassLoader classLoader) {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        byte[] byteCode = defineClass(cw, classDescriptor, classSignature, namespace, name, properties);
        String className = classDescriptor.replace('/', '.');
        Class<?> generated = classLoader.getGeneratedClass(className, byteCode);
        return generated;
    }

    public static class BeanProperty {
        private Class<?> type;
        private String name;
        private String signature;
        private String genericSignature;

        public BeanProperty(String name, Class<?> javaClass, Type type) {
            super();
            this.name = name;
            this.signature = CodeGenerationHelper.getJAXWSSignature(javaClass);
            this.type = javaClass;
            this.genericSignature = CodeGenerationHelper.getJAXWSSignature(type);
        }

        public String getName() {
            return name;
        }

        public String getSignature() {
            return signature;
        }

        public String getGenericSignature() {
            return genericSignature;
        }

        public Class<?> getType() {
            return type;
        }
    }

    public XMLAdapterExtensionPoint getXmlAdapters() {
        return xmlAdapters;
    }

    public void setXmlAdapters(XMLAdapterExtensionPoint xmlAdapters) {
        this.xmlAdapters = xmlAdapters;
    }
}
TOP

Related Classes of org.apache.tuscany.sca.interfacedef.java.jaxws.BaseBeanGenerator

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.