--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 15:06:17 2013 -0400
@@ -28,7 +28,6 @@
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;
@@ -53,16 +52,14 @@
* <p>To create a proxy for some interface {@code Foo}:
* <pre>
* InvocationHandler handler = new MyInvocationHandler(...);
- * Class proxyClass = Proxy.getProxyClass(
- * Foo.class.getClassLoader(), new Class[] { Foo.class });
- * Foo f = (Foo) proxyClass.
- * getConstructor(new Class[] { InvocationHandler.class }).
- * newInstance(new Object[] { handler });
+ * Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ * Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ * newInstance(handler);
* </pre>
* or more simply:
* <pre>
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- * new Class[] { Foo.class },
+ * new Class<?>[] { Foo.class },
* handler);
* </pre>
*
@@ -91,7 +88,11 @@
* <p>A proxy class has the following properties:
*
* <ul>
- * <li>Proxy classes are public, final, and not abstract.
+ * <li>Proxy classes are <em>public, final, and not abstract</em> if
+ * all proxy interfaces are public.</li>
+ *
+ * <li>Proxy classes are <em>non-public, final, and not abstract</em> if
+ * any of the proxy interfaces is non-public.</li>
*
* <li>The unqualified name of a proxy class is unspecified. The space
* of class names that begin with the string {@code "$Proxy"}
@@ -273,76 +274,17 @@
* @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 (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
- // all proxy interfaces are public
- return false;
- }
- 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
* will be defined by the specified class loader and will implement
- * all of the supplied interfaces. If a proxy class for the same
- * permutation of interfaces has already been defined by the class
- * loader, then the existing proxy class will be returned; otherwise,
+ * all of the supplied interfaces. If any of the given interfaces
+ * is non-public, the proxy class will be non-public. If a proxy class
+ * for the same permutation of interfaces has already been defined by the
+ * class loader, then the existing proxy class will be returned; otherwise,
* a proxy class for those interfaces will be generated dynamically
* and defined by the class loader.
*
@@ -407,6 +349,22 @@
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
+ * @throws SecurityException if a security manager, <em>s</em>, is present
+ * and any of the following conditions is met:
+ * <ul>
+ * <li> the given {@code loader} is {@code null} and
+ * the caller's class loader is not {@code null} and the
+ * invocation of {@link SecurityManager#checkPermission
+ * s.checkPermission} with
+ * {@code RuntimePermission("getClassLoader")} permission
+ * denies access.</li>
+ * <li> the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to any one of the
+ * given proxy interfaces.</li>
+ * </ul>
+
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
*/
@@ -449,9 +407,7 @@
if (sm != null) {
ClassLoader ccl = caller.getClassLoader();
if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
- if (!ProxyAccessHelper.allowNullLoader) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
@@ -593,6 +549,7 @@
try {
String proxyPkg = null; // package to define proxy class in
+ int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
@@ -602,6 +559,7 @@
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
+ accessFlags = Modifier.FINAL;
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
@@ -637,7 +595,7 @@
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
- proxyName, interfaces);
+ proxyName, interfaces, accessFlags);
try {
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
@@ -678,12 +636,7 @@
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
- * handler. This method is equivalent to:
- * <pre>
- * Proxy.getProxyClass(loader, interfaces).
- * getConstructor(new Class[] { InvocationHandler.class }).
- * newInstance(new Object[] { handler });
- * </pre>
+ * handler.
*
* <p>{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
@@ -699,6 +652,27 @@
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
+ * @throws SecurityException if a security manager, <em>s</em>, is present
+ * and any of the following conditions is met:
+ * <ul>
+ * <li> the given {@code loader} is {@code null} and
+ * the caller's class loader is not {@code null} and the
+ * invocation of {@link SecurityManager#checkPermission
+ * s.checkPermission} with
+ * {@code RuntimePermission("getClassLoader")} permission
+ * denies access;</li>
+ * <li> the caller's class loader is not the same as or an
+ * ancestor of the class loader for the current class and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to any one of the
+ * given proxy interfaces.</li>
+ * <li> any of the given proxy interfaces is non-public and the
+ * caller class is not in the same {@linkplain Package runtime package}
+ * as the non-public interface and the invocation of
+ * {@link SecurityManager#checkPermission s.checkPermission} with
+ * {@code ReflectPermission("newProxyInPackage.{package name}")}
+ * permission denies access.</li>
+ * </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
@@ -728,24 +702,61 @@
* Invoke its constructor with the designated invocation handler.
*/
try {
+ if (sm != null) {
+ checkNewProxyPermission(Reflection.getCallerClass(), cl);
+ }
+
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);
+ if (!Modifier.isPublic(cl.getModifiers())) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ cons.setAccessible(true);
+ return null;
}
});
+ }
+ return cons.newInstance(new Object[]{h});
+ } catch (IllegalAccessException|InstantiationException e) {
+ throw new InternalError(e.toString(), e);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
} else {
- return newInstance(cons, ih);
+ throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
+ private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ String pcn = proxyClass.getName();
+ if (pcn.startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
+ // all proxy interfaces are public
+ return;
+ }
+
+ ClassLoader ccl = caller.getClassLoader();
+ ClassLoader pcl = proxyClass.getClassLoader();
+
+ // do permission check if the caller is in a different runtime package
+ // of the proxy class
+ int n = pcn.lastIndexOf('.');
+ String pkg = (n == -1) ? "" : pcn.substring(0, n);
+
+ n = caller.getName().lastIndexOf('.');
+ String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
+
+ if (pcl != ccl || !pkg.equals(callerPkg)) {
+ sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
+ }
+ }
+ }
+
private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
try {
return cons.newInstance(new Object[] {h} );
--- a/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java Wed Apr 17 15:06:17 2013 -0400
@@ -26,12 +26,7 @@
package java.lang.reflect;
/**
- * The Permission class for reflective operations. A
- * ReflectPermission is a <em>named permission</em> and has no
- * actions. The only name currently defined is {@code suppressAccessChecks},
- * which allows suppressing the standard Java language access checks
- * -- for public, default (package) access, protected, and private
- * members -- performed by reflected objects at their point of use.
+ * The Permission class for reflective operations.
* <P>
* The following table
* provides a summary description of what the permission allows,
@@ -47,11 +42,21 @@
*
* <tr>
* <td>suppressAccessChecks</td>
- * <td>ability to access
- * fields and invoke methods in a class. Note that this includes
- * not only public, but protected and private fields and methods as well.</td>
+ * <td>ability to suppress the standard Java language access checks
+ * on fields and methods in a class; allow access not only public members
+ * but also allow access to default (package) access, protected,
+ * and private members.</td>
* <td>This is dangerous in that information (possibly confidential) and
- * methods normally unavailable would be accessible to malicious code.</td>
+ * methods normally unavailable would be accessible to malicious code.</td>
+ * </tr>
+ * <tr>
+ * <td>newProxyInPackage.{package name}</td>
+ * <td>ability to create a proxy instance in the specified package of which
+ * the non-public interface that the proxy class implements.</td>
+ * <td>This gives code access to classes in packages to which it normally
+ * does not have access and the dynamic proxy class is in the system
+ * protection domain. Malicious code may use these classes to
+ * help in its attempt to compromise security in the system.</td>
* </tr>
*
* </table>
@@ -63,6 +68,7 @@
* @see Field#set
* @see Method#invoke
* @see Constructor#newInstance
+ * @see Proxy#newProxyInstance
*
* @since 1.2
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/DoubleSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012, 2013, 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.
+ */
+package java.util;
+
+import java.util.function.DoubleConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and
+ * average.
+ *
+ * <p>This class is designed to work with (though does not require)
+ * {@linkplain java.util.stream streams}. For example, you can compute
+ * summary statistics on a stream of doubles with:
+ * <pre> {@code
+ * DoubleSummaryStatistics stats = doubleStream.collect(DoubleSummaryStatistics::new,
+ * DoubleSummaryStatistics::accept,
+ * DoubleSummaryStatistics::combine);
+ * }</pre>
+ *
+ * <p>{@code DoubleSummaryStatistics} can be used as a
+ * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction}
+ * target for a {@linkplain java.util.stream.Stream stream}. For example:
+ *
+ * <pre> {@code
+ * DoubleSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toDoubleSummaryStatistics(Person::getWeight));
+ *}</pre>
+ *
+ * This computes, in a single pass, the count of people, as well as the minimum,
+ * maximum, sum, and average of their weights.
+ *
+ * @implNote This implementation is not thread safe. However, it is safe to use
+ * {@link java.util.stream.Collectors#toDoubleSummaryStatistics(java.util.function.ToDoubleFunction)
+ * Collectors.toDoubleStatistics()} on a parallel stream, because the parallel
+ * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
+ * provides the necessary partitioning, isolation, and merging of results for
+ * safe and efficient parallel execution.
+ * @since 1.8
+ */
+public class DoubleSummaryStatistics implements DoubleConsumer {
+ private long count;
+ private double sum;
+ private double min = Double.POSITIVE_INFINITY;
+ private double max = Double.NEGATIVE_INFINITY;
+
+ /**
+ * Construct an empty instance with zero count, zero sum,
+ * {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
+ * max and zero average.
+ */
+ public DoubleSummaryStatistics() { }
+
+ /**
+ * Records another value into the summary information.
+ *
+ * @param value the input value
+ */
+ @Override
+ public void accept(double value) {
+ ++count;
+ sum += value;
+ min = Math.min(min, value);
+ max = Math.max(max, value);
+ }
+
+ /**
+ * Combines the state of another {@code DoubleSummaryStatistics} into this
+ * one.
+ *
+ * @param other another {@code DoubleSummaryStatistics}
+ * @throws NullPointerException if {@code other} is null
+ */
+ public void combine(DoubleSummaryStatistics other) {
+ count += other.count;
+ sum += other.sum;
+ min = Math.min(min, other.min);
+ max = Math.max(max, other.max);
+ }
+
+ /**
+ * Return the count of values recorded.
+ *
+ * @return the count of values
+ */
+ public final long getCount() {
+ return count;
+ }
+
+ /**
+ * Returns the sum of values recorded, or zero if no values have been
+ * recorded. The sum returned can vary depending upon the order in which
+ * values are recorded. This is due to accumulated rounding error in
+ * addition of values of differing magnitudes. Values sorted by increasing
+ * absolute magnitude tend to yield more accurate results. If any recorded
+ * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
+ * sum will be {@code NaN}.
+ *
+ * @return the sum of values, or zero if none
+ */
+ public final double getSum() {
+ return sum;
+ }
+
+ /**
+ * Returns the minimum recorded value, {@code Double.NaN} if any recorded
+ * value was NaN or {@code Double.POSITIVE_INFINITY} if no values were
+ * recorded. Unlike the numerical comparison operators, this method
+ * considers negative zero to be strictly smaller than positive zero.
+ *
+ * @return the minimum recorded value, {@code Double.NaN} if any recorded
+ * value was NaN or {@code Double.POSITIVE_INFINITY} if no values were
+ * recorded
+ */
+ public final double getMin() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum recorded value, {@code Double.NaN} if any recorded
+ * value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were
+ * recorded. Unlike the numerical comparison operators, this method
+ * considers negative zero to be strictly smaller than positive zero.
+ *
+ * @return the maximum recorded value, {@code Double.NaN} if any recorded
+ * value was NaN or {@code Double.NEGATIVE_INFINITY} if no values were
+ * recorded
+ */
+ public final double getMax() {
+ return max;
+ }
+
+ /**
+ * Returns the average of values recorded, or zero if no values have been
+ * recorded. The average returned can vary depending upon the order in
+ * which values are recorded. This is due to accumulated rounding error in
+ * addition of values of differing magnitudes. Values sorted by increasing
+ * absolute magnitude tend to yield more accurate results. If any recorded
+ * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
+ * average will be {@code NaN}.
+ *
+ * @return the average of values, or zero if none
+ */
+ public final double getAverage() {
+ return getCount() > 0 ? getSum() / getCount() : 0.0d;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Returns a non-empty string representation of this object suitable for
+ * debugging. The exact presentation format is unspecified and may vary
+ * between implementations and versions.
+ */
+ @Override
+ public String toString() {
+ return String.format(
+ "%s{count=%d, sum=%f, min=%f, average=%f, max=%f}",
+ this.getClass().getSimpleName(),
+ getCount(),
+ getSum(),
+ getMin(),
+ getAverage(),
+ getMax());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/IntSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 2013, 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.
+ */
+package java.util;
+
+import java.util.function.IntConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and
+ * average.
+ *
+ * <p>This class is designed to work with (though does not require)
+ * {@linkplain java.util.stream streams}. For example, you can compute
+ * summary statistics on a stream of ints with:
+ * <pre> {@code
+ * IntSummaryStatistics stats = intStream.collect(IntSummaryStatistics::new,
+ * IntSummaryStatistics::accept,
+ * IntSummaryStatistics::combine);
+ * }</pre>
+ *
+ * <p>{@code IntSummaryStatistics} can be used as a
+ * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction}
+ * target for a {@linkplain java.util.stream.Stream stream}. For example:
+ *
+ * <pre> {@code
+ * IntSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toIntSummaryStatistics(Person::getDependents));
+ *}</pre>
+ *
+ * This computes, in a single pass, the count of people, as well as the minimum,
+ * maximum, sum, and average of their number of dependents.
+ *
+ * @implNote This implementation is not thread safe. However, it is safe to use
+ * {@link java.util.stream.Collectors#toIntSummaryStatistics(java.util.function.ToIntFunction)
+ * Collectors.toIntStatistics()} on a parallel stream, because the parallel
+ * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
+ * provides the necessary partitioning, isolation, and merging of results for
+ * safe and efficient parallel execution.
+ *
+ * <p>This implementation does not check for overflow of the sum.
+ * @since 1.8
+ */
+public class IntSummaryStatistics implements IntConsumer {
+ private long count;
+ private long sum;
+ private int min = Integer.MAX_VALUE;
+ private int max = Integer.MIN_VALUE;
+
+ /**
+ * Construct an empty instance with zero count, zero sum,
+ * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
+ * average.
+ */
+ public IntSummaryStatistics() { }
+
+ /**
+ * Records a new value into the summary information
+ *
+ * @param value the input value
+ */
+ @Override
+ public void accept(int value) {
+ ++count;
+ sum += value;
+ min = Math.min(min, value);
+ max = Math.max(max, value);
+ }
+
+ /**
+ * Combines the state of another {@code IntSummaryStatistics} into this one.
+ *
+ * @param other another {@code IntSummaryStatistics}
+ * @throws NullPointerException if {@code other} is null
+ */
+ public void combine(IntSummaryStatistics other) {
+ count += other.count;
+ sum += other.sum;
+ min = Math.min(min, other.min);
+ max = Math.max(max, other.max);
+ }
+
+ /**
+ * Returns the count of values recorded.
+ *
+ * @return the count of values
+ */
+ public final long getCount() {
+ return count;
+ }
+
+ /**
+ * Returns the sum of values recorded, or zero if no values have been
+ * recorded.
+ *
+ * @return the sum of values, or zero if none
+ */
+ public final long getSum() {
+ return sum;
+ }
+
+ /**
+ * Returns the minimum value recorded, or {@code Integer.MAX_VALUE} if no
+ * values have been recorded.
+ *
+ * @return the minimum value, or {@code Integer.MAX_VALUE} if none
+ */
+ public final int getMin() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum value recorded, or {@code Integer.MIN_VALUE} if no
+ * values have been recorded.
+ *
+ * @return the maximum value, or {@code Integer.MIN_VALUE} if none
+ */
+ public final int getMax() {
+ return max;
+ }
+
+ /**
+ * Returns the average of values recorded, or zero if no values have been
+ * recorded.
+ *
+ * @return the average of values, or zero if none
+ */
+ public final double getAverage() {
+ return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
+ }
+
+ @Override
+ /**
+ * {@inheritDoc}
+ *
+ * Returns a non-empty string representation of this object suitable for
+ * debugging. The exact presentation format is unspecified and may vary
+ * between implementations and versions.
+ */
+ public String toString() {
+ return String.format(
+ "%s{count=%d, sum=%d, min=%d, average=%d, max=%d}",
+ this.getClass().getSimpleName(),
+ getCount(),
+ getSum(),
+ getMin(),
+ getAverage(),
+ getMax());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/LongSummaryStatistics.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2012, 2013, 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.
+ */
+package java.util;
+
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A state object for collecting statistics such as count, min, max, sum, and
+ * average.
+ *
+ * <p>This class is designed to work with (though does not require)
+ * {@linkplain java.util.stream streams}. For example, you can compute
+ * summary statistics on a stream of longs with:
+ * <pre> {@code
+ * LongSummaryStatistics stats = longStream.collect(LongSummaryStatistics::new,
+ * LongSummaryStatistics::accept,
+ * LongSummaryStatistics::combine);
+ * }</pre>
+ *
+ * <p>{@code LongSummaryStatistics} can be used as a
+ * {@linkplain java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduction}
+ * target for a {@linkplain java.util.stream.Stream stream}. For example:
+ *
+ * <pre> {@code
+ * LongSummaryStatistics stats = people.stream()
+ * .collect(Collectors.toLongSummaryStatistics(Person::getAge));
+ *}</pre>
+ *
+ * This computes, in a single pass, the count of people, as well as the minimum,
+ * maximum, sum, and average of their ages in milliseconds.
+ *
+ * @implNote This implementation is not thread safe. However, it is safe to use
+ * {@link java.util.stream.Collectors#toLongSummaryStatistics(java.util.function.ToLongFunction)
+ * Collectors.toLongStatistics()} on a parallel stream, because the parallel
+ * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
+ * provides the necessary partitioning, isolation, and merging of results for
+ * safe and efficient parallel execution.
+ *
+ * <p>This implementation does not check for overflow of the sum.
+ * @since 1.8
+ */
+public class LongSummaryStatistics implements LongConsumer, IntConsumer {
+ private long count;
+ private long sum;
+ private long min = Long.MAX_VALUE;
+ private long max = Long.MIN_VALUE;
+
+ /**
+ * Construct an empty instance with zero count, zero sum,
+ * {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
+ * average.
+ */
+ public LongSummaryStatistics() { }
+
+ /**
+ * Records a new {@code int} value into the summary information.
+ *
+ * @param value the input value
+ */
+ @Override
+ public void accept(int value) {
+ accept((long) value);
+ }
+
+ /**
+ * Records a new {@code long} value into the summary information.
+ *
+ * @param value the input value
+ */
+ @Override
+ public void accept(long value) {
+ ++count;
+ sum += value;
+ min = Math.min(min, value);
+ max = Math.max(max, value);
+ }
+
+ /**
+ * Combines the state of another {@code LongSummaryStatistics} into this
+ * one.
+ *
+ * @param other another {@code LongSummaryStatistics}
+ * @throws NullPointerException if {@code other} is null
+ */
+ public void combine(LongSummaryStatistics other) {
+ count += other.count;
+ sum += other.sum;
+ min = Math.min(min, other.min);
+ max = Math.max(max, other.max);
+ }
+
+ /**
+ * Returns the count of values recorded.
+ *
+ * @return the count of values
+ */
+ public final long getCount() {
+ return count;
+ }
+
+ /**
+ * Returns the sum of values recorded, or zero if no values have been
+ * recorded.
+ *
+ * @return the sum of values, or zero if none
+ */
+ public final long getSum() {
+ return sum;
+ }
+
+ /**
+ * Returns the minimum value recorded, or {@code Long.MAX_VALUE} if no
+ * values have been recorded.
+ *
+ * @return the minimum value, or {@code Long.MAX_VALUE} if none
+ */
+ public final long getMin() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum value recorded, or {@code Long.MIN_VALUE} if no
+ * values have been recorded
+ *
+ * @return the maximum value, or {@code Long.MIN_VALUE} if none
+ */
+ public final long getMax() {
+ return max;
+ }
+
+ /**
+ * Returns the average of values recorded, or zero if no values have been
+ * recorded.
+ *
+ * @return The average of values, or zero if none
+ */
+ public final double getAverage() {
+ return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
+ }
+
+ @Override
+ /**
+ * {@inheritDoc}
+ *
+ * Returns a non-empty string representation of this object suitable for
+ * debugging. The exact presentation format is unspecified and may vary
+ * between implementations and versions.
+ */
+ public String toString() {
+ return String.format(
+ "%s{count=%d, sum=%d, min=%d, average=%d, max=%d}",
+ this.getClass().getSimpleName(),
+ getCount(),
+ getSum(),
+ getMin(),
+ getAverage(),
+ getMax());
+ }
+}
--- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Apr 17 15:06:17 2013 -0400
@@ -27,11 +27,14 @@
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
-import java.io.FileOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -314,12 +317,25 @@
"sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
/**
- * Generate a proxy class given a name and a list of proxy interfaces.
+ * Generate a public proxy class given a name and a list of proxy interfaces.
*/
public static byte[] generateProxyClass(final String name,
- Class[] interfaces)
+ Class<?>[] interfaces) {
+ return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
+ }
+
+ /**
+ * Generate a proxy class given a name and a list of proxy interfaces.
+ *
+ * @param name the class name of the proxy class
+ * @param interfaces proxy interfaces
+ * @param accessFlags access flags of the proxy class
+ */
+ public static byte[] generateProxyClass(final String name,
+ Class<?>[] interfaces,
+ int accessFlags)
{
- ProxyGenerator gen = new ProxyGenerator(name, interfaces);
+ ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
final byte[] classFile = gen.generateClassFile();
if (saveGeneratedFiles) {
@@ -327,10 +343,16 @@
new java.security.PrivilegedAction<Void>() {
public Void run() {
try {
- FileOutputStream file =
- new FileOutputStream(dotToSlash(name) + ".class");
- file.write(classFile);
- file.close();
+ int i = name.lastIndexOf('.');
+ Path path;
+ if (i > 0) {
+ Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+ Files.createDirectories(dir);
+ path = dir.resolve(name.substring(i+1, name.length()) + ".class");
+ } else {
+ path = Paths.get(name + ".class");
+ }
+ Files.write(path, classFile);
return null;
} catch (IOException e) {
throw new InternalError(
@@ -364,21 +386,23 @@
/** proxy interfaces */
private Class[] interfaces;
+ /** proxy class access flags */
+ private int accessFlags;
+
/** constant pool of class being generated */
private ConstantPool cp = new ConstantPool();
/** FieldInfo struct for each field of generated class */
- private List<FieldInfo> fields = new ArrayList<FieldInfo>();
+ private List<FieldInfo> fields = new ArrayList<>();
/** MethodInfo struct for each method of generated class */
- private List<MethodInfo> methods = new ArrayList<MethodInfo>();
+ private List<MethodInfo> methods = new ArrayList<>();
/**
* maps method signature string to list of ProxyMethod objects for
* proxy methods with that signature
*/
- private Map<String, List<ProxyMethod>> proxyMethods =
- new HashMap<String,List<ProxyMethod>>();
+ private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
/** count of ProxyMethod objects added to proxyMethods */
private int proxyMethodCount = 0;
@@ -390,9 +414,10 @@
* A ProxyGenerator object contains the state for the ongoing
* generation of a particular proxy class.
*/
- private ProxyGenerator(String className, Class[] interfaces) {
+ private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
this.className = className;
this.interfaces = interfaces;
+ this.accessFlags = accessFlags;
}
/**
@@ -422,10 +447,9 @@
* earlier interfaces precedence over later ones with duplicate
* methods.
*/
- for (int i = 0; i < interfaces.length; i++) {
- Method[] methods = interfaces[i].getMethods();
- for (int j = 0; j < methods.length; j++) {
- addProxyMethod(methods[j], interfaces[i]);
+ for (Class<?> intf : interfaces) {
+ for (Method m : intf.getMethods()) {
+ addProxyMethod(m, intf);
}
}
@@ -480,8 +504,8 @@
*/
cp.getClass(dotToSlash(className));
cp.getClass(superclassName);
- for (int i = 0; i < interfaces.length; i++) {
- cp.getClass(dotToSlash(interfaces[i].getName()));
+ for (Class<?> intf: interfaces) {
+ cp.getClass(dotToSlash(intf.getName()));
}
/*
@@ -508,7 +532,7 @@
cp.write(dout); // (write constant pool)
// u2 access_flags;
- dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
+ dout.writeShort(accessFlags);
// u2 this_class;
dout.writeShort(cp.getClass(dotToSlash(className)));
// u2 super_class;
@@ -517,9 +541,9 @@
// u2 interfaces_count;
dout.writeShort(interfaces.length);
// u2 interfaces[interfaces_count];
- for (int i = 0; i < interfaces.length; i++) {
+ for (Class<?> intf : interfaces) {
dout.writeShort(cp.getClass(
- dotToSlash(interfaces[i].getName())));
+ dotToSlash(intf.getName())));
}
// u2 fields_count;
@@ -576,7 +600,7 @@
* compatibly with the throws clauses of both
* overridden methods.
*/
- List<Class<?>> legalExceptions = new ArrayList<Class<?>>();
+ List<Class<?>> legalExceptions = new ArrayList<>();
collectCompatibleTypes(
exceptionTypes, pm.exceptionTypes, legalExceptions);
collectCompatibleTypes(
@@ -588,7 +612,7 @@
}
}
} else {
- sigmethods = new ArrayList<ProxyMethod>(3);
+ sigmethods = new ArrayList<>(3);
proxyMethods.put(sig, sigmethods);
}
sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
@@ -618,7 +642,7 @@
* List of return types that are not yet known to be
* assignable from ("covered" by) any of the others.
*/
- LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<Class<?>>();
+ LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
nextNewReturnType:
for (ProxyMethod pm : methods) {
@@ -833,8 +857,8 @@
// u2 number_of_exceptions;
out.writeShort(declaredExceptions.length);
// u2 exception_index_table[number_of_exceptions];
- for (int i = 0; i < declaredExceptions.length; i++) {
- out.writeShort(declaredExceptions[i]);
+ for (short value : declaredExceptions) {
+ out.writeShort(value);
}
}
@@ -1525,11 +1549,11 @@
Class<?>[] with,
List<Class<?>> list)
{
- for (int i = 0; i < from.length; i++) {
- if (!list.contains(from[i])) {
- for (int j = 0; j < with.length; j++) {
- if (with[j].isAssignableFrom(from[i])) {
- list.add(from[i]);
+ for (Class<?> fc: from) {
+ if (!list.contains(fc)) {
+ for (Class<?> wc: with) {
+ if (wc.isAssignableFrom(fc)) {
+ list.add(fc);
break;
}
}
@@ -1559,15 +1583,14 @@
* need to be caught.
*/
private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
- List<Class<?>> uniqueList = new ArrayList<Class<?>>();
+ List<Class<?>> uniqueList = new ArrayList<>();
// unique exceptions to catch
uniqueList.add(Error.class); // always catch/rethrow these
uniqueList.add(RuntimeException.class);
nextException:
- for (int i = 0; i < exceptions.length; i++) {
- Class<?> ex = exceptions[i];
+ for (Class<?> ex: exceptions) {
if (ex.isAssignableFrom(Throwable.class)) {
/*
* If Throwable is declared to be thrown by the proxy method,
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Wed Apr 17 15:06:17 2013 -0400
@@ -30,6 +30,8 @@
import java.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import sun.reflect.ConstantPool;
import sun.reflect.generics.parser.SignatureParser;
@@ -253,12 +255,15 @@
* Returns an annotation of the given type backed by the given
* member -> value map.
*/
- public static Annotation annotationForMap(
- Class<? extends Annotation> type, Map<String, Object> memberValues)
+ public static Annotation annotationForMap(final Class<? extends Annotation> type,
+ final Map<String, Object> memberValues)
{
- return (Annotation) Proxy.newProxyInstance(
- type.getClassLoader(), new Class<?>[] { type },
- new AnnotationInvocationHandler(type, memberValues));
+ return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
+ public Annotation run() {
+ return (Annotation) Proxy.newProxyInstance(
+ type.getClassLoader(), new Class<?>[] { type },
+ new AnnotationInvocationHandler(type, memberValues));
+ }});
}
/**
--- a/jdk/src/share/classes/sun/rmi/server/Util.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/sun/rmi/server/Util.java Wed Apr 17 15:06:17 2013 -0400
@@ -48,6 +48,7 @@
import java.security.MessageDigest;
import java.security.DigestOutputStream;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
@@ -140,17 +141,20 @@
return createStub(remoteClass, clientRef);
}
- ClassLoader loader = implClass.getClassLoader();
- Class[] interfaces = getRemoteInterfaces(implClass);
- InvocationHandler handler =
+ final ClassLoader loader = implClass.getClassLoader();
+ final Class[] interfaces = getRemoteInterfaces(implClass);
+ final InvocationHandler handler =
new RemoteObjectInvocationHandler(clientRef);
/* REMIND: private remote interfaces? */
try {
- return (Remote) Proxy.newProxyInstance(loader,
- interfaces,
- handler);
+ return AccessController.doPrivileged(new PrivilegedAction<Remote>() {
+ public Remote run() {
+ return (Remote) Proxy.newProxyInstance(loader,
+ interfaces,
+ handler);
+ }});
} catch (IllegalArgumentException e) {
throw new StubNotFoundException("unable to create proxy", e);
}
--- a/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java Wed Apr 17 15:06:17 2013 -0400
@@ -130,8 +130,12 @@
*/
@SuppressWarnings("unchecked")
public <T extends Provider> T newProxyInstance() {
- return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
- new Class<?>[] { providerType }, this);
+ final InvocationHandler ih = this;
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
+ new Class<?>[] { providerType }, ih);
+ }});
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013, 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.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.ReflectPermission;
+import java.security.AccessControlException;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.security.SecurityPermission;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 8004260
+ * @summary Test proxy classes that implement non-public interface
+ *
+ * @build p.Foo
+ * @run main/othervm NonPublicProxyClass grant
+ * @run main/othervm NonPublicProxyClass deny
+ * @run main/othervm NonPublicProxyClass
+ */
+public class NonPublicProxyClass {
+ public interface PublicInterface {
+ void foo();
+ }
+ interface NonPublicInterface {
+ void bar();
+ }
+
+ public static void main(String[] args) throws Exception {
+ ClassLoader loader = ClassLoader.getSystemClassLoader();
+ Class<?> zipConstantsClass = Class.forName("java.util.zip.ZipConstants", false, null);
+ Class<?> fooClass = Class.forName("p.Foo");
+
+ NonPublicProxyClass test1 =
+ new NonPublicProxyClass(loader, PublicInterface.class, NonPublicInterface.class);
+ NonPublicProxyClass test2 =
+ new NonPublicProxyClass(loader, fooClass, PublicInterface.class);
+ NonPublicProxyClass test3 =
+ new NonPublicProxyClass(null, zipConstantsClass);
+
+ if (args.length == 1) {
+ switch (args[0]) {
+ case "grant": Policy.setPolicy(new NewInstancePolicy(true));
+ break;
+ case "deny" : Policy.setPolicy(new NewInstancePolicy(false));
+ break;
+ default: throw new IllegalArgumentException(args[0]);
+ }
+ System.setSecurityManager(new SecurityManager());
+ }
+
+ test1.run();
+ test2.run();
+ test3.run();
+ System.out.format("Test passed: security %s%n",
+ (args.length == 0 ? "manager not installed" : Policy.getPolicy()));
+ }
+
+ private final ClassLoader loader;
+ private final Class<?>[] interfaces;
+ private final InvocationHandler handler = newInvocationHandler();
+ private Class<?> proxyClass;
+ public NonPublicProxyClass(ClassLoader loader, Class<?> ... intfs) {
+ this.loader = loader;
+ this.interfaces = intfs;
+ }
+
+ public void run() throws Exception {
+ boolean hasAccess = loader != null || hasAccess();
+ try {
+ proxyClass = Proxy.getProxyClass(loader, interfaces);
+ if (!hasAccess) {
+ throw new RuntimeException("should have no permission to create proxy class");
+ }
+ } catch (AccessControlException e) {
+ if (hasAccess) {
+ throw e;
+ }
+ if (e.getPermission().getClass() != RuntimePermission.class ||
+ !e.getPermission().getName().equals("getClassLoader")) {
+ throw e;
+ }
+ return;
+ }
+
+ if (Modifier.isPublic(proxyClass.getModifiers())) {
+ throw new RuntimeException(proxyClass + " must be non-public");
+ }
+ newProxyInstance();
+ newInstanceFromConstructor(proxyClass);
+ }
+
+ private boolean hasAccess() {
+ if (System.getSecurityManager() == null) {
+ return true;
+ }
+ NewInstancePolicy policy = NewInstancePolicy.class.cast(Policy.getPolicy());
+ return policy.grant;
+ }
+
+ private final static String NEW_PROXY_IN_PKG = "newProxyInPackage.";
+ private void newProxyInstance() {
+ // expect newProxyInstance to succeed if it's in the same runtime package
+ int i = proxyClass.getName().lastIndexOf('.');
+ String pkg = (i != -1) ? proxyClass.getName().substring(0, i) : "";
+ boolean hasAccess = pkg.isEmpty() || hasAccess();
+ try {
+ Proxy.newProxyInstance(loader, interfaces, handler);
+ if (!hasAccess) {
+ throw new RuntimeException("ERROR: Proxy.newProxyInstance should fail " + proxyClass);
+ }
+ } catch (AccessControlException e) {
+ if (hasAccess) {
+ throw e;
+ }
+ if (e.getPermission().getClass() != ReflectPermission.class ||
+ !e.getPermission().getName().equals(NEW_PROXY_IN_PKG + pkg)) {
+ throw e;
+ }
+ }
+ }
+
+ private void newInstanceFromConstructor(Class<?> proxyClass)
+ throws Exception
+ {
+ // expect newInstance to succeed if it's in the same runtime package
+ boolean isSamePackage = proxyClass.getName().lastIndexOf('.') == -1;
+ try {
+ Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
+ cons.newInstance(newInvocationHandler());
+ if (!isSamePackage) {
+ throw new RuntimeException("ERROR: Constructor.newInstance should not succeed");
+ }
+ } catch (IllegalAccessException e) {
+ if (isSamePackage) {
+ throw e;
+ }
+ }
+ }
+
+ private static InvocationHandler newInvocationHandler() {
+ return new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ Class<?>[] intfs = proxy.getClass().getInterfaces();
+ System.out.println("Proxy for " + Arrays.toString(intfs)
+ + " " + method.getName() + " is being invoked");
+ return null;
+ }
+ };
+ }
+
+ static class NewInstancePolicy extends Policy {
+ final PermissionCollection permissions = new Permissions();
+ final boolean grant;
+ NewInstancePolicy(boolean grant) {
+ this.grant = grant;
+ permissions.add(new SecurityPermission("getPolicy"));
+ if (grant) {
+ permissions.add(new RuntimePermission("getClassLoader"));
+ permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "p"));
+ permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "java.util.zip"));
+ }
+ }
+ public PermissionCollection getPermissions(ProtectionDomain domain) {
+ return permissions;
+ }
+
+ public PermissionCollection getPermissions(CodeSource codesource) {
+ return permissions;
+ }
+
+ public boolean implies(ProtectionDomain domain, Permission perm) {
+ return permissions.implies(perm);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("policy: ");
+ Enumeration<Permission> perms = permissions.elements();
+ while (perms.hasMoreElements()) {
+ sb.append("\n").append(perms.nextElement().toString());
+ }
+ return sb.toString();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 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.lang.reflect.*;
+import java.security.*;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8004260
+ * @summary Test making a proxy instance that implements a non-public
+ * interface with and without security manager installed
+ * @build p.Foo p.Bar
+ * @run main SimpleProxy
+ */
+public class SimpleProxy {
+ public static void main(String[] args) throws Exception {
+ ClassLoader loader = SimpleProxy.class.getClassLoader();
+ Class<?> fooClass = Class.forName("p.Foo");
+ Class<?> barClass = Class.forName("p.Bar");
+
+ makeProxy(loader, fooClass);
+
+ System.setSecurityManager(new SecurityManager());
+ try {
+ makeProxy(loader, barClass);
+ throw new RuntimeException("should fail to new proxy instance of a non-public interface");
+ } catch (AccessControlException e) {
+ if (e.getPermission().getClass() != ReflectPermission.class ||
+ !e.getPermission().getName().equals("newProxyInPackage.p")) {
+ throw e;
+ }
+ }
+ }
+
+ private static void makeProxy(ClassLoader loader, Class<?> cls) {
+ Class<?>[] intfs = new Class<?>[] { cls };
+ Proxy.newProxyInstance(loader, intfs, new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ Class<?>[] intfs = proxy.getClass().getInterfaces();
+ System.out.println("Proxy for " + Arrays.toString(intfs)
+ + " " + method.getName() + " is being invoked");
+ return null;
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package p;
+interface Bar {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java Wed Apr 17 15:06:17 2013 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package p;
+interface Foo {
+}
--- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Wed Apr 17 12:50:45 2013 -0400
+++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Wed Apr 17 15:06:17 2013 -0400
@@ -16,6 +16,9 @@
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "setContextClassLoader";
+ permission java.lang.reflect.ReflectPermission "newProxyInPackage.";
+ permission java.lang.reflect.ReflectPermission "newProxyInPackage.java.util.zip";
+
// used by TestLibrary to determine test environment
permission java.util.PropertyPermission "test.classes", "read";
permission java.util.PropertyPermission "test.src", "read";