Author: scheu Date: Mon May 10 16:28:22 2010 New Revision: 942814 URL: http://svn.apache.org/viewvc?rev=942814&view=rev Log: AXIS2-4708 Contributor:Rich Scheuerle Summary: JAX-WS change to prefer referenced JAXB classes during JAXBContext construction. A validation test is contributed with the code.
Added: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean1.java axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean2.java axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean1.java axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean2.java Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/JAXBContextTest.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBContextFromClasses.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/runtime/description/marshal/impl/PackageSetBuilder.java Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/JAXBContextTest.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/JAXBContextTest.java?rev=942814&r1=942813&r2=942814&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/JAXBContextTest.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/JAXBContextTest.java Mon May 10 16:28:22 2010 @@ -186,4 +186,30 @@ public class JAXBContextTest extends Abs assertTrue(jaxbContext4 != jaxbContext3); assertTrue(context4.contains("org.test.addnumbers")); } + + public void test03() throws JAXBException { + // Simulate a web services that references a.Bean2 and b.Bean1 + // Note that both these beans are in the same namespace + // but not the same package. + // Also note that there are other colliding classes in the + // packages. + TreeSet<String> context = new TreeSet<String>(); + context.add("org.apache.axis2.jaxws.misc.a"); + context.add("org.apache.axis2.jaxws.misc.b"); + context.add("[org.apache.axis2.jaxws.misc.a.Bean2]"); + context.add("[org.apache.axis2.jaxws.misc.b.Bean1]"); + + + JAXBContext jaxbContext = JAXBUtils.getJAXBContext(context); + + // Ensure that the jaxbContext IS produced and contains + // both a.Bean2 and b.Bean1. + String jaxbContextString = jaxbContext.toString(); + + assertTrue("The JAXBContext should contain a.Bean2: " + jaxbContextString, + jaxbContextString.indexOf("org.apache.axis2.jaxws.misc.a.Bean2") > 0); + assertTrue("The JAXBContext should contain b.Bean1: " + jaxbContextString, + jaxbContextString.indexOf("org.apache.axis2.jaxws.misc.b.Bean1") > 0); + + } } \ No newline at end of file Added: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean1.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean1.java?rev=942814&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean1.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean1.java Mon May 10 16:28:22 2010 @@ -0,0 +1,25 @@ +/* + * 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.misc.a; + +import javax.xml.bind.annotation.XmlType; + +...@xmltype(name="bean1", namespace="urn://sample") +public class Bean1 { +} Added: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean2.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean2.java?rev=942814&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean2.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/a/Bean2.java Mon May 10 16:28:22 2010 @@ -0,0 +1,25 @@ +/* + * 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.misc.a; + +import javax.xml.bind.annotation.XmlType; + +...@xmltype(name="bean2", namespace="urn://sample") +public class Bean2 { +} Added: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean1.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean1.java?rev=942814&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean1.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean1.java Mon May 10 16:28:22 2010 @@ -0,0 +1,25 @@ +/* + * 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.misc.b; + +import javax.xml.bind.annotation.XmlType; + +...@xmltype(name="bean1", namespace="urn://sample") +public class Bean1 { +} Added: axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean2.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean2.java?rev=942814&view=auto ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean2.java (added) +++ axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/misc/b/Bean2.java Mon May 10 16:28:22 2010 @@ -0,0 +1,25 @@ +/* + * 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.misc.b; + +import javax.xml.bind.annotation.XmlType; + +...@xmltype(name="bean2", namespace="urn://sample") +public class Bean2 { +} Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBContextFromClasses.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBContextFromClasses.java?rev=942814&r1=942813&r2=942814&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBContextFromClasses.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBContextFromClasses.java Mon May 10 16:28:22 2010 @@ -66,12 +66,21 @@ public class JAXBContextFromClasses { * * @param classArray * @param cl + * @param properties + * @param classRefs optional List<String> of class references * @return JAXBContext * @throws JAXBException */ public static JAXBContext newInstance(Class[] classArray, + ClassLoader cl, + Map<String, ?> properties) throws JAXBException { + return newInstance(classArray, cl, properties, new ArrayList<String>()); + } + + public static JAXBContext newInstance(Class[] classArray, ClassLoader cl, - Map<String, ?> properties) + Map<String, ?> properties, + List<String> classRefs) throws JAXBException { JAXBContext jaxbContext = null; try { @@ -95,7 +104,7 @@ public class JAXBContextFromClasses { original.add(classArray[i]); } ArrayList<Class> best = new ArrayList<Class>(); - jaxbContext = findBestSet(original, cl, best, properties); + jaxbContext = findBestSet(original, cl, best, properties, classRefs); } @@ -144,40 +153,43 @@ public class JAXBContextFromClasses { /** * Utility class that quickly divides a list of classes into two categories. - * The primary category classes contain JAXB annotations. - * The secondary category classes do not contain JAXB annotations + * The primary category classes contains classes that are referenced. + * The secondary category classes are the remaining classes * @param original * @param primary * @param secondary */ - static void separate(List<Class> original, List<Class> primary, List<Class> secondary) { + static void separate(List<Class> original, + List<Class> primary, + List<Class> secondary, + List<String> classRefs) { for (int i=0; i<original.size(); i++) { Class cls = original.get(i); + String clsName = cls.getCanonicalName(); if (commonArrayClasses.contains(cls)) { if (log.isDebugEnabled()) { log.debug("This looks like a JAXB common class. Adding it to primary list:" + cls.getName()); } primary.add(cls); - } else if (getAnnotation(cls, XmlType.class) != null || - getAnnotation(cls, XmlRootElement.class) != null) { + } else if (classRefs.contains(clsName)) { if (log.isDebugEnabled()) { - log.debug("This looks like a JAXB class. Adding it to primary list:" + - cls.getName()); + log.debug("This is a referenced class. Adding it to primary list:" + + clsName); } Package pkg = cls.getPackage(); if (pkg != null && pkg.getName().endsWith(".jaxws")) { if (log.isDebugEnabled()) { log.debug("This looks like a jaxws generated Class. Adding it to the front of the primary list:" + - cls.getName()); + cls.getName()); } primary.add(0,cls); // Add to the front of the list } else { - primary.add(cls); // This looks like a JAXB class...add it + primary.add(cls); } } else { if (log.isDebugEnabled()) { - log.debug("This may not be a JAXB class. Adding it to secondary list:" + + log.debug("This class is not referenced by the web service. Adding it to secondary list:" + cls.getName()); } Package pkg = cls.getPackage(); @@ -188,7 +200,7 @@ public class JAXBContextFromClasses { } secondary.add(0,cls); // Add to the front of the list } else { - secondary.add(cls); // This looks like it might be something else...not JAXB + secondary.add(cls); } } } @@ -199,13 +211,15 @@ public class JAXBContextFromClasses { * of classes and returns the JAXBContext for this minimal set. * @param original List<Class> * @param cl ClassLoader - * @param ListMClass> is populated with the minimal, best set of classes + * @param List<Class> is populated with the minimal, best set of classes + * @param List<String> input list of classes that are directly referenced in the web service api * @return JAXBContext */ static JAXBContext findBestSet(List<Class> original, ClassLoader cl, List<Class> best, - Map<String, ?> properties) { + Map<String, ?> properties, + List<String> classRefs) { if (log.isDebugEnabled()) { log.debug("Could not construct JAXBContext with the initial list."); @@ -214,11 +228,11 @@ public class JAXBContextFromClasses { JAXBContext jc = null; Class[] clsArray = new Class[0]; - // Divide the list into the classes that have JAXB annotations (primary) - // and those that do not (secondary) + // Divide the list into the classes that are referenced (primary) + // and the rest (secondary) ArrayList<Class> primary = new ArrayList<Class> (); ArrayList<Class> secondary = new ArrayList<Class> (); - separate(original, primary, secondary); + separate(original, primary, secondary, classRefs); // Prime the pump // Build a JAXBContext with the primary classes Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java?rev=942814&r1=942813&r2=942814&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java (original) +++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/message/databinding/JAXBUtils.java Mon May 10 16:28:22 2010 @@ -287,20 +287,27 @@ public class JAXBUtils { TreeSet<String> validContextPackages = new TreeSet<String>(contextPackages); - pruneDirectives(validContextPackages); + List<String> classRefs = pruneDirectives(validContextPackages); int numPackages = validContextPackages.size(); ClassLoader tryCl = cl; - contextValue = createJAXBContextValue(validContextPackages, cl, forceArrays, properties); + contextValue = createJAXBContextValue(validContextPackages, + cl, + forceArrays, + properties, + classRefs); // If we don't get all the classes, try the cached classloader if (cacheKey != null && numPackages != validContextPackages.size()) { tryCl = cacheKey; validContextPackages = new TreeSet<String>(contextPackages); - pruneDirectives(validContextPackages); - contextValue = createJAXBContextValue(validContextPackages, cacheKey, - forceArrays, properties); + classRefs = pruneDirectives(validContextPackages); + contextValue = createJAXBContextValue(validContextPackages, + cacheKey, + forceArrays, + properties, + classRefs); } synchronized (jaxbMap) { // Add the context value with the original package set @@ -370,10 +377,12 @@ public class JAXBUtils { * "com.A" * "com.C" * @param contextPackages + * @return List<String> class references */ - protected static void pruneDirectives(TreeSet<String> contextPackages) { + protected static List<String> pruneDirectives(TreeSet<String> contextPackages) { List<String> removePkgsList = new ArrayList<String>(); List<String> strongPkgsList = new ArrayList<String>(); + List<String> classRefs = new ArrayList<String>(); // Walk the contextPackages looking for entries representing directives Iterator<String> it = contextPackages.iterator(); @@ -404,6 +413,17 @@ public class JAXBUtils { strongPkg = strongPkg.trim(); strongPkgsList.add(strongPkg); } + if (entry.startsWith("[")) { + if (log.isDebugEnabled()) { + log.debug("Class Reference found:" + entry); + } + // Remove the entry using an iterator remove() + it.remove(); + + // Store the class + String cls = entry.substring(1, entry.length()-1); + classRefs.add(cls); + } } // Now walk the contextPackages and remove the overriden packages @@ -422,6 +442,7 @@ public class JAXBUtils { // Now add back all of the strong packages contextPackages.addAll(strongPkgsList); + return classRefs; } /** @@ -431,13 +452,15 @@ public class JAXBUtils { * @param cl ClassLoader * @param forceArrays boolean (true if JAXBContext must include all arrays) * @param properties Map of properties for the JAXBContext.newInstance creation method + * @param classRefs List of class references * @return JAXBContextValue (JAXBContext + constructionType) * @throws JAXBException */ private static JAXBContextValue createJAXBContextValue(TreeSet<String> contextPackages, ClassLoader cl, boolean forceArrays, - Map<String, ?> properties) throws JAXBException { + Map<String, ?> properties, + List<String> classRefs) throws JAXBException { JAXBContextValue contextValue = null; if (log.isDebugEnabled()) { @@ -597,7 +620,7 @@ public class JAXBUtils { //Lets add all common array classes addCommonArrayClasses(fullList); Class[] classArray = fullList.toArray(new Class[0]); - JAXBContext context = JAXBContext_newInstance(classArray, cl, properties); + JAXBContext context = JAXBContext_newInstance(classArray, cl, properties, classRefs); if (context != null) { if (forceArrays) { contextValue = new JAXBContextValue(context, CONSTRUCTION_TYPE.BY_CLASS_ARRAY_PLUS_ARRAYS); @@ -1287,12 +1310,15 @@ public class JAXBUtils { * * @param classArray * @param cl ClassLoader that loaded the classes + * @param properties Map<String, ?> + * @param ClassRefs List<String> * @return * @throws Exception */ private static JAXBContext JAXBContext_newInstance(final Class[] classArray, final ClassLoader cl, - Map<String, ?> properties) + Map<String, ?> properties, + List<String> classRefs) throws JAXBException { // NOTE: This method must remain private because it uses AccessController JAXBContext jaxbContext = null; @@ -1307,7 +1333,10 @@ public class JAXBUtils { } // Get JAXBContext from classes - jaxbContext = JAXBContextFromClasses.newInstance(classArray, cl, properties); + jaxbContext = JAXBContextFromClasses.newInstance(classArray, + cl, + properties, + classRefs); return jaxbContext; } 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=942814&r1=942813&r2=942814&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 May 10 16:28:22 2010 @@ -296,21 +296,25 @@ public class PackageSetBuilder { } // Also consider the request and response wrappers - String requestWrapperPkg = getPackageFromClassName(msrd.getRequestWrapperClassName(opDesc)); + String requestWrapperName = msrd.getRequestWrapperClassName(opDesc); + String requestWrapperPkg = getPackageFromClassName(requestWrapperName); if (log.isDebugEnabled()) { log.debug("Package from Request Wrapper annotation = " + requestWrapperPkg); } if (requestWrapperPkg != null) { set.add(requestWrapperPkg); set.add("@" + requestWrapperPkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + requestWrapperName + "]"); // Indicates a actual class reference } - String responseWrapperPkg = getPackageFromClassName(msrd.getResponseWrapperClassName(opDesc)); + String responseWrapperName = msrd.getResponseWrapperClassName(opDesc); + String responseWrapperPkg = getPackageFromClassName(responseWrapperName); if (log.isDebugEnabled()) { log.debug("Package from Response Wrapper annotation = " + responseWrapperPkg); } if (responseWrapperPkg != null) { set.add(responseWrapperPkg); set.add("@" + responseWrapperPkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + responseWrapperName + "]"); // Indicates a actual class reference } // The wrapper class and the element defining the wrapper may be @@ -353,6 +357,7 @@ public class PackageSetBuilder { if (pkg != null) { set.add(pkg); set.add("@" + pkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + cls.getCanonicalName() + "]"); // Indicates a actual class reference } } } @@ -384,6 +389,7 @@ public class PackageSetBuilder { if (pkg != null) { set.add(pkg); set.add("@" + pkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + paramClass.getCanonicalName() + "]"); // Indicates a actual class reference } } } @@ -471,6 +477,7 @@ public class PackageSetBuilder { if (pkg != null) { set.add(pkg); set.add("@" + pkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + tClass.getCanonicalName() + "]"); // Indicates a actual class reference } // If there is an xmlType, and it maps to a package then add // an override if the package is different. @@ -519,6 +526,7 @@ public class PackageSetBuilder { if (pkg != null) { set.add(pkg); set.add("@" + pkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + eClass.getCanonicalName() + "]"); // Indicates a actual class reference } if (pkg != null) { @@ -661,6 +669,7 @@ public class PackageSetBuilder { } set.add(pkg); set.add("@" + pkg); // Indicates a package from an actual class reference (versus namespace) + set.add("[" + seeAlso[i].getCanonicalName() + "]"); // Indicates a actual class reference } } }