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;}
+ }
+
+}