You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by em...@apache.org on 2007/12/07 07:19:51 UTC

svn commit: r602001 - in /incubator/cxf/trunk/rt/frontend: jaxws/src/main/java/org/apache/cxf/jaxws/ jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/ jaxws/src/test/java/org/apache/cxf/jaxws/ simple/src/main/java/org/apache/cxf/service/factory/

Author: ema
Date: Thu Dec  6 22:19:49 2007
New Revision: 602001

URL: http://svn.apache.org/viewvc?rev=602001&view=rev
Log:
Polish WrapperClassGenerator and test it against JAXB

Modified:
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/WrapperHelper.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/WrapperClassGeneratorTest.java
    incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java?rev=602001&r1=602000&r2=602001&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/WrapperClassGenerator.java Thu Dec  6 22:19:49 2007
@@ -21,6 +21,8 @@
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlAttachmentRef;
@@ -30,6 +32,7 @@
 import javax.xml.namespace.QName;
 
 import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.helpers.JavaUtils;
 import org.apache.cxf.jaxws.util.ASMHelper;
 import org.apache.cxf.service.factory.ReflectionServiceFactoryBean;
 import org.apache.cxf.service.model.InterfaceInfo;
@@ -47,11 +50,12 @@
 public final class WrapperClassGenerator extends ASMHelper {
     private List<Class> wrapperBeanList = new java.util.concurrent.CopyOnWriteArrayList<Class>();
     private InterfaceInfo interfaceInfo;
-    
+
     public WrapperClassGenerator(InterfaceInfo inf) {
         interfaceInfo = inf;
-        
+
     }
+
     private String getPackageName(Method method) {
         Package pkg = method.getDeclaringClass().getPackage();
         if (pkg == null) {
@@ -62,8 +66,8 @@
     }
 
     private Annotation[] getMethodParameterAnnotations(final MessagePartInfo mpi) {
-        Annotation[][] paramAnno = 
-            (Annotation[][])mpi.getProperty(ReflectionServiceFactoryBean.METHOD_PARAM_ANNOTATIONS);
+        Annotation[][] paramAnno = (Annotation[][])mpi
+            .getProperty(ReflectionServiceFactoryBean.METHOD_PARAM_ANNOTATIONS);
         int index = mpi.getIndex();
         if (paramAnno != null && index < paramAnno.length && index >= 0) {
             return paramAnno[index];
@@ -84,18 +88,20 @@
         }
         return list;
     }
-    
+
     public List<Class> genearte() {
         for (OperationInfo opInfo : interfaceInfo.getOperations()) {
             if (opInfo.isUnwrappedCapable()) {
                 Method method = (Method)opInfo.getProperty(ReflectionServiceFactoryBean.METHOD);
                 MessageInfo messageInfo = opInfo.getUnwrappedOperation().getInput();
                 createWrapperClass(messageInfo, method, true);
+
                 messageInfo = opInfo.getUnwrappedOperation().getOutput();
                 if (messageInfo != null) {
                     createWrapperClass(messageInfo, method, false);
                 }
-                
+
+
             }
         }
         return wrapperBeanList;
@@ -104,18 +110,15 @@
     private void createWrapperClass(MessageInfo messageInfo, Method method, boolean isRequest) {
 
         QName wrapperElement = messageInfo.getName();
-        
+
         ClassWriter cw = createClassWriter();
         String className = getPackageName(method) + ".jaxws." + StringUtils.capitalize(method.getName());
         if (!isRequest) {
             className = className + "Response";
         }
         String classFileName = periodToSlashes(className);
-        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
-                 classFileName, null, "java/lang/Object",
-                 null);
-
-        // cw.visitSource("AddNumbers.java", null);
+        cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classFileName, null,
+                 "java/lang/Object", null);
 
         AnnotationVisitor av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlRootElement;", true);
         av0.visit("name", wrapperElement.getLocalPart());
@@ -131,27 +134,69 @@
         av0.visit("namespace", wrapperElement.getNamespaceURI());
         av0.visitEnd();
 
-        
-        
+        // add constructor
+        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
+        mv.visitCode();
+        Label lbegin = new Label();
+        mv.visitLabel(lbegin);
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+        mv.visitInsn(Opcodes.RETURN);
+        Label lend = new Label();
+        mv.visitLabel(lend);
+        mv.visitLocalVariable("this", "L" + classFileName + ";", null, lbegin, lend, 0);
+        mv.visitMaxs(1, 1);
+        mv.visitEnd();
+
         for (MessagePartInfo mpi : messageInfo.getMessageParts()) {
             generateMessagePart(cw, mpi, method, classFileName);
         }
 
         cw.visitEnd();
+        java.io.FileOutputStream fout;
+        try {
+            fout = new java.io.FileOutputStream(new java.io.File("d:/AddNumbers.class"));
+            fout.write(cw.toByteArray());
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
         Class<?> clz = loadClass(className, method.getDeclaringClass(), cw.toByteArray());
         messageInfo.getMessagePart(0).setTypeClass(clz);
         wrapperBeanList.add(clz);
 
     }
-    
+
     private void generateMessagePart(ClassWriter cw, MessagePartInfo mpi, Method method, String className) {
         String classFileName = periodToSlashes(className);
-        final Class[] paramClasses = method.getParameterTypes();
-        int idx = mpi.getIndex();
         String name = mpi.getName().getLocalPart();
-        Class clz = paramClasses[idx];
+        Class clz = mpi.getTypeClass();
+        Object obj = mpi.getProperty(ReflectionServiceFactoryBean.RAW_CLASS);
+        if (obj != null) {
+            clz = (Class)obj;
+        }
+        Class genericTypeClass = null;
+        Type genericType = (Type)mpi.getProperty(ReflectionServiceFactoryBean.GENERIC_TYPE);
+        if (genericType instanceof ParameterizedType) {
+            ParameterizedType ptype = (ParameterizedType)genericType;
+
+            Type[] types = ptype.getActualTypeArguments();
+            // TODO: more complex Parameterized type
+            if (types.length > 0 && types[0] instanceof Class) {
+                genericTypeClass = (Class)types[0];
+            }
+        }
         String classCode = getClassCode(clz);
-        FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, name, classCode, null, null);
+
+        String filedDescriptor = null;
+        if (genericTypeClass != null) {
+            filedDescriptor = classCode.substring(0, classCode.lastIndexOf(";")) + "<"
+                              + getClassCode(genericTypeClass) + ">;";
+        }
+        String fieldName = JavaUtils.makeNonJavaKeyword(name);
+
+        FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldName, classCode, filedDescriptor, null);
         AnnotationVisitor av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlElement;", true);
         av0.visit("name", name);
         av0.visit("namespace", "");
@@ -169,25 +214,26 @@
                 av0.visit("type", ((XmlJavaTypeAdapter)ann).type());
                 av0.visitEnd();
             } else if (ann instanceof XmlAttachmentRef) {
-                av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/adapters/XmlAttachmentRef;", true);
+                av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlAttachmentRef;", true);
                 av0.visitEnd();
             } else if (ann instanceof XmlList) {
-                av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/adapters/XmlList;", true);
+                av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlList;", true);
                 av0.visitEnd();
             }
+
         }
 
         fv.visitEnd();
 
         String methodName = StringUtils.capitalize(name);
-        
-        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, 
-                                          "get" + methodName, "()" + classCode , null, null);
+
+        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "get" + methodName, "()" + classCode, null,
+                                          null);
         mv.visitCode();
         Label l2 = new Label();
         mv.visitLabel(l2);
         mv.visitVarInsn(Opcodes.ALOAD, 0);
-        mv.visitFieldInsn(Opcodes.GETFIELD, classFileName, name, classCode);
+        mv.visitFieldInsn(Opcodes.GETFIELD, classFileName, fieldName, classCode);
         mv.visitInsn(Opcodes.ARETURN);
         Label l3 = new Label();
         mv.visitLabel(l3);
@@ -201,19 +247,18 @@
         mv.visitLabel(l4);
         mv.visitVarInsn(Opcodes.ALOAD, 0);
         mv.visitVarInsn(Opcodes.ALOAD, 1);
-        mv.visitFieldInsn(Opcodes.PUTFIELD, className, name, classCode);
+        mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName, classCode);
         Label l5 = new Label();
         mv.visitLabel(l5);
         mv.visitInsn(Opcodes.RETURN);
         Label l6 = new Label();
         mv.visitLabel(l6);
-    
+
         mv.visitLocalVariable("this", "L" + classFileName + ";", null, l4, l6, 0);
-        mv.visitLocalVariable(name, classCode, null, l4, l6, 1);
+        mv.visitLocalVariable(fieldName, classCode, null, l4, l6, 1);
         mv.visitMaxs(2, 2);
 
         mv.visitEnd();
-    
+
     }
-    
 }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/WrapperHelper.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/WrapperHelper.java?rev=602001&r1=602000&r2=602001&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/WrapperHelper.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/WrapperHelper.java Thu Dec  6 22:19:49 2007
@@ -53,9 +53,14 @@
         List<Field> fields = new ArrayList<Field>(partNames.size());
         
         Method allMethods[] = wrapperType.getMethods();
+        String packageName = wrapperType.getName().substring(0, wrapperType.getName().lastIndexOf("."));
         
-        String objectFactoryClassName = wrapperType.getPackage().getName()
-                                        + ".ObjectFactory";
+        //if wrappertype class is generated by ASM,getPackage() always return null
+        if (wrapperType.getPackage() != null) {
+            packageName = wrapperType.getPackage().getName();
+        }
+        
+        String objectFactoryClassName = packageName + ".ObjectFactory";
 
         Object objectFactory = null;
         try {
@@ -325,4 +330,5 @@
         }
     }
     
+ 
 }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/WrapperClassGeneratorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/WrapperClassGeneratorTest.java?rev=602001&r1=602000&r2=602001&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/WrapperClassGeneratorTest.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/WrapperClassGeneratorTest.java Thu Dec  6 22:19:49 2007
@@ -19,9 +19,15 @@
 
 package org.apache.cxf.jaxws;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
 import org.apache.cxf.BusFactory;
+import org.apache.cxf.jaxws.interceptors.WrapperHelper;
 import org.apache.cxf.jaxws.service.AddNumbersImpl;
 import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
 import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
@@ -39,7 +45,7 @@
     }
     
     @org.junit.Test
-    public void testForAttachementRef() {
+    public void testForXmlList() throws Exception {
         JaxWsImplementorInfo implInfo = 
             new JaxWsImplementorInfo(AddNumbersImpl.class);
         JaxWsServiceFactoryBean jaxwsFac = new JaxWsServiceFactoryBean(implInfo);
@@ -48,7 +54,75 @@
         ServiceInfo serviceInfo =  service.getServiceInfos().get(0);
         InterfaceInfo interfaceInfo = serviceInfo.getInterface();
         WrapperClassGenerator wrapperClassGenerator = new WrapperClassGenerator(interfaceInfo);
-        List<Class> list = wrapperClassGenerator.genearte();
-        assertEquals(2, list.size());       
+        List<Class> wrapperClassList = wrapperClassGenerator.genearte();
+        assertEquals(2, wrapperClassList.size());
+
+        Class requestClass = wrapperClassList.get(0);
+        Class responseClass = wrapperClassList.get(1);
+        if (!requestClass.getSimpleName().equals("AddNumbers")) {
+            Class tmp = requestClass;
+            requestClass = responseClass;
+            responseClass = tmp;
+        }
+                        
+        // Create request wrapper Object
+        List<String> partNames = Arrays.asList(new String[] {"arg0"});
+        List<String> elTypeNames = Arrays.asList(new String[] {"list"});
+        List<Class<?>> partClasses = Arrays.asList(new Class<?>[] {List.class});
+           
+        String className = requestClass.getName();
+        className = className.substring(0, className.lastIndexOf(".") + 1);
+        
+        WrapperHelper wh = WrapperHelper.createWrapperHelper(requestClass,
+                                                             partNames, elTypeNames, partClasses);        
+        
+        List<Object> paraList = new ArrayList<Object>();
+        List<String> valueList = new ArrayList<String>();
+        valueList.add("str1");
+        valueList.add("str2");
+        valueList.add("str3");
+        paraList.add(valueList);
+        Object requestObj = wh.createWrapperObject(paraList);
+        // Create response wrapper Object
+        
+        partNames = Arrays.asList(new String[] {"return"});
+        elTypeNames = Arrays.asList(new String[] {"list"});
+        partClasses = Arrays.asList(new Class<?>[] {List.class});
+           
+        className = responseClass.getName();
+        className = className.substring(0, className.lastIndexOf(".") + 1);
+        
+        wh = WrapperHelper.createWrapperHelper(responseClass,
+                                                             partNames, elTypeNames, partClasses);        
+        List<Object> resPara = new ArrayList<Object>();
+        List<Integer> intValueList = new ArrayList<Integer>();
+        intValueList.add(1);
+        intValueList.add(2);
+        intValueList.add(3);
+        resPara.add(intValueList);
+        Object responseObj = wh.createWrapperObject(resPara);
+              
+        JAXBContext jaxbContext = JAXBContext.newInstance(wrapperClassList.toArray(new Class[]{}));
+        java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        
+        //check marshall wrapper
+        marshaller.marshal(requestObj, bout);      
+        String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" 
+            + "<ns2:addNumbers xmlns:ns2=\"http://service.jaxws.cxf.apache.org/\">" 
+            + "<arg0>str1 str2 str3</arg0></ns2:addNumbers>";
+
+        assertEquals("The generated request wrapper class does not contain the correct annotations", 
+                     expected, bout.toString());
+       
+        
+        bout.reset();
+        marshaller.marshal(responseObj, bout);       
+        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" 
+            + "<ns2:addNumbersResponse xmlns:ns2=\"http://service.jaxws.cxf.apache.org/\">" 
+            + "<return>1</return><return>2</return><return>3</return></ns2:addNumbersResponse>";
+        assertEquals("The generated response wrapper class is not correct", expected,  bout.toString());
+     
     }
+  
 }

Modified: incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java?rev=602001&r1=602000&r2=602001&view=diff
==============================================================================
--- incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java (original)
+++ incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ReflectionServiceFactoryBean.java Thu Dec  6 22:19:49 2007
@@ -117,6 +117,7 @@
 
     public static final String ENDPOINT_CLASS = "endpoint.class";
     public static final String GENERIC_TYPE = "generic.type";
+    public static final String RAW_CLASS = "rawclass";
     public static final String MODE_OUT = "messagepart.mode.out";
     public static final String MODE_INOUT = "messagepart.mode.inout";
     public static final String HOLDER = "messagepart.isholder";
@@ -1264,6 +1265,11 @@
             rawClass = getHolderClass(paramType);
         }
         part.setProperty(GENERIC_TYPE, type);
+        //if rawClass is List<String>, it will be converted to array 
+        //and set it to type class
+        if (Collection.class.isAssignableFrom(rawClass)) {
+            part.setProperty(RAW_CLASS, rawClass);
+        }
         part.setTypeClass(rawClass);
     }
 
@@ -1647,6 +1653,7 @@
         }
         return null;
     }
+    
     protected String getResponseWrapperClassName(Method selected) {
         for (AbstractServiceConfiguration c : serviceConfigurations) {
             String cls = c.getResponseWrapperClassName(selected);