1 /* 2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.ws.model; 27 28 import java.lang.reflect.Field; 29 import javax.xml.ws.WebServiceException; 30 import java.lang.reflect.InvocationTargetException; 31 import java.lang.reflect.Method; 32 import java.net.URL; 33 import java.security.AccessController; 34 import java.security.PrivilegedAction; 35 import java.security.PrivilegedActionException; 36 import java.security.PrivilegedExceptionAction; 37 import java.security.ProtectionDomain; 38 import java.util.logging.Level; 39 import java.util.logging.Logger; 40 41 /** 42 * A {@link ClassLoader} used to "inject" wrapper and exception bean classes 43 * into the VM. 44 * 45 * @author Jitendra kotamraju 46 */ 47 final class Injector { 48 49 private static final Logger LOGGER = Logger.getLogger(Injector.class.getName()); 50 51 private static Method defineClass; 52 private static Method resolveClass; 53 private static Method getPackage; 54 private static Method definePackage; 55 private static Object U; 56 57 static { 58 try { 59 Method[] m = AccessController.doPrivileged( 60 new PrivilegedAction<Method[]>() { 61 @Override 62 public Method[] run() { 63 return new Method[]{ 64 getMethod(ClassLoader.class, "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE), 65 getMethod(ClassLoader.class, "resolveClass", Class.class), 66 getMethod(ClassLoader.class, "getPackage", String.class), 67 getMethod(ClassLoader.class, "definePackage", 68 String.class, String.class, String.class, String.class, 69 String.class, String.class, String.class, URL.class) 70 }; 71 } 72 } 73 ); 74 defineClass = m[0]; 75 resolveClass = m[1]; 76 getPackage = m[2]; 77 definePackage = m[3]; 78 79 } catch (Throwable t) { 80 try { 81 U = AccessController.doPrivileged(new PrivilegedExceptionAction() { 82 @Override 83 public Object run() throws Exception { 84 Class u = Class.forName("sun.misc.Unsafe"); 85 Field theUnsafe = u.getDeclaredField("theUnsafe"); 86 theUnsafe.setAccessible(true); 87 return theUnsafe.get(null); 88 } 89 }); 90 defineClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { 91 @Override 92 public Method run() throws Exception { 93 try { 94 return U.getClass().getMethod("defineClass", 95 new Class[]{String.class, 96 byte[].class, 97 Integer.TYPE, 98 Integer.TYPE, 99 ClassLoader.class, 100 ProtectionDomain.class}); 101 } catch (NoSuchMethodException | SecurityException ex) { 102 throw ex; 103 } 104 } 105 }); 106 } catch (SecurityException | PrivilegedActionException ex) { 107 Logger.getLogger(Injector.class.getName()).log(Level.SEVERE, null, ex); 108 WebServiceException we = new WebServiceException(ex); 109 we.addSuppressed(t); 110 throw we; 111 } 112 } 113 } 114 115 private static Method getMethod(final Class<?> c, final String methodname, final Class<?>... params) { 116 try { 117 Method m = c.getDeclaredMethod(methodname, params); 118 m.setAccessible(true); 119 return m; 120 } catch (NoSuchMethodException e) { 121 // impossible 122 throw new NoSuchMethodError(e.getMessage()); 123 } 124 } 125 126 static synchronized Class inject(ClassLoader cl, String className, byte[] image) { 127 // To avoid race conditions let us check if the classloader 128 // already contains the class 129 try { 130 return cl.loadClass(className); 131 } catch (ClassNotFoundException e) { 132 // nothing to do 133 } 134 try { 135 if (definePackage == null) { 136 return (Class) defineClass.invoke(U, className.replace('/', '.'), image, 0, image.length, cl, Injector.class.getProtectionDomain()); 137 } 138 int packIndex = className.lastIndexOf('.'); 139 if (packIndex != -1) { 140 String pkgname = className.substring(0, packIndex); 141 // Check if package already loaded. 142 Package pkg = (Package) getPackage.invoke(cl, pkgname); 143 if (pkg == null) { 144 definePackage.invoke(cl, pkgname, null, null, null, null, null, null, null); 145 } 146 } 147 148 Class c = (Class) defineClass.invoke(cl, className.replace('/', '.'), image, 0, image.length); 149 resolveClass.invoke(cl, c); 150 return c; 151 } catch (IllegalAccessException | InvocationTargetException e) { 152 if (LOGGER.isLoggable(Level.FINE)) { 153 LOGGER.log(Level.FINE, "Unable to inject " + className, e); 154 } 155 throw new WebServiceException(e); 156 } 157 } 158 159 }