Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. Oracle designates this |
aoqi@0 | 8 | * particular file as subject to the "Classpath" exception as provided |
aoqi@0 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
aoqi@0 | 10 | * |
aoqi@0 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 15 | * accompanied this code). |
aoqi@0 | 16 | * |
aoqi@0 | 17 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 20 | * |
aoqi@0 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 22 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 23 | * questions. |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | package com.sun.tools.internal.xjc.runtime; |
aoqi@0 | 27 | |
aoqi@0 | 28 | import java.util.ArrayList; |
aoqi@0 | 29 | import java.util.List; |
aoqi@0 | 30 | import java.util.Map; |
aoqi@0 | 31 | import java.util.StringTokenizer; |
aoqi@0 | 32 | |
aoqi@0 | 33 | import javax.xml.bind.JAXBContext; |
aoqi@0 | 34 | import javax.xml.bind.JAXBException; |
aoqi@0 | 35 | |
aoqi@0 | 36 | /** |
aoqi@0 | 37 | * This class implements the actual logic of {@link JAXBContext#newInstance}. |
aoqi@0 | 38 | * |
aoqi@0 | 39 | * <p> |
aoqi@0 | 40 | * This class works as a facade and all the actual work is delegated to |
aoqi@0 | 41 | * a JAXB provider that happens to be in the runtime (not necessarily the JAXB RI.) |
aoqi@0 | 42 | * This allows the generated code to be run with any JAXB provider. |
aoqi@0 | 43 | * |
aoqi@0 | 44 | * <p> |
aoqi@0 | 45 | * This code is only used when XJC generates interfaces/implementations. |
aoqi@0 | 46 | * |
aoqi@0 | 47 | * <p> |
aoqi@0 | 48 | * The trick to make this work is two ObjectFactory classes that we generate |
aoqi@0 | 49 | * in the interface/implementation mode. |
aoqi@0 | 50 | * |
aoqi@0 | 51 | * <p> |
aoqi@0 | 52 | * The public ObjectFactory follows the spec, and this is the one that's exposed |
aoqi@0 | 53 | * to users. The public ObjectFactory refers to interfaces, so they aren't |
aoqi@0 | 54 | * directly usable by a JAXB 2.0 implementation. |
aoqi@0 | 55 | * |
aoqi@0 | 56 | * <p> |
aoqi@0 | 57 | * The private one lives in the impl package, and this one is indistinguishable |
aoqi@0 | 58 | * from the ObjectFactory that we generate for the value class generation mode. |
aoqi@0 | 59 | * This private ObjectFactory refers to implementation classes, which are |
aoqi@0 | 60 | * also indistinguishable from value classes that JAXB generates. |
aoqi@0 | 61 | * |
aoqi@0 | 62 | * <p> |
aoqi@0 | 63 | * All in all, the private ObjectFactory plus implementation classes give |
aoqi@0 | 64 | * a JAXB provider an illusion that they are dealing with value classes |
aoqi@0 | 65 | * that happens to implement some interfaces. |
aoqi@0 | 66 | * |
aoqi@0 | 67 | * <p> |
aoqi@0 | 68 | * In this way, the JAXB RI can provide the portability even for the |
aoqi@0 | 69 | * interface/implementation generation mode. |
aoqi@0 | 70 | * |
aoqi@0 | 71 | * @since 2.0 |
aoqi@0 | 72 | * @author Kohsuke Kawaguchi |
aoqi@0 | 73 | */ |
aoqi@0 | 74 | public class JAXBContextFactory { |
aoqi@0 | 75 | private static final String DOT_OBJECT_FACTORY = ".ObjectFactory"; |
aoqi@0 | 76 | private static final String IMPL_DOT_OBJECT_FACTORY = ".impl.ObjectFactory"; |
aoqi@0 | 77 | |
aoqi@0 | 78 | /** |
aoqi@0 | 79 | * The JAXB API will invoke this method via reflection |
aoqi@0 | 80 | */ |
aoqi@0 | 81 | public static JAXBContext createContext( Class[] classes, Map properties ) throws JAXBException { |
aoqi@0 | 82 | Class[] r = new Class[classes.length]; |
aoqi@0 | 83 | boolean modified = false; |
aoqi@0 | 84 | |
aoqi@0 | 85 | // find any reference to our 'public' ObjectFactory and |
aoqi@0 | 86 | // replace that to our 'private' ObjectFactory. |
aoqi@0 | 87 | for( int i=0; i<r.length; i++ ) { |
aoqi@0 | 88 | Class c = classes[i]; |
aoqi@0 | 89 | String name = c.getName(); |
aoqi@0 | 90 | if(name.endsWith(DOT_OBJECT_FACTORY) |
aoqi@0 | 91 | && !name.endsWith(IMPL_DOT_OBJECT_FACTORY)) { |
aoqi@0 | 92 | // we never generate into the root package, so no need to worry about FQCN "ObjectFactory" |
aoqi@0 | 93 | |
aoqi@0 | 94 | // if we find one, tell the real JAXB provider to |
aoqi@0 | 95 | // load foo.bar.impl.ObjectFactory |
aoqi@0 | 96 | name = name.substring(0,name.length()-DOT_OBJECT_FACTORY.length())+IMPL_DOT_OBJECT_FACTORY; |
aoqi@0 | 97 | |
aoqi@0 | 98 | try { |
aoqi@0 | 99 | c = getClassClassLoader(c).loadClass(name); |
aoqi@0 | 100 | } catch (ClassNotFoundException e) { |
aoqi@0 | 101 | throw new JAXBException(e); |
aoqi@0 | 102 | } |
aoqi@0 | 103 | |
aoqi@0 | 104 | modified = true; |
aoqi@0 | 105 | } |
aoqi@0 | 106 | |
aoqi@0 | 107 | r[i] = c; |
aoqi@0 | 108 | } |
aoqi@0 | 109 | |
aoqi@0 | 110 | if(!modified) { |
aoqi@0 | 111 | // if the class list doesn't contain any of our classes, |
aoqi@0 | 112 | // this ContextFactory shouldn't have been called in the first place |
aoqi@0 | 113 | // if we simply continue, we'll just end up with the infinite recursion. |
aoqi@0 | 114 | |
aoqi@0 | 115 | // the only case that I can think of where this could happen is |
aoqi@0 | 116 | // when the user puts additional classes into the JAXB-generated |
aoqi@0 | 117 | // package and pass them to JAXBContext.newInstance(). |
aoqi@0 | 118 | // Under normal use, this shouldn't happen. |
aoqi@0 | 119 | |
aoqi@0 | 120 | // anyway, bail out now. |
aoqi@0 | 121 | // if you hit this problem and wondering how to get around the problem, |
aoqi@0 | 122 | // subscribe and send a note to users@jaxb.dev.java.net (http://jaxb.dev.java.net/) |
aoqi@0 | 123 | throw new JAXBException("Unable to find a JAXB implementation to delegate"); |
aoqi@0 | 124 | } |
aoqi@0 | 125 | |
aoqi@0 | 126 | // delegate to the JAXB provider in the system |
aoqi@0 | 127 | return JAXBContext.newInstance(r,properties); |
aoqi@0 | 128 | } |
aoqi@0 | 129 | |
aoqi@0 | 130 | |
aoqi@0 | 131 | /** |
aoqi@0 | 132 | * The JAXB API will invoke this method via reflection |
aoqi@0 | 133 | */ |
aoqi@0 | 134 | public static JAXBContext createContext( String contextPath, |
aoqi@0 | 135 | ClassLoader classLoader, Map properties ) throws JAXBException { |
aoqi@0 | 136 | |
aoqi@0 | 137 | List<Class> classes = new ArrayList<Class>(); |
aoqi@0 | 138 | StringTokenizer tokens = new StringTokenizer(contextPath,":"); |
aoqi@0 | 139 | |
aoqi@0 | 140 | // each package should be pointing to a JAXB RI generated |
aoqi@0 | 141 | // content interface package. |
aoqi@0 | 142 | // |
aoqi@0 | 143 | // translate them into a list of private ObjectFactories. |
aoqi@0 | 144 | try { |
aoqi@0 | 145 | while(tokens.hasMoreTokens()) { |
aoqi@0 | 146 | String pkg = tokens.nextToken(); |
aoqi@0 | 147 | classes.add(classLoader.loadClass(pkg+IMPL_DOT_OBJECT_FACTORY)); |
aoqi@0 | 148 | } |
aoqi@0 | 149 | } catch (ClassNotFoundException e) { |
aoqi@0 | 150 | throw new JAXBException(e); |
aoqi@0 | 151 | } |
aoqi@0 | 152 | |
aoqi@0 | 153 | // delegate to the JAXB provider in the system |
aoqi@0 | 154 | return JAXBContext.newInstance(classes.toArray(new Class[classes.size()]),properties); |
aoqi@0 | 155 | } |
aoqi@0 | 156 | |
aoqi@0 | 157 | private static ClassLoader getClassClassLoader(final Class c) { |
aoqi@0 | 158 | if (System.getSecurityManager() == null) { |
aoqi@0 | 159 | return c.getClassLoader(); |
aoqi@0 | 160 | } else { |
aoqi@0 | 161 | return (ClassLoader) java.security.AccessController.doPrivileged( |
aoqi@0 | 162 | new java.security.PrivilegedAction() { |
aoqi@0 | 163 | public java.lang.Object run() { |
aoqi@0 | 164 | return c.getClassLoader(); |
aoqi@0 | 165 | } |
aoqi@0 | 166 | }); |
aoqi@0 | 167 | } |
aoqi@0 | 168 | } |
aoqi@0 | 169 | |
aoqi@0 | 170 | } |