1 /*
   2  * Copyright (c) 2008, 2014, 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 javax.xml.ws.WebServiceException;
  29 import java.lang.reflect.InvocationTargetException;
  30 import java.lang.reflect.Method;
  31 import java.net.URL;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedAction;
  34 import java.util.logging.Level;
  35 import java.util.logging.Logger;
  36 
  37 /**
  38  * A {@link ClassLoader} used to "inject" wrapper and exception bean classes
  39  * into the VM.
  40  *
  41  * @author Jitendra kotamraju
  42  */
  43 final class Injector {
  44 
  45     private static final Logger LOGGER = Logger.getLogger(Injector.class.getName());
  46 
  47     private static final Method defineClass;
  48     private static final Method resolveClass;
  49     private static final Method getPackage;
  50     private static final Method definePackage;
  51 
  52     static {
  53         Method[] m = AccessController.doPrivileged(
  54                 new PrivilegedAction<Method[]>() {
  55                     @Override
  56                     public Method[] run() {
  57                         return new Method[]{
  58                                 getMethod(ClassLoader.class, "defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE),
  59                                 getMethod(ClassLoader.class, "resolveClass", Class.class),
  60                                 getMethod(ClassLoader.class, "getPackage", String.class),
  61                                 getMethod(ClassLoader.class, "definePackage",
  62                                         String.class, String.class, String.class, String.class,
  63                                         String.class, String.class, String.class, URL.class)
  64                         };
  65                     }
  66                 }
  67         );
  68         defineClass = m[0];
  69         resolveClass = m[1];
  70         getPackage = m[2];
  71         definePackage = m[3];
  72     }
  73 
  74     private static Method getMethod(final Class<?> c, final String methodname, final Class<?>... params) {
  75         try {
  76             Method m = c.getDeclaredMethod(methodname, params);
  77             m.setAccessible(true);
  78             return m;
  79         } catch (NoSuchMethodException e) {
  80             // impossible
  81             throw new NoSuchMethodError(e.getMessage());
  82         }
  83     }
  84 
  85     static synchronized Class inject(ClassLoader cl, String className, byte[] image) {
  86         // To avoid race conditions let us check if the classloader
  87         // already contains the class
  88         try {
  89             return cl.loadClass(className);
  90         } catch (ClassNotFoundException e) {
  91             // nothing to do
  92         }
  93         try {
  94             int packIndex = className.lastIndexOf('.');
  95             if (packIndex != -1) {
  96                 String pkgname = className.substring(0, packIndex);
  97                 // Check if package already loaded.
  98                 Package pkg = (Package)getPackage.invoke(cl, pkgname);
  99                 if (pkg == null) {
 100                     definePackage.invoke(cl, pkgname, null, null, null, null, null, null, null);
 101                 }
 102             }
 103 
 104             Class c = (Class)defineClass.invoke(cl,className.replace('/','.'),image,0,image.length);
 105             resolveClass.invoke(cl, c);
 106             return c;
 107         } catch (IllegalAccessException e) {
 108             LOGGER.log(Level.FINE,"Unable to inject "+className,e);
 109             throw new WebServiceException(e);
 110         } catch (InvocationTargetException e) {
 111             LOGGER.log(Level.FINE,"Unable to inject "+className,e);
 112             throw new WebServiceException(e);
 113         }
 114     }
 115 
 116 }