summaryrefslogtreecommitdiff
path: root/external/ikvm/openjdk/java/lang/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'external/ikvm/openjdk/java/lang/reflect')
-rw-r--r--external/ikvm/openjdk/java/lang/reflect/Constructor.java6
-rw-r--r--external/ikvm/openjdk/java/lang/reflect/Field.java186
-rw-r--r--external/ikvm/openjdk/java/lang/reflect/Method.java6
-rw-r--r--external/ikvm/openjdk/java/lang/reflect/Proxy.java159
4 files changed, 287 insertions, 70 deletions
diff --git a/external/ikvm/openjdk/java/lang/reflect/Constructor.java b/external/ikvm/openjdk/java/lang/reflect/Constructor.java
index e62e87728d..b13d30a543 100644
--- a/external/ikvm/openjdk/java/lang/reflect/Constructor.java
+++ b/external/ikvm/openjdk/java/lang/reflect/Constructor.java
@@ -25,6 +25,7 @@
package java.lang.reflect;
+import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.ConstructorRepository;
@@ -501,15 +502,14 @@ public final
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = Reflection.getCallerClass(2);
-
+ Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
diff --git a/external/ikvm/openjdk/java/lang/reflect/Field.java b/external/ikvm/openjdk/java/lang/reflect/Field.java
index c796d20a1f..b2cb46b3f0 100644
--- a/external/ikvm/openjdk/java/lang/reflect/Field.java
+++ b/external/ikvm/openjdk/java/lang/reflect/Field.java
@@ -25,6 +25,7 @@
package java.lang.reflect;
+import sun.reflect.CallerSensitive;
import sun.reflect.FieldAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.FieldRepository;
@@ -34,7 +35,6 @@ import sun.reflect.generics.scope.ClassScope;
import java.lang.annotation.Annotation;
import java.util.Map;
import sun.reflect.annotation.AnnotationParser;
-import ikvm.internal.CallerID;
/**
@@ -365,11 +365,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).get(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).get(obj);
}
/**
@@ -394,11 +399,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public boolean getBoolean(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getBoolean(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getBoolean(obj);
}
/**
@@ -423,11 +433,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public byte getByte(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getByte(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getByte(obj);
}
/**
@@ -454,11 +469,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public char getChar(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getChar(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getChar(obj);
}
/**
@@ -485,11 +505,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public short getShort(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getShort(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getShort(obj);
}
/**
@@ -516,11 +541,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public int getInt(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getInt(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getInt(obj);
}
/**
@@ -547,11 +577,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public long getLong(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getLong(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getLong(obj);
}
/**
@@ -578,11 +613,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public float getFloat(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getFloat(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getFloat(obj);
}
/**
@@ -609,11 +649,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#get
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public double getDouble(Object obj)
throws IllegalArgumentException, IllegalAccessException
{
- return getFieldAccessor(obj, CallerID.getCallerID()).getDouble(obj);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ return getFieldAccessor(obj).getDouble(obj);
}
/**
@@ -682,11 +727,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).set(obj, value);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).set(obj, value);
}
/**
@@ -713,11 +763,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setBoolean(Object obj, boolean z)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setBoolean(obj, z);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setBoolean(obj, z);
}
/**
@@ -744,11 +799,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setByte(Object obj, byte b)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setByte(obj, b);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setByte(obj, b);
}
/**
@@ -775,11 +835,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setChar(Object obj, char c)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setChar(obj, c);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setChar(obj, c);
}
/**
@@ -806,11 +871,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setShort(Object obj, short s)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setShort(obj, s);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setShort(obj, s);
}
/**
@@ -837,11 +907,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setInt(Object obj, int i)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setInt(obj, i);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setInt(obj, i);
}
/**
@@ -868,11 +943,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setLong(Object obj, long l)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setLong(obj, l);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setLong(obj, l);
}
/**
@@ -899,11 +979,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setFloat(Object obj, float f)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setFloat(obj, f);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setFloat(obj, f);
}
/**
@@ -930,21 +1015,25 @@ class Field extends AccessibleObject implements Member {
* by this method fails.
* @see Field#set
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public void setDouble(Object obj, double d)
throws IllegalArgumentException, IllegalAccessException
{
- getFieldAccessor(obj, CallerID.getCallerID()).setDouble(obj, d);
+ if (!override) {
+ if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
+ checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ }
+ }
+ getFieldAccessor(obj).setDouble(obj, d);
}
- // Convenience routine which performs security checks
- private FieldAccessor getFieldAccessor(Object obj, CallerID callerID)
+ // security check is done before calling this method
+ private FieldAccessor getFieldAccessor(Object obj)
throws IllegalAccessException
{
- doSecurityCheck(obj, callerID);
boolean ov = override;
- FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor;
- return (a != null)? a : acquireFieldAccessor(ov);
+ FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
+ return (a != null) ? a : acquireFieldAccessor(ov);
}
// NOTE that there is no synchronization used here. It is correct
@@ -989,19 +1078,6 @@ class Field extends AccessibleObject implements Member {
}
}
- // NOTE: be very careful if you change the stack depth of this
- // routine. The depth of the "getCallerClass" call is hardwired so
- // that the compiler can have an easier time if this gets inlined.
- private void doSecurityCheck(Object obj, CallerID callerID) throws IllegalAccessException {
- if (!override) {
- if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = callerID.getCallerClass();
-
- checkAccess(caller, clazz, obj, modifiers);
- }
- }
- }
-
/*
* Utility routine to paper over array type names
*/
diff --git a/external/ikvm/openjdk/java/lang/reflect/Method.java b/external/ikvm/openjdk/java/lang/reflect/Method.java
index b1548d6bbe..dce789a4f1 100644
--- a/external/ikvm/openjdk/java/lang/reflect/Method.java
+++ b/external/ikvm/openjdk/java/lang/reflect/Method.java
@@ -26,6 +26,7 @@
package java.lang.reflect;
import ikvm.internal.CallerID;
+import sun.reflect.CallerSensitive;
import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;
import sun.reflect.generics.repository.MethodRepository;
@@ -578,15 +579,14 @@ public final
* @exception ExceptionInInitializerError if the initialization
* provoked by this method fails.
*/
- @ikvm.internal.HasCallerID
+ @CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- Class<?> caller = CallerID.getCallerID().getCallerClass();
-
+ Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
diff --git a/external/ikvm/openjdk/java/lang/reflect/Proxy.java b/external/ikvm/openjdk/java/lang/reflect/Proxy.java
index d4a391f738..3d9850e032 100644
--- a/external/ikvm/openjdk/java/lang/reflect/Proxy.java
+++ b/external/ikvm/openjdk/java/lang/reflect/Proxy.java
@@ -27,6 +27,9 @@ package java.lang.reflect;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -36,6 +39,10 @@ import java.util.Set;
import java.util.List;
import java.util.WeakHashMap;
import sun.misc.ProxyGenerator;
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+import sun.reflect.misc.ReflectUtil;
+import sun.security.util.SecurityConstants;
/**
* {@code Proxy} provides static methods for creating dynamic proxy
@@ -265,9 +272,67 @@ public class Proxy implements java.io.Serializable {
* @param h the invocation handler for this proxy instance
*/
protected Proxy(InvocationHandler h) {
+ doNewInstanceCheck();
this.h = h;
}
+ private static class ProxyAccessHelper {
+ // The permission is implementation specific.
+ static final Permission PROXY_PERMISSION =
+ new ReflectPermission("proxyConstructorNewInstance");
+ // These system properties are defined to provide a short-term
+ // workaround if customers need to disable the new security checks.
+ static final boolean allowNewInstance;
+ static final boolean allowNullLoader;
+ static {
+ allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
+ allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
+ }
+
+ private static boolean getBooleanProperty(final String key) {
+ String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key);
+ }
+ });
+ return Boolean.valueOf(s);
+ }
+
+ static boolean needsNewInstanceCheck(Class<?> proxyClass) {
+ if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
+ return false;
+ }
+
+ if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
+ for (Class<?> intf : proxyClass.getInterfaces()) {
+ if (!Modifier.isPublic(intf.getModifiers())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ /*
+ * Access check on a proxy class that implements any non-public interface.
+ *
+ * @throws SecurityException if a security manager exists, and
+ * the caller does not have the permission.
+ */
+ private void doNewInstanceCheck() {
+ SecurityManager sm = System.getSecurityManager();
+ Class<?> proxyClass = this.getClass();
+ if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
+ try {
+ sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
+ } catch (SecurityException e) {
+ throw new SecurityException("Not allowed to construct a Proxy "
+ + "instance that implements a non-public interface", e);
+ }
+ }
+ }
+
/**
* Returns the {@code java.lang.Class} object for a proxy class
* given a class loader and an array of interfaces. The proxy class
@@ -342,10 +407,59 @@ public class Proxy implements java.io.Serializable {
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
*/
+ @CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
throws IllegalArgumentException
{
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
+ }
+
+ return getProxyClass0(loader, interfaces);
+ }
+
+ /*
+ * Check permissions required to create a Proxy class.
+ *
+ * To define a proxy class, it performs the access checks as in
+ * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
+ * 1. "getClassLoader" permission check if loader == null
+ * 2. checkPackageAccess on the interfaces it implements
+ *
+ * To get a constructor and new instance of a proxy class, it performs
+ * the package access check on the interfaces it implements
+ * as in Class.getConstructor.
+ *
+ * If an interface is non-public, the proxy class must be defined by
+ * the defining loader of the interface. If the caller's class loader
+ * is not the same as the defining loader of the interface, the VM
+ * will throw IllegalAccessError when the generated proxy class is
+ * being defined via the defineClass0 method.
+ */
+ private static void checkProxyAccess(Class<?> caller,
+ ClassLoader loader,
+ Class<?>... interfaces)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ ClassLoader ccl = caller.getClassLoader();
+ if (loader == null && ccl != null) {
+ if (!ProxyAccessHelper.allowNullLoader) {
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+ }
+ }
+ ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
+ }
+ }
+
+ /**
+ * Generate a proxy class. Must call the checkProxyAccess method
+ * to perform permission checks before calling this.
+ */
+ private static Class<?> getProxyClass0(ClassLoader loader,
+ Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
@@ -497,8 +611,9 @@ public class Proxy implements java.io.Serializable {
}
}
- if (proxyPkg == null) { // if no non-public proxy interfaces,
- proxyPkg = ""; // use the unnamed package
+ if (proxyPkg == null) {
+ // if no non-public proxy interfaces, use com.sun.proxy package
+ proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
generate: do
@@ -592,6 +707,7 @@ generate: do
* if the invocation handler, {@code h}, is
* {@code null}
*/
+ @CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
@@ -601,25 +717,50 @@ generate: do
throw new NullPointerException();
}
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
+ }
+
/*
* Look up or generate the designated proxy class.
*/
- Class<?> cl = getProxyClass(loader, interfaces);
+ Class<?> cl = getProxyClass0(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
- Constructor cons = cl.getConstructor(constructorParams);
- return cons.newInstance(new Object[] { h });
+ final Constructor<?> cons = cl.getConstructor(constructorParams);
+ final InvocationHandler ih = h;
+ if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
+ // create proxy instance with doPrivilege as the proxy class may
+ // implement non-public interfaces that requires a special permission
+ return AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ return newInstance(cons, ih);
+ }
+ });
+ } else {
+ return newInstance(cons, ih);
+ }
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
- } catch (IllegalAccessException e) {
- throw new InternalError(e.toString());
- } catch (InstantiationException e) {
+ }
+ }
+
+ private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
+ try {
+ return cons.newInstance(new Object[] {h} );
+ } catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
- throw new InternalError(e.toString());
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ } else {
+ throw new InternalError(t.toString());
+ }
}
}