mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-12 07:58:43 +00:00
8164908: ReflectionFactory support for IIOP and custom serialization
Add support for serialization to sun.reflect.ReflectionFactory Reviewed-by: alanb, chegar, plevart, amlu
This commit is contained in:
parent
033650f9e0
commit
e89ce16097
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1413,27 +1413,7 @@ public class ObjectStreamClass implements Serializable {
|
||||
* returned constructor (if any).
|
||||
*/
|
||||
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
|
||||
Class<?> initCl = cl;
|
||||
while (Serializable.class.isAssignableFrom(initCl)) {
|
||||
if ((initCl = initCl.getSuperclass()) == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
|
||||
int mods = cons.getModifiers();
|
||||
if ((mods & Modifier.PRIVATE) != 0 ||
|
||||
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
|
||||
!packageEquals(cl, initCl)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
cons = reflFactory.newConstructorForSerialization(cl, cons);
|
||||
cons.setAccessible(true);
|
||||
return cons;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
return reflFactory.newConstructorForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,14 +25,25 @@
|
||||
|
||||
package jdk.internal.reflect;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
@ -57,6 +68,9 @@ public class ReflectionFactory {
|
||||
// Provides access to package-private mechanisms in java.lang.reflect
|
||||
private static volatile LangReflectAccess langReflectAccess;
|
||||
|
||||
/* Method for static class initializer <clinit>, or null */
|
||||
private static volatile Method hasStaticInitializerMethod;
|
||||
|
||||
//
|
||||
// "Inflation" mechanism. Loading bytecodes to implement
|
||||
// Method.invoke() and Constructor.newInstance() currently costs
|
||||
@ -337,16 +351,41 @@ public class ReflectionFactory {
|
||||
//
|
||||
//
|
||||
|
||||
public Constructor<?> newConstructorForSerialization
|
||||
(Class<?> classToInstantiate, Constructor<?> constructorToCall)
|
||||
{
|
||||
// Fast path
|
||||
if (constructorToCall.getDeclaringClass() == classToInstantiate) {
|
||||
return constructorToCall;
|
||||
public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
|
||||
if (!Externalizable.class.isAssignableFrom(cl)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Constructor<?> cons = cl.getConstructor();
|
||||
cons.setAccessible(true);
|
||||
return cons;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
|
||||
Class<?> initCl = cl;
|
||||
while (Serializable.class.isAssignableFrom(initCl)) {
|
||||
if ((initCl = initCl.getSuperclass()) == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Constructor<?> constructorToCall;
|
||||
try {
|
||||
constructorToCall = initCl.getDeclaredConstructor();
|
||||
int mods = constructorToCall.getModifiers();
|
||||
if ((mods & Modifier.PRIVATE) != 0 ||
|
||||
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
|
||||
!packageEquals(cl, initCl))) {
|
||||
return null;
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstructorAccessor acc = new MethodAccessorGenerator().
|
||||
generateSerializationConstructor(classToInstantiate,
|
||||
generateSerializationConstructor(cl,
|
||||
constructorToCall.getParameterTypes(),
|
||||
constructorToCall.getExceptionTypes(),
|
||||
constructorToCall.getModifiers(),
|
||||
@ -364,9 +403,151 @@ public class ReflectionFactory {
|
||||
langReflectAccess().
|
||||
getConstructorParameterAnnotations(constructorToCall));
|
||||
setConstructorAccessor(c, acc);
|
||||
c.setAccessible(true);
|
||||
return c;
|
||||
}
|
||||
|
||||
public final MethodHandle readObjectForSerialization(Class<?> cl) {
|
||||
return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
|
||||
}
|
||||
|
||||
public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
|
||||
return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
|
||||
}
|
||||
|
||||
public final MethodHandle writeObjectForSerialization(Class<?> cl) {
|
||||
return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
|
||||
}
|
||||
|
||||
private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
|
||||
String methodName,
|
||||
Class<?> streamClass) {
|
||||
if (!Serializable.class.isAssignableFrom(cl)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Method meth = cl.getDeclaredMethod(methodName, streamClass);
|
||||
int mods = meth.getModifiers();
|
||||
if (meth.getReturnType() != Void.TYPE ||
|
||||
Modifier.isStatic(mods) ||
|
||||
!Modifier.isPrivate(mods)) {
|
||||
return null;
|
||||
}
|
||||
meth.setAccessible(true);
|
||||
return MethodHandles.lookup().unreflect(meth);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
} catch (IllegalAccessException ex1) {
|
||||
throw new InternalError("Error", ex1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a MethodHandle for {@code writeReplace} on the serializable class
|
||||
* or null if no match found.
|
||||
* @param cl a serializable class
|
||||
* @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
|
||||
*/
|
||||
public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
|
||||
return getReplaceResolveForSerialization(cl, "writeReplace");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a MethodHandle for {@code readResolve} on the serializable class
|
||||
* or null if no match found.
|
||||
* @param cl a serializable class
|
||||
* @returns the {@code writeReplace} MethodHandle or {@code null} if not found
|
||||
*/
|
||||
public final MethodHandle readResolveForSerialization(Class<?> cl) {
|
||||
return getReplaceResolveForSerialization(cl, "readResolve");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup readResolve or writeReplace on a class with specified
|
||||
* signature constraints.
|
||||
* @param cl a serializable class
|
||||
* @param methodName the method name to find
|
||||
* @returns a MethodHandle for the method or {@code null} if not found or
|
||||
* has the wrong signature.
|
||||
*/
|
||||
private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
|
||||
String methodName) {
|
||||
if (!Serializable.class.isAssignableFrom(cl)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> defCl = cl;
|
||||
while (defCl != null) {
|
||||
try {
|
||||
Method m = defCl.getDeclaredMethod(methodName);
|
||||
if (m.getReturnType() != Object.class) {
|
||||
return null;
|
||||
}
|
||||
int mods = m.getModifiers();
|
||||
if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
|
||||
return null;
|
||||
} else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
|
||||
// fall through
|
||||
} else if (Modifier.isPrivate(mods) && (cl != defCl)) {
|
||||
return null;
|
||||
} else if (!packageEquals(cl, defCl)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// Normal return
|
||||
m.setAccessible(true);
|
||||
return MethodHandles.lookup().unreflect(m);
|
||||
} catch (IllegalAccessException ex0) {
|
||||
// setAccessible should prevent IAE
|
||||
throw new InternalError("Error", ex0);
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
defCl = defCl.getSuperclass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given class defines a static initializer method,
|
||||
* false otherwise.
|
||||
*/
|
||||
public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
|
||||
Method m = hasStaticInitializerMethod;
|
||||
if (m == null) {
|
||||
try {
|
||||
m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
|
||||
new Class<?>[]{Class.class});
|
||||
m.setAccessible(true);
|
||||
hasStaticInitializerMethod = m;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new InternalError("No such method hasStaticInitializer on "
|
||||
+ ObjectStreamClass.class, ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (Boolean) m.invoke(null, cl);
|
||||
} catch (InvocationTargetException | IllegalAccessException ex) {
|
||||
throw new InternalError("Exception invoking hasStaticInitializer", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the accessible constructor for OptionalDataException signaling eof.
|
||||
* @returns the eof constructor for OptionalDataException
|
||||
*/
|
||||
public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
|
||||
try {
|
||||
Constructor<OptionalDataException> boolCtor =
|
||||
OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
|
||||
boolCtor.setAccessible(true);
|
||||
return boolCtor;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
throw new InternalError("Constructor not found", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Internals only below this point
|
||||
@ -426,4 +607,17 @@ public class ReflectionFactory {
|
||||
}
|
||||
return langReflectAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if classes are defined in the classloader and same package, false
|
||||
* otherwise.
|
||||
* @param cl1 a class
|
||||
* @param cl2 another class
|
||||
* @returns true if the two classes are in the same classloader and package
|
||||
*/
|
||||
private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
|
||||
return cl1.getClassLoader() == cl2.getClassLoader() &&
|
||||
Objects.equals(cl1.getPackage(), cl2.getPackage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,24 +25,34 @@
|
||||
|
||||
package sun.reflect;
|
||||
|
||||
import java.io.OptionalDataException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* ReflectionFactory supports custom serialization.
|
||||
* Its methods support the creation of uninitialized objects, invoking serialization
|
||||
* private methods for readObject, writeObject, readResolve, and writeReplace.
|
||||
* <p>
|
||||
* ReflectionFactory access is restricted, if a security manager is active,
|
||||
* unless the permission {@code RuntimePermission("reflectionFactoryAccess")}
|
||||
* is granted.
|
||||
*/
|
||||
public class ReflectionFactory {
|
||||
|
||||
private static final ReflectionFactory soleInstance = new ReflectionFactory();
|
||||
private final jdk.internal.reflect.ReflectionFactory delegate;
|
||||
|
||||
private ReflectionFactory() {
|
||||
delegate = AccessController.doPrivileged(
|
||||
private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged(
|
||||
new PrivilegedAction<jdk.internal.reflect.ReflectionFactory>() {
|
||||
public jdk.internal.reflect.ReflectionFactory run() {
|
||||
return jdk.internal.reflect.ReflectionFactory.getReflectionFactory();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
private ReflectionFactory() {}
|
||||
|
||||
private static final Permission REFLECTION_FACTORY_ACCESS_PERM
|
||||
= new RuntimePermission("reflectionFactoryAccess");
|
||||
@ -53,7 +63,7 @@ public class ReflectionFactory {
|
||||
*
|
||||
* <p> First, if there is a security manager, its {@code checkPermission}
|
||||
* method is called with a {@link java.lang.RuntimePermission} with target
|
||||
* {@code "reflectionFactoryAccess"}. This may result in a securit
|
||||
* {@code "reflectionFactoryAccess"}. This may result in a security
|
||||
* exception.
|
||||
*
|
||||
* <p> The returned {@code ReflectionFactory} object should be carefully
|
||||
@ -61,6 +71,7 @@ public class ReflectionFactory {
|
||||
* data and invoke private methods, as well as to load unverified bytecodes.
|
||||
* It must never be passed to untrusted code.
|
||||
*
|
||||
* @return the ReflectionFactory
|
||||
* @throws SecurityException if a security manager exists and its
|
||||
* {@code checkPermission} method doesn't allow access to
|
||||
* the RuntimePermission "reflectionFactoryAccess".
|
||||
@ -73,11 +84,129 @@ public class ReflectionFactory {
|
||||
return soleInstance;
|
||||
}
|
||||
|
||||
public Constructor<?> newConstructorForSerialization(Class<?> classToInstantiate,
|
||||
Constructor<?> constructorToCall)
|
||||
/**
|
||||
* Returns an accessible no-arg constructor for a class.
|
||||
* The no-arg constructor is found searching the class and its supertypes.
|
||||
*
|
||||
* @param cl the class to instantiate
|
||||
* @return a no-arg constructor for the class or {@code null} if
|
||||
* the class or supertypes do not have a suitable no-arg constructor
|
||||
*/
|
||||
public final Constructor<?> newConstructorForSerialization(Class<?> cl)
|
||||
{
|
||||
return delegate.newConstructorForSerialization(classToInstantiate,
|
||||
constructorToCall);
|
||||
return delegate.newConstructorForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an accessible no-arg constructor for an externalizable class to be
|
||||
* initialized using a public no-argument constructor.
|
||||
*
|
||||
* @param cl the class to instantiate
|
||||
* @return A no-arg constructor for the class; returns {@code null} if
|
||||
* the class does not implement {@link java.io.Externalizable}
|
||||
*/
|
||||
public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
|
||||
return delegate.newConstructorForExternalization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direct MethodHandle for the {@code readObject} method on
|
||||
* a Serializable class.
|
||||
* The first argument of {@link MethodHandle#invoke} is the serializable
|
||||
* object and the second argument is the {@code ObjectInputStream} passed to
|
||||
* {@code readObject}.
|
||||
*
|
||||
* @param cl a Serializable class
|
||||
* @return a direct MethodHandle for the {@code readObject} method of the class or
|
||||
* {@code null} if the class does not have a {@code readObject} method
|
||||
*/
|
||||
public final MethodHandle readObjectForSerialization(Class<?> cl) {
|
||||
return delegate.readObjectForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direct MethodHandle for the {@code readObjectNoData} method on
|
||||
* a Serializable class.
|
||||
* The first argument of {@link MethodHandle#invoke} is the serializable
|
||||
* object and the second argument is the {@code ObjectInputStream} passed to
|
||||
* {@code readObjectNoData}.
|
||||
*
|
||||
* @param cl a Serializable class
|
||||
* @return a direct MethodHandle for the {@code readObjectNoData} method
|
||||
* of the class or {@code null} if the class does not have a
|
||||
* {@code readObjectNoData} method
|
||||
*/
|
||||
public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
|
||||
return delegate.readObjectNoDataForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direct MethodHandle for the {@code writeObject} method on
|
||||
* a Serializable class.
|
||||
* The first argument of {@link MethodHandle#invoke} is the serializable
|
||||
* object and the second argument is the {@code ObjectOutputStream} passed to
|
||||
* {@code writeObject}.
|
||||
*
|
||||
* @param cl a Serializable class
|
||||
* @return a direct MethodHandle for the {@code writeObject} method of the class or
|
||||
* {@code null} if the class does not have a {@code writeObject} method
|
||||
*/
|
||||
public final MethodHandle writeObjectForSerialization(Class<?> cl) {
|
||||
return delegate.writeObjectForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direct MethodHandle for the {@code readResolve} method on
|
||||
* a serializable class.
|
||||
* The single argument of {@link MethodHandle#invoke} is the serializable
|
||||
* object.
|
||||
*
|
||||
* @param cl the Serializable class
|
||||
* @return a direct MethodHandle for the {@code readResolve} method of the class or
|
||||
* {@code null} if the class does not have a {@code readResolve} method
|
||||
*/
|
||||
public final MethodHandle readResolveForSerialization(Class<?> cl) {
|
||||
return delegate.readResolveForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a direct MethodHandle for the {@code writeReplace} method on
|
||||
* a serializable class.
|
||||
* The single argument of {@link MethodHandle#invoke} is the serializable
|
||||
* object.
|
||||
*
|
||||
* @param cl the Serializable class
|
||||
* @return a direct MethodHandle for the {@code writeReplace} method of the class or
|
||||
* {@code null} if the class does not have a {@code writeReplace} method
|
||||
*/
|
||||
public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
|
||||
return delegate.writeReplaceForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the class has a static initializer.
|
||||
* The presence of a static initializer is used to compute the serialVersionUID.
|
||||
* @param cl a serializable class
|
||||
* @return {@code true} if the class has a static initializer,
|
||||
* otherwise {@code false}
|
||||
*/
|
||||
public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
|
||||
return delegate.hasStaticInitializerForSerialization(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new OptionalDataException with {@code eof} set to {@code true}
|
||||
* or {@code false}.
|
||||
* @param bool the value of {@code eof} in the created OptionalDataException
|
||||
* @return a new OptionalDataException
|
||||
*/
|
||||
public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
|
||||
Constructor<OptionalDataException> cons = delegate.newOptionalDataExceptionForSerialization();
|
||||
try {
|
||||
return cons.newInstance(bool);
|
||||
} catch (InstantiationException|IllegalAccessException|InvocationTargetException ex) {
|
||||
throw new InternalError("unable to create OptionalDataException", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.rmi.UnexpectedException;
|
||||
|
||||
import javax.rmi.CORBA.Stub;
|
||||
import javax.rmi.CORBA.Util;
|
||||
|
||||
import org.omg.CORBA.SystemException;
|
||||
import org.omg.CORBA.portable.ApplicationException;
|
||||
import org.omg.CORBA.portable.OutputStream;
|
||||
import org.omg.CORBA.portable.RemarshalException;
|
||||
import org.omg.CORBA.portable.ServantObject;
|
||||
|
||||
|
||||
/**
|
||||
* ObjectStreamTest$Echo Stub class generated by rmic, do not edit.
|
||||
*/
|
||||
public class ObjectStreamTest$_Echo_Stub extends Stub implements ObjectStreamTest.Echo {
|
||||
|
||||
private static final String[] _type_ids = {
|
||||
"RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
|
||||
};
|
||||
|
||||
private static final long serialVersionUID = 5217577841494640354L;
|
||||
|
||||
public String[] _ids() {
|
||||
return _type_ids.clone();
|
||||
}
|
||||
|
||||
public Object echo(Object arg0) throws java.rmi.RemoteException {
|
||||
if (!Util.isLocal(this)) {
|
||||
try {
|
||||
org.omg.CORBA.portable.InputStream in = null;
|
||||
try {
|
||||
OutputStream out = _request("echo", true);
|
||||
Util.writeAny(out,arg0);
|
||||
in = _invoke(out);
|
||||
return Util.readAny(in);
|
||||
} catch (ApplicationException ex) {
|
||||
in = ex.getInputStream();
|
||||
String $_id = in.read_string();
|
||||
throw new UnexpectedException($_id);
|
||||
} catch (RemarshalException ex) {
|
||||
return echo(arg0);
|
||||
} finally {
|
||||
_releaseReply(in);
|
||||
}
|
||||
} catch (SystemException ex) {
|
||||
throw Util.mapSystemException(ex);
|
||||
}
|
||||
} else {
|
||||
ServantObject so = _servant_preinvoke("echo",ObjectStreamTest.Echo.class);
|
||||
if (so == null) {
|
||||
return echo(arg0);
|
||||
}
|
||||
try {
|
||||
Object arg0Copy = Util.copyObject(arg0,_orb());
|
||||
Object result = ((ObjectStreamTest.Echo)so.servant).echo(arg0Copy);
|
||||
return Util.copyObject(result,_orb());
|
||||
} catch (Throwable ex) {
|
||||
Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
|
||||
throw Util.wrapException(exCopy);
|
||||
} finally {
|
||||
_servant_postinvoke(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.rmi.Remote;
|
||||
|
||||
import javax.rmi.CORBA.Tie;
|
||||
import javax.rmi.CORBA.Util;
|
||||
|
||||
import org.omg.CORBA.BAD_OPERATION;
|
||||
import org.omg.CORBA.ORB;
|
||||
import org.omg.CORBA.SystemException;
|
||||
import org.omg.CORBA.portable.InputStream;
|
||||
import org.omg.CORBA.portable.OutputStream;
|
||||
import org.omg.CORBA.portable.ResponseHandler;
|
||||
import org.omg.CORBA.portable.UnknownException;
|
||||
import org.omg.CORBA_2_3.portable.ObjectImpl;
|
||||
|
||||
|
||||
/**
|
||||
* ObjectStreamClass$Echo server tie class generated by rmic, do not edit.
|
||||
*/
|
||||
public class ObjectStreamTest$_Server_Tie extends ObjectImpl implements Tie {
|
||||
|
||||
volatile private ObjectStreamTest.Server target = null;
|
||||
|
||||
private static final String[] _type_ids = {
|
||||
"RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
|
||||
};
|
||||
|
||||
public void setTarget(Remote target) {
|
||||
this.target = (ObjectStreamTest.Server) target;
|
||||
}
|
||||
|
||||
public Remote getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public org.omg.CORBA.Object thisObject() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
_orb().disconnect(this);
|
||||
_set_delegate(null);
|
||||
target = null;
|
||||
}
|
||||
|
||||
public ORB orb() {
|
||||
return _orb();
|
||||
}
|
||||
|
||||
public void orb(ORB orb) {
|
||||
orb.connect(this);
|
||||
}
|
||||
|
||||
public String[] _ids() {
|
||||
return _type_ids.clone();
|
||||
}
|
||||
|
||||
public OutputStream _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
|
||||
try {
|
||||
ObjectStreamTest.Server target = this.target;
|
||||
if (target == null) {
|
||||
throw new java.io.IOException();
|
||||
}
|
||||
org.omg.CORBA_2_3.portable.InputStream in =
|
||||
(org.omg.CORBA_2_3.portable.InputStream) _in;
|
||||
if (method.equals("echo")) {
|
||||
Object arg0 = Util.readAny(in);
|
||||
Object result = target.echo(arg0);
|
||||
OutputStream out = reply.createReply();
|
||||
Util.writeAny(out,result);
|
||||
return out;
|
||||
}
|
||||
throw new BAD_OPERATION();
|
||||
} catch (SystemException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
throw new UnknownException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
433
jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
Normal file
433
jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
Normal file
@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.PropertyPermission;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingException;
|
||||
import javax.rmi.CORBA.Util;
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
|
||||
import org.omg.CORBA_2_3.ORB;
|
||||
import org.omg.CORBA_2_3.portable.OutputStream;
|
||||
import org.omg.CORBA_2_3.portable.InputStream;
|
||||
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterSuite;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.TestNG;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.*
|
||||
* @compile ObjectStreamTest.java ObjectStreamTest$_Echo_Stub.java ObjectStreamTest$_Server_Tie.java
|
||||
* @modules java.corba/com.sun.corba.se.impl.io java.base/java.io java.corba/com.sun.corba.se.impl.activation
|
||||
* @summary Tests of ReflectionFactory use in IIOP Serialization
|
||||
* @run testng/othervm
|
||||
* -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
|
||||
* -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
|
||||
* @run testng/othervm/policy=security.policy
|
||||
* -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
|
||||
* -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class ObjectStreamTest {
|
||||
|
||||
enum Colors {RED, GREEN, YELLOW}
|
||||
|
||||
static Set<Colors> colorSet = new HashSet<>();
|
||||
|
||||
static {
|
||||
colorSet.add(Colors.RED);
|
||||
colorSet.add(Colors.GREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* The process spawned to run orbd.
|
||||
*/
|
||||
static Process orbdProcess;
|
||||
static Thread orbThread;
|
||||
|
||||
@DataProvider(name = "Objects")
|
||||
static Object[][] patterns() {
|
||||
BigInteger bigInteger = new BigInteger("8943892002309239");
|
||||
InetAddress inetAddr;
|
||||
try {
|
||||
inetAddr = java.net.InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
|
||||
} catch (UnknownHostException ignored) {
|
||||
inetAddr = null;
|
||||
// ignored
|
||||
}
|
||||
HashMap<String, Object> hashMap = new HashMap<>();
|
||||
hashMap.put("BigInteger", bigInteger);
|
||||
hashMap.put("InetAddress", inetAddr);
|
||||
hashMap.put("String", "bString");
|
||||
Object[][] patterns = new Object[][]{
|
||||
{"aString"},
|
||||
{Integer.valueOf(5)},
|
||||
{new SimpleObject(4, 4.0f)},
|
||||
{Arrays.asList("a", "b", "c")},
|
||||
{new String[]{"x", "y", "z"}},
|
||||
{new ArrayList<Object>(1)}, // uses readObject/writeObject
|
||||
{new StringBuffer("abc")}, // Has serialPersistentFields
|
||||
{new StringBuilder("abc")},
|
||||
{Colors.RED},
|
||||
{inetAddr},
|
||||
{LocalTime.MIDNIGHT}, // uses writeReplace/readResolve
|
||||
{new LongAdder()}, // uses writeReplace/readResolve
|
||||
{EnumSet.allOf(Colors.class)}, // used writeReplace/readResolve
|
||||
{bigInteger},
|
||||
{new BigDecimal(bigInteger)},
|
||||
{hashMap},
|
||||
{new PropertyPermission("abc", "read")}, // has serialPersistentFields
|
||||
};
|
||||
return patterns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check ObjectStreamClass facts match between core serialization and CORBA.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
@Test(dataProvider = "Objects")
|
||||
static void factCheck(Serializable value) {
|
||||
Class<?> clazz = value.getClass();
|
||||
java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz);
|
||||
java.io.ObjectStreamField[] sFields = sOSC.getFields();
|
||||
com.sun.corba.se.impl.io.ObjectStreamClass cOSC = corbaLookup(clazz);
|
||||
com.sun.corba.se.impl.io.ObjectStreamField[] cFields = cOSC.getFields();
|
||||
|
||||
Assert.assertEquals(sFields.length, cFields.length, "Different number of fields");
|
||||
for (int i = 0; i < sFields.length; i++) {
|
||||
Assert.assertEquals(sFields[i].getName(), cFields[i].getName(), "different field names " + cFields[i].getName());
|
||||
Assert.assertEquals(sFields[i].getType(), cFields[i].getType(), "different field types " + cFields[i].getName());
|
||||
Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(), "different field typestrings " + cFields[i].getName());
|
||||
}
|
||||
|
||||
Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class<?>[]) null),
|
||||
corbaMethod("hasReadObject", cOSC, (Class<?>[]) null), "hasReadObject: " + value.getClass());
|
||||
|
||||
Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class<?>[]) null),
|
||||
corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null), "hasWriteObject: " + value.getClass());
|
||||
|
||||
Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class<?>[]) null),
|
||||
corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null), "hasWriteReplace: " + value.getClass());
|
||||
|
||||
Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class<?>[]) null),
|
||||
corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null), "hasReadResolve: " + value.getClass());
|
||||
|
||||
Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class<?>[]) null),
|
||||
corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null), "getSerialVersionUID: " + value.getClass());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test that objects written using Util.writeAny can be serialized
|
||||
* and deserialized using Util.readAny to equivalent objects.
|
||||
*/
|
||||
@Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
|
||||
static void WriteValueObjectStreamTest01(Serializable value) throws Exception {
|
||||
ORB orb = (ORB) ORB.init(new String[0], null);
|
||||
|
||||
OutputStream out = (OutputStream) orb.create_output_stream();
|
||||
Util.writeAny(out, value);
|
||||
|
||||
InputStream in = (InputStream) out.create_input_stream();
|
||||
Object actual = Util.readAny(in);
|
||||
|
||||
checkEquals(actual, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that objects can be echoed to a server and come back equivalent.
|
||||
*/
|
||||
@Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
|
||||
static void echoObjects(Serializable value) throws Exception {
|
||||
Context initialNamingContext = Server.init();
|
||||
Echo echo = (Echo) PortableRemoteObject.narrow(
|
||||
initialNamingContext.lookup(Server.serverID), Echo.class);
|
||||
Object actual = echo.echo(value);
|
||||
checkEquals(actual, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the value and result are equals, with some tests depending on the type.
|
||||
* @param expected the expected value
|
||||
* @param actual the actual value
|
||||
*/
|
||||
static void checkEquals(Object actual, Object expected) {
|
||||
Class<?> cl = expected.getClass();
|
||||
Assert.assertEquals(actual.getClass(), cl, "type of value not equal to class of result");
|
||||
try {
|
||||
if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) {
|
||||
Assert.assertEquals(actual, expected, "echo'd object not equal");
|
||||
} else {
|
||||
Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
|
||||
}
|
||||
} catch (NoSuchMethodException ex) {
|
||||
Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an object to a String, and correctly for arrays.
|
||||
* @param obj an object
|
||||
* @return the tostring for the object.
|
||||
*/
|
||||
static String toString(Object obj) {
|
||||
return obj.getClass().isArray()
|
||||
? Arrays.toString((Object[]) obj)
|
||||
: Objects.toString(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleObject to test round trip.
|
||||
*/
|
||||
static class SimpleObject implements Serializable {
|
||||
private static final long serialVersionUID = 5217577841494640354L;
|
||||
|
||||
private int i = 0;
|
||||
private float f = 0.0f;
|
||||
|
||||
SimpleObject(int i, float f) {
|
||||
this.i = i;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
SimpleObject that = (SimpleObject) o;
|
||||
|
||||
if (i != that.i) return false;
|
||||
return Float.compare(that.f, f) == 0;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = i;
|
||||
result = 31 * result + (f != +0.0f ? Float.floatToIntBits(f) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleObject{" +
|
||||
"i=" + i +
|
||||
", f=" + f +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lookup the CORBA ObjectStreamClass instance for a class.
|
||||
* @param clazz the class
|
||||
* @return the CORBA ObjectStreamClass instance for the class
|
||||
*/
|
||||
static com.sun.corba.se.impl.io.ObjectStreamClass corbaLookup(Class<?> clazz) {
|
||||
Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
|
||||
|
||||
try {
|
||||
Method meth = oscClass.getDeclaredMethod("lookup", Class.class);
|
||||
meth.setAccessible(true);
|
||||
return (com.sun.corba.se.impl.io.ObjectStreamClass) meth.invoke(null, clazz);
|
||||
} catch (NoSuchMethodException noMeth) {
|
||||
throw new RuntimeException("missing method", noMeth);
|
||||
} catch (IllegalAccessException | InvocationTargetException rex) {
|
||||
throw new RuntimeException("invocation failed", rex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup aand invoke method on a serializable object via the CORBA ObjectStreamClass.
|
||||
* @param methodName method name
|
||||
* @param osc CORBA ObjectStreamClass
|
||||
* @param argClasses method arguments
|
||||
* @return the value returned from invoking the method
|
||||
*/
|
||||
static Object corbaMethod(String methodName, com.sun.corba.se.impl.io.ObjectStreamClass osc, Class<?>... argClasses) {
|
||||
Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
|
||||
|
||||
try {
|
||||
Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
|
||||
meth.setAccessible(true);
|
||||
return meth.invoke(osc);
|
||||
|
||||
} catch (NoSuchMethodException noMeth) {
|
||||
throw new RuntimeException("missing method" + osc.getName()
|
||||
+ "::" + methodName, noMeth);
|
||||
} catch (IllegalAccessException | InvocationTargetException rex) {
|
||||
throw new RuntimeException("invocation failed", rex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lookup aand invoke method on a serializable object via java.io.ObjectStreamClass.
|
||||
* @param methodName method name
|
||||
* @param osc java.io.ObjectStreamClass
|
||||
* @param argClasses method arguments
|
||||
* @return the value returned from invoking the method
|
||||
*/
|
||||
static Object baseMethod(String methodName, java.io.ObjectStreamClass osc, Class<?>... argClasses) {
|
||||
Class<?> oscClass = java.io.ObjectStreamClass.class;
|
||||
|
||||
try {
|
||||
Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
|
||||
meth.setAccessible(true);
|
||||
return meth.invoke(osc);
|
||||
|
||||
} catch (NoSuchMethodException noMeth) {
|
||||
throw new RuntimeException("missing method: " + osc.getName()
|
||||
+ "::" + methodName, noMeth);
|
||||
} catch (IllegalAccessException | InvocationTargetException rex) {
|
||||
throw new RuntimeException("invocation failed", rex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple echo interface to check serialization/deserialization.
|
||||
*/
|
||||
interface Echo extends Remote {
|
||||
Object echo(Object obj) throws RemoteException;
|
||||
}
|
||||
|
||||
static class Server extends PortableRemoteObject implements Echo {
|
||||
|
||||
public static final String serverID = "ObjectStreamTestServer";
|
||||
|
||||
private static Context initialNamingContext;
|
||||
|
||||
private static Server server;
|
||||
|
||||
public Server() throws RemoteException {
|
||||
super();
|
||||
}
|
||||
|
||||
public Object echo(Object obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
public static Context init() {
|
||||
if (initialNamingContext == null) {
|
||||
try {
|
||||
startOrbd();
|
||||
Thread.sleep(5000L); // Give it 5 seconds
|
||||
} catch (Exception eex) {
|
||||
throw new RuntimeException("Orbd", eex);
|
||||
}
|
||||
for (int i = 0; i < 1; i++) {
|
||||
try {
|
||||
Thread.sleep(1L);
|
||||
initialNamingContext = new InitialContext();
|
||||
server = new Server();
|
||||
initialNamingContext.rebind(serverID, server);
|
||||
} catch (CommunicationException | InterruptedException cex) {
|
||||
System.out.printf("retry #%d sec: ex: %s%n", i, cex);
|
||||
} catch (NamingException ex) {
|
||||
throw new RuntimeException("can't initialize naming context", ex);
|
||||
} catch (RemoteException rex) {
|
||||
throw new RuntimeException("can't initialize server", rex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (initialNamingContext == null) {
|
||||
Assert.fail("Can't initialize the Orb, no naming context");
|
||||
}
|
||||
return initialNamingContext;
|
||||
}
|
||||
}
|
||||
|
||||
static void startOrbd() throws Exception {
|
||||
System.out.println("\nStarting orbd with NS port 1050 ");
|
||||
JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd")
|
||||
.addToolArg("-ORBInitialHost").addToolArg("localhost")
|
||||
.addToolArg("-ORBInitialPort").addToolArg("1050");
|
||||
|
||||
System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand()));
|
||||
ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand());
|
||||
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
orbdProcess = pb.start();
|
||||
}
|
||||
|
||||
@AfterSuite
|
||||
static void killOrbd() throws Exception {
|
||||
if (orbdProcess != null) {
|
||||
orbdProcess.destroyForcibly();
|
||||
orbdProcess.waitFor();
|
||||
System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n",
|
||||
orbdProcess.getPid(), orbdProcess.exitValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Main can be used to run the tests from the command line with only testng.jar.
|
||||
@SuppressWarnings("raw_types")
|
||||
@Test(enabled = false)
|
||||
public static void main(String[] args) {
|
||||
Class<?>[] testclass = {ObjectStreamTest.class};
|
||||
TestNG testng = new TestNG();
|
||||
testng.setTestClasses(testclass);
|
||||
testng.run();
|
||||
}
|
||||
|
||||
}
|
||||
15
jdk/test/com/sun/corba/serialization/security.policy
Normal file
15
jdk/test/com/sun/corba/serialization/security.policy
Normal file
@ -0,0 +1,15 @@
|
||||
// Individual Permissions for ObjectStreamTest
|
||||
grant {
|
||||
// Permissions needed to run the test
|
||||
permission java.util.PropertyPermission "*", "read";
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
|
||||
permission java.net.SocketPermission "*", "resolve,connect,listen,accept";
|
||||
|
||||
// Permissions to allow ObjectTest to use IIOP ObjectStreamClass
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.corba.se.impl.io";
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
permission java.lang.RuntimePermission "accessDeclaredMembers";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
|
||||
permission java.io.SerializablePermission "enableSubclassImplementation";
|
||||
};
|
||||
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8137058
|
||||
* @summary Basic test for the unsupported newConstructorForSerialization
|
||||
* @modules jdk.unsupported
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import sun.reflect.ReflectionFactory;
|
||||
|
||||
public class NewConstructorForSerialization {
|
||||
|
||||
private static Constructor<?> getConstructor(Class<?> type)
|
||||
throws NoSuchMethodException
|
||||
{
|
||||
ReflectionFactory factory = ReflectionFactory.getReflectionFactory();
|
||||
Constructor<?> objectConstructor = type.getConstructor((Class[]) null);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<?> c = (Constructor<?>) factory
|
||||
.newConstructorForSerialization(type, objectConstructor);
|
||||
return c;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println(getConstructor(Object.class).newInstance());
|
||||
System.out.println(getConstructor(Foo.class).newInstance());
|
||||
System.out.println(getConstructor(Bar.class).newInstance());
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
public Foo() { }
|
||||
}
|
||||
|
||||
static class Bar extends Foo {
|
||||
public Bar() { }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import sun.reflect.ReflectionFactory;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.TestNG;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8137058 8164908
|
||||
* @run testng ReflectionFactoryTest
|
||||
* @run testng/othervm/policy=security.policy ReflectionFactoryTest
|
||||
* @summary Basic test for the unsupported ReflectionFactory
|
||||
* @modules jdk.unsupported
|
||||
*/
|
||||
|
||||
public class ReflectionFactoryTest {
|
||||
|
||||
// Initialized by init()
|
||||
static ReflectionFactory factory;
|
||||
|
||||
@DataProvider(name = "ClassConstructors")
|
||||
static Object[][] classConstructors() {
|
||||
return new Object[][] {
|
||||
{Object.class},
|
||||
{Foo.class},
|
||||
{Bar.class},
|
||||
};
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
static void init() {
|
||||
factory = ReflectionFactory.getReflectionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the correct Constructor is selected and run.
|
||||
* @param type type of object to create
|
||||
* @throws NoSuchMethodException - error
|
||||
* @throws InstantiationException - error
|
||||
* @throws IllegalAccessException - error
|
||||
* @throws InvocationTargetException - error
|
||||
*/
|
||||
@Test(dataProvider="ClassConstructors")
|
||||
static void testConstructor(Class<?> type)
|
||||
throws NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, InvocationTargetException
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<?> c = factory.newConstructorForSerialization(type);
|
||||
|
||||
Object o = c.newInstance();
|
||||
Assert.assertEquals(o.getClass(), type, "Instance is wrong type");
|
||||
if (o instanceof Foo) {
|
||||
Foo foo = (Foo)o;
|
||||
foo.check();
|
||||
}
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
private int foo;
|
||||
public Foo() {
|
||||
this.foo = 1;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "foo: " + foo;
|
||||
}
|
||||
|
||||
public void check() {
|
||||
int expectedFoo = 1;
|
||||
Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
|
||||
}
|
||||
}
|
||||
|
||||
static class Bar extends Foo implements Serializable {
|
||||
private int bar;
|
||||
public Bar() {
|
||||
this.bar = 1;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + ", bar: " + bar;
|
||||
}
|
||||
|
||||
public void check() {
|
||||
super.check();
|
||||
int expectedBar = 0;
|
||||
Assert.assertEquals(bar, expectedBar, "bar() constructor not run");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test newConstructorForExternalization returns the constructor and it can be called.
|
||||
* @throws NoSuchMethodException - error
|
||||
* @throws InstantiationException - error
|
||||
* @throws IllegalAccessException - error
|
||||
* @throws InvocationTargetException - error
|
||||
*/
|
||||
@Test
|
||||
static void newConstructorForExternalization()
|
||||
throws NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, InvocationTargetException {
|
||||
Constructor<?> cons = factory.newConstructorForExternalization(Ext.class);
|
||||
Ext ext = (Ext)cons.newInstance();
|
||||
Assert.assertEquals(ext.ext, 1, "Constructor not run");
|
||||
}
|
||||
|
||||
static class Ext implements Externalizable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
int ext;
|
||||
|
||||
public Ext() {
|
||||
ext = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
|
||||
}
|
||||
|
||||
@Test
|
||||
static void testReadWriteObjectForSerialization() throws Throwable {
|
||||
MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class);
|
||||
Assert.assertNotNull(readObjectMethod, "readObjectMethod not found");
|
||||
|
||||
MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class);
|
||||
Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found");
|
||||
|
||||
MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class);
|
||||
Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found");
|
||||
|
||||
MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class);
|
||||
Assert.assertNotNull(readResolveMethod, "readResolveMethod not found");
|
||||
|
||||
MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class);
|
||||
Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found");
|
||||
|
||||
byte[] data = null;
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
|
||||
Ser ser = new Ser();
|
||||
|
||||
writeReplaceMethod.invoke(ser);
|
||||
Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called");
|
||||
Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called");
|
||||
|
||||
writeObjectMethod.invoke(ser, oos);
|
||||
Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called");
|
||||
Assert.assertTrue(ser.writeObjectCalled, "writeObject not called");
|
||||
oos.flush();
|
||||
data = baos.toByteArray();
|
||||
}
|
||||
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
ObjectInputStream ois = new ObjectInputStream(bais)) {
|
||||
Ser ser2 = new Ser();
|
||||
|
||||
readObjectMethod.invoke(ser2, ois);
|
||||
Assert.assertTrue(ser2.readObjectCalled, "readObject not called");
|
||||
Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called");
|
||||
Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
|
||||
|
||||
readObjectNoDataMethod.invoke(ser2, ois);
|
||||
Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
|
||||
Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
|
||||
Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
|
||||
|
||||
readResolveMethod.invoke(ser2);
|
||||
Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
|
||||
Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
|
||||
Assert.assertTrue(ser2.readResolveCalled, "readResolve not called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
static void hasStaticInitializer() {
|
||||
boolean actual = factory.hasStaticInitializerForSerialization(Ser.class);
|
||||
Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong");
|
||||
}
|
||||
|
||||
static class Ser implements Serializable {
|
||||
private static final long serialVersionUID = 2L;
|
||||
static {
|
||||
// Define a static class initialization method
|
||||
}
|
||||
|
||||
boolean readObjectCalled = false;
|
||||
boolean readObjectNoDataCalled = false;
|
||||
boolean writeObjectCalled = false;
|
||||
boolean readResolveCalled = false;
|
||||
boolean writeReplaceCalled = false;
|
||||
|
||||
public Ser() {}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException {
|
||||
Assert.assertFalse(writeObjectCalled, "readObject called too many times");
|
||||
readObjectCalled = ois.readBoolean();
|
||||
}
|
||||
|
||||
private void readObjectNoData(ObjectInputStream ois) throws IOException {
|
||||
Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times");
|
||||
readObjectNoDataCalled = true;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
Assert.assertFalse(writeObjectCalled, "writeObject called too many times");
|
||||
writeObjectCalled = true;
|
||||
oos.writeBoolean(writeObjectCalled);
|
||||
}
|
||||
|
||||
private Object writeReplace() {
|
||||
Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times");
|
||||
writeReplaceCalled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
Assert.assertFalse(readResolveCalled, "readResolve called too many times");
|
||||
readResolveCalled = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the constructor of OptionalDataExceptions.
|
||||
*/
|
||||
@Test
|
||||
static void newOptionalDataException() {
|
||||
OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true);
|
||||
Assert.assertTrue(ode.eof, "eof wrong");
|
||||
ode = factory.newOptionalDataExceptionForSerialization(false);
|
||||
Assert.assertFalse(ode.eof, "eof wrong");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Main can be used to run the tests from the command line with only testng.jar.
|
||||
@SuppressWarnings("raw_types")
|
||||
@Test(enabled = false)
|
||||
public static void main(String[] args) {
|
||||
Class<?>[] testclass = {ReflectionFactoryTest.class};
|
||||
TestNG testng = new TestNG();
|
||||
testng.setTestClasses(testclass);
|
||||
testng.run();
|
||||
}
|
||||
}
|
||||
11
jdk/test/sun/reflect/ReflectionFactory/security.policy
Normal file
11
jdk/test/sun/reflect/ReflectionFactory/security.policy
Normal file
@ -0,0 +1,11 @@
|
||||
// Individual Permissions for ReflectionFactoryTest
|
||||
grant {
|
||||
// Permissions needed to run the test
|
||||
permission java.util.PropertyPermission "*", "read";
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
|
||||
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
permission java.lang.RuntimePermission "accessDeclaredMembers";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
|
||||
permission java.lang.RuntimePermission "reflectionFactoryAccess";
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user