1 /*
   2  * Copyright (c) 2001, 2016, 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 sun.reflect;
  27 
  28 import java.io.OptionalDataException;
  29 import java.lang.invoke.MethodHandle;
  30 import java.lang.reflect.Constructor;
  31 import java.lang.reflect.InvocationTargetException;
  32 import java.security.AccessController;
  33 import java.security.Permission;
  34 import java.security.PrivilegedAction;
  35 
  36 /**
  37  * ReflectionFactory supports custom serialization.
  38  * Its methods support the creation of uninitialized objects, invoking serialization
  39  * private methods for readObject, writeObject, readResolve, and writeReplace.
  40  * <p>
  41  * ReflectionFactory access is restricted, if a security manager is active,
  42  * unless the permission {@code RuntimePermission("reflectionFactoryAccess")}
  43  * is granted.
  44  */
  45 public class ReflectionFactory {
  46 
  47     private static final ReflectionFactory soleInstance = new ReflectionFactory();
  48     private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged(
  49             new PrivilegedAction<jdk.internal.reflect.ReflectionFactory>() {
  50                 public jdk.internal.reflect.ReflectionFactory run() {
  51                     return jdk.internal.reflect.ReflectionFactory.getReflectionFactory();
  52                 }
  53             });
  54 
  55     private ReflectionFactory() {}
  56 
  57     private static final Permission REFLECTION_FACTORY_ACCESS_PERM
  58             = new RuntimePermission("reflectionFactoryAccess");
  59 
  60     /**
  61      * Provides the caller with the capability to instantiate reflective
  62      * objects.
  63      *
  64      * <p> First, if there is a security manager, its {@code checkPermission}
  65      * method is called with a {@link java.lang.RuntimePermission} with target
  66      * {@code "reflectionFactoryAccess"}.  This may result in a security
  67      * exception.
  68      *
  69      * <p> The returned {@code ReflectionFactory} object should be carefully
  70      * guarded by the caller, since it can be used to read and write private
  71      * data and invoke private methods, as well as to load unverified bytecodes.
  72      * It must never be passed to untrusted code.
  73      *
  74      * @return the ReflectionFactory
  75      * @throws SecurityException if a security manager exists and its
  76      *         {@code checkPermission} method doesn't allow access to
  77      *         the RuntimePermission "reflectionFactoryAccess".
  78      */
  79     public static ReflectionFactory getReflectionFactory() {
  80         SecurityManager security = System.getSecurityManager();
  81         if (security != null) {
  82             security.checkPermission(REFLECTION_FACTORY_ACCESS_PERM);
  83         }
  84         return soleInstance;
  85     }
  86 
  87     /**
  88      * Returns an accessible no-arg constructor for a class.
  89      * The no-arg constructor is found searching the class and its supertypes.
  90      *
  91      * @param cl the class to instantiate
  92      * @return a no-arg constructor for the class or {@code null} if
  93      *     the class or supertypes do not have a suitable no-arg constructor
  94      */
  95     public final Constructor<?> newConstructorForSerialization(Class<?> cl)
  96     {
  97         return delegate.newConstructorForSerialization(cl);
  98     }
  99 
 100     /**
 101      * Returns an accessible no-arg constructor for an externalizable class to be
 102      * initialized using a public no-argument constructor.
 103      *
 104      * @param cl the class to instantiate
 105      * @return A no-arg constructor for the class; returns {@code null} if
 106      *     the class does not implement {@link java.io.Externalizable}
 107      */
 108     public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
 109         return delegate.newConstructorForExternalization(cl);
 110     }
 111 
 112     /**
 113      * Returns a direct MethodHandle for the {@code readObject} method on
 114      * a Serializable class.
 115      * The first argument of {@link MethodHandle#invoke} is the serializable
 116      * object and the second argument is the {@code ObjectInputStream} passed to
 117      * {@code readObject}.
 118      *
 119      * @param cl a Serializable class
 120      * @return  a direct MethodHandle for the {@code readObject} method of the class or
 121      *          {@code null} if the class does not have a {@code readObject} method
 122      */
 123     public final MethodHandle readObjectForSerialization(Class<?> cl) {
 124         return delegate.readObjectForSerialization(cl);
 125     }
 126 
 127     /**
 128      * Returns a direct MethodHandle for the {@code readObjectNoData} method on
 129      * a Serializable class.
 130      * The first argument of {@link MethodHandle#invoke} is the serializable
 131      * object and the second argument is the {@code ObjectInputStream} passed to
 132      * {@code readObjectNoData}.
 133      *
 134      * @param cl a Serializable class
 135      * @return  a direct MethodHandle for the {@code readObjectNoData} method
 136      *          of the class or {@code null} if the class does not have a
 137      *          {@code readObjectNoData} method
 138      */
 139     public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
 140         return delegate.readObjectNoDataForSerialization(cl);
 141     }
 142 
 143     /**
 144      * Returns a direct MethodHandle for the {@code writeObject} method on
 145      * a Serializable class.
 146      * The first argument of {@link MethodHandle#invoke} is the serializable
 147      * object and the second argument is the {@code ObjectOutputStream} passed to
 148      * {@code writeObject}.
 149      *
 150      * @param cl a Serializable class
 151      * @return  a direct MethodHandle for the {@code writeObject} method of the class or
 152      *          {@code null} if the class does not have a {@code writeObject} method
 153      */
 154     public final MethodHandle writeObjectForSerialization(Class<?> cl) {
 155         return delegate.writeObjectForSerialization(cl);
 156     }
 157 
 158     /**
 159      * Returns a direct MethodHandle for the {@code readResolve} method on
 160      * a serializable class.
 161      * The single argument of {@link MethodHandle#invoke} is the serializable
 162      * object.
 163      *
 164      * @param cl the Serializable class
 165      * @return  a direct MethodHandle for the {@code readResolve} method of the class or
 166      *          {@code null} if the class does not have a {@code readResolve} method
 167      */
 168     public final MethodHandle readResolveForSerialization(Class<?> cl) {
 169         return delegate.readResolveForSerialization(cl);
 170     }
 171 
 172     /**
 173      * Returns a direct MethodHandle for the {@code writeReplace} method on
 174      * a serializable class.
 175      * The single argument of {@link MethodHandle#invoke} is the serializable
 176      * object.
 177      *
 178      * @param cl the Serializable class
 179      * @return  a direct MethodHandle for the {@code writeReplace} method of the class or
 180      *          {@code null} if the class does not have a {@code writeReplace} method
 181      */
 182     public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
 183         return delegate.writeReplaceForSerialization(cl);
 184     }
 185 
 186     /**
 187      * Returns true if the class has a static initializer.
 188      * The presence of a static initializer is used to compute the serialVersionUID.
 189      * @param cl a serializable class
 190      * @return {@code true} if the class has a static initializer,
 191      *          otherwise {@code false}
 192      */
 193     public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
 194         return delegate.hasStaticInitializerForSerialization(cl);
 195     }
 196 
 197     /**
 198      * Returns a new OptionalDataException with {@code eof} set to {@code true}
 199      * or {@code false}.
 200      * @param bool the value of {@code eof} in the created OptionalDataException
 201      * @return  a new OptionalDataException
 202      */
 203     public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
 204         Constructor<OptionalDataException> cons = delegate.newOptionalDataExceptionForSerialization();
 205         try {
 206             return cons.newInstance(bool);
 207         } catch (InstantiationException|IllegalAccessException|InvocationTargetException ex) {
 208             throw new InternalError("unable to create OptionalDataException", ex);
 209         }
 210     }
 211 }
 212