Author: scheu
Date: Mon Jul 12 20:08:38 2010
New Revision: 963459

URL: http://svn.apache.org/viewvc?rev=963459&view=rev
Log:
AXIS2-4765
Contributor:Rich Scheuerle
Inspect generics to determine how to build a JAXBContext for JAX-WS 
applications.

Added:
    
axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/utility/ClassUtilsTests.java
Modified:
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/GorillaDLWProxyTests.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/GorillaProxyImpl.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/sei/GorillaInterface.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/ClassUtils.java

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/GorillaDLWProxyTests.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/GorillaDLWProxyTests.java?rev=963459&r1=963458&r2=963459&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/GorillaDLWProxyTests.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/GorillaDLWProxyTests.java
 Mon Jul 12 20:08:38 2010
@@ -159,6 +159,8 @@ public class GorillaDLWProxyTests extend
                 
assertTrue(observedKey.contains("org.apache.axis2.jaxws.proxy.gorilla_dlw.data"));
                 // Check for the package referenced only by an @XmlSeeAlso
                 assertTrue(observedKey.contains("org.test.stock2"));
+                // Check for the package referenced in the return type List<> 
generic
+                assertTrue(observedKey.contains("org.test.stock1"));
             }
             
             
@@ -178,6 +180,8 @@ public class GorillaDLWProxyTests extend
                 
assertTrue(observedKey.contains("org.apache.axis2.jaxws.proxy.gorilla_dlw.data"));
                 // Check for the package referenced only by an @XmlSeeAlso
                 assertTrue(observedKey.contains("org.test.stock2"));
+                // Check for the package referenced in the return type List<> 
generic
+                assertTrue(observedKey.contains("org.test.stock1"));
             }
         }catch(Exception e){ 
             e.printStackTrace(); 

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/GorillaProxyImpl.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/GorillaProxyImpl.java?rev=963459&r1=963458&r2=963459&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/GorillaProxyImpl.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/GorillaProxyImpl.java
 Mon Jul 12 20:08:38 2010
@@ -150,5 +150,11 @@ public class GorillaProxyImpl implements
                        
                }
        }
+       
+       /**
+     * The following non-doc method is not invoked.  It is only present to 
test the 
+     * generic reflection code. 
+     */
+       public List<org.test.stock1.GetPrice> sampleMethod() { return null;}
     
 }

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/sei/GorillaInterface.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/sei/GorillaInterface.java?rev=963459&r1=963458&r2=963459&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/sei/GorillaInterface.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/proxy/gorilla_dlw/sei/GorillaInterface.java
 Mon Jul 12 20:08:38 2010
@@ -331,4 +331,11 @@ public interface GorillaInterface {
     public void echoPolymorphicDate(
         @WebParam(name = "request", targetNamespace = 
"http://org/apache/axis2/jaxws/proxy/gorilla_dlw/data";)
         XMLGregorianCalendar request);
+    
+    /**
+     * The following non-doc method is not invoked.  It is only present to 
test the 
+     * generic reflection code. 
+     */
+    @WebMethod
+    public List<org.test.stock1.GetPrice> sampleMethod();
 }

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java?rev=963459&r1=963458&r2=963459&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java
 Mon Jul 12 20:08:38 2010
@@ -48,20 +48,26 @@ import javax.jws.WebService;
 import javax.wsdl.Definition;
 import javax.wsdl.WSDLException;
 import javax.xml.bind.JAXBElement;
+import javax.xml.ws.Holder;
+import javax.xml.ws.Response;
+
 import java.io.File;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Method;
+import java.lang.reflect.Type;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.Future;
 
 /**
  * In order to marshal or unmarshal the user data, we need to know the set of 
packages involved.
@@ -336,6 +342,14 @@ public class PackageSetBuilder {
             set.addAll(packages);
         }
         
+        // See if the Method is available.  If so, additional reflection
+        // can be performed to obtain the generic references
+        Method m = getMethod(opDesc, msrd);
+        if (log.isDebugEnabled()) {
+            log.debug("Method obtained:" + m);
+        }
+
+        
         // In most doc/literal cases, the @RequestWrapper or @ResponseWrapper 
classes are successfully found.
         // The wrapper classes contain the representation of the parameters, 
thus the parameters don't need
         // to be separately processed.
@@ -344,7 +358,11 @@ public class PackageSetBuilder {
             if (log.isDebugEnabled()) {
                 log.debug("Collect the packages of the parameters");
             }
-            addPackagesFromParameters(set, opDesc) ;          
+            addPackagesFromParameters(set, opDesc);
+            if (m != null) {
+                addPackagesFromParameters(set, m);
+            }
+     
         }
 
         // Finally consider the result type
@@ -359,9 +377,123 @@ public class PackageSetBuilder {
                 set.add("@" + pkg);  // Indicates a package from an actual 
class reference (versus namespace)
                 set.add("[" + cls.getCanonicalName() + "]");  // Indicates a 
actual class reference
             }
+            if (m != null) {
+                addPackagesFromReturn(set, m);
+            }
+
         }
     }
     
+    /**
+     * Get Method associated with this OperationDesc
+     * @param opDesc
+     * @param msrd
+     * @return Method or null
+     */
+    private static Method getMethod(OperationDescription opDesc, 
+            MarshalServiceRuntimeDescription msrd) {
+        Method m = null;
+        try {
+            m = msrd.getMethod(opDesc);
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Method could not be obtained due to " + t);
+            }
+        }
+        return m;
+    }
+
+    /**
+     * add package information by reflecting the parameters on Method m
+     * @param set
+     * @param m
+     */
+    private static void addPackagesFromParameters(TreeSet<String> set, Method 
m) {
+        if (log.isDebugEnabled()) {
+            log.debug("enter addPackagesFromParameters for " + m);
+        }
+        try {
+            if (m != null) {
+                Set<Class> classes = new HashSet<Class>();
+                // Build a set of all of the classes referenced in the 
parameters (including
+                // generic argument references
+                for(Type type : m.getGenericParameterTypes()) {
+                    classes = ClassUtils.getClasses(type, classes);
+                }
+                addClassesToPackageSet(classes, set);
+            }
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Could not reflect the information on method " + m + 
" due to " + t);
+                log.debug("Processing continues");
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("exit addPackagesFromParameters");
+        }
+    }
+
+    /**
+     * add package information by reflecting the return type on Method m
+     * @param set
+     * @param m
+     */
+    private static void addPackagesFromReturn(TreeSet<String> set, Method m) {
+        if (log.isDebugEnabled()) {
+            log.debug("enter addPackagesFromReturn for " + m);
+        }
+        try {
+            if (m != null) {
+                Set<Class> classes = new HashSet<Class>();
+                // Build a set of all of the classes referenced in the 
return(including
+                // generic argument references
+                classes = ClassUtils.getClasses(m.getGenericReturnType(), 
classes);
+                addClassesToPackageSet(classes, set);
+            }
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Could not reflect the information on method " + m + 
" due to " + t);
+                log.debug("Processing continues");
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("exit addPackagesFromReturn");
+        }
+    }
+
+    /**
+     * Add all of the packages/names in classSet to our package set collection
+     * @param classSet
+     * @param set
+     */
+    private static void addClassesToPackageSet(Set<Class> classSet, 
TreeSet<String> set) {
+        if (log.isDebugEnabled()) {
+            log.debug("enter addClassesToPackageSet");
+        }
+        if (classSet != null) {
+            for (Class clz : classSet) {
+                if (clz != null &&
+                        clz != Holder.class &&
+                        clz != Future.class &&
+                        clz != Response.class) {
+                    Package pkg = clz.getPackage();
+                    //For primitive types there is no package
+                    String pkgText = (pkg != null) ? pkg.getName() : null;
+                    if (pkg != null) {
+                        String name = clz.getCanonicalName();
+                        if (log.isDebugEnabled()) {
+                            log.debug(" adding class " + name);
+                        }   
+                        set.add("@" + pkgText);  // Indicates a package from 
an actual class reference
+                        set.add("[" + name + "]");  // Indicates a actual 
class referenced
+                    }
+                }
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("exit addClassesToPackageSet");
+        }
+    }
     
     /**
      * addPackagesFromParameters
@@ -377,10 +509,7 @@ public class PackageSetBuilder {
                     // Get the actual type of the parameter.
                     // For example if the parameter is Holder<A>, the A.class 
is
                     // returned.
-                    // TODO Unfortunately the ParameterDescriptor only provides
-                    // the class, not the full generic.  So if the parameter
-                    // is List<A>, only List is returned.  The 
ParameterDescriptor
-                    // and this logic will need to be improved to handle that 
case.
+                    // NOTE Generics are handled by the 
addPackagesFromParameters(Method..) method
                     Class paramClass = pDesc.getParameterActualType();
                     String pkg = getPackageFromClass(paramClass);
                     if (log.isDebugEnabled()) {

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/ClassUtils.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/ClassUtils.java?rev=963459&r1=963458&r2=963459&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/ClassUtils.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/utility/ClassUtils.java
 Mon Jul 12 20:08:38 2010
@@ -19,9 +19,17 @@
 
 package org.apache.axis2.jaxws.utility;
 
-import org.apache.axis2.java.security.AccessController;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.jws.WebService;
 import javax.xml.ws.Holder;
@@ -29,12 +37,10 @@ import javax.xml.ws.Service;
 import javax.xml.ws.WebFault;
 import javax.xml.ws.WebServiceClient;
 import javax.xml.ws.WebServiceProvider;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.security.PrivilegedAction;
-import java.util.HashMap;
+
+import org.apache.axis2.java.security.AccessController;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /** Contains static Class utility methods related to method parameter/argument 
marshalling. */
 public class ClassUtils {
@@ -305,5 +311,39 @@ public class ClassUtils {
             }
         });
     }
+    
+    /**
+     * 
+     */
+    public static Set<Class> getClasses(Type type, Set<Class> list) {
+       if (list == null) {
+               list = new HashSet<Class>();
+       }
+       try {
+               if (type instanceof Class) {
+                       list.add( (Class)type);
+               }
+               if (type instanceof ParameterizedType) {
+                       ParameterizedType pt = (ParameterizedType) type;
+                       getClasses(pt.getRawType(), list);
+                       Type types[] = pt.getActualTypeArguments();
+                       if (types != null) {
+                               for (int i=0; i<types.length; i++) {
+                                       getClasses(types[i], list);
+                               }
+                       }
+               } 
+               if (type instanceof GenericArrayType) {
+                       GenericArrayType gat = (GenericArrayType) type;
+                       getClasses(gat.getGenericComponentType(), list);
+               }
+       } catch (Throwable t) {
+               if (log.isDebugEnabled()) {
+                       log.debug("Problem occurred in getClasses. Processing 
continues " + t);
+               }
+       }
+       return list;
+    }
+    
 }
 

Added: 
axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/utility/ClassUtilsTests.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/utility/ClassUtilsTests.java?rev=963459&view=auto
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/utility/ClassUtilsTests.java
 (added)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/utility/ClassUtilsTests.java
 Mon Jul 12 20:08:38 2010
@@ -0,0 +1,90 @@
+/*
+ * 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.axis2.jaxws.utility;
+
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * Test the utility methods in the ClassUtils class
+ */
+public class ClassUtilsTests extends TestCase {
+    
+    
+    public void test1() throws Exception {
+        
+       Method m = Sample.class.getMethod("method1", null);
+       Set<Class> set = ClassUtils.getClasses(m.getGenericReturnType(), null);
+       
+       assertTrue(set.contains(int.class));
+       assertTrue(!(set.contains(List.class)));
+       assertTrue(!(set.contains(BigInteger.class)));
+       assertTrue(!(set.contains(Float.class)));
+       assertTrue(!(set.contains(HashMap.class)));
+        
+    }
+    
+    public void test2() throws Exception {
+        
+       Method m = Sample.class.getMethod("method2", null);
+       Set<Class> set = ClassUtils.getClasses(m.getGenericReturnType(), null);
+       
+       assertTrue(!(set.contains(int.class)));
+       assertTrue((set.contains(List.class)));
+       assertTrue((set.contains(BigInteger.class)));
+       assertTrue(!(set.contains(Float.class)));
+       assertTrue(!(set.contains(HashMap.class)));
+    }
+    
+    public void test3() throws Exception {
+        
+       Method m = Sample.class.getMethod("method3", null);
+       Set<Class> set = ClassUtils.getClasses(m.getGenericReturnType(), null);
+       assertTrue(!(set.contains(int.class)));
+       assertTrue((set.contains(List.class)));
+       assertTrue((set.contains(BigInteger.class)));
+       assertTrue(!(set.contains(Float.class)));
+       assertTrue(!(set.contains(HashMap.class)));
+    }
+    
+    public void test4() throws Exception {
+        
+       Method m = Sample.class.getMethod("method4", null);
+       Set<Class> set = ClassUtils.getClasses(m.getGenericReturnType(), null);
+       assertTrue(!(set.contains(int.class)));
+       assertTrue((set.contains(List.class)));
+       assertTrue(!(set.contains(BigInteger.class)));
+       assertTrue((set.contains(Float.class)));
+       assertTrue((set.contains(HashMap.class)));
+    }
+    
+    class Sample {
+       public int method1() { return 0;}
+       public List<BigInteger> method2() { return null;}
+       public List<BigInteger[]>[] method3() { return null;}
+       public List<HashMap<Integer, Float[]>>[] method4() { return null;}
+    }
+
+}


Reply via email to