This commit is contained in:
J. Duke 2017-07-05 22:40:11 +02:00
commit 3c1a419a4e
85 changed files with 3909 additions and 1676 deletions

View File

@ -393,3 +393,4 @@ a22e2671d88f6b22a4aa82e3966986542ed2a381 jdk-9+146
3ffc3e886c74736e387f3685e86b557cdea706c8 jdk-9+148
b119012d1c2ab2570fe8718633840d0c1f1f441d jdk-9+149
6234069ff9789f7582e1faa32cb6283cbd1a5a2d jdk-9+150
71a766d4c18041a7f833ee22823125b02e1a7f1e jdk-9+151

View File

@ -147,15 +147,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS],
EXTRA_CXXFLAGS="$with_extra_cxxflags"
EXTRA_LDFLAGS="$with_extra_ldflags"
# Hotspot needs these set in their legacy form
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $EXTRA_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $EXTRA_CXXFLAGS"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $EXTRA_LDFLAGS"
AC_SUBST(LEGACY_EXTRA_CFLAGS)
AC_SUBST(LEGACY_EXTRA_CXXFLAGS)
AC_SUBST(LEGACY_EXTRA_LDFLAGS)
AC_SUBST(EXTRA_CFLAGS)
AC_SUBST(EXTRA_CXXFLAGS)
AC_SUBST(EXTRA_LDFLAGS)
@ -192,10 +183,6 @@ AC_DEFUN([FLAGS_SETUP_SYSROOT_FLAGS],
$1SYSROOT_CFLAGS="-isysroot [$]$1SYSROOT"
$1SYSROOT_LDFLAGS="-isysroot [$]$1SYSROOT"
fi
# Propagate the sysroot args to hotspot
$1LEGACY_EXTRA_CFLAGS="[$]$1LEGACY_EXTRA_CFLAGS [$]$1SYSROOT_CFLAGS"
$1LEGACY_EXTRA_CXXFLAGS="[$]$1LEGACY_EXTRA_CXXFLAGS [$]$1SYSROOT_CFLAGS"
$1LEGACY_EXTRA_LDFLAGS="[$]$1LEGACY_EXTRA_LDFLAGS [$]$1SYSROOT_LDFLAGS"
# The global CFLAGS and LDFLAGS variables need these for configure to function
$1CFLAGS="[$]$1CFLAGS [$]$1SYSROOT_CFLAGS"
$1CPPFLAGS="[$]$1CPPFLAGS [$]$1SYSROOT_CFLAGS"

View File

@ -854,9 +854,6 @@ SYSROOT_CFLAGS
EXTRA_LDFLAGS
EXTRA_CXXFLAGS
EXTRA_CFLAGS
LEGACY_EXTRA_LDFLAGS
LEGACY_EXTRA_CXXFLAGS
LEGACY_EXTRA_CFLAGS
EXE_SUFFIX
OBJ_SUFFIX
STATIC_LIBRARY
@ -5170,7 +5167,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1482828098
DATE_WHEN_GENERATED=1483542685
###############################################################################
#
@ -31290,8 +31287,6 @@ $as_echo "yes" >&6; }
as_fn_error $? "--enable-static-build is only supported for macosx builds" "$LINENO" 5
fi
STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1"
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS"
CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
STATIC_BUILD=true
@ -31493,15 +31488,6 @@ fi
EXTRA_CXXFLAGS="$with_extra_cxxflags"
EXTRA_LDFLAGS="$with_extra_ldflags"
# Hotspot needs these set in their legacy form
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $EXTRA_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $EXTRA_CXXFLAGS"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $EXTRA_LDFLAGS"
@ -31533,10 +31519,6 @@ fi
SYSROOT_CFLAGS="-isysroot $SYSROOT"
SYSROOT_LDFLAGS="-isysroot $SYSROOT"
fi
# Propagate the sysroot args to hotspot
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $SYSROOT_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $SYSROOT_CFLAGS"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $SYSROOT_LDFLAGS"
# The global CFLAGS and LDFLAGS variables need these for configure to function
CFLAGS="$CFLAGS $SYSROOT_CFLAGS"
CPPFLAGS="$CPPFLAGS $SYSROOT_CFLAGS"
@ -44053,10 +44035,6 @@ $as_echo "$BUILD_DEVKIT_ROOT" >&6; }
BUILD_SYSROOT_CFLAGS="-isysroot $BUILD_SYSROOT"
BUILD_SYSROOT_LDFLAGS="-isysroot $BUILD_SYSROOT"
fi
# Propagate the sysroot args to hotspot
BUILD_LEGACY_EXTRA_CFLAGS="$BUILD_LEGACY_EXTRA_CFLAGS $BUILD_SYSROOT_CFLAGS"
BUILD_LEGACY_EXTRA_CXXFLAGS="$BUILD_LEGACY_EXTRA_CXXFLAGS $BUILD_SYSROOT_CFLAGS"
BUILD_LEGACY_EXTRA_LDFLAGS="$BUILD_LEGACY_EXTRA_LDFLAGS $BUILD_SYSROOT_LDFLAGS"
# The global CFLAGS and LDFLAGS variables need these for configure to function
BUILD_CFLAGS="$BUILD_CFLAGS $BUILD_SYSROOT_CFLAGS"
BUILD_CPPFLAGS="$BUILD_CPPFLAGS $BUILD_SYSROOT_CFLAGS"
@ -52779,9 +52757,8 @@ $as_echo_n "checking if native coverage is enabled... " >&6; }
$as_echo "yes" >&6; }
GCOV_CFLAGS="-fprofile-arcs -ftest-coverage -fno-inline"
GCOV_LDFLAGS="-fprofile-arcs"
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $GCOV_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $GCOV_CFLAGS"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $GCOV_LDFLAGS"
JVM_CFLAGS="$JVM_CFLAGS $GCOV_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $GCOV_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $GCOV_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $GCOV_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $GCOV_CFLAGS"
@ -52982,7 +52959,7 @@ $as_echo "yes, forced" >&6; }
$as_echo "no, forced" >&6; }
BUILD_GTEST="false"
elif test "x$enable_hotspot_gtest" = "x"; then
if test "x$GTEST_DIR_EXISTS" = "xtrue" && test "x$OPENJDK_TARGET_OS" != "xaix"; then
if test "x$GTEST_DIR_EXISTS" = "xtrue"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
BUILD_GTEST="true"

View File

@ -320,9 +320,8 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
AC_MSG_RESULT([yes])
GCOV_CFLAGS="-fprofile-arcs -ftest-coverage -fno-inline"
GCOV_LDFLAGS="-fprofile-arcs"
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $GCOV_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $GCOV_CFLAGS"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $GCOV_LDFLAGS"
JVM_CFLAGS="$JVM_CFLAGS $GCOV_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $GCOV_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $GCOV_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $GCOV_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $GCOV_CFLAGS"
@ -360,8 +359,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_BUILD],
AC_MSG_ERROR([--enable-static-build is only supported for macosx builds])
fi
STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1"
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS"
CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
STATIC_BUILD=true

View File

@ -263,6 +263,7 @@ var getJibProfilesCommon = function (input, data) {
labels: "open"
};
common.configure_args_64bit = ["--with-target-bits=64"];
common.configure_args_32bit = ["--with-target-bits=32"];
/**
@ -419,7 +420,7 @@ var getJibProfilesProfiles = function (input, common, data) {
target_os: "linux",
target_cpu: "x64",
dependencies: ["devkit"],
configure_args: ["--with-zlib=system"],
configure_args: concat(common.configure_args_64bit, "--with-zlib=system"),
default_make_targets: ["docs-bundles"],
},
@ -436,27 +437,30 @@ var getJibProfilesProfiles = function (input, common, data) {
target_os: "macosx",
target_cpu: "x64",
dependencies: ["devkit"],
configure_args: concat(common.configure_args, "--with-zlib=system"),
configure_args: concat(common.configure_args_64bit, "--with-zlib=system"),
},
"solaris-x64": {
target_os: "solaris",
target_cpu: "x64",
dependencies: ["devkit", "cups"],
configure_args: ["--with-zlib=system", "--enable-dtrace"],
configure_args: concat(common.configure_args_64bit,
"--with-zlib=system", "--enable-dtrace"),
},
"solaris-sparcv9": {
target_os: "solaris",
target_cpu: "sparcv9",
dependencies: ["devkit", "cups"],
configure_args: ["--with-zlib=system", "--enable-dtrace"],
configure_args: concat(common.configure_args_64bit,
"--with-zlib=system", "--enable-dtrace"),
},
"windows-x64": {
target_os: "windows",
target_cpu: "x64",
dependencies: ["devkit", "freetype"],
configure_args: concat(common.configure_args_64bit),
},
"windows-x86": {
@ -518,11 +522,11 @@ var getJibProfilesProfiles = function (input, common, data) {
target_os: "linux",
target_cpu: "x64",
dependencies: ["devkit"],
configure_args: [
configure_args: concat(common.configure_args_64bit, [
"--with-zlib=system",
"--with-jvm-variants=zero",
"--enable-libffi-bundling"
]
])
},
"linux-x86-zero": {

View File

@ -393,3 +393,4 @@ dc49e0922a8e4387cbf8670bbe1dc51c9874b74b jdk-9+147
f95cc86b6ac22ec1ade5d4f825dc7782adeea228 jdk-9+148
00b19338e505690abe93d5995ed74a473d969c2c jdk-9+149
9205e980062a5c4530b51021c6e274025f4ccbdf jdk-9+150
77f827f5bbad3ef795664bc675f72d98d156b9f8 jdk-9+151

View File

@ -553,3 +553,4 @@ a82cb5350cad96a0b4de496afebe3ded89f27efa jdk-9+146
5e4e893520ecdbd517c6ed6375f0885664fe62c4 jdk-9+148
30e1996bd55da36183434f24ed964adebf9ca71e jdk-9+149
98fe046473c90204cbc9b34c512b9fc10dfb8479 jdk-9+150
2a2ac7d9f52c8cb2b80077e515b5840b947e640c jdk-9+151

View File

@ -49,6 +49,7 @@ else
DEST := $(JDK_OUTPUTDIR)/lib, \
FILES := $(filter-out %$(SHARED_LIBRARY_SUFFIX), $(LIB_TARGETS)), \
MACRO := link-file-relative, \
LOG_ACTION := Creating symlink, \
))
TARGETS += $(COPY_LIBS) $(LINK_LIBS)

View File

@ -393,3 +393,4 @@ ce81d03ad7320dca3d673374c1a33bc0efd9136a jdk-9+143
c45db75bfe8bc20bb80b4a009ae3f69c9cd2d885 jdk-9+148
5978df8bfa3894f2b3d07b7256f25f78dffb1f9c jdk-9+149
f85154af719f99a3b4d81b67a8b4c18a650d10f9 jdk-9+150
13c6906bfc861d99dc35a19c80b7a99f0b0ac58d jdk-9+151

View File

@ -393,3 +393,4 @@ c41140100bf1e5c10c7b8f3bde91c16eff7485f5 jdk-9+147
9098b2b9d997d65af0026fc2f39cf75234e26bc5 jdk-9+148
5a846396a24c7aff01d6a8feaa7afc0a6369f04d jdk-9+149
71e198ef3839045e829a879af1d709be16ab0f88 jdk-9+150
d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151

View File

@ -532,11 +532,13 @@ public final class FilePermission extends Permission implements Serializable {
* simple {@code npath} is inside a wildcard {@code npath} if and only if
* {@code simple_npath.relativize(wildcard_npath)} is exactly "..",
* a simple {@code npath} is recursively inside a wildcard {@code npath}
* if and only if {@code simple_npath.relativize(wildcard_npath)}
* is a series of one or more "..". An invalid {@code FilePermission} does
* not imply any object except for itself. An invalid {@code FilePermission}
* is not implied by any object except for itself or a {@code FilePermission}
* on {@literal "<<ALL FILES>>"} whose actions is a superset of this
* if and only if {@code simple_npath.relativize(wildcard_npath)} is a
* series of one or more "..". This means "/-" implies "/foo" but not "foo".
* <p>
* An invalid {@code FilePermission} does not imply any object except for
* itself. An invalid {@code FilePermission} is not implied by any object
* except for itself or a {@code FilePermission} on
* {@literal "<<ALL FILES>>"} whose actions is a superset of this
* invalid {@code FilePermission}. Even if two {@code FilePermission}
* are created with the same invalid path, one does not imply the other.
*

View File

@ -26,8 +26,6 @@
package java.lang;
import java.lang.annotation.Annotation;
import java.lang.module.ModuleDescriptor.Version;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
import java.lang.ref.SoftReference;
import java.io.IOException;
@ -42,7 +40,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Layer;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@ -54,7 +51,6 @@ import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@ -62,19 +58,15 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleHashes;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.ConstantPool;
import jdk.internal.reflect.Reflection;
@ -532,7 +524,8 @@ public final class Class<T> implements java.io.Serializable,
}
try {
Class<?>[] empty = {};
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
final Constructor<T> c = getReflectionFactory().copyConstructor(
getConstructor0(empty, Member.DECLARED));
// Disable accessibility checks on the constructor
// since we have to do the security check here anyway
// (the stack depth is wrong for the Constructor's
@ -1024,6 +1017,11 @@ public final class Class<T> implements java.io.Serializable,
* @return an array of interfaces directly implemented by this class
*/
public Class<?>[] getInterfaces() {
// defensively copy before handing over to user code
return getInterfaces(true);
}
private Class<?>[] getInterfaces(boolean cloneArray) {
ReflectionData<T> rd = reflectionData();
if (rd == null) {
// no cloning required
@ -1034,8 +1032,8 @@ public final class Class<T> implements java.io.Serializable,
interfaces = getInterfaces0();
rd.interfaces = interfaces;
}
// defensively copy before handing over to user code
return interfaces.clone();
// defensively copy if requested
return cloneArray ? interfaces.clone() : interfaces;
}
}
@ -1767,15 +1765,6 @@ public final class Class<T> implements java.io.Serializable,
* Class} object, including those declared by the class or interface and
* those inherited from superclasses and superinterfaces.
*
* <p> If this {@code Class} object represents a type that has multiple
* public methods with the same name and parameter types, but different
* return types, then the returned array has a {@code Method} object for
* each such method.
*
* <p> If this {@code Class} object represents a type with a class
* initialization method {@code <clinit>}, then the returned array does
* <em>not</em> have a corresponding {@code Method} object.
*
* <p> If this {@code Class} object represents an array type, then the
* returned array has a {@code Method} object for each of the public
* methods inherited by the array type from {@code Object}. It does not
@ -1788,16 +1777,54 @@ public final class Class<T> implements java.io.Serializable,
* has length 0. (Note that a {@code Class} object which represents a class
* always has public methods, inherited from {@code Object}.)
*
* <p> If this {@code Class} object represents a primitive type or void,
* then the returned array has length 0.
*
* <p> Static methods declared in superinterfaces of the class or interface
* represented by this {@code Class} object are not considered members of
* the class or interface.
* <p> The returned array never contains methods with names "{@code <init>}"
* or "{@code <clinit>}".
*
* <p> The elements in the returned array are not sorted and are not in any
* particular order.
*
* <p> Generally, the result is computed as with the following 4 step algorithm.
* Let C be the class or interface represented by this {@code Class} object:
* <ol>
* <li> A union of methods is composed of:
* <ol type="a">
* <li> C's declared public instance and static methods as returned by
* {@link #getDeclaredMethods()} and filtered to include only public
* methods.</li>
* <li> If C is a class other than {@code Object}, then include the result
* of invoking this algorithm recursively on the superclass of C.</li>
* <li> Include the results of invoking this algorithm recursively on all
* direct superinterfaces of C, but include only instance methods.</li>
* </ol></li>
* <li> Union from step 1 is partitioned into subsets of methods with same
* signature (name, parameter types) and return type.</li>
* <li> Within each such subset only the most specific methods are selected.
* Let method M be a method from a set of methods with same signature
* and return type. M is most specific if there is no such method
* N != M from the same set, such that N is more specific than M.
* N is more specific than M if:
* <ol type="a">
* <li> N is declared by a class and M is declared by an interface; or</li>
* <li> N and M are both declared by classes or both by interfaces and
* N's declaring type is the same as or a subtype of M's declaring type
* (clearly, if M's and N's declaring types are the same type, then
* M and N are the same method).</li>
* </ol></li>
* <li> The result of this algorithm is the union of all selected methods from
* step 3.</li>
* </ol>
*
* @apiNote There may be more than one method with a particular name
* and parameter types in a class because while the Java language forbids a
* class to declare multiple methods with the same signature but different
* return types, the Java virtual machine does not. This
* increased flexibility in the virtual machine can be used to
* implement various language features. For example, covariant
* returns can be implemented with {@linkplain
* java.lang.reflect.Method#isBridge bridge methods}; the bridge
* method and the overriding method would have the same
* signature but different return types.
*
* @return the array of {@code Method} objects representing the
* public methods of this class
* @throws SecurityException
@ -1900,12 +1927,13 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
return getReflectionFactory().copyField(field);
}
@ -1919,47 +1947,69 @@ public final class Class<T> implements java.io.Serializable,
* order. If {@code parameterTypes} is {@code null}, it is
* treated as if it were an empty array.
*
* <p> If the {@code name} is "{@code <init>}" or "{@code <clinit>}" a
* {@code NoSuchMethodException} is raised. Otherwise, the method to
* be reflected is determined by the algorithm that follows. Let C be the
* class or interface represented by this object:
* <OL>
* <LI> C is searched for a <I>matching method</I>, as defined below. If a
* matching method is found, it is reflected.</LI>
* <LI> If no matching method is found by step 1 then:
* <OL TYPE="a">
* <LI> If C is a class other than {@code Object}, then this algorithm is
* invoked recursively on the superclass of C.</LI>
* <LI> If C is the class {@code Object}, or if C is an interface, then
* the superinterfaces of C (if any) are searched for a matching
* method. If any such method is found, it is reflected.</LI>
* </OL></LI>
* </OL>
* <p> If this {@code Class} object represents an array type, then this
* method finds any public method inherited by the array type from
* {@code Object} except method {@code clone()}.
*
* <p> To find a matching method in a class or interface C:&nbsp; If C
* declares exactly one public method with the specified name and exactly
* the same formal parameter types, that is the method reflected. If more
* than one such method is found in C, and one of these methods has a
* return type that is more specific than any of the others, that method is
* reflected; otherwise one of the methods is chosen arbitrarily.
* <p> If this {@code Class} object represents an interface then this
* method does not find any implicitly declared method from
* {@code Object}. Therefore, if no methods are explicitly declared in
* this interface or any of its superinterfaces, then this method does not
* find any method.
*
* <p>Note that there may be more than one matching method in a
* class because while the Java language forbids a class to
* declare multiple methods with the same signature but different
* <p> This method does not find any method with name "{@code <init>}" or
* "{@code <clinit>}".
*
* <p> Generally, the method to be reflected is determined by the 4 step
* algorithm that follows.
* Let C be the class or interface represented by this {@code Class} object:
* <ol>
* <li> A union of methods is composed of:
* <ol type="a">
* <li> C's declared public instance and static methods as returned by
* {@link #getDeclaredMethods()} and filtered to include only public
* methods that match given {@code name} and {@code parameterTypes}</li>
* <li> If C is a class other than {@code Object}, then include the result
* of invoking this algorithm recursively on the superclass of C.</li>
* <li> Include the results of invoking this algorithm recursively on all
* direct superinterfaces of C, but include only instance methods.</li>
* </ol></li>
* <li> This union is partitioned into subsets of methods with same
* return type (the selection of methods from step 1 also guarantees that
* they have the same method name and parameter types).</li>
* <li> Within each such subset only the most specific methods are selected.
* Let method M be a method from a set of methods with same VM
* signature (return type, name, parameter types).
* M is most specific if there is no such method N != M from the same
* set, such that N is more specific than M. N is more specific than M
* if:
* <ol type="a">
* <li> N is declared by a class and M is declared by an interface; or</li>
* <li> N and M are both declared by classes or both by interfaces and
* N's declaring type is the same as or a subtype of M's declaring type
* (clearly, if M's and N's declaring types are the same type, then
* M and N are the same method).</li>
* </ol></li>
* <li> The result of this algorithm is chosen arbitrarily from the methods
* with most specific return type among all selected methods from step 3.
* Let R be a return type of a method M from the set of all selected methods
* from step 3. M is a method with most specific return type if there is
* no such method N != M from the same set, having return type S != R,
* such that S is a subtype of R as determined by
* R.class.{@link #isAssignableFrom}(S.class).
* </ol>
*
* @apiNote There may be more than one method with matching name and
* parameter types in a class because while the Java language forbids a
* class to declare multiple methods with the same signature but different
* return types, the Java virtual machine does not. This
* increased flexibility in the virtual machine can be used to
* implement various language features. For example, covariant
* returns can be implemented with {@linkplain
* java.lang.reflect.Method#isBridge bridge methods}; the bridge
* method and the method being overridden would have the same
* signature but different return types.
*
* <p> If this {@code Class} object represents an array type, then this
* method does not find the {@code clone()} method.
*
* <p> Static methods declared in superinterfaces of the class or interface
* represented by this {@code Class} object are not considered members of
* the class or interface.
* method and the overriding method would have the same
* signature but different return types. This method would return the
* overriding method as it would have a more specific return type.
*
* @param name the name of the method
* @param parameterTypes the list of parameters
@ -1983,12 +2033,13 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Method method = getMethod0(name, parameterTypes, true);
Method method = getMethod0(name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
return getReflectionFactory().copyMethod(method);
}
/**
@ -2004,7 +2055,9 @@ public final class Class<T> implements java.io.Serializable,
* "&lt;init&gt;"or "&lt;clinit&gt;".
*/
Method getMethodOrNull(String name, Class<?>... parameterTypes) {
return getMethod0(name, parameterTypes, true);
Objects.requireNonNull(name);
Method method = getMethod0(name, parameterTypes);
return method == null ? null : getReflectionFactory().copyMethod(method);
}
@ -2041,7 +2094,8 @@ public final class Class<T> implements java.io.Serializable,
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.PUBLIC);
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.PUBLIC));
}
@ -2283,12 +2337,13 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException {
Objects.requireNonNull(name);
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
return getReflectionFactory().copyField(field);
}
@ -2343,12 +2398,13 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
return getReflectionFactory().copyMethod(method);
}
@ -2394,7 +2450,8 @@ public final class Class<T> implements java.io.Serializable,
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return getConstructor0(parameterTypes, Member.DECLARED);
return getReflectionFactory().copyConstructor(
getConstructor0(parameterTypes, Member.DECLARED));
}
/**
@ -3004,180 +3061,6 @@ public final class Class<T> implements java.io.Serializable,
return res;
}
static class MethodArray {
// Don't add or remove methods except by add() or remove() calls.
private Method[] methods;
private int length;
private int defaults;
MethodArray() {
this(20);
}
MethodArray(int initialSize) {
if (initialSize < 2)
throw new IllegalArgumentException("Size should be 2 or more");
methods = new Method[initialSize];
length = 0;
defaults = 0;
}
boolean hasDefaults() {
return defaults != 0;
}
void add(Method m) {
if (length == methods.length) {
methods = Arrays.copyOf(methods, 2 * methods.length);
}
methods[length++] = m;
if (m != null && m.isDefault())
defaults++;
}
void addAll(Method[] ma) {
for (Method m : ma) {
add(m);
}
}
void addAll(MethodArray ma) {
for (int i = 0; i < ma.length(); i++) {
add(ma.get(i));
}
}
void addIfNotPresent(Method newMethod) {
for (int i = 0; i < length; i++) {
Method m = methods[i];
if (m == newMethod || (m != null && m.equals(newMethod))) {
return;
}
}
add(newMethod);
}
void addAllIfNotPresent(MethodArray newMethods) {
for (int i = 0; i < newMethods.length(); i++) {
Method m = newMethods.get(i);
if (m != null) {
addIfNotPresent(m);
}
}
}
/* Add Methods declared in an interface to this MethodArray.
* Static methods declared in interfaces are not inherited.
*/
void addInterfaceMethods(Method[] methods) {
for (Method candidate : methods) {
if (!Modifier.isStatic(candidate.getModifiers())) {
add(candidate);
}
}
}
int length() {
return length;
}
Method get(int i) {
return methods[i];
}
Method getFirst() {
for (Method m : methods)
if (m != null)
return m;
return null;
}
void removeByNameAndDescriptor(Method toRemove) {
for (int i = 0; i < length; i++) {
Method m = methods[i];
if (m != null && matchesNameAndDescriptor(m, toRemove)) {
remove(i);
}
}
}
private void remove(int i) {
if (methods[i] != null && methods[i].isDefault())
defaults--;
methods[i] = null;
}
private boolean matchesNameAndDescriptor(Method m1, Method m2) {
return m1.getReturnType() == m2.getReturnType() &&
m1.getName() == m2.getName() && // name is guaranteed to be interned
arrayContentsEq(m1.getParameterTypes(),
m2.getParameterTypes());
}
void compactAndTrim() {
int newPos = 0;
// Get rid of null slots
for (int pos = 0; pos < length; pos++) {
Method m = methods[pos];
if (m != null) {
if (pos != newPos) {
methods[newPos] = m;
}
newPos++;
}
}
if (newPos != methods.length) {
methods = Arrays.copyOf(methods, newPos);
}
}
/* Removes all Methods from this MethodArray that have a more specific
* default Method in this MethodArray.
*
* Users of MethodArray are responsible for pruning Methods that have
* a more specific <em>concrete</em> Method.
*/
void removeLessSpecifics() {
if (!hasDefaults())
return;
for (int i = 0; i < length; i++) {
Method m = get(i);
if (m == null || !m.isDefault())
continue;
for (int j = 0; j < length; j++) {
if (i == j)
continue;
Method candidate = get(j);
if (candidate == null)
continue;
if (!matchesNameAndDescriptor(m, candidate))
continue;
if (hasMoreSpecificClass(m, candidate))
remove(j);
}
}
}
Method[] getArray() {
return methods;
}
// Returns true if m1 is more specific than m2
static boolean hasMoreSpecificClass(Method m1, Method m2) {
Class<?> m1Class = m1.getDeclaringClass();
Class<?> m2Class = m2.getDeclaringClass();
return m1Class != m2Class && m2Class.isAssignableFrom(m1Class);
}
}
// Returns an array of "root" methods. These Method objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyMethod.
@ -3190,51 +3073,29 @@ public final class Class<T> implements java.io.Serializable,
}
// No cached value available; compute value recursively.
// Start by fetching public declared methods
MethodArray methods = new MethodArray();
{
Method[] tmp = privateGetDeclaredMethods(true);
methods.addAll(tmp);
// Start by fetching public declared methods...
PublicMethods pms = new PublicMethods();
for (Method m : privateGetDeclaredMethods(/* publicOnly */ true)) {
pms.merge(m);
}
// Now recur over superclass and direct superinterfaces.
// Go over superinterfaces first so we can more easily filter
// out concrete implementations inherited from superclasses at
// the end.
MethodArray inheritedMethods = new MethodArray();
for (Class<?> i : getInterfaces()) {
inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods());
}
if (!isInterface()) {
Class<?> c = getSuperclass();
if (c != null) {
MethodArray supers = new MethodArray();
supers.addAll(c.privateGetPublicMethods());
// Filter out concrete implementations of any
// interface methods
for (int i = 0; i < supers.length(); i++) {
Method m = supers.get(i);
if (m != null &&
!Modifier.isAbstract(m.getModifiers()) &&
!m.isDefault()) {
inheritedMethods.removeByNameAndDescriptor(m);
}
}
// Insert superclass's inherited methods before
// superinterfaces' to satisfy getMethod's search
// order
supers.addAll(inheritedMethods);
inheritedMethods = supers;
// ...then recur over superclass methods...
Class<?> sc = getSuperclass();
if (sc != null) {
for (Method m : sc.privateGetPublicMethods()) {
pms.merge(m);
}
}
// Filter out all local methods from inherited ones
for (int i = 0; i < methods.length(); i++) {
Method m = methods.get(i);
inheritedMethods.removeByNameAndDescriptor(m);
// ...and finally over direct superinterfaces.
for (Class<?> intf : getInterfaces(/* cloneArray */ false)) {
for (Method m : intf.privateGetPublicMethods()) {
// static interface methods are not inherited
if (!Modifier.isStatic(m.getModifiers())) {
pms.merge(m);
}
}
}
methods.addAllIfNotPresent(inheritedMethods);
methods.removeLessSpecifics();
methods.compactAndTrim();
res = methods.getArray();
res = pms.toArray();
if (rd != null) {
rd.publicMethods = res;
}
@ -3246,17 +3107,20 @@ public final class Class<T> implements java.io.Serializable,
// Helpers for fetchers of one field, method, or constructor
//
// This method does not copy the returned Field object!
private static Field searchFields(Field[] fields, String name) {
String internedName = name.intern();
for (Field field : fields) {
if (field.getName() == internedName) {
return getReflectionFactory().copyField(field);
if (field.getName().equals(name)) {
return field;
}
}
return null;
}
private Field getField0(String name) throws NoSuchFieldException {
// Returns a "root" Field object. This Field object must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyField.
private Field getField0(String name) {
// Note: the intent is that the search algorithm this routine
// uses be equivalent to the ordering imposed by
// privateGetPublicFields(). It fetches only the declared
@ -3270,7 +3134,7 @@ public final class Class<T> implements java.io.Serializable,
return res;
}
// Direct superinterfaces, recursively
Class<?>[] interfaces = getInterfaces();
Class<?>[] interfaces = getInterfaces(/* cloneArray */ false);
for (Class<?> c : interfaces) {
if ((res = c.getField0(name)) != null) {
return res;
@ -3288,87 +3152,85 @@ public final class Class<T> implements java.io.Serializable,
return null;
}
// This method does not copy the returned Method object!
private static Method searchMethods(Method[] methods,
String name,
Class<?>[] parameterTypes)
{
ReflectionFactory fact = getReflectionFactory();
Method res = null;
String internedName = name.intern();
for (Method m : methods) {
if (m.getName() == internedName
&& arrayContentsEq(parameterTypes, m.getParameterTypes())
if (m.getName().equals(name)
&& arrayContentsEq(parameterTypes,
fact.getExecutableSharedParameterTypes(m))
&& (res == null
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
|| (res.getReturnType() != m.getReturnType()
&& res.getReturnType().isAssignableFrom(m.getReturnType()))))
res = m;
}
return (res == null ? res : getReflectionFactory().copyMethod(res));
return res;
}
private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
MethodArray interfaceCandidates = new MethodArray(2);
Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
if (res != null)
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
// Returns a "root" Method object. This Method object must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyMethod.
private Method getMethod0(String name, Class<?>[] parameterTypes) {
PublicMethods.MethodList res = getMethodsRecursive(
name,
parameterTypes == null ? EMPTY_CLASS_ARRAY : parameterTypes,
/* includeStatic */ true);
return res == null ? null : res.getMostSpecific();
}
// Returns a list of "root" Method objects. These Method objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyMethod.
private PublicMethods.MethodList getMethodsRecursive(String name,
Class<?>[] parameterTypes,
boolean includeStatic) {
// 1st check declared public methods
Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true);
PublicMethods.MethodList res = PublicMethods.MethodList
.filter(methods, name, parameterTypes, includeStatic);
// if there is at least one match among declared methods, we need not
// search any further as such match surely overrides matching methods
// declared in superclass(es) or interface(s).
if (res != null) {
return res;
}
// Not found on class or superclass directly
interfaceCandidates.removeLessSpecifics();
return interfaceCandidates.getFirst(); // may be null
}
private Method privateGetMethodRecursive(String name,
Class<?>[] parameterTypes,
boolean includeStaticMethods,
MethodArray allInterfaceCandidates) {
// Note: the intent is that the search algorithm this routine
// uses be equivalent to the ordering imposed by
// privateGetPublicMethods(). It fetches only the declared
// public methods for each class, however, to reduce the
// number of Method objects which have to be created for the
// common case where the method being requested is declared in
// the class which is being queried.
//
// Due to default methods, unless a method is found on a superclass,
// methods declared in any superinterface needs to be considered.
// Collect all candidates declared in superinterfaces in {@code
// allInterfaceCandidates} and select the most specific if no match on
// a superclass is found.
// Must _not_ return root methods
Method res;
// Search declared public methods
if ((res = searchMethods(privateGetDeclaredMethods(true),
name,
parameterTypes)) != null) {
if (includeStaticMethods || !Modifier.isStatic(res.getModifiers()))
return res;
}
// Search superclass's methods
if (!isInterface()) {
Class<? super T> c = getSuperclass();
if (c != null) {
if ((res = c.getMethod0(name, parameterTypes, true)) != null) {
return res;
}
}
}
// Search superinterfaces' methods
Class<?>[] interfaces = getInterfaces();
for (Class<?> c : interfaces)
if ((res = c.getMethod0(name, parameterTypes, false)) != null)
allInterfaceCandidates.add(res);
// Not found
return null;
// if there was no match among declared methods,
// we must consult the superclass (if any) recursively...
Class<?> sc = getSuperclass();
if (sc != null) {
res = sc.getMethodsRecursive(name, parameterTypes, includeStatic);
}
// ...and coalesce the superclass methods with methods obtained
// from directly implemented interfaces excluding static methods...
for (Class<?> intf : getInterfaces(/* cloneArray */ false)) {
res = PublicMethods.MethodList.merge(
res, intf.getMethodsRecursive(name, parameterTypes,
/* includeStatic */ false));
}
return res;
}
// Returns a "root" Constructor object. This Constructor object must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyConstructor.
private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
int which) throws NoSuchMethodException
{
ReflectionFactory fact = getReflectionFactory();
Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
for (Constructor<T> constructor : constructors) {
if (arrayContentsEq(parameterTypes,
constructor.getParameterTypes())) {
return getReflectionFactory().copyConstructor(constructor);
fact.getExecutableSharedParameterTypes(constructor))) {
return constructor;
}
}
throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));

View File

@ -0,0 +1,272 @@
/*
* 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.
*/
package java.lang;
import jdk.internal.reflect.ReflectionFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A collection of most specific public methods. Methods are added to it using
* {@link #merge(Method)} method. Only the most specific methods for a
* particular signature are kept.
*/
final class PublicMethods {
/**
* a map of (method name, parameter types) -> linked list of Method(s)
*/
private final Map<Key, MethodList> map = new LinkedHashMap<>();
/**
* keeps track of the number of collected methods
*/
private int methodCount;
/**
* Merges new method with existing methods. New method is either
* ignored (if a more specific method with same signature exists) or added
* to the collection. When it is added to the collection, it may replace one
* or more existing methods with same signature if they are less specific
* than added method.
* See comments in code...
*/
void merge(Method method) {
Key key = new Key(method);
MethodList existing = map.get(key);
int xLen = existing == null ? 0 : existing.length();
MethodList merged = MethodList.merge(existing, method);
methodCount += merged.length() - xLen;
// replace if head of list changed
if (merged != existing) {
map.put(key, merged);
}
}
/**
* Dumps methods to array.
*/
Method[] toArray() {
Method[] array = new Method[methodCount];
int i = 0;
for (MethodList ml : map.values()) {
for (; ml != null; ml = ml.next) {
array[i++] = ml.method;
}
}
return array;
}
/**
* Method (name, parameter types) tuple.
*/
private static final class Key {
private static final ReflectionFactory reflectionFactory =
AccessController.doPrivileged(
new ReflectionFactory.GetReflectionFactoryAction());
private final String name; // must be interned (as from Method.getName())
private final Class<?>[] ptypes;
Key(Method method) {
name = method.getName();
ptypes = reflectionFactory.getExecutableSharedParameterTypes(method);
}
static boolean matches(Method method,
String name, // may not be interned
Class<?>[] ptypes) {
return method.getName().equals(name) &&
Arrays.equals(
reflectionFactory.getExecutableSharedParameterTypes(method),
ptypes
);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key that = (Key) o;
//noinspection StringEquality (guaranteed interned String(s))
return name == that.name &&
Arrays.equals(ptypes, that.ptypes);
}
@Override
public int hashCode() {
return System.identityHashCode(name) + // guaranteed interned String
31 * Arrays.hashCode(ptypes);
}
}
/**
* Node of a inked list containing Method(s) sharing the same
* (name, parameter types) tuple.
*/
static final class MethodList {
Method method;
MethodList next;
private MethodList(Method method) {
this.method = method;
}
/**
* @return the head of a linked list containing given {@code methods}
* filtered by given method {@code name}, parameter types
* {@code ptypes} and including or excluding static methods as
* requested by {@code includeStatic} flag.
*/
static MethodList filter(Method[] methods, String name,
Class<?>[] ptypes, boolean includeStatic) {
MethodList head = null, tail = null;
for (Method method : methods) {
if ((includeStatic || !Modifier.isStatic(method.getModifiers())) &&
Key.matches(method, name, ptypes)) {
if (tail == null) {
head = tail = new MethodList(method);
} else {
tail = tail.next = new MethodList(method);
}
}
}
return head;
}
/**
* This method should only be called with the {@code head} (possibly null)
* of a list of Method(s) that share the same (method name, parameter types)
* and another {@code methodList} that also contains Method(s) with the
* same and equal (method name, parameter types) as the 1st list.
* It modifies the 1st list and returns the head of merged list
* containing only the most specific methods for each signature
* (i.e. return type). The returned head of the merged list may or
* may not be the same as the {@code head} of the given list.
* The given {@code methodList} is not modified.
*/
static MethodList merge(MethodList head, MethodList methodList) {
for (MethodList ml = methodList; ml != null; ml = ml.next) {
head = merge(head, ml.method);
}
return head;
}
private static MethodList merge(MethodList head, Method method) {
Class<?> dclass = method.getDeclaringClass();
Class<?> rtype = method.getReturnType();
MethodList prev = null;
for (MethodList l = head; l != null; l = l.next) {
// eXisting method
Method xmethod = l.method;
// only merge methods with same signature:
// (return type, name, parameter types) tuple
// as we only keep methods with same (name, parameter types)
// tuple together in one list, we only need to check return type
if (rtype == xmethod.getReturnType()) {
Class<?> xdclass = xmethod.getDeclaringClass();
if (dclass.isInterface() == xdclass.isInterface()) {
// both methods are declared by interfaces
// or both by classes
if (dclass.isAssignableFrom(xdclass)) {
// existing method is the same or overrides
// new method - ignore new method
return head;
}
if (xdclass.isAssignableFrom(dclass)) {
// new method overrides existing
// method - knock out existing method
if (prev != null) {
prev.next = l.next;
} else {
head = l.next;
}
// keep iterating
} else {
// unrelated (should only happen for interfaces)
prev = l;
// keep iterating
}
} else if (dclass.isInterface()) {
// new method is declared by interface while
// existing method is declared by class -
// ignore new method
return head;
} else /* xdclass.isInterface() */ {
// new method is declared by class while
// existing method is declared by interface -
// knock out existing method
if (prev != null) {
prev.next = l.next;
} else {
head = l.next;
}
// keep iterating
}
} else {
// distinct signatures
prev = l;
// keep iterating
}
}
// append new method to the list
if (prev == null) {
head = new MethodList(method);
} else {
prev.next = new MethodList(method);
}
return head;
}
private int length() {
int len = 1;
for (MethodList ml = next; ml != null; ml = ml.next) {
len++;
}
return len;
}
/**
* @return 1st method in list with most specific return type
*/
Method getMostSpecific() {
Method m = method;
Class<?> rt = m.getReturnType();
for (MethodList ml = next; ml != null; ml = ml.next) {
Method m2 = ml.method;
Class<?> rt2 = m2.getReturnType();
if (rt2 != rt && rt.isAssignableFrom(rt2)) {
// found more specific return type
m = m2;
rt = rt2;
}
}
return m;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2017, 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
@ -1786,10 +1786,6 @@ public abstract class VarHandle {
AccessMode(final String methodName, AccessType at) {
this.methodName = methodName;
this.at = at;
// Assert that return type is correct
// Otherwise, when disabled avoid using reflection
assert at.returnType == getReturnType(methodName);
}
/**
@ -1821,16 +1817,6 @@ public abstract class VarHandle {
throw new IllegalArgumentException("No AccessMode value for method name " + methodName);
}
private static Class<?> getReturnType(String name) {
try {
Method m = VarHandle.class.getMethod(name, Object[].class);
return m.getReturnType();
}
catch (Exception e) {
throw newInternalError(e);
}
}
@ForceInline
static MemberName getMemberName(int ordinal, VarForm vform) {
return vform.memberName_table[ordinal];

View File

@ -240,6 +240,11 @@ public final class Constructor<T> extends Executable {
}
@Override
Class<?>[] getSharedParameterTypes() {
return parameterTypes;
}
/**
* {@inheritDoc}
*/

View File

@ -222,6 +222,10 @@ public abstract class Executable extends AccessibleObject
*/
public abstract TypeVariable<?>[] getTypeParameters();
// returns shared array of parameter types - must never give it out
// to the untrusted code...
abstract Class<?>[] getSharedParameterTypes();
/**
* Returns an array of {@code Class} objects that represent the formal
* parameter types, in declaration order, of the executable

View File

@ -290,6 +290,11 @@ public final class Method extends Executable {
} else { return getReturnType();}
}
@Override
Class<?>[] getSharedParameterTypes() {
return parameterTypes;
}
/**
* {@inheritDoc}
*/

View File

@ -132,6 +132,10 @@ class ReflectAccess implements jdk.internal.reflect.LangReflectAccess {
return ex.getTypeAnnotationBytes();
}
public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
return ex.getSharedParameterTypes();
}
//
// Copying routines, needed to quickly fabricate new Field,
// Method, and Constructor objects from templates

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -172,6 +172,8 @@ public class ChoiceFormat extends NumberFormat {
/**
* Sets the pattern.
* @param newPattern See the class description.
* @exception NullPointerException if {@code newPattern}
* is {@code null}
*/
public void applyPattern(String newPattern) {
StringBuffer[] segments = new StringBuffer[2];
@ -309,6 +311,8 @@ public class ChoiceFormat extends NumberFormat {
* Constructs with limits and corresponding formats based on the pattern.
*
* @param newPattern the new pattern string
* @exception NullPointerExcpetion if {@code newPattern} is
* {@code null}
* @see #applyPattern
*/
public ChoiceFormat(String newPattern) {
@ -320,6 +324,8 @@ public class ChoiceFormat extends NumberFormat {
*
* @param limits limits in ascending order
* @param formats corresponding format strings
* @exception NullPointerException if {@code limits} or {@code formats}
* is {@code null}
* @see #setChoices
*/
public ChoiceFormat(double[] limits, String[] formats) {
@ -339,6 +345,8 @@ public class ChoiceFormat extends NumberFormat {
* When formatting with object Y,
* if the object is a NumberFormat, then ((NumberFormat) Y).format(X)
* is called. Otherwise Y.toString() is called.
* @exception NullPointerException if {@code limits} or
* {@code formats} is {@code null}
*/
public void setChoices(double[] limits, String formats[]) {
if (limits.length != formats.length) {
@ -386,6 +394,8 @@ public class ChoiceFormat extends NumberFormat {
* @param number number to be formatted and substituted.
* @param toAppendTo where text is appended.
* @param status ignore no useful status is returned.
* @exception NullPointerException if {@code toAppendTo}
* is {@code null}
*/
public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition status) {
@ -414,6 +424,9 @@ public class ChoiceFormat extends NumberFormat {
* status.index is unchanged and status.errorIndex is set to the
* first index of the character that caused the parse to fail.
* @return A Number representing the value of the number parsed.
* @exception NullPointerException if {@code status} is {@code null}
* or if {@code text} is {@code null} and the list of
* choice strings is not empty.
*/
public Number parse(String text, ParsePosition status) {
// find the best number (defined as the one with the longest parse)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -141,6 +141,25 @@ import sun.util.locale.provider.LocaleServiceProviderPool;
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
* @implSpec
* <ul><li>The {@link #format(Date, StringBuffer, FieldPosition)} and
* {@link #parse(String, ParsePosition)} methods may throw
* {@code NullPointerException}, if any of their parameter is {@code null}.
* The subclass may provide its own implementation and specification about
* {@code NullPointerException}.</li>
* <li>The {@link #setCalendar(Calendar)}, {@link
* #setNumberFormat(NumberFormat)} and {@link #setTimeZone(TimeZone)} methods
* do not throw {@code NullPointerException} when their parameter is
* {@code null}, but any subsequent operations on the same instance may throw
* {@code NullPointerException}.</li>
* <li>The {@link #getCalendar()}, {@link #getNumberFormat()} and
* {@link getTimeZone()} methods may return {@code null}, if the respective
* values of this instance is set to {@code null} through the corresponding
* setter methods. For Example: {@link #getTimeZone()} may return {@code null},
* if the {@code TimeZone} value of this instance is set as
* {@link #setTimeZone(java.util.TimeZone) setTimeZone(null)}.</li>
* </ul>
*
* @see Format
* @see NumberFormat
* @see SimpleDateFormat
@ -296,6 +315,8 @@ public abstract class DateFormat extends Format {
* the begin index and end index of fieldPosition will be set to
* 5 and 8, respectively, for the first occurrence of the timezone
* pattern character 'z'.
* @exception IllegalArgumentException if the {@code Format} cannot format
* the given {@code obj}.
* @see java.text.Format
*/
public final StringBuffer format(Object obj, StringBuffer toAppendTo,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -514,6 +514,8 @@ public class DecimalFormat extends NumberFormat {
* @param result where the text is to be appended
* @param fieldPosition On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @exception NullPointerException if {@code result} or
* {@code fieldPosition} is {@code null}
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string
@ -632,6 +634,8 @@ public class DecimalFormat extends NumberFormat {
* @param result where the text is to be appended
* @param fieldPosition On input: an alignment field, if desired.
* On output: the offsets of the alignment field.
* @exception NullPointerException if {@code result} or
* {@code fieldPosition} is {@code null}
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -356,6 +356,8 @@ public class MessageFormat extends Format {
*
* @param pattern the pattern for this message format
* @exception IllegalArgumentException if the pattern is invalid
* @exception NullPointerException if {@code pattern} is
* {@code null}
*/
public MessageFormat(String pattern) {
this.locale = Locale.getDefault(Locale.Category.FORMAT);
@ -373,6 +375,8 @@ public class MessageFormat extends Format {
* @param pattern the pattern for this message format
* @param locale the locale for this message format
* @exception IllegalArgumentException if the pattern is invalid
* @exception NullPointerException if {@code pattern} is
* {@code null}
* @since 1.4
*/
public MessageFormat(String pattern, Locale locale) {
@ -420,6 +424,8 @@ public class MessageFormat extends Format {
*
* @param pattern the pattern for this message format
* @exception IllegalArgumentException if the pattern is invalid
* @exception NullPointerException if {@code pattern} is
* {@code null}
*/
@SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
public void applyPattern(String pattern) {
@ -814,6 +820,7 @@ public class MessageFormat extends Format {
* @exception IllegalArgumentException if an argument in the
* <code>arguments</code> array is not of the type
* expected by the format element(s) that use it.
* @exception NullPointerException if {@code result} is {@code null}
*/
public final StringBuffer format(Object[] arguments, StringBuffer result,
FieldPosition pos)
@ -835,6 +842,7 @@ public class MessageFormat extends Format {
* or if an argument in the <code>arguments</code> array
* is not of the type expected by the format element(s)
* that use it.
* @exception NullPointerException if {@code pattern} is {@code null}
*/
public static String format(String pattern, Object ... arguments) {
MessageFormat temp = new MessageFormat(pattern);
@ -858,6 +866,7 @@ public class MessageFormat extends Format {
* @exception IllegalArgumentException if an argument in the
* <code>arguments</code> array is not of the type
* expected by the format element(s) that use it.
* @exception NullPointerException if {@code result} is {@code null}
*/
public final StringBuffer format(Object arguments, StringBuffer result,
FieldPosition pos)
@ -947,6 +956,8 @@ public class MessageFormat extends Format {
* @param source the string to parse
* @param pos the parse position
* @return an array of parsed objects
* @exception NullPointerException if {@code pos} is {@code null}
* for a non-null {@code source} string.
*/
public Object[] parse(String source, ParsePosition pos) {
if (source == null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -174,6 +174,13 @@ import sun.util.locale.provider.LocaleServiceProviderPool;
* If multiple threads access a format concurrently, it must be synchronized
* externally.
*
* @implSpec The {@link #format(double, StringBuffer, FieldPosition)},
* {@link #format(long, StringBuffer, FieldPosition)} and
* {@link #parse(String, ParsePosition)} methods may throw
* {@code NullPointerException}, if any of their parameter is {@code null}.
* The subclass may provide its own implementation and specification about
* {@code NullPointerException}.
*
* @see DecimalFormat
* @see ChoiceFormat
* @author Mark Davis

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -905,6 +905,7 @@ public class SimpleDateFormat extends DateFormat {
* @param startDate During parsing, two digit years will be placed in the range
* <code>startDate</code> to <code>startDate + 100 years</code>.
* @see #get2DigitYearStart
* @throws NullPointerException if {@code startDate} is {@code null}.
* @since 1.2
*/
public void set2DigitYearStart(Date startDate) {
@ -933,7 +934,7 @@ public class SimpleDateFormat extends DateFormat {
* @param pos the formatting position. On input: an alignment field,
* if desired. On output: the offsets of the alignment field.
* @return the formatted date-time string.
* @exception NullPointerException if the given {@code date} is {@code null}.
* @exception NullPointerException if any of the parameters is {@code null}.
*/
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo,

View File

@ -292,12 +292,12 @@ import java.util.Set;
* W week-of-month number 4
* E day-of-week text Tue; Tuesday; T
* e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
* F week-of-month number 3
* F day-of-week-in-month number 3
*
* a am-pm-of-day text PM
* h clock-hour-of-am-pm (1-12) number 12
* K hour-of-am-pm (0-11) number 0
* k clock-hour-of-am-pm (1-24) number 0
* k clock-hour-of-day (1-24) number 24
*
* H hour-of-day (0-23) number 0
* m minute-of-hour number 30

View File

@ -1486,12 +1486,12 @@ public final class DateTimeFormatterBuilder {
* W week-of-month number 4
* E day-of-week text Tue; Tuesday; T
* e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
* F week-of-month number 3
* F day-of-week-in-month number 3
*
* a am-pm-of-day text PM
* h clock-hour-of-am-pm (1-12) number 12
* K hour-of-am-pm (0-11) number 0
* k clock-hour-of-am-pm (1-24) number 0
* k clock-hour-of-day (1-24) number 24
*
* H hour-of-day (0-23) number 0
* m minute-of-hour number 30

View File

@ -871,13 +871,13 @@ public final class ZoneRules implements Serializable {
/**
* Gets the previous transition before the specified instant.
* <p>
* This returns details of the previous transition after the specified instant.
* This returns details of the previous transition before the specified instant.
* For example, if the instant represents a point where "summer" daylight saving time
* applies, then the method will return the transition from the previous "winter" time.
*
* @param instant the instant to get the previous transition after, not null, but null
* may be ignored if the rules have a single offset for all instants
* @return the previous transition after the specified instant, null if this is before the first transition
* @return the previous transition before the specified instant, null if this is before the first transition
*/
public ZoneOffsetTransition previousTransition(Instant instant) {
if (savingsInstantTransitions.length == 0) {

View File

@ -187,7 +187,7 @@ class Random implements java.io.Serializable {
*
* This is a linear congruential pseudorandom number generator, as
* defined by D. H. Lehmer and described by Donald E. Knuth in
* <i>The Art of Computer Programming,</i> Volume 3:
* <i>The Art of Computer Programming,</i> Volume 2:
* <i>Seminumerical Algorithms</i>, section 3.2.1.
*
* @param bits random bits
@ -570,7 +570,7 @@ class Random implements java.io.Serializable {
* }}</pre>
* This uses the <i>polar method</i> of G. E. P. Box, M. E. Muller, and
* G. Marsaglia, as described by Donald E. Knuth in <i>The Art of
* Computer Programming</i>, Volume 3: <i>Seminumerical Algorithms</i>,
* Computer Programming</i>, Volume 2: <i>Seminumerical Algorithms</i>,
* section 3.4.1, subsection C, algorithm P. Note that it generates two
* independent values at the cost of only one call to {@code StrictMath.log}
* and one call to {@code StrictMath.sqrt}.

View File

@ -74,7 +74,7 @@
* {@link java.util.function.Function} (unary function from {@code T} to {@code R}),
* {@link java.util.function.Consumer} (unary function from {@code T} to {@code void}),
* {@link java.util.function.Predicate} (unary function from {@code T} to {@code boolean}),
* and {@link java.util.function.Supplier} (nilary function to {@code R}).
* and {@link java.util.function.Supplier} (nullary function to {@code R}).
* </li>
*
* <li>Function shapes have a natural arity based on how they are most

View File

@ -96,6 +96,9 @@ public interface LangReflectAccess {
/** Gets the "parameterAnnotations" field from a Constructor (used for serialization) */
public byte[] getConstructorParameterAnnotations(Constructor<?> c);
/** Gets the shared array of parameter types of an Executable. */
public Class<?>[] getExecutableSharedParameterTypes(Executable ex);
//
// Copying routines, needed to quickly fabricate new Field,
// Method, and Constructor objects from templates

View File

@ -345,6 +345,10 @@ public class ReflectionFactory {
return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
}
public Class<?>[] getExecutableSharedParameterTypes(Executable ex) {
return langReflectAccess().getExecutableSharedParameterTypes(ex);
}
//--------------------------------------------------------------------------
//
// Routines used by serialization

View File

@ -26,7 +26,6 @@
package sun.net.www;
import java.util.BitSet;
import java.io.UnsupportedEncodingException;
import java.io.File;
import java.net.URL;
import java.net.MalformedURLException;
@ -49,7 +48,7 @@ public class ParseUtil {
static BitSet encodedInPath;
static {
encodedInPath = new BitSet(256);
encodedInPath = new BitSet(128);
// Set the bits corresponding to characters that are encoded in the
// path component of a URI.
@ -102,14 +101,45 @@ public class ParseUtil {
* dependent File.separatorChar.
*/
public static String encodePath(String path, boolean flag) {
char[] retCC = new char[path.length() * 2 + 16];
int retLen = 0;
char[] pathCC = path.toCharArray();
if (flag && File.separatorChar != '/') {
return encodePath(path, 0, File.separatorChar);
} else {
int index = firstEncodeIndex(path);
if (index > -1) {
return encodePath(path, index, '/');
} else {
return path;
}
}
}
int n = path.length();
for (int i=0; i<n; i++) {
private static int firstEncodeIndex(String path) {
int len = path.length();
for (int i = 0; i < len; i++) {
char c = path.charAt(i);
if (c == '/' || c == '.' ||
c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9') {
continue;
} else if (c > 0x007F || encodedInPath.get(c)) {
return i;
}
}
return -1;
}
private static String encodePath(String path, int index, char sep) {
char[] pathCC = path.toCharArray();
char[] retCC = new char[pathCC.length * 2 + 16 - index];
if (index > 0) {
System.arraycopy(pathCC, 0, retCC, 0, index);
}
int retLen = index;
for (int i = index; i < pathCC.length; i++) {
char c = pathCC[i];
if ((!flag && c == '/') || (flag && c == File.separatorChar))
if (c == sep)
retCC[retLen++] = '/';
else {
if (c <= 0x007F) {
@ -117,11 +147,11 @@ public class ParseUtil {
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9') {
retCC[retLen++] = c;
} else
if (encodedInPath.get(c))
} else if (encodedInPath.get(c)) {
retLen = escape(retCC, c, retLen);
else
} else {
retCC[retLen++] = c;
}
} else if (c > 0x07FF) {
retLen = escape(retCC, (char)(0xE0 | ((c >> 12) & 0x0F)), retLen);
retLen = escape(retCC, (char)(0x80 | ((c >> 6) & 0x3F)), retLen);

View File

@ -242,8 +242,9 @@ class InputRecord implements Record, Closeable {
// 2: ClientHello.client_version
// 32: ClientHello.random
// 1: length byte of ClientHello.session_id
// 2: length bytes of ClientHello.cipher_suites
// 2: empty ClientHello.compression_methods
int requiredSize = 46 + sessionIdLen + ((cipherSpecLen * 2 ) / 3 );
int requiredSize = 48 + sessionIdLen + ((cipherSpecLen * 2 ) / 3 );
byte[] converted = new byte[requiredSize];
/*

View File

@ -935,12 +935,20 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}
private static TrustManager[] getTrustManagers() throws Exception {
KeyStore ks =
TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManagerFactory.getDefaultAlgorithm());
if ("SunJSSE".equals(tmf.getProvider().getName())) {
// The implementation will load the default KeyStore
// automatically. Cached trust materials may be used
// for performance improvement.
tmf.init((KeyStore)null);
} else {
// Use the explicitly specified KeyStore for third party's
// TrustManagerFactory implementation.
KeyStore ks = TrustStoreManager.getTrustedKeyStore();
tmf.init(ks);
}
return tmf.getTrustManagers();
}

View File

@ -32,6 +32,7 @@ import java.security.cert.*;
import javax.net.ssl.*;
import sun.security.validator.Validator;
import sun.security.validator.TrustStoreUtil;
abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
@ -47,7 +48,7 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
protected void engineInit(KeyStore ks) throws KeyStoreException {
if (ks == null) {
try {
ks = getCacertsKeyStore("trustmanager");
trustManager = getInstance(TrustStoreManager.getTrustedCerts());
} catch (SecurityException se) {
// eat security exceptions but report other throwables
if (debug != null && Debug.isOn("trustmanager")) {
@ -72,14 +73,17 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
"SunX509: skip default keystore: " + e);
}
throw new KeyStoreException(
"problem accessing trust store" + e);
"problem accessing trust store", e);
}
} else {
trustManager = getInstance(TrustStoreUtil.getTrustedCerts(ks));
}
trustManager = getInstance(ks);
isInitialized = true;
}
abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
abstract X509TrustManager getInstance(
Collection<X509Certificate> trustedCerts);
abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException;
@ -126,126 +130,14 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
});
}
/**
* Returns the keystore with the configured CA certificates.
*/
static KeyStore getCacertsKeyStore(String dbgname) throws Exception
{
String storeFileName = null;
File storeFile = null;
FileInputStream fis = null;
String defaultTrustStoreType;
String defaultTrustStoreProvider;
final HashMap<String,String> props = new HashMap<>();
final String sep = File.separator;
KeyStore ks = null;
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
props.put("trustStore", System.getProperty(
"javax.net.ssl.trustStore"));
props.put("javaHome", System.getProperty(
"java.home"));
props.put("trustStoreType", System.getProperty(
"javax.net.ssl.trustStoreType",
KeyStore.getDefaultType()));
props.put("trustStoreProvider", System.getProperty(
"javax.net.ssl.trustStoreProvider", ""));
props.put("trustStorePasswd", System.getProperty(
"javax.net.ssl.trustStorePassword", ""));
return null;
}
});
/*
* Try:
* javax.net.ssl.trustStore (if this variable exists, stop)
* jssecacerts
* cacerts
*
* If none exists, we use an empty keystore.
*/
try {
storeFileName = props.get("trustStore");
if (!"NONE".equals(storeFileName)) {
if (storeFileName != null) {
storeFile = new File(storeFileName);
fis = getFileInputStream(storeFile);
} else {
String javaHome = props.get("javaHome");
storeFile = new File(javaHome + sep + "lib" + sep
+ "security" + sep +
"jssecacerts");
if ((fis = getFileInputStream(storeFile)) == null) {
storeFile = new File(javaHome + sep + "lib" + sep
+ "security" + sep +
"cacerts");
fis = getFileInputStream(storeFile);
}
}
if (fis != null) {
storeFileName = storeFile.getPath();
} else {
storeFileName = "No File Available, using empty keystore.";
}
}
defaultTrustStoreType = props.get("trustStoreType");
defaultTrustStoreProvider = props.get("trustStoreProvider");
if (debug != null && Debug.isOn(dbgname)) {
System.out.println("trustStore is: " + storeFileName);
System.out.println("trustStore type is : " +
defaultTrustStoreType);
System.out.println("trustStore provider is : " +
defaultTrustStoreProvider);
}
/*
* Try to initialize trust store.
*/
if (defaultTrustStoreType.length() != 0) {
if (debug != null && Debug.isOn(dbgname)) {
System.out.println("init truststore");
}
if (defaultTrustStoreProvider.length() == 0) {
ks = KeyStore.getInstance(defaultTrustStoreType);
} else {
ks = KeyStore.getInstance(defaultTrustStoreType,
defaultTrustStoreProvider);
}
char[] passwd = null;
String defaultTrustStorePassword =
props.get("trustStorePasswd");
if (defaultTrustStorePassword.length() != 0)
passwd = defaultTrustStorePassword.toCharArray();
// if trustStore is NONE, fis will be null
ks.load(fis, passwd);
// Zero out the temporary password storage
if (passwd != null) {
for (int i = 0; i < passwd.length; i++) {
passwd[i] = (char)0;
}
}
}
} finally {
if (fis != null) {
fis.close();
}
}
return ks;
}
public static final class SimpleFactory extends TrustManagerFactoryImpl {
@Override
X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
X509TrustManager getInstance(
Collection<X509Certificate> trustedCerts) {
return new X509TrustManagerImpl(
Validator.TYPE_SIMPLE, trustedCerts);
}
@Override
X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException {
@ -253,13 +145,15 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
("SunX509 TrustManagerFactory does not use "
+ "ManagerFactoryParameters");
}
}
}
public static final class PKIXFactory extends TrustManagerFactoryImpl {
@Override
X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
X509TrustManager getInstance(
Collection<X509Certificate> trustedCerts) {
return new X509TrustManagerImpl(Validator.TYPE_PKIX, trustedCerts);
}
@Override
X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException {

View File

@ -0,0 +1,395 @@
/*
* 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.
*/
package sun.security.ssl;
import java.lang.ref.WeakReference;
import java.io.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import sun.security.action.*;
import sun.security.validator.TrustStoreUtil;
/**
* Collection of static utility methods to manage the default trusted KeyStores
* effectively.
*/
final class TrustStoreManager {
private static final Debug debug = Debug.getInstance("ssl");
// A singleton service to manage the default trusted KeyStores effectively.
private static final TrustAnchorManager tam = new TrustAnchorManager();
// Restrict instantiation of this class.
private TrustStoreManager() {
// empty
}
/**
* Return an unmodifiable set of all trusted X509Certificates contained
* in the default trusted KeyStore.
*/
public static Set<X509Certificate> getTrustedCerts() throws Exception {
return tam.getTrustedCerts(TrustStoreDescriptor.createInstance());
}
/**
* Return an instance of the default trusted KeyStore.
*/
public static KeyStore getTrustedKeyStore() throws Exception {
return tam.getKeyStore(TrustStoreDescriptor.createInstance());
}
/**
* A descriptor of the default trusted KeyStore.
*
* The preference of the default trusted KeyStore is:
* javax.net.ssl.trustStore
* jssecacerts
* cacerts
*/
private static final class TrustStoreDescriptor {
private static final String fileSep = File.separator;
private static final String defaultStorePath =
GetPropertyAction.privilegedGetProperty("java.home") +
fileSep + "lib" + fileSep + "security";
private static final String defaultStore =
defaultStorePath + fileSep + "cacerts";
private static final String jsseDefaultStore =
defaultStorePath + fileSep + "jssecacerts";
// the trust store name
private final String storeName;
// the trust store type, JKS/PKCS12
private final String storeType;
// the provider of the trust store
private final String storeProvider;
// the password used for the trust store
private final String storePassword;
// the File object of the trust store
private final File storeFile;
// the last modified time of the store
private final long lastModified;
private TrustStoreDescriptor(String storeName, String storeType,
String storeProvider, String storePassword,
File storeFile, long lastModified) {
this.storeName = storeName;
this.storeType = storeType;
this.storeProvider = storeProvider;
this.storePassword = storePassword;
this.storeFile = storeFile;
this.lastModified = lastModified;
if (debug != null && Debug.isOn("trustmanager")) {
System.out.println(
"trustStore is: " + storeName + "\n" +
"trustStore type is: " + storeType + "\n" +
"trustStore provider is: " + storeProvider + "\n" +
"the last modified time is: " + (new Date(lastModified)));
}
}
/**
* Create an instance of TrustStoreDescriptor for the default
* trusted KeyStore.
*/
static TrustStoreDescriptor createInstance() {
return AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public TrustStoreDescriptor run() {
// Get the system properties for trust store.
String storePropName = System.getProperty(
"javax.net.ssl.trustStore", jsseDefaultStore);
String storePropType = System.getProperty(
"javax.net.ssl.trustStoreType",
KeyStore.getDefaultType());
String storePropProvider = System.getProperty(
"javax.net.ssl.trustStoreProvider", "");
String storePropPassword = System.getProperty(
"javax.net.ssl.trustStorePassword", "");
String temporaryName = "";
File temporaryFile = null;
long temporaryTime = 0L;
if (!"NONE".equals(storePropName)) {
String[] fileNames =
new String[] {storePropName, defaultStore};
for (String fileName : fileNames) {
File f = new File(fileName);
if (f.isFile() && f.canRead()) {
temporaryName = fileName;;
temporaryFile = f;
temporaryTime = f.lastModified();
break;
}
// Not break, the file is inaccessible.
if (debug != null &&
Debug.isOn("trustmanager")) {
System.out.println(
"Inaccessible trust store: " +
storePropName);
}
}
} else {
temporaryName = storePropName;
}
return new TrustStoreDescriptor(
temporaryName, storePropType, storePropProvider,
storePropPassword, temporaryFile, temporaryTime);
}
});
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof TrustStoreDescriptor) {
TrustStoreDescriptor that = (TrustStoreDescriptor)obj;
return ((this.lastModified == that.lastModified) &&
Objects.equals(this.storeName, that.storeName) &&
Objects.equals(this.storeType, that.storeType) &&
Objects.equals(this.storeProvider, that.storeProvider));
}
return false;
}
// Please be careful if computing security-sensitive attributes'
// hash code. For example the storePassword should not be computed.
@Override
public int hashCode() {
int result = 17;
if (storeName != null && !storeName.isEmpty()) {
result = 31 * result + storeName.hashCode();
}
if (storeType != null && !storeType.isEmpty()) {
result = 31 * result + storeType.hashCode();
}
if (storeProvider != null && !storeProvider.isEmpty()) {
result = 31 * result + storeProvider.hashCode();
}
if (storeFile != null) {
result = 31 * result + storeFile.hashCode();
}
if (lastModified != 0L) {
result = (int)(31 * result + lastModified);
}
return result;
}
}
/**
* The trust anchors manager used to expedite the performance.
*
* This class can be used to provide singleton services to access default
* trust KeyStore more effectively.
*/
private static final class TrustAnchorManager {
// Last trust store descriptor.
private TrustStoreDescriptor descriptor;
// The key store used for the trust anchors.
//
// Use weak reference so that the heavy loaded KeyStore object can
// be atomically cleared, and reloaded if needed.
private WeakReference<KeyStore> ksRef;
// The trusted X.509 certificates in the key store.
//
// Use weak reference so that the heavy loaded certificates collection
// objects can be atomically cleared, and reloaded if needed.
private WeakReference<Set<X509Certificate>> csRef;
private TrustAnchorManager() {
this.descriptor = null;
this.ksRef = new WeakReference<>(null);
this.csRef = new WeakReference<>(null);
}
/**
* Get the default trusted KeyStore with the specified descriptor.
*
* @return null if the underlying KeyStore is not available.
*/
synchronized KeyStore getKeyStore(
TrustStoreDescriptor descriptor) throws Exception {
TrustStoreDescriptor temporaryDesc = this.descriptor;
KeyStore ks = ksRef.get();
if ((ks != null) && descriptor.equals(temporaryDesc)) {
return ks;
}
// Reload a new key store.
if ((debug != null) && Debug.isOn("trustmanager")) {
System.out.println("Reload the trust store");
}
ks = loadKeyStore(descriptor);
this.descriptor = descriptor;
this.ksRef = new WeakReference<>(ks);
return ks;
}
/**
* Get trusted certificates in the default trusted KeyStore with
* the specified descriptor.
*
* @return empty collection if the underlying KeyStore is not available.
*/
synchronized Set<X509Certificate> getTrustedCerts(
TrustStoreDescriptor descriptor) throws Exception {
KeyStore ks = null;
TrustStoreDescriptor temporaryDesc = this.descriptor;
Set<X509Certificate> certs = csRef.get();
if (certs != null) {
if (descriptor.equals(temporaryDesc)) {
return certs;
} else {
// Use the new descriptor.
this.descriptor = descriptor;
}
} else {
// Try to use the cached store at first.
if (descriptor.equals(temporaryDesc)) {
ks = ksRef.get();
} else {
// Use the new descriptor.
this.descriptor = descriptor;
}
}
// Reload the trust store if needed.
if (ks == null) {
if ((debug != null) && Debug.isOn("trustmanager")) {
System.out.println("Reload the trust store");
}
ks = loadKeyStore(descriptor);
}
// Reload trust certs from the key store.
if ((debug != null) && Debug.isOn("trustmanager")) {
System.out.println("Reload trust certs");
}
certs = loadTrustedCerts(ks);
if ((debug != null) && Debug.isOn("trustmanager")) {
System.out.println("Reloaded " + certs.size() + " trust certs");
}
// Note that as ks is a local variable, it is not
// necessary to add it to the ksRef weak reference.
this.csRef = new WeakReference<>(certs);
return certs;
}
/**
* Load the the KeyStore as described in the specified descriptor.
*/
private static KeyStore loadKeyStore(
TrustStoreDescriptor descriptor) throws Exception {
if (!"NONE".equals(descriptor.storeName) &&
descriptor.storeFile == null) {
// No file available, no KeyStore available.
if (debug != null && Debug.isOn("trustmanager")) {
System.out.println("No available key store");
}
return null;
}
KeyStore ks;
if (descriptor.storeProvider.isEmpty()) {
ks = KeyStore.getInstance(descriptor.storeType);
} else {
ks = KeyStore.getInstance(
descriptor.storeType, descriptor.storeProvider);
}
char[] password = null;
if (!descriptor.storePassword.isEmpty()) {
password = descriptor.storePassword.toCharArray();
}
if (!"NONE".equals(descriptor.storeName)) {
try (FileInputStream fis = AccessController.doPrivileged(
new OpenFileInputStreamAction(descriptor.storeFile))) {
ks.load(fis, password);
} catch (FileNotFoundException fnfe) {
// No file available, no KeyStore available.
if (debug != null && Debug.isOn("trustmanager")) {
System.out.println(
"Not available key store: " + descriptor.storeName);
}
return null;
}
} else {
ks.load(null, password);
}
return ks;
}
/**
* Load trusted certificates from the specified KeyStore.
*/
private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) {
if (ks == null) {
return Collections.<X509Certificate>emptySet();
}
return TrustStoreUtil.getTrustedCerts(ks);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -68,16 +68,21 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
private static final Debug debug = Debug.getInstance("ssl");
X509TrustManagerImpl(String validatorType, KeyStore ks)
throws KeyStoreException {
X509TrustManagerImpl(String validatorType,
Collection<X509Certificate> trustedCerts) {
this.validatorType = validatorType;
this.pkixParams = null;
if (ks == null) {
if (trustedCerts == null) {
trustedCerts = Collections.<X509Certificate>emptySet();
} else {
trustedCerts = KeyStores.getTrustedCerts(ks);
}
showTrustedCerts();
this.trustedCerts = trustedCerts;
if (debug != null && Debug.isOn("trustmanager")) {
showTrustedCerts();
}
}
X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
@ -90,7 +95,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
Validator v = getValidator(Validator.VAR_TLS_SERVER);
trustedCerts = v.getTrustedCertificates();
serverValidator = v;
showTrustedCerts();
if (debug != null && Debug.isOn("trustmanager")) {
showTrustedCerts();
}
}
@Override
@ -305,22 +313,20 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
private void showTrustedCerts() {
if (debug != null && Debug.isOn("trustmanager")) {
for (X509Certificate cert : trustedCerts) {
System.out.println("adding as trusted cert:");
System.out.println(" Subject: "
+ cert.getSubjectX500Principal());
System.out.println(" Issuer: "
+ cert.getIssuerX500Principal());
System.out.println(" Algorithm: "
+ cert.getPublicKey().getAlgorithm()
+ "; Serial number: 0x"
+ cert.getSerialNumber().toString(16));
System.out.println(" Valid from "
+ cert.getNotBefore() + " until "
+ cert.getNotAfter());
System.out.println();
}
for (X509Certificate cert : trustedCerts) {
System.out.println("adding as trusted cert:");
System.out.println(" Subject: "
+ cert.getSubjectX500Principal());
System.out.println(" Issuer: "
+ cert.getIssuerX500Principal());
System.out.println(" Algorithm: "
+ cert.getPublicKey().getAlgorithm()
+ "; Serial number: 0x"
+ cert.getSerialNumber().toString(16));
System.out.println(" Valid from "
+ cert.getNotBefore() + " until "
+ cert.getNotAfter());
System.out.println();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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,76 +25,33 @@
package sun.security.validator;
import java.io.*;
import java.util.*;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Enumeration;
import java.security.*;
import java.security.cert.*;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
import sun.security.action.*;
/**
* Collection of static utility methods related to KeyStores.
* Collection of static utility methods related to trust anchor KeyStores.
*
* @author Andreas Sterbenz
*/
public class KeyStores {
public final class TrustStoreUtil {
private KeyStores() {
private TrustStoreUtil() {
// empty
}
// in the future, all accesses to the system cacerts keystore should
// go through this class. but not right now.
/*
private static final String javaHome =
(String)AccessController.doPrivileged(new GetPropertyAction("java.home"));
private static final char SEP = File.separatorChar;
private static KeyStore caCerts;
private static KeyStore getKeyStore(String type, String name,
char[] password) throws IOException {
if (type == null) {
type = "JKS";
}
try {
KeyStore ks = KeyStore.getInstance(type);
FileInputStream in = (FileInputStream)AccessController.doPrivileged
(new OpenFileInputStreamAction(name));
ks.load(in, password);
return ks;
} catch (GeneralSecurityException e) {
// XXX
throw new IOException();
} catch (PrivilegedActionException e) {
throw (IOException)e.getCause();
}
}
/**
* Return a KeyStore with the contents of the lib/security/cacerts file.
* The file is only opened once per JVM invocation and the contents
* cached subsequently.
*
public static synchronized KeyStore getCaCerts() throws IOException {
if (caCerts != null) {
return caCerts;
}
String name = javaHome + SEP + "lib" + SEP + "security" + SEP + "cacerts";
caCerts = getKeyStore(null, name, null);
return caCerts;
}
*/
/**
* Return a Set with all trusted X509Certificates contained in
* this KeyStore.
* Return an unmodifiable Set with all trusted X509Certificates contained
* in the specified KeyStore.
*/
public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
Set<X509Certificate> set = new HashSet<X509Certificate>();
Set<X509Certificate> set = new HashSet<>();
try {
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
String alias = e.nextElement();
@ -113,8 +70,10 @@ public class KeyStores {
}
} catch (KeyStoreException e) {
// ignore
//
// This should be rare, but better to log this in the future.
}
return set;
}
return Collections.unmodifiableSet(set);
}
}

View File

@ -166,7 +166,7 @@ public abstract class Validator {
*/
public static Validator getInstance(String type, String variant,
KeyStore ks) {
return getInstance(type, variant, KeyStores.getTrustedCerts(ks));
return getInstance(type, variant, TrustStoreUtil.getTrustedCerts(ks));
}
/**

View File

@ -1248,6 +1248,7 @@ ParseArguments(int *pargc, char ***pargv,
char *value = NULL;
int kind = GetOpt(&argc, &argv, &option, &value);
jboolean has_arg = value != NULL && JLI_StrLen(value) > 0;
jboolean has_arg_any_len = value != NULL;
/*
* Option to set main entry point
@ -1269,7 +1270,7 @@ ParseArguments(int *pargc, char ***pargv,
JLI_StrCCmp(arg, "--class-path=") == 0 ||
JLI_StrCmp(arg, "-classpath") == 0 ||
JLI_StrCmp(arg, "-cp") == 0) {
REPORT_ERROR (has_arg, ARG_ERROR1, arg);
REPORT_ERROR (has_arg_any_len, ARG_ERROR1, arg);
SetClassPath(value);
mode = LM_CLASS;
} else if (JLI_StrCmp(arg, "--list-modules") == 0 ||

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2017, 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
@ -226,7 +226,12 @@ handleSetLength(FD fd, jlong length)
if (fstat64(fd, &sb) == 0 && length > sb.st_blocks*512) {
RESTARTABLE(fallocate64(fd, 0, 0, length), result);
return result;
// Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
if (result == 0) {
return 0;
} else if (errno != EOPNOTSUPP && errno != ENOSYS) {
return result;
}
}
#endif
RESTARTABLE(ftruncate64(fd, length), result);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2017, 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
@ -197,14 +197,17 @@ Java_sun_nio_ch_FileDispatcherImpl_allocate0(JNIEnv *env, jobject this,
* any blocks which can cause a SIGBUS error if the file is subsequently
* memory-mapped.
*/
return handle(env,
fallocate64(fdval(env, fdo), 0, 0, size),
"Allocation failed");
#else
// Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
int result = fallocate64(fdval(env, fdo), 0, 0, size);
if (result == 0) {
return 0;
} else if (errno != EOPNOTSUPP && errno != ENOSYS) {
return handle(env, result, "Allocation failed");
}
#endif
return handle(env,
ftruncate64(fdval(env, fdo), size),
"Truncation failed");
#endif
}
JNIEXPORT jlong JNICALL

View File

@ -64,7 +64,7 @@ import jdk.internal.reflect.Reflection;
*</ul>
*
*<P>
* @ImplNote
* @implNote
* {@code DriverManager} initialization is done lazily and looks up service
* providers using the thread context class loader. The drivers loaded and
* available to an application will depend on the thread context class loader of

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, 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
@ -275,6 +275,10 @@ public abstract class TransformService implements Transform {
dom = true;
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException("No such provider: " +
provider);
}
Service s = p.getService("TransformService", algorithm);
if (s != null) {
String value = s.getAttribute("MechanismType");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, 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
@ -305,6 +305,10 @@ public abstract class XMLSignatureFactory {
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException("No such provider: " +
provider);
}
Service s = p.getService("XMLSignatureFactory", mechanismType);
if (s != null) {
Object obj = null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2017, 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
@ -258,6 +258,10 @@ public abstract class KeyInfoFactory {
throw new NoSuchProviderException();
}
Provider p = Security.getProvider(provider);
if (p == null) {
throw new NoSuchProviderException("No such provider: " +
provider);
}
Service s = p.getService("KeyInfoFactory", mechanismType);
if (s != null) {
Object obj = null;

View File

@ -298,7 +298,11 @@ final class GssKrb5Client extends GssKrb5Base implements SaslClient {
Boolean.valueOf(integrity)});
}
intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
if (privacy || integrity) {
// Last paragraph of RFC 4752 3.1: size ... MUST be 0 if the
// client does not support any security layer
intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3);
}
if (authzID != null) {
// copy authorization id
System.arraycopy(authzID, 0, gssInToken, 4, authzID.length);

View File

@ -49,7 +49,7 @@ interface B3 extends D3 { void m(); }
interface C3 extends D3 { void m(); }
interface D3 { void m() ; }
// B.m, D.m
// B.m
interface A4 extends B4, C4 {}
interface B4 extends D4 { void m(); }
interface C4 extends D4 {}
@ -92,7 +92,7 @@ public class StarInheritance {
Class [] l3 = {B3.class, C3.class};
test(A3.class.getMethods(), new ArrayList(Arrays.asList(l3)));
Class [] l4 = {B4.class, D4.class};
Class [] l4 = {B4.class};
test(A4.class.getMethods(), new ArrayList(Arrays.asList(l4)));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -24,12 +24,15 @@
/*
* @test
* @run testng VarHandleTestAccessModeMethodNames
* @modules java.base/java.lang.invoke:open
*/
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.stream.Stream;
import static org.testng.Assert.assertEquals;
@ -43,7 +46,6 @@ public class VarHandleTestAccessModeMethodNames {
toArray(Object[][]::new);
}
@Test(dataProvider = "accessModesProvider")
public void testMethodName(VarHandle.AccessMode am) {
assertEquals(am.methodName(), toMethodName(am.name()));
@ -58,4 +60,22 @@ public class VarHandleTestAccessModeMethodNames {
}
return s.toString();
}
@Test(dataProvider = "accessModesProvider")
public void testReturnType(VarHandle.AccessMode am) throws Exception {
assertEquals(getReturnType(am.methodName()), getAccessModeReturnType(am));
}
private static Class<?> getReturnType(String name) throws Exception {
return VarHandle.class.getMethod(name, Object[].class).getReturnType();
}
private static Class<?> getAccessModeReturnType(VarHandle.AccessMode am) throws Exception {
Field field_am_at = VarHandle.AccessMode.class.getDeclaredField("at");
field_am_at.setAccessible(true);
Field field_at_returnType = field_am_at.getType().getDeclaredField("returnType");
field_at_returnType.setAccessible(true);
return (Class<?>) field_at_returnType.get(field_am_at.get(am));
}
}

View File

@ -36,9 +36,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@ -55,7 +54,7 @@ public class FilterNotMostSpecific {
for (MethodDesc expected : expectedMethods) {
if (expected.isGetMethodReturn()) {
try {
Method m = iface.getMethod(expected.name());
Method m = iface.getMethod(expected.name(), expected.parameterTypes());
if (!assertMatch(expected, m))
fail(failMsg(expected, m, iface));
else
@ -72,26 +71,18 @@ public class FilterNotMostSpecific {
public void testGetMethods(Class<?> iface) {
List<Method> foundMethods = filterObjectMethods(iface.getMethods());
MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class);
Set<Method> used = new HashSet<>();
for (MethodDesc expected : expectedMethods) {
boolean found = false;
for (Method m : foundMethods) {
if (used.contains(m))
continue;
if(expected.name().equals(m.getName()) &&
expected.declaringClass() ==m.getDeclaringClass()) {
if (assertMatch(expected, m)) {
found = true;
assertMatch(expected, m);
used.add(m);
break;
}
}
if (! found)
fail("On: "+ iface +"\nDid not find " + toMethodString(expected) + " among " + foundMethods);
if (!found)
fail("On: "+ iface +"\nDid not find " + toMethodString(expected) +
" among " + foundMethods);
}
assertEquals(foundMethods.size(), expectedMethods.length,
"\non: " + iface +
@ -104,6 +95,11 @@ public class FilterNotMostSpecific {
return false;
if (expected.declaringClass() != m.getDeclaringClass())
return false;
if (!Arrays.equals(expected.parameterTypes(), m.getParameterTypes()))
return false;
if (expected.returnType() != NotSpecified.class &&
expected.returnType() != m.getReturnType())
return false;
if (expected.kind() == MethodKind.ABSTRACT)
assertTrue(Modifier.isAbstract(m.getModifiers()), m + " should be ABSTRACT");
@ -128,8 +124,13 @@ public class FilterNotMostSpecific {
}
private String toMethodString(MethodDesc m) {
return m.declaringClass().getSimpleName().toString() + "." +
m.name() + "()";
return (m.returnType() != NotSpecified.class
? m.returnType().getSimpleName() + " "
: "") +
m.declaringClass().getSimpleName().toString() + "." +
m.name() + Stream.of(m.parameterTypes())
.map(cl -> cl.getSimpleName())
.collect(Collectors.joining(", ", "(", ")"));
}
private List<String> toMethodStrings(MethodDesc[] m) {
@ -142,11 +143,16 @@ public class FilterNotMostSpecific {
@Repeatable(MethodDescs.class)
public @interface MethodDesc {
String name();
Class<?> returnType() default NotSpecified.class;
Class<?>[] parameterTypes() default {};
Class<?> declaringClass();
MethodKind kind() default MethodKind.ABSTRACT;
boolean isGetMethodReturn() default false;
}
// special type marking a not-specified return type in @MethodDesc
interface NotSpecified {}
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodDescs {
MethodDesc[] value();
@ -172,22 +178,18 @@ public class FilterNotMostSpecific {
@MethodDesc(name="nonDefault", declaringClass=Jbis.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=I.class)
interface P2 extends Jbis, Jprim {}
@MethodDesc(name="nonDefault", declaringClass=Jbis.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=I.class)
interface P3 extends Jbis, Jprim, I {}
@MethodDesc(name="nonDefault", declaringClass=I.class,
@MethodDesc(name="nonDefault", declaringClass=J.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=J.class)
interface P4 extends I, J {}
@MethodDesc(name="nonDefault", declaringClass=J.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=I.class)
interface P5 extends J, I {}
@MethodDesc(name="nonDefault", declaringClass=J.class,
@ -198,14 +200,12 @@ public class FilterNotMostSpecific {
isGetMethodReturn=true)
interface K1M extends J { void nonDefault(); }
@MethodDesc(name="nonDefault", declaringClass=I.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=J.class)
interface K2 extends I, J {}
@MethodDesc(name="nonDefault", declaringClass=J.class,
isGetMethodReturn=true)
interface K2 extends I, J {}
@MethodDesc(name="nonDefault", declaringClass=J.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=I.class)
interface K2O extends J, I {}
@MethodDesc(name="nonDefault", declaringClass=K2M.class,
@ -244,21 +244,18 @@ public class FilterNotMostSpecific {
@MethodDesc(name="isDefault", declaringClass=M.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
isGetMethodReturn=true)
interface N2 extends M, L {}
@MethodDesc(name="isDefault", declaringClass=M.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="nonDefault", declaringClass=M.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
interface N22 extends L, M {}
@MethodDesc(name="isDefault", declaringClass=N2D.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
isGetMethodReturn=true)
interface N2D extends M, L { default void isDefault() {}}
@ -277,48 +274,36 @@ public class FilterNotMostSpecific {
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface O1 extends L, M, N2DN {}
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface O2 extends M, N2DN, L {}
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
interface O3 extends N2DN, L, M {}
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
abstract class C1 implements L, M, N2DN {}
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
abstract class C2 implements M, N2DN, L {}
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
abstract class C3 implements N2DN, L, M {}
@ -345,88 +330,54 @@ public class FilterNotMostSpecific {
@MethodDesc(name="isDefault", declaringClass=R1.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R1 extends L, M, N2DN { void isDefault(); }
@MethodDesc(name="isDefault", declaringClass=R2.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R2 extends M, N2DN, L { void isDefault(); }
@MethodDesc(name="isDefault", declaringClass=R3.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
interface R3 extends N2DN, L, M { void isDefault(); }
// this one is strange but logical, getMethod finds N2DN first, which is
// default but not the most specific
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=R1.class)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="isDefault", declaringClass=R1.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R4 extends L, M, N2DN, R1 {}
// this one is strange but logical, getMethod finds N2DN first, which is
// default but not the most specific
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=R2.class)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
@MethodDesc(name="isDefault", declaringClass=R2.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R5 extends M, N2DN, R2, L {}
// this one is strange but logical, getMethod finds N2DN first, which is
// default but not the most specific
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=R3.class)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="isDefault", declaringClass=R3.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
interface R6 extends N2DN, R3, L, M {}
// the following three finds the "right" one
@MethodDesc(name="isDefault", declaringClass=R1.class,
isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="nonDefault", declaringClass=L.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R7 extends L, M, R1, N2DN {}
@MethodDesc(name="isDefault", declaringClass=R2.class,
isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class,
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class)
interface R8 extends M, R2, N2DN, L {}
@MethodDesc(name="isDefault", declaringClass=R3.class,
isGetMethodReturn=true)
@MethodDesc(name="isDefault", declaringClass=N2DN.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="nonDefault", declaringClass=L.class)
@MethodDesc(name="nonDefault", declaringClass=M.class)
@MethodDesc(name="nonDefault", declaringClass=N2DN.class,
isGetMethodReturn=true)
interface R9 extends R3, N2DN, L, M {}
@ -445,51 +396,40 @@ public class FilterNotMostSpecific {
interface Z3 extends Z2, Z1 { void z(); }
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z3.class)
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn = true)
interface Z41 extends Z1, Z2, Z3 { }
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z3.class)
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn = true)
interface Z42 extends Z2, Z3, Z1 { }
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT)
isGetMethodReturn = true)
interface Z43 extends Z3, Z1, Z2 { }
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z3.class)
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn = true)
abstract class ZC41 implements Z1, Z2, Z3 { }
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z3.class)
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn = true)
abstract class ZC42 implements Z2, Z3, Z1 { }
@MethodDesc(name="z", declaringClass=Z3.class,
isGetMethodReturn=true)
@MethodDesc(name="z", declaringClass=Z2.class,
kind=MethodKind.DEFAULT)
isGetMethodReturn = true)
abstract class ZC43 implements Z3, Z1, Z2 { }
// More reabstraction + concretization
interface X1 { default void x() {} }
interface X2 extends X1 { void x(); }
@MethodDesc(name="x", declaringClass=X1.class,
kind=MethodKind.DEFAULT, isGetMethodReturn=true)
@MethodDesc(name="x", declaringClass=X2.class)
@MethodDesc(name="x", declaringClass=X2.class,
isGetMethodReturn=true)
interface X31 extends X1, X2 {}
@MethodDesc(name="x", declaringClass=X2.class,
isGetMethodReturn=true)
@MethodDesc(name="x", declaringClass=X1.class,
kind=MethodKind.DEFAULT)
interface X32 extends X2, X1 {}
@MethodDesc(name="x", declaringClass=X3.class,
@ -524,85 +464,107 @@ public class FilterNotMostSpecific {
interface K extends I, J { void nonDefault(); }
@MethodDesc(name="nonDefault", declaringClass=I.class,
@MethodDesc(name="nonDefault", declaringClass=K.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=J.class)
@MethodDesc(name="nonDefault", declaringClass=K.class)
abstract class ZZ1 implements I, J, K {}
@MethodDesc(name="nonDefault", declaringClass=I.class,
@MethodDesc(name="nonDefault", declaringClass=K.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=J.class)
@MethodDesc(name="nonDefault", declaringClass=K.class)
abstract class ZZ2 extends ZZ1 implements K, I, J {}
@MethodDesc(name="nonDefault", declaringClass=I.class,
@MethodDesc(name="nonDefault", declaringClass=K.class,
isGetMethodReturn=true)
@MethodDesc(name="nonDefault", declaringClass=J.class)
@MethodDesc(name="nonDefault", declaringClass=K.class)
abstract class ZZ3 extends ZZ2 implements J, K, I {}
// bridges
interface B1A { Object m(); }
interface B1B extends B1A { Map m(); }
// bridges...
@MethodDesc(name="m", declaringClass=B1C.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=B1C.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", declaringClass=B1C.class,
kind=MethodKind.DEFAULT)
interface B1C extends B1B { HashMap m(); }
interface B1 { Object m(); }
interface B2A extends B1 { Map m(); }
interface B2B extends B1 { HashMap m(); }
@MethodDesc(name="m", declaringClass=B2.class,
@MethodDesc(name="m", returnType=Object.class, declaringClass=B3A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B3A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass=B3A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=B2.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", declaringClass=B2.class,
kind=MethodKind.DEFAULT)
interface B2 extends B1C { HashMap m(); }
interface B3A extends B2A { HashMap m(); }
@MethodDesc(name="m", declaringClass=B2.class, //HahsMap
@MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=B2.class, //Map
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", declaringClass=B2.class, //Object
kind=MethodKind.DEFAULT)
interface B3A extends B2, B1A {}
interface B4A extends B3A { HashMap m(); }
// this one is funny since HashMap isn't a bridge thus not a default
@MethodDesc(name="m", declaringClass=B2.class, //HashMap
@MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=B2.class, //Map
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", declaringClass=B2.class, //Object
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", declaringClass=B1C.class) //HashMap
interface B3B extends B2, B1C {}
interface B5A2 extends B4A, B1 {}
@MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class,
isGetMethodReturn=true)
interface B5A4A extends B4A, B3A {}
// ... + most specific return type for getMethod from two unrelated interfaces
@MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class,
isGetMethodReturn=true)
interface B3AB extends B2A, B2B {}
@MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class,
kind = MethodKind.DEFAULT)
@MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class)
@MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class,
isGetMethodReturn=true)
interface B3BA extends B2B, B2A {}
// same name different params type
interface A1 { void m(); void m(int i); void m(int i, int j); }
interface A2A extends A1 { void m(); void m(int i); void m(int i, int j); }
interface A2B extends A1 { void m(); void m(int i); default void m(int i, int j) {} }
@MethodDesc(name="m", declaringClass=A1.class,
@MethodDesc(name="m", parameterTypes = {}, declaringClass=A2A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2A.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=A1.class)
@MethodDesc(name="m", declaringClass=A1.class)
@MethodDesc(name="m", declaringClass=A2A.class)
@MethodDesc(name="m", declaringClass=A2A.class)
@MethodDesc(name="m", declaringClass=A2A.class)
interface A3A extends A1, A2A {}
@MethodDesc(name="m", declaringClass=A1.class,
@MethodDesc(name="m", parameterTypes = {}, declaringClass=A2B.class,
isGetMethodReturn=true)
@MethodDesc(name="m", declaringClass=A1.class)
@MethodDesc(name="m", declaringClass=A2B.class)
@MethodDesc(name="m", declaringClass=A2B.class)
@MethodDesc(name="m", declaringClass=A2B.class,
kind=MethodKind.DEFAULT)
@MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2B.class,
isGetMethodReturn=true)
@MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2B.class,
kind = MethodKind.DEFAULT, isGetMethodReturn=true)
interface A3B extends A1, A2B {}
// method in directly implemented interface overrides interface method
// inherited by superclass
interface E { void m(); }
interface F extends E { void m(); }
abstract class G implements E {}
@MethodDesc(name="m", declaringClass=F.class, isGetMethodReturn=true)
abstract class H extends G implements F {}
@DataProvider
public Object[][] getCases() { return CASES; }
public static final Class<?>[][] CASES = {
@ -680,12 +642,16 @@ public class FilterNotMostSpecific {
{ XC42.class },
{ XC43.class },
{ B1C.class },
{ B2.class },
{ B3A.class },
{ B3B.class },
{ B4A.class },
{ B5A2.class },
{ B5A4A.class },
{ B3AB.class },
{ B3BA.class },
{ A3A.class },
{ A3B.class },
{ H.class },
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,529 @@
/*
* 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 javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;
/*
* @test
* @bug 8062389
* @summary Nearly exhaustive test of Class.getMethod() and Class.getMethods()
* @run main PublicMethodsTest
*/
public class PublicMethodsTest {
public static void main(String[] args) {
Case c = new Case1();
int[] diffs = new int[1];
try (Stream<Map.Entry<int[], Map<String, String>>>
expected = expectedResults(c)) {
diffResults(c, expected)
.forEach(diff -> {
System.out.println(diff);
diffs[0]++;
});
}
if (diffs[0] > 0) {
throw new RuntimeException(
"There were " + diffs[0] + " differences.");
}
}
// use this to generate .results file for particular case
public static class Generate {
public static void main(String[] args) {
Case c = new Case1();
dumpResults(generateResults(c))
.forEach(System.out::println);
}
}
interface Case {
Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(.+?)}");
// possible variants of interface method
List<String> INTERFACE_METHODS = List.of(
"", "void m();", "default void m() {}", "static void m() {}"
);
// possible variants of class method
List<String> CLASS_METHODS = List.of(
"", "public abstract void m();",
"public void m() {}", "public static void m() {}"
);
// template with placeholders parsed with PLACEHOLDER_PATTERN
String template();
// map of replacementKey (== PLACEHOLDER_PATTERN captured group #1) ->
// list of possible replacements
Map<String, List<String>> replacements();
// ordered list of replacement keys
List<String> replacementKeys();
// names of types occurring in the template
List<String> classNames();
}
static class Case1 implements Case {
private static final String TEMPLATE = Stream.of(
"interface I { ${I} }",
"interface J { ${J} }",
"interface K extends I, J { ${K} }",
"abstract class C { ${C} }",
"abstract class D extends C implements I { ${D} }",
"abstract class E extends D implements J, K { ${E} }"
).collect(joining("\n"));
private static final Map<String, List<String>> REPLACEMENTS = Map.of(
"I", INTERFACE_METHODS,
"J", INTERFACE_METHODS,
"K", INTERFACE_METHODS,
"C", CLASS_METHODS,
"D", CLASS_METHODS,
"E", CLASS_METHODS
);
private static final List<String> REPLACEMENT_KEYS = REPLACEMENTS
.keySet().stream().sorted().collect(Collectors.toList());
@Override
public String template() {
return TEMPLATE;
}
@Override
public Map<String, List<String>> replacements() {
return REPLACEMENTS;
}
@Override
public List<String> replacementKeys() {
return REPLACEMENT_KEYS;
}
@Override
public List<String> classNames() {
// just by accident, names of classes are equal to replacement keys
// (this need not be the case in general)
return REPLACEMENT_KEYS;
}
}
// generate all combinations as a tuple of indexes into lists of
// replacements. The index of the element in int[] tuple represents the index
// of the key in replacementKeys() list. The value of the element in int[] tuple
// represents the index of the replacement string in list of strings in the
// value of the entry of replacements() map with the corresponding key.
static Stream<int[]> combinations(Case c) {
int[] sizes = c.replacementKeys().stream()
.mapToInt(key -> c.replacements().get(key).size())
.toArray();
return Stream.iterate(
new int[sizes.length],
state -> state != null,
state -> {
int[] newState = state.clone();
for (int i = 0; i < state.length; i++) {
if (++newState[i] < sizes[i]) {
return newState;
}
newState[i] = 0;
}
// wrapped-around
return null;
}
);
}
// given the combination of indexes, return the expanded template
static String expandTemplate(Case c, int[] combination) {
// 1st create a map: key -> replacement string
Map<String, String> map = new HashMap<>(combination.length * 4 / 3 + 1);
for (int i = 0; i < combination.length; i++) {
String key = c.replacementKeys().get(i);
String repl = c.replacements().get(key).get(combination[i]);
map.put(key, repl);
}
return Case.PLACEHOLDER_PATTERN
.matcher(c.template())
.replaceAll(match -> map.get(match.group(1)));
}
/**
* compile expanded template into a ClassLoader that sees compiled classes
*/
static ClassLoader compile(String source) throws CompileException {
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
if (javac == null) {
throw new AssertionError("No Java compiler tool found.");
}
ErrorsCollector errorsCollector = new ErrorsCollector();
StandardJavaFileManager standardJavaFileManager =
javac.getStandardFileManager(errorsCollector, Locale.ROOT,
Charset.forName("UTF-8"));
TestFileManager testFileManager = new TestFileManager(
standardJavaFileManager, source);
JavaCompiler.CompilationTask javacTask;
try {
javacTask = javac.getTask(
null, // use System.err
testFileManager,
errorsCollector,
null,
null,
List.of(testFileManager.getJavaFileForInput(
StandardLocation.SOURCE_PATH,
TestFileManager.TEST_CLASS_NAME,
JavaFileObject.Kind.SOURCE))
);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
javacTask.call();
if (errorsCollector.hasError()) {
throw new CompileException(errorsCollector.getErrors());
}
return new TestClassLoader(ClassLoader.getSystemClassLoader(),
testFileManager);
}
static class CompileException extends Exception {
CompileException(List<Diagnostic<?>> diagnostics) {
super(diagnostics.stream()
.map(diag -> diag.toString())
.collect(Collectors.joining("\n")));
}
}
static class TestFileManager
extends ForwardingJavaFileManager<StandardJavaFileManager> {
static final String TEST_CLASS_NAME = "Test";
private final String testSource;
private final Map<String, ClassFileObject> classes = new HashMap<>();
TestFileManager(StandardJavaFileManager fileManager, String source) {
super(fileManager);
testSource = "public class " + TEST_CLASS_NAME + " {}\n" +
source; // the rest of classes are package-private
}
@Override
public JavaFileObject getJavaFileForInput(Location location,
String className,
JavaFileObject.Kind kind)
throws IOException {
if (location == StandardLocation.SOURCE_PATH &&
kind == JavaFileObject.Kind.SOURCE &&
TEST_CLASS_NAME.equals(className)) {
return new SourceFileObject(className, testSource);
}
return super.getJavaFileForInput(location, className, kind);
}
private static class SourceFileObject extends SimpleJavaFileObject {
private final String source;
SourceFileObject(String className, String source) {
super(
URI.create("memory:/src/" +
className.replace('.', '/') + ".java"),
Kind.SOURCE
);
this.source = source;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return source;
}
}
@Override
public JavaFileObject getJavaFileForOutput(Location location,
String className,
JavaFileObject.Kind kind,
FileObject sibling)
throws IOException {
if (kind == JavaFileObject.Kind.CLASS) {
ClassFileObject cfo = new ClassFileObject(className);
classes.put(className, cfo);
return cfo;
}
return super.getJavaFileForOutput(location, className, kind, sibling);
}
private static class ClassFileObject extends SimpleJavaFileObject {
final String className;
ByteArrayOutputStream byteArrayOutputStream;
ClassFileObject(String className) {
super(
URI.create("memory:/out/" +
className.replace('.', '/') + ".class"),
Kind.CLASS
);
this.className = className;
}
@Override
public OutputStream openOutputStream() throws IOException {
return byteArrayOutputStream = new ByteArrayOutputStream();
}
byte[] getBytes() {
if (byteArrayOutputStream == null) {
throw new IllegalStateException(
"No class file written for class: " + className);
}
return byteArrayOutputStream.toByteArray();
}
}
byte[] getClassBytes(String className) {
ClassFileObject cfo = classes.get(className);
return (cfo == null) ? null : cfo.getBytes();
}
}
static class ErrorsCollector implements DiagnosticListener<JavaFileObject> {
private final List<Diagnostic<?>> errors = new ArrayList<>();
@Override
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errors.add(diagnostic);
}
}
boolean hasError() {
return !errors.isEmpty();
}
List<Diagnostic<?>> getErrors() {
return errors;
}
}
static class TestClassLoader extends ClassLoader {
private final TestFileManager fileManager;
public TestClassLoader(ClassLoader parent, TestFileManager fileManager) {
super(parent);
this.fileManager = fileManager;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classBytes = fileManager.getClassBytes(name);
if (classBytes == null) {
throw new ClassNotFoundException(name);
}
return defineClass(name, classBytes, 0, classBytes.length);
}
}
static Map<String, String> generateResult(Case c, ClassLoader cl) {
return
c.classNames()
.stream()
.map(cn -> {
try {
return Class.forName(cn, false, cl);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Class not found: " + cn, e);
}
})
.flatMap(clazz -> Stream.of(
Map.entry(clazz.getName() + ".gM", generateGetMethodResult(clazz)),
Map.entry(clazz.getName() + ".gMs", generateGetMethodsResult(clazz))
))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
static String generateGetMethodResult(Class<?> clazz) {
try {
Method m = clazz.getMethod("m");
return m.getDeclaringClass().getName() + "." + m.getName();
} catch (NoSuchMethodException e) {
return "-";
}
}
static String generateGetMethodsResult(Class<?> clazz) {
return Stream.of(clazz.getMethods())
.filter(m -> m.getDeclaringClass() != Object.class)
.map(m -> m.getDeclaringClass().getName()
+ "." + m.getName())
.collect(Collectors.joining(", ", "[", "]"));
}
static Stream<Map.Entry<int[], Map<String, String>>> generateResults(Case c) {
return combinations(c)
.flatMap(comb -> {
String src = expandTemplate(c, comb);
ClassLoader cl;
try {
cl = compile(src);
} catch (CompileException e) {
// ignore uncompilable combinations
return Stream.empty();
}
// compilation was successful -> generate result
return Stream.of(Map.entry(
comb,
generateResult(c, cl)
));
});
}
static Stream<Map.Entry<int[], Map<String, String>>> expectedResults(Case c) {
try {
BufferedReader r = new BufferedReader(new InputStreamReader(
c.getClass().getResourceAsStream(
c.getClass().getSimpleName() + ".results"),
"UTF-8"
));
return parseResults(r.lines())
.onClose(() -> {
try {
r.close();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
});
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
static Stream<Map.Entry<int[], Map<String, String>>> parseResults(
Stream<String> lines
) {
return lines
.map(l -> l.split(Pattern.quote("#")))
.map(lkv -> Map.entry(
Stream.of(lkv[0].split(Pattern.quote(",")))
.mapToInt(Integer::parseInt)
.toArray(),
Stream.of(lkv[1].split(Pattern.quote("|")))
.map(e -> e.split(Pattern.quote("=")))
.collect(toMap(ekv -> ekv[0], ekv -> ekv[1]))
));
}
static Stream<String> dumpResults(
Stream<Map.Entry<int[], Map<String, String>>> results
) {
return results
.map(le ->
IntStream.of(le.getKey())
.mapToObj(String::valueOf)
.collect(joining(","))
+ "#" +
le.getValue().entrySet().stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(joining("|"))
);
}
static Stream<String> diffResults(
Case c,
Stream<Map.Entry<int[], Map<String, String>>> expectedResults
) {
return expectedResults
.flatMap(exp -> {
int[] comb = exp.getKey();
Map<String, String> expected = exp.getValue();
String src = expandTemplate(c, comb);
ClassLoader cl;
try {
cl = compile(src);
} catch (CompileException ce) {
return Stream.of(src + "\n" +
"got compilation error: " + ce);
}
Map<String, String> actual = generateResult(c, cl);
if (actual.equals(expected)) {
return Stream.empty();
} else {
Map<String, String> diff = new HashMap<>(expected);
diff.entrySet().removeAll(actual.entrySet());
return Stream.of(
diff.entrySet()
.stream()
.map(e -> "expected: " + e.getKey() + ": " +
e.getValue() + "\n" +
" actual: " + e.getKey() + ": " +
actual.get(e.getKey()) + "\n")
.collect(joining("\n", src + "\n\n", "\n"))
);
}
});
}
}

View File

@ -26,7 +26,7 @@
* @summary Stress test connections through the loopback interface
* @run main StressLoopback
* @run main/othervm -Djdk.net.useFastTcpLoopback StressLoopback
* @key randomness
* @key randomness intermittent
*/
import java.nio.ByteBuffer;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -54,7 +54,8 @@ public class AltSecurityManager implements Runnable {
static final String ACTIVATION = "sun.rmi.server.Activation";
// children should exit in at least this time.
static long TIME_OUT = 15000;
private static final long TIME_OUT =
(long)(15000 * TestLibrary.getTimeoutFactor());
public AltSecurityManager(int port) {
if (port <= 0) {

View File

@ -22,7 +22,7 @@
/*
* @test
* @bug 8049429
* @bug 8049429 8172273
* @modules java.management
* jdk.crypto.ec/sun.security.ec
* @summary Test that all cipher suites work in all versions and all client
@ -30,6 +30,21 @@
* and all checking is done on the client side.
* @compile CipherTestUtils.java JSSEClient.java JSSEServer.java
* @run main/othervm
* -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCIPHER=SSL_RSA_WITH_RC4_128_MD5
* TestJSSE
* @run main/othervm
* -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCIPHER=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* TestJSSE
* @run main/othervm
* -DSERVER_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCLIENT_PROTOCOL=SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2
* -DCIPHER=TLS_DHE_RSA_WITH_AES_128_CBC_SHA
* TestJSSE
* @run main/othervm
* -DSERVER_PROTOCOL=SSLv3
* -DCLIENT_PROTOCOL=SSLv3
* -DCIPHER=SSL_RSA_WITH_RC4_128_MD5

View File

@ -31,7 +31,7 @@
* @bug 7109274
* @summary Consider disabling support for X.509 certificates with RSA keys
* less than 1024 bits
*
* @library /javax/net/ssl/templates
* @run main/othervm DisabledShortRSAKeys PKIX TLSv1.2
* @run main/othervm DisabledShortRSAKeys SunX509 TLSv1.2
* @run main/othervm DisabledShortRSAKeys PKIX TLSv1.1
@ -56,20 +56,7 @@ import java.security.interfaces.*;
import java.util.Base64;
public class DisabledShortRSAKeys {
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static boolean separateServerThread = true;
public class DisabledShortRSAKeys extends SSLSocketTemplate {
/*
* Where do we find the keystores?
@ -122,82 +109,51 @@ public class DisabledShortRSAKeys {
static char passphrase[] = "passphrase".toCharArray();
/*
* Is the server ready to serve?
*/
volatile static boolean serverReady = false;
/*
* Turn on SSL debugging?
*/
static boolean debug = false;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doServerSide() throws Exception {
SSLContext context = generateSSLContext(null, targetCertStr,
targetPrivateKey);
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)sslssf.createServerSocket(serverPort);
serverPort = sslServerSocket.getLocalPort();
@Override
protected SSLContext createClientSSLContext() throws Exception {
return generateSSLContext(trustedCertStr, null, null);
}
/*
* Signal Client, we're ready for his connect.
*/
serverReady = true;
@Override
protected SSLContext createServerSSLContext() throws Exception {
return generateSSLContext(null, targetCertStr, targetPrivateKey);
}
try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
try (InputStream sslIS = sslSocket.getInputStream()) {
@Override
protected void runServerApplication(SSLSocket socket) throws Exception {
try {
try (InputStream sslIS = socket.getInputStream()) {
sslIS.read();
}
throw new Exception(
"RSA keys shorter than 1024 bits should be disabled");
throw new Exception("RSA keys shorter than 1024 bits should be disabled");
} catch (SSLHandshakeException sslhe) {
// the expected exception, ignore
}
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doClientSide() throws Exception {
@Override
protected void runClientApplication(SSLSocket socket) throws Exception {
/*
* Wait for server to get started.
*/
while (!serverReady) {
Thread.sleep(50);
}
SSLContext context = generateSSLContext(trustedCertStr, null, null);
SSLSocketFactory sslsf = context.getSocketFactory();
try (SSLSocket sslSocket =
(SSLSocket)sslsf.createSocket("localhost", serverPort)) {
try {
// only enable the target protocol
sslSocket.setEnabledProtocols(new String[] {enabledProtocol});
socket.setEnabledProtocols(new String[] { enabledProtocol });
// enable a block cipher
sslSocket.setEnabledCipherSuites(
new String[] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"});
socket.setEnabledCipherSuites(
new String[] { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" });
try (OutputStream sslOS = sslSocket.getOutputStream()) {
try (OutputStream sslOS = socket.getOutputStream()) {
sslOS.write('B');
sslOS.flush();
}
throw new Exception(
"RSA keys shorter than 1024 bits should be disabled");
"RSA keys shorter than 1024 bits should be disabled");
} catch (SSLHandshakeException sslhe) {
// the expected exception, ignore
}
@ -207,16 +163,16 @@ public class DisabledShortRSAKeys {
* =============================================================
* The remainder is just support stuff
*/
private static String tmAlgorithm; // trust manager
private static String enabledProtocol; // the target protocol
private static String tmAlgorithm; // trust manager
private static String enabledProtocol; // the target protocol
private static void parseArguments(String[] args) {
tmAlgorithm = args[0];
enabledProtocol = args[1];
tmAlgorithm = args[0];
enabledProtocol = args[1];
}
private static SSLContext generateSSLContext(String trustedCertStr,
String keyCertStr, String keySpecStr) throws Exception {
String keyCertStr, String keySpecStr) throws Exception {
// generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@ -239,10 +195,10 @@ public class DisabledShortRSAKeys {
if (keyCertStr != null) {
// generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
Base64.getMimeDecoder().decode(keySpecStr));
Base64.getMimeDecoder().decode(keySpecStr));
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey priKey =
(RSAPrivateKey)kf.generatePrivate(priKeySpec);
(RSAPrivateKey)kf.generatePrivate(priKeySpec);
// generate certificate chain
is = new ByteArrayInputStream(keyCertStr.getBytes());
@ -281,13 +237,6 @@ public class DisabledShortRSAKeys {
return ctx;
}
// use any free port by default
volatile int serverPort = 0;
volatile Exception serverException = null;
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
if (debug)
System.setProperty("javax.net.debug", "all");
@ -300,142 +249,7 @@ public class DisabledShortRSAKeys {
/*
* Start the tests.
*/
new DisabledShortRSAKeys();
new DisabledShortRSAKeys().run();
}
Thread clientThread = null;
Thread serverThread = null;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
DisabledShortRSAKeys() throws Exception {
Exception startException = null;
try {
if (separateServerThread) {
startServer(true);
startClient(false);
} else {
startClient(true);
startServer(false);
}
} catch (Exception e) {
startException = e;
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
if (serverThread != null) {
serverThread.join();
}
} else {
if (clientThread != null) {
clientThread.join();
}
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception local;
Exception remote;
if (separateServerThread) {
remote = serverException;
local = clientException;
} else {
remote = clientException;
local = serverException;
}
Exception exception = null;
/*
* Check various exception conditions.
*/
if ((local != null) && (remote != null)) {
// If both failed, return the curthread's exception.
local.initCause(remote);
exception = local;
} else if (local != null) {
exception = local;
} else if (remote != null) {
exception = remote;
} else if (startException != null) {
exception = startException;
}
/*
* If there was an exception *AND* a startException,
* output it.
*/
if (exception != null) {
if (exception != startException && startException != null) {
exception.addSuppressed(startException);
}
throw exception;
}
// Fall-through: no exception to throw!
}
void startServer(boolean newThread) throws Exception {
if (newThread) {
serverThread = new Thread() {
public void run() {
try {
doServerSide();
} catch (Exception e) {
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System.err.println("Server died...");
serverReady = true;
serverException = e;
}
}
};
serverThread.start();
} else {
try {
doServerSide();
} catch (Exception e) {
serverException = e;
} finally {
serverReady = true;
}
}
}
void startClient(boolean newThread) throws Exception {
if (newThread) {
clientThread = new Thread() {
public void run() {
try {
doClientSide();
} catch (Exception e) {
/*
* Our client thread just died.
*/
System.err.println("Client died...");
clientException = e;
}
}
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2017, 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 8172003
* @summary Test that TransformService.getInstance() throws a
* NoSuchProviderException when provider is unknown
* @run main UnknownProvider
*/
import javax.xml.crypto.dsig.TransformService;
import javax.xml.crypto.dsig.Transform;
import java.security.NoSuchProviderException;
import java.security.NoSuchAlgorithmException;
public class UnknownProvider {
public static void main(String[] args) throws NoSuchAlgorithmException {
try {
TransformService ts = TransformService.getInstance(
Transform.BASE64, "DOM", "SomeProviderThatDoesNotExist");
}
catch(NoSuchProviderException e) {
// this is expected
}
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 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 8172003
* @summary Test that XMLSignatureFactory.getInstance() throws a
* NoSuchProviderException when provider is unknown
* @run main UnknownProvider
*/
import javax.xml.crypto.dsig.XMLSignatureFactory;
import java.security.NoSuchProviderException;
public class UnknownProvider {
public static void main(String[] args) {
try {
XMLSignatureFactory sf = XMLSignatureFactory.getInstance(
"DOM", "SomeProviderThatDoesNotExist");
}
catch(NoSuchProviderException e) {
// this is expected
}
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 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 8172003
* @summary Test that KeyInfoFactory.getInstance() throws a
* NoSuchProviderException when provider is unknown
* @run main UnknownProvider
*/
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import java.security.NoSuchProviderException;
public class UnknownProvider {
public static void main(String[] args) {
try {
KeyInfoFactory fac = KeyInfoFactory.getInstance(
"DOM", "SomeProviderThatDoesNotExist");
}
catch(NoSuchProviderException e) {
// this is expected
}
}
}

View File

@ -35,7 +35,7 @@ import static org.testng.Assert.assertTrue;
/**
* Utility class for creating test modules.
*/
public class ModuleSourceBuilder {
public class ModuleInfoMaker {
private static String MODULE_INFO_JAVA = "module-info.java";
private static Pattern MODULE_PATTERN =
Pattern.compile("module\\s+((?:\\w+\\.)*)");
@ -45,7 +45,7 @@ public class ModuleSourceBuilder {
Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)");
private final Path dir;
public ModuleSourceBuilder(Path dir) {
public ModuleInfoMaker(Path dir) {
this.dir = dir;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2014, 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
@ -21,27 +21,32 @@
* questions.
*/
/*
* This test is run using PostThruProxy.sh
*/
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import javax.net.*;
import javax.net.ssl.*;
import java.security.cert.*;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
/*
* This test case is written to test the https POST through a proxy.
* There is no proxy authentication done.
*
* PostThruProxy.java -- includes a simple server that serves
* http POST method requests in secure channel, and a client
* that makes https POST request through a proxy.
* @test
* @bug 4423074
* @modules java.base/sun.net.www
* @summary This test case is written to test the https POST through a proxy.
* There is no proxy authentication done. It includes a simple server
* that serves http POST method requests in secure channel, and a client
* that makes https POST request through a proxy.
* @library /test/lib
* @compile OriginServer.java ProxyTunnelServer.java
* @run main/othervm PostThruProxy
*/
public class PostThruProxy {
private static final String TEST_SRC = System.getProperty("test.src", ".");
private static final int TIMEOUT = 30000;
/*
* Where do we find the keystores?
*/
@ -76,14 +81,10 @@ public class PostThruProxy {
/*
* Main method to create the server and client
*/
public static void main(String args[]) throws Exception
{
String keyFilename =
args[1] + "/" + pathToStores +
"/" + keyStoreFile;
String trustFilename =
args[1] + "/" + pathToStores +
"/" + trustStoreFile;
public static void main(String args[]) throws Exception {
String keyFilename = TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String trustFilename = TEST_SRC + "/" + pathToStores + "/"
+ trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
@ -95,10 +96,9 @@ public class PostThruProxy {
* setup the server
*/
try {
ServerSocketFactory ssf =
PostThruProxy.getServerSocketFactory(useSSL);
ServerSocketFactory ssf = getServerSocketFactory(useSSL);
ServerSocket ss = ssf.createServerSocket(serverPort);
ss.setSoTimeout(30000); // 30 seconds
ss.setSoTimeout(TIMEOUT); // 30 seconds
serverPort = ss.getLocalPort();
new TestServer(ss);
} catch (Exception e) {
@ -108,35 +108,29 @@ public class PostThruProxy {
}
// trigger the client
try {
doClientSide(args[0]);
doClientSide();
} catch (Exception e) {
System.out.println("Client side failed: " +
e.getMessage());
throw e;
}
}
}
private static ServerSocketFactory getServerSocketFactory
(boolean useSSL) throws Exception {
if (useSSL) {
SSLServerSocketFactory ssf = null;
// set up key manager to do server authentication
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("JKS");
char[] passphrase = passwd.toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(System.getProperty(
"javax.net.ssl.keyStore")), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getServerSocketFactory();
return ssf;
return ctx.getServerSocketFactory();
} else {
return ServerSocketFactory.getDefault();
}
@ -147,7 +141,7 @@ public class PostThruProxy {
*/
static String postMsg = "Testing HTTP post on a https server";
static void doClientSide(String hostname) throws Exception {
static void doClientSide() throws Exception {
HostnameVerifier reservedHV =
HttpsURLConnection.getDefaultHostnameVerifier();
try {
@ -162,10 +156,12 @@ public class PostThruProxy {
*/
HttpsURLConnection.setDefaultHostnameVerifier(
new NameVerifier());
URL url = new URL("https://" + hostname+ ":" + serverPort);
URL url = new URL("https://" + getHostname() +":" + serverPort);
Proxy p = new Proxy(Proxy.Type.HTTP, pAddr);
HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p);
https.setConnectTimeout(TIMEOUT);
https.setReadTimeout(TIMEOUT);
https.setDoOutput(true);
https.setRequestMethod("POST");
PrintStream ps = null;
@ -190,6 +186,9 @@ public class PostThruProxy {
if (ps != null)
ps.close();
throw e;
} catch (SocketTimeoutException e) {
System.out.println("Client can not get response in time: "
+ e.getMessage());
}
} finally {
HttpsURLConnection.setDefaultHostnameVerifier(reservedHV);
@ -210,4 +209,13 @@ public class PostThruProxy {
pserver.start();
return new InetSocketAddress("localhost", pserver.getPort());
}
private static String getHostname() {
try {
OutputAnalyzer oa = ProcessTools.executeCommand("hostname");
return oa.getOutput().trim();
} catch (Throwable e) {
throw new RuntimeException("Get hostname failed.", e);
}
}
}

View File

@ -1,62 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2003, 2012, 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 4423074
# @summary Need to rebase all the duplicated classes from Merlin
# @modules java.base/sun.net.www
HOSTNAME=`uname -n`
OS=`uname -s`
case "$OS" in
SunOS | Linux | Darwin | AIX )
PS=":"
FS="/"
;;
CYGWIN* )
PS=";"
FS="/"
;;
Windows* )
PS=";"
FS="\\"
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
EXTRAOPTS="--add-exports java.base/sun.net.www=ALL-UNNAMED"
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
${TESTSRC}${FS}OriginServer.java \
${TESTSRC}${FS}ProxyTunnelServer.java \
${TESTSRC}${FS}PostThruProxy.java
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} \
PostThruProxy ${HOSTNAME} ${TESTSRC}
exit

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2014, 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
@ -21,28 +21,32 @@
* questions.
*/
/*
* This test is run through PostThruProxyWithAuth.sh
*/
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import javax.net.*;
import javax.net.ssl.*;
import java.security.cert.*;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
/*
* This test case is written to test the https POST through a proxy
* with proxy authentication.
*
* PostThruProxyWithAuth.java -- includes a simple server that serves
* http POST method requests in secure channel, and a client
* that makes https POST request through a proxy.
* @test
* @bug 4423074
* @modules java.base/sun.net.www
* @summary This test case is written to test the https POST through a proxy
* with proxy authentication. It includes a simple server that serves
* http POST method requests in secure channel, and a client that
* makes https POST request through a proxy.
* @library /test/lib
* @compile OriginServer.java ProxyTunnelServer.java
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes= PostThruProxyWithAuth
*/
public class PostThruProxyWithAuth {
private static final String TEST_SRC = System.getProperty("test.src", ".");
private static final int TIMEOUT = 30000;
/*
* Where do we find the keystores?
*/
@ -78,14 +82,10 @@ public class PostThruProxyWithAuth {
/*
* Main method to create the server and client
*/
public static void main(String args[]) throws Exception
{
String keyFilename =
args[1] + "/" + pathToStores +
"/" + keyStoreFile;
String trustFilename =
args[1] + "/" + pathToStores +
"/" + trustStoreFile;
public static void main(String args[]) throws Exception {
String keyFilename = TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String trustFilename = TEST_SRC + "/" + pathToStores + "/"
+ trustStoreFile;
System.setProperty("javax.net.ssl.keyStore", keyFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
@ -97,10 +97,9 @@ public class PostThruProxyWithAuth {
* setup the server
*/
try {
ServerSocketFactory ssf =
PostThruProxyWithAuth.getServerSocketFactory(useSSL);
ServerSocketFactory ssf = getServerSocketFactory(useSSL);
ServerSocket ss = ssf.createServerSocket(serverPort);
ss.setSoTimeout(30000); // 30 seconds
ss.setSoTimeout(TIMEOUT); // 30 seconds
serverPort = ss.getLocalPort();
new TestServer(ss);
} catch (Exception e) {
@ -110,7 +109,7 @@ public class PostThruProxyWithAuth {
}
// trigger the client
try {
doClientSide(args[0]);
doClientSide();
} catch (Exception e) {
System.out.println("Client side failed: " +
e.getMessage());
@ -121,24 +120,18 @@ public class PostThruProxyWithAuth {
private static ServerSocketFactory getServerSocketFactory
(boolean useSSL) throws Exception {
if (useSSL) {
SSLServerSocketFactory ssf = null;
// set up key manager to do server authentication
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
SSLContext ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("JKS");
char[] passphrase = passwd.toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(System.getProperty(
"javax.net.ssl.keyStore")), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getServerSocketFactory();
return ssf;
return ctx.getServerSocketFactory();
} else {
return ServerSocketFactory.getDefault();
}
@ -149,7 +142,7 @@ public class PostThruProxyWithAuth {
*/
static String postMsg = "Testing HTTP post on a https server";
static void doClientSide(String hostname) throws Exception {
static void doClientSide() throws Exception {
/*
* setup up a proxy
*/
@ -161,10 +154,12 @@ public class PostThruProxyWithAuth {
*/
HttpsURLConnection.setDefaultHostnameVerifier(
new NameVerifier());
URL url = new URL("https://" + hostname + ":" + serverPort);
URL url = new URL("https://" + getHostname() + ":" + serverPort);
Proxy p = new Proxy(Proxy.Type.HTTP, pAddr);
HttpsURLConnection https = (HttpsURLConnection)url.openConnection(p);
https.setConnectTimeout(TIMEOUT);
https.setReadTimeout(TIMEOUT);
https.setDoOutput(true);
https.setRequestMethod("POST");
PrintStream ps = null;
@ -188,6 +183,9 @@ public class PostThruProxyWithAuth {
if (ps != null)
ps.close();
throw e;
} catch (SocketTimeoutException e) {
System.out.println("Client can not get response in time: "
+ e.getMessage());
}
}
@ -221,4 +219,13 @@ public class PostThruProxyWithAuth {
"test123".toCharArray());
}
}
private static String getHostname() {
try {
OutputAnalyzer oa = ProcessTools.executeCommand("hostname");
return oa.getOutput().trim();
} catch (Throwable e) {
throw new RuntimeException("Get hostname failed.", e);
}
}
}

View File

@ -1,62 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2003, 2012, 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 4423074
# @summary Need to rebase all the duplicated classes from Merlin
# @modules java.base/sun.net.www
HOSTNAME=`uname -n`
OS=`uname -s`
case "$OS" in
SunOS | Linux | Darwin | AIX )
PS=":"
FS="/"
;;
CYGWIN* )
PS=";"
FS="/"
;;
Windows* )
PS=";"
FS="\\"
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
EXTRAOPTS="--add-exports java.base/sun.net.www=ALL-UNNAMED"
${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} \
-d . ${TESTSRC}${FS}OriginServer.java \
${TESTSRC}${FS}ProxyTunnelServer.java \
${TESTSRC}${FS}PostThruProxyWithAuth.java
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} \
-Djdk.http.auth.tunneling.disabledSchemes= \
PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC}
exit

View File

@ -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
@ -32,13 +32,14 @@
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import javax.net.ServerSocketFactory;
import sun.net.www.*;
import java.util.Base64;
public class ProxyTunnelServer extends Thread {
private static final int TIMEOUT = 30000;
private static ServerSocket ss = null;
/*
* holds the registered user's username and password
@ -64,8 +65,9 @@ public class ProxyTunnelServer extends Thread {
public ProxyTunnelServer() throws IOException {
if (ss == null) {
ss = (ServerSocket) ServerSocketFactory.getDefault().
createServerSocket(0);
ss = (ServerSocket) ServerSocketFactory.getDefault()
.createServerSocket(0);
ss.setSoTimeout(TIMEOUT);
}
}
@ -86,6 +88,9 @@ public class ProxyTunnelServer extends Thread {
try {
clientSocket = ss.accept();
processRequests();
} catch (SocketTimeoutException e) {
System.out.println(
"Proxy can not get response in time: " + e.getMessage());
} catch (Exception e) {
System.out.println("Proxy Failed: " + e);
e.printStackTrace();
@ -188,8 +193,8 @@ public class ProxyTunnelServer extends Thread {
serverToClient.start();
System.out.println("Proxy: Started tunneling.......");
clientToServer.join();
serverToClient.join();
clientToServer.join(TIMEOUT);
serverToClient.join(TIMEOUT);
System.out.println("Proxy: Finished tunneling........");
clientToServer.close();
@ -219,13 +224,11 @@ public class ProxyTunnelServer extends Thread {
int BUFFER_SIZE = 400;
byte[] buf = new byte[BUFFER_SIZE];
int bytesRead = 0;
int count = 0; // keep track of the amount of data transfer
try {
while ((bytesRead = input.read(buf)) >= 0) {
output.write(buf, 0, bytesRead);
output.flush();
count += bytesRead;
}
} catch (IOException e) {
/*
@ -236,7 +239,7 @@ public class ProxyTunnelServer extends Thread {
}
}
public void close() {
private void close() {
try {
if (!sockIn.isClosed())
sockIn.close();
@ -275,7 +278,7 @@ public class ProxyTunnelServer extends Thread {
serverPort = Integer.parseInt(connectInfo.substring(endi+1));
} catch (Exception e) {
throw new IOException("Proxy recieved a request: "
+ connectStr);
+ connectStr, e);
}
serverInetAddr = InetAddress.getByName(serverName);
}

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 7152176 8168518
* @bug 7152176 8168518 8172017
* @summary More krb5 tests
* @library ../../../../java/security/testlibrary/ /test/lib
* @run main/othervm/timeout=300 ReplayCacheTestProc
@ -75,19 +75,28 @@ public class ReplayCacheTestProc {
private static String HOST = "localhost";
private static final String SERVICE;
private static long uid;
private static String cwd;
static {
String tmp = System.getProperty("test.service");
SERVICE = (tmp == null) ? "service" : tmp;
uid = jdk.internal.misc.VM.geteuid();
// Where should the rcache be saved. KRB5RCACHEDIR is not
// recognized on Solaris (might be supported on Solaris 12),
// and directory name is different when launched by root.
// See manpage krb5envvar(5) on KRB5RCNAME.
if (System.getProperty("os.name").startsWith("SunOS")) {
if (uid == 0) {
cwd = "/var/krb5/rcache/root/";
} else {
cwd = "/var/krb5/rcache/";
}
} else {
cwd = System.getProperty("user.dir");
}
}
// Where should the rcache be saved. It seems KRB5RCACHEDIR is not
// recognized on Solaris. Maybe version too low? I see 1.6.
private static String cwd =
System.getProperty("os.name").startsWith("SunOS") ?
"/var/krb5/rcache/" :
System.getProperty("user.dir");
private static MessageDigest md5, sha256;
static {
@ -99,7 +108,6 @@ public class ReplayCacheTestProc {
}
}
private static long uid;
public static void main0(String[] args) throws Exception {
System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
@ -114,8 +122,6 @@ public class ReplayCacheTestProc {
Ex[] result;
int numPerType = 2; // number of acceptors per type
uid = jdk.internal.misc.VM.geteuid();
KDC kdc = KDC.create(OneKDC.REALM, HOST, 0, true);
for (int i=0; i<nc; i++) {
kdc.addPrincipal(client(i), OneKDC.PASS);

View File

@ -23,14 +23,13 @@
/*
* @test
* @bug 7110803
* @bug 7110803 8170732
* @summary SASL service for multiple hostnames
* @compile -XDignore.symbol.file SaslBasic.java
* @run main/othervm SaslBasic bound
* @run main/othervm SaslBasic unbound
* @run main/othervm SaslBasic bound auth-int
* @run main/othervm SaslBasic unbound auth-conf
* @run main/othervm SaslBasic bound auth
*/
import com.sun.security.jgss.InquireType;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
@ -51,7 +50,7 @@ public class SaslBasic {
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
HashMap clntprops = new HashMap();
clntprops.put(Sasl.QOP, "auth-conf");
clntprops.put(Sasl.QOP, args[1]);
SaslClient sc = Sasl.createSaslClient(
new String[]{"GSSAPI"}, null, "server",
name, clntprops, null);
@ -74,9 +73,11 @@ public class SaslBasic {
});
byte[] token = new byte[0];
byte[] lastClientToken = null;
while (!sc.isComplete() || !ss.isComplete()) {
if (!sc.isComplete()) {
token = sc.evaluateChallenge(token);
lastClientToken = token;
}
if (!ss.isComplete()) {
token = ss.evaluateResponse(token);
@ -94,11 +95,20 @@ public class SaslBasic {
if (key == null) {
throw new Exception("Extended negotiated property not read");
}
byte[] hello = "hello".getBytes();
token = sc.wrap(hello, 0, hello.length);
token = ss.unwrap(token, 0, token.length);
if (!Arrays.equals(hello, token)) {
throw new Exception("Message altered");
if (args[1].equals("auth")) {
// 8170732. These are the maximum size bytes after jgss/krb5 wrap.
if (lastClientToken[17] != 0 || lastClientToken[18] != 0
|| lastClientToken[19] != 0) {
throw new Exception("maximum size for auth must be 0");
}
} else {
byte[] hello = "hello".getBytes();
token = sc.wrap(hello, 0, hello.length);
token = ss.unwrap(token, 0, token.length);
if (!Arrays.equals(hello, token)) {
throw new Exception("Message altered");
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -21,18 +21,21 @@
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 4919147
* @summary Support for token-based KeyStores
* @run main/othervm BadTSProvider
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
*/
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.*;
public class BadTSProvider {
@ -179,13 +182,19 @@ public class BadTSProvider {
// XXX this test must be updated if the exception message changes
Throwable cause = se.getCause();
if (cause instanceof java.security.NoSuchAlgorithmException == false) {
if (!(cause instanceof NoSuchAlgorithmException)) {
se.printStackTrace();
throw new Exception("Unexpected exception" + se);
}
cause = cause.getCause();
if (cause instanceof java.security.NoSuchProviderException == false) {
if (!(cause instanceof KeyStoreException)) {
se.printStackTrace();
throw new Exception("Unexpected exception" + se);
}
cause = cause.getCause();
if (!(cause instanceof NoSuchProviderException)) {
se.printStackTrace();
throw new Exception("Unexpected exception" + se);
}

View File

@ -31,7 +31,7 @@
* @bug 4392475
* @library /javax/net/ssl/templates
* @summary Calling setWantClientAuth(true) disables anonymous suites
* @run main/othervm AnonCipherWithWantClientAuth
* @run main/othervm -Djavax.net.debug=all AnonCipherWithWantClientAuth
*/
import java.io.InputStream;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -45,7 +45,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import sun.security.validator.KeyStores;
import sun.security.validator.TrustStoreUtil;
import sun.security.validator.Validator;
@ -113,7 +113,7 @@ public class EndEntityExtensionCheck {
Validator v = Validator.getInstance(Validator.TYPE_SIMPLE,
Validator.VAR_TLS_CLIENT,
KeyStores.getTrustedCerts(ks));
TrustStoreUtil.getTrustedCerts(ks));
try {
v.validate(chain);
throw new Exception("Chain should not have validated " +

View File

@ -27,7 +27,7 @@
* @summary Basic argument validation for --add-exports
* @library /lib/testlibrary
* @modules jdk.compiler
* @build AddExportsTestWarningError CompilerUtils ModuleSourceBuilder
* @build AddExportsTestWarningError CompilerUtils ModuleInfoMaker
* @build jdk.testlibrary.*
* @run testng AddExportsTestWarningError
*/
@ -59,7 +59,7 @@ public class AddExportsTestWarningError {
@BeforeTest
public void setup() throws Exception {
ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR);
ModuleInfoMaker builder = new ModuleInfoMaker(SRC_DIR);
builder.writeJavaFiles("m1",
"module m1 { }",
"package p1; public class C1 { " +

View File

@ -27,7 +27,7 @@
* @summary Basic argument validation for --add-reads
* @library /lib/testlibrary
* @modules jdk.compiler
* @build AddReadsTestWarningError CompilerUtils ModuleSourceBuilder
* @build AddReadsTestWarningError CompilerUtils ModuleInfoMaker
* @build jdk.testlibrary.*
* @run testng AddReadsTestWarningError
*/
@ -59,7 +59,7 @@ public class AddReadsTestWarningError {
@BeforeTest
public void setup() throws Exception {
ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR);
ModuleInfoMaker builder = new ModuleInfoMaker(SRC_DIR);
builder.writeJavaFiles("m1",
"module m1 { requires m4; }",
"package p1; public class C1 { " +

View File

@ -95,19 +95,20 @@ public class JavaClassPathTest {
public Object[][] classpath() {
return new Object[][]{
// true indicates that class path default to current working directory
{ "", "." },
{ "-Djava.class.path", "." },
{ "-Djava.class.path=", "" },
{ "-Djava.class.path=.", "." },
{ List.of(), "." },
{ List.of("-cp", ""), "" },
{ List.of("-cp", "."), "." },
{ List.of("-Djava.class.path"), "." },
{ List.of("-Djava.class.path="), "" },
{ List.of("-Djava.class.path=."), "." },
};
}
@Test(dataProvider = "classpath")
public void testUnnamedModule(String option, String expected) throws Throwable {
List<String> args = new ArrayList<>();
if (!option.isEmpty()) {
args.add(option);
}
public void testUnnamedModule(List<String> options, String expected)
throws Throwable
{
List<String> args = new ArrayList<>(options);
args.add(TEST_MAIN);
args.add(Boolean.toString(true));
args.add(expected);
@ -195,8 +196,12 @@ public class JavaClassPathTest {
}
private OutputAnalyzer execute(List<String> options) throws Throwable {
ProcessBuilder pb =
createJavaProcessBuilder(options.toArray(new String[0]));
ProcessBuilder pb = createJavaProcessBuilder(
options.stream()
.map(this::autoQuote)
.toArray(String[]::new)
);
Map<String,String> env = pb.environment();
// remove CLASSPATH environment variable
String value = env.remove("CLASSPATH");
@ -205,4 +210,16 @@ public class JavaClassPathTest {
.errorTo(System.out);
}
private static final boolean IS_WINDOWS
= System.getProperty("os.name").startsWith("Windows");
/*
* Autoquote empty string argument on Windows
*/
private String autoQuote(String arg) {
if (IS_WINDOWS && arg.isEmpty()) {
return "\"\"";
}
return arg;
}
}

View File

@ -67,14 +67,17 @@ ifneq ($(LIBS_DIR), )
# or risk invalidating the build output from external changes.
ifeq ($(filter $(OUTPUT_ROOT)/%, $(LIBS_DIR)), )
LINK_MACRO := install-file
LOG_ACTION := Copying
else
LINK_MACRO := link-file-relative
LOG_ACTION := Creating symlink
endif
$(eval $(call SetupCopyFiles, LINK_LIBS, \
SRC := $(LIBS_DIR), \
DEST := $(JDK_OUTPUTDIR)/lib, \
FILES := $(filter-out %$(SHARED_LIBRARY_SUFFIX), $(call CacheFind, $(LIBS_DIR))), \
MACRO := $(LINK_MACRO), \
LOG_ACTION := $(LOG_ACTION), \
))
TARGETS += $(COPY_LIBS) $(LINK_LIBS)
endif

View File

@ -630,13 +630,12 @@ else
# in javadoc.
java.desktop-gensrc-jdk: java.base-gensrc
# The annotation processing for jdk.vm.ci needs java.base classes from the
# current JDK.
jdk.vm.ci-gensrc-hotspot: java.base-java
# The annotation processing for jdk.vm.compiler needs classes from the current JDK.
jdk.vm.compiler-gensrc-hotspot: java.base-java java.management-java \
jdk.management-java jdk.vm.ci-java jdk.unsupported-java
# The annotation processing for jdk.vm.ci and jdk.vm.compiler needs classes
# from the current JDK.
jdk.vm.ci-gensrc-hotspot: $(addsuffix -java, \
$(call FindTransitiveDepsForModule, jdk.vm.ci))
jdk.vm.compiler-gensrc-hotspot: $(addsuffix -java, \
$(call FindTransitiveDepsForModule, jdk.vm.compiler))
# For jdk.vm.compiler, the gensrc step is generating a module-info.java.extra
# file to be processed by the gensrc-moduleinfo target.

View File

@ -76,6 +76,7 @@ else
$(filter $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/%, \
$(TARGETS))), \
MACRO := link-file-relative, \
LOG_ACTION := Creating symlink, \
))
endif

View File

@ -694,8 +694,9 @@ define AddFileToCopy
# 2 : Dest file
# 3 : Variable to add targets to
# 4 : Macro to call for copy operation
# 5 : Action text to log
$2: $1
$$(call LogInfo, Copying $$(patsubst $(OUTPUT_ROOT)/%,%,$$@))
$$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUT_ROOT)/%,%,$$@))
$$($$(strip $4))
$3 += $2
@ -721,6 +722,7 @@ identity = \
# Default is 'install-file'
# NAME_MACRO : Optionally supply a macro that rewrites the target file name
# based on the source file name
# LOG_ACTION : Optionally specify a different action text for log messages
SetupCopyFiles = $(NamedParamsMacroTemplate)
define SetupCopyFilesBody
@ -737,6 +739,10 @@ define SetupCopyFilesBody
$1_NAME_MACRO := identity
endif
ifeq ($$($1_LOG_ACTION), )
$1_LOG_ACTION := Copying
endif
# Remove any trailing slash from SRC and DEST
$1_SRC := $$(patsubst %/,%,$$($1_SRC))
$1_DEST := $$(patsubst %/,%,$$($1_DEST))
@ -744,7 +750,7 @@ define SetupCopyFilesBody
$$(foreach f, $$(patsubst $$($1_SRC)/%,%,$$($1_FILES)), \
$$(eval $$(call AddFileToCopy, $$($1_SRC)/$$f, \
$$($1_DEST)/$$(call $$(strip $$($1_NAME_MACRO)),$$(if $$($1_FLATTEN),$$(notdir $$f),$$f)), \
$1, $$($1_MACRO))))
$1, $$($1_MACRO), $$($1_LOG_ACTION))))
endef

View File

@ -384,3 +384,4 @@ a7f21ee6ed30695a6de14e74035d2857a754f62b jdk-9+144
0a4bc2f049132ddc20985565bb41b2be8a458dda jdk-9+148
c281306d33d83c92e0d870ace385d5f99678d7e7 jdk-9+149
ace1d994bca775d6545a4c874ae73d1dfc9ec18b jdk-9+150
2a0437036a64853334e538044eb68d2df70075fa jdk-9+151

View File

@ -24,33 +24,33 @@ and downlaoded using
You can clone Nashorn Mercurial forest using this command:
hg fclone http://hg.openjdk.java.net/nashorn/jdk8 nashorn~jdk8
hg fclone http://hg.openjdk.java.net/nashorn/jdk9 nashorn~jdk9
To update your copy of the forest (fwith the latest code:
(cd nashorn~jdk8 ; hg fpull)
(cd nashorn~jdk9 ; hg fpull)
Or just the nashorn subdirectory with
(cd nashorn~jdk8/nashorn ; hg pull -u)
(cd nashorn~jdk9/nashorn ; hg pull -u)
To learn about Mercurial in detail, please visit http://hgbook.red-bean.com.
- How to build?
To build Nashorn, you need to install JDK 8. You may use the Nashorn
To build Nashorn, you need to install JDK 9. You may use the Nashorn
forest build (recommended) or down load from java.net. You will need to
set JAVA_HOME environmental variable to point to your JDK installation
directory.
cd nashorn~jdk8/nashorn/make
cd nashorn~jdk9/nashorn/make
ant clean; ant
- How to run?
Use the jjs script (see RELESE_README):
cd nashorn~jdk8/nashorn
cd nashorn~jdk9/nashorn
sh bin/jjs <your .js file>
Nashorn supports javax.script API. It is possible to drop nashorn.jar in
@ -64,7 +64,7 @@ Look for samples under the directory test/src/jdk/nashorn/api/scripting/.
Comprehensive development documentation is found in the Nashorn JavaDoc. You can
build it using:
cd nashorn~jdk8/nashorn/make
cd nashorn~jdk9/nashorn/make
ant javadoc
after which you can view the generated documentation at dist/javadoc/index.html.
@ -90,7 +90,7 @@ Alternatively, you can check it out elsewhere and make
test/script/external/test262 a symbolic link to that directory. After
you've done this, you can run the ECMA-262 tests using:
cd nashorn~jdk8/nashorn/make
cd nashorn~jdk9/nashorn/make
ant test262
Ant target to get/update external test suites:
@ -101,7 +101,7 @@ Ant target to get/update external test suites:
These tests take time, so we have a parallelized runner for them that
takes advantage of all processor cores on the computer:
cd nashorn~jdk8/nashorn/make
cd nashorn~jdk9/nashorn/make
ant test262parallel
- How to write your own test?

View File

@ -1,20 +0,0 @@
The Nashorn repo is in the process of being migrated to OpenJDK and as such is
incomplete in several areas.
- The build system is not fully integrated. When complete, Nashorn will be
installed in its proper location in the JRE.
- Once integrated, the correct version of the JDK will be wrapped around
Nashorn. In the meantime, ensure you use JDK8 b68 or later.
- The jjs tool has not been implemented in binary form yet. Use "sh bin/jjs"
(or bin/jjs.bat on windows) in the interm.
- The Dynalink component is not fully integrated into Nashorn as yet, but will
be when details are finalized.
- And, finally Nashorn is still in development. To stay up to date, subscribe
to nashorn-dev@openjdk.java.net at
http://mail.openjdk.java.net/mailman/listinfo/nashorn-dev.

View File

@ -267,7 +267,7 @@
<!-- generate javadoc for Nashorn classes -->
<target name="javadoc" depends="jar">
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
<javadoc destdir="${dist.javadoc.dir}" use="yes"
windowtitle="${nashorn.product.name} ${nashorn.version}"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
<arg value="--module-source-path"/>
@ -285,7 +285,7 @@
<!-- generate javadoc only for nashorn extension api classes -->
<target name="nashornapi" depends="jar">
<mkdir dir="${dist.nashornapi.javadoc.dir}"/>
<javadoc destdir="${dist.nashornapi.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
<javadoc destdir="${dist.nashornapi.javadoc.dir}" use="yes"
extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
<arg value="--module-source-path"/>

View File

@ -82,197 +82,6 @@
*/
/**
* <p>
* Dynalink is a library for dynamic linking of high-level operations on objects.
* These operations include "read a property",
* "write a property", "invoke a function" and so on. Dynalink is primarily
* useful for implementing programming languages where at least some expressions
* have dynamic types (that is, types that can not be decided statically), and
* the operations on dynamic types are expressed as
* {@link java.lang.invoke.CallSite call sites}. These call sites will be
* linked to appropriate target {@link java.lang.invoke.MethodHandle method handles}
* at run time based on actual types of the values the expressions evaluated to.
* These can change between invocations, necessitating relinking the call site
* multiple times to accommodate new types; Dynalink handles all that and more.
* <p>
* Dynalink supports implementation of programming languages with object models
* that differ (even radically) from the JVM's class-based model and have their
* custom type conversions.
* <p>
* Dynalink is closely related to, and relies on, the {@link java.lang.invoke}
* package.
* <p>
*
* While {@link java.lang.invoke} provides a low level API for dynamic linking
* of {@code invokedynamic} call sites, it does not provide a way to express
* higher level operations on objects, nor methods that implement them. These
* operations are the usual ones in object-oriented environments: property
* access, access of elements of collections, invocation of methods and
* constructors (potentially with multiple dispatch, e.g. link- and run-time
* equivalents of Java overloaded method resolution). These are all functions
* that are normally desired in a language on the JVM. If a language is
* statically typed and its type system matches that of the JVM, it can
* accomplish this with use of the usual invocation, field access, etc.
* instructions (e.g. {@code invokevirtual}, {@code getfield}). However, if the
* language is dynamic (hence, types of some expressions are not known until
* evaluated at run time), or its object model or type system don't match
* closely that of the JVM, then it should use {@code invokedynamic} call sites
* instead and let Dynalink manage them.
* <h2>Example</h2>
* Dynalink is probably best explained by an example showing its use. Let's
* suppose you have a program in a language where you don't have to declare the
* type of an object and you want to access a property on it:
* <pre>
* var color = obj.color;
* </pre>
* If you generated a Java class to represent the above one-line program, its
* bytecode would look something like this:
* <pre>
* aload 2 // load "obj" on stack
* invokedynamic "GET:PROPERTY:color"(Object)Object // invoke property getter on object of unknown type
* astore 3 // store the return value into local variable "color"
* </pre>
* In order to link the {@code invokedynamic} instruction, we need a bootstrap
* method. A minimalist bootstrap method with Dynalink could look like this:
* <pre>
* import java.lang.invoke.*;
* import jdk.dynalink.*;
* import jdk.dynalink.support.*;
*
* class MyLanguageRuntime {
* private static final DynamicLinker dynamicLinker = new DynamicLinkerFactory().createLinker();
*
* public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
* return dynamicLinker.link(
* new SimpleRelinkableCallSite(
* new CallSiteDescriptor(lookup, parseOperation(name), type)));
* }
*
* private static Operation parseOperation(String name) {
* ...
* }
* }
* </pre>
* There are several objects of significance in the above code snippet:
* <ul>
* <li>{@link jdk.dynalink.DynamicLinker} is the main object in Dynalink, it
* coordinates the linking of call sites to method handles that implement the
* operations named in them. It is configured and created using a
* {@link jdk.dynalink.DynamicLinkerFactory}.</li>
* <li>When the bootstrap method is invoked, it needs to create a
* {@link java.lang.invoke.CallSite} object. In Dynalink, these call sites need
* to additionally implement the {@link jdk.dynalink.RelinkableCallSite}
* interface. "Relinkable" here alludes to the fact that if the call site
* encounters objects of different types at run time, its target will be changed
* to a method handle that can perform the operation on the newly encountered
* type. {@link jdk.dynalink.support.SimpleRelinkableCallSite} and
* {@link jdk.dynalink.support.ChainedCallSite} (not used in the above example)
* are two implementations already provided by the library.</li>
* <li>Dynalink uses {@link jdk.dynalink.CallSiteDescriptor} objects to
* preserve the parameters to the bootstrap method: the lookup and the method type,
* as it will need them whenever it needs to relink a call site.</li>
* <li>Dynalink uses {@link jdk.dynalink.Operation} objects to express
* dynamic operations. It does not prescribe how would you encode the operations
* in your call site, though. That is why in the above example the
* {@code parseOperation} function is left empty, and you would be expected to
* provide the code to parse the string {@code "GET:PROPERTY:color"}
* in the call site's name into a named property getter operation object as
* {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}.
* </ul>
* <p>What can you already do with the above setup? {@code DynamicLinkerFactory}
* by default creates a {@code DynamicLinker} that can link Java objects with the
* usual Java semantics. If you have these three simple classes:
* <pre>
* public class A {
* public String color;
* public A(String color) { this.color = color; }
* }
*
* public class B {
* private String color;
* public B(String color) { this.color = color; }
* public String getColor() { return color; }
* }
*
* public class C {
* private int color;
* public C(int color) { this.color = color; }
* public int getColor() { return color; }
* }
* </pre>
* and you somehow create their instances and pass them to your call site in your
* programming language:
* <pre>
* for each(var obj in [new A("red"), new B("green"), new C(0x0000ff)]) {
* print(obj.color);
* }
* </pre>
* then on first invocation, Dynalink will link the {@code .color} getter
* operation to a field getter for {@code A.color}, on second invocation it will
* relink it to {@code B.getColor()} returning a {@code String}, and finally on
* third invocation it will relink it to {@code C.getColor()} returning an {@code int}.
* The {@code SimpleRelinkableCallSite} we used above only remembers the linkage
* for the last encountered type (it implements what is known as a <i>monomorphic
* inline cache</i>). Another already provided implementation,
* {@link jdk.dynalink.support.ChainedCallSite} will remember linkages for
* several different types (it is a <i>polymorphic inline cache</i>) and is
* probably a better choice in serious applications.
* <h2>Dynalink and bytecode creation</h2>
* {@code CallSite} objects are usually created as part of bootstrapping
* {@code invokedynamic} instructions in bytecode. Hence, Dynalink is typically
* used as part of language runtimes that compile programs into Java
* {@code .class} bytecode format. Dynalink does not address the aspects of
* either creating bytecode classes or loading them into the JVM. That said,
* Dynalink can also be used without bytecode compilation (e.g. in language
* interpreters) by creating {@code CallSite} objects explicitly and associating
* them with representations of dynamic operations in the interpreted program
* (e.g. a typical representation would be some node objects in a syntax tree).
* <h2>Available operations</h2>
* Dynalink defines several standard operations in its
* {@link jdk.dynalink.StandardOperation} class. The linker for Java
* objects can link all of these operations, and you are encouraged to at
* minimum support and use these operations in your language too. The
* standard operations {@code GET} and {@code SET} need to be combined with
* at least one {@link jdk.dynalink.Namespace} to be useful, e.g. to express a
* property getter, you'd use {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY)}.
* Dynalink defines three standard namespaces in the {@link jdk.dynalink.StandardNamespace} class.
* To associate a fixed name with an operation, you can use
* {@link jdk.dynalink.NamedOperation} as in the previous example:
* {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}
* expresses a getter for the property named "color".
* <h2>Operations on multiple namespaces</h2>
* Some languages might not have separate namespaces on objects for
* properties, elements, and methods, and a source language construct might
* address several of them at once. Dynalink supports specifying multiple
* {@link jdk.dynalink.Namespace} objects with {@link jdk.dynalink.NamespaceOperation}.
* <h2>Language-specific linkers</h2>
* Languages that define their own object model different than the JVM
* class-based model and/or use their own type conversions will need to create
* their own language-specific linkers. See the {@link jdk.dynalink.linker}
* package and specifically the {@link jdk.dynalink.linker.GuardingDynamicLinker}
* interface to get started.
* <h2>Dynalink and Java objects</h2>
* The {@code DynamicLinker} objects created by {@code DynamicLinkerFactory} by
* default contain an internal instance of
* {@code BeansLinker}, which is a language-specific linker
* that implements the usual Java semantics for all of the above operations and
* can link any Java object that no other language-specific linker has managed
* to link. This way, all language runtimes have built-in interoperability with
* ordinary Java objects. See {@link jdk.dynalink.beans.BeansLinker} for details
* on how it links the various operations.
* <h2>Cross-language interoperability</h2>
* A {@code DynamicLinkerFactory} can be configured with a
* {@link jdk.dynalink.DynamicLinkerFactory#setClassLoader(ClassLoader) class
* loader}. It will try to instantiate all
* {@link jdk.dynalink.linker.GuardingDynamicLinkerExporter} classes visible to
* that class loader and compose the linkers they provide into the
* {@code DynamicLinker} it creates. This allows for interoperability between
* languages: if you have two language runtimes A and B deployed in your JVM and
* they export their linkers through the above mechanism, language runtime A
* will have a language-specific linker instance from B and vice versa inside
* their {@code DynamicLinker} objects. This means that if an object from
* language runtime B gets passed to code from language runtime A, the linker
* from B will get a chance to link the call site in A when it encounters the
* object from B.
* Contains interfaces and classes that are used to link an {@code invokedynamic} call site.
*/
package jdk.dynalink;

View File

@ -24,7 +24,198 @@
*/
/**
* Dynalink
* <p>
* Dynalink is a library for dynamic linking of high-level operations on objects.
* These operations include "read a property",
* "write a property", "invoke a function" and so on. Dynalink is primarily
* useful for implementing programming languages where at least some expressions
* have dynamic types (that is, types that can not be decided statically), and
* the operations on dynamic types are expressed as
* {@link java.lang.invoke.CallSite call sites}. These call sites will be
* linked to appropriate target {@link java.lang.invoke.MethodHandle method handles}
* at run time based on actual types of the values the expressions evaluated to.
* These can change between invocations, necessitating relinking the call site
* multiple times to accommodate new types; Dynalink handles all that and more.
* <p>
* Dynalink supports implementation of programming languages with object models
* that differ (even radically) from the JVM's class-based model and have their
* custom type conversions.
* <p>
* Dynalink is closely related to, and relies on, the {@link java.lang.invoke}
* package.
* <p>
*
* While {@link java.lang.invoke} provides a low level API for dynamic linking
* of {@code invokedynamic} call sites, it does not provide a way to express
* higher level operations on objects, nor methods that implement them. These
* operations are the usual ones in object-oriented environments: property
* access, access of elements of collections, invocation of methods and
* constructors (potentially with multiple dispatch, e.g. link- and run-time
* equivalents of Java overloaded method resolution). These are all functions
* that are normally desired in a language on the JVM. If a language is
* statically typed and its type system matches that of the JVM, it can
* accomplish this with use of the usual invocation, field access, etc.
* instructions (e.g. {@code invokevirtual}, {@code getfield}). However, if the
* language is dynamic (hence, types of some expressions are not known until
* evaluated at run time), or its object model or type system don't match
* closely that of the JVM, then it should use {@code invokedynamic} call sites
* instead and let Dynalink manage them.
* <h2>Example</h2>
* Dynalink is probably best explained by an example showing its use. Let's
* suppose you have a program in a language where you don't have to declare the
* type of an object and you want to access a property on it:
* <pre>
* var color = obj.color;
* </pre>
* If you generated a Java class to represent the above one-line program, its
* bytecode would look something like this:
* <pre>
* aload 2 // load "obj" on stack
* invokedynamic "GET:PROPERTY:color"(Object)Object // invoke property getter on object of unknown type
* astore 3 // store the return value into local variable "color"
* </pre>
* In order to link the {@code invokedynamic} instruction, we need a bootstrap
* method. A minimalist bootstrap method with Dynalink could look like this:
* <pre>
* import java.lang.invoke.*;
* import jdk.dynalink.*;
* import jdk.dynalink.support.*;
*
* class MyLanguageRuntime {
* private static final DynamicLinker dynamicLinker = new DynamicLinkerFactory().createLinker();
*
* public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
* return dynamicLinker.link(
* new SimpleRelinkableCallSite(
* new CallSiteDescriptor(lookup, parseOperation(name), type)));
* }
*
* private static Operation parseOperation(String name) {
* ...
* }
* }
* </pre>
* There are several objects of significance in the above code snippet:
* <ul>
* <li>{@link jdk.dynalink.DynamicLinker} is the main object in Dynalink, it
* coordinates the linking of call sites to method handles that implement the
* operations named in them. It is configured and created using a
* {@link jdk.dynalink.DynamicLinkerFactory}.</li>
* <li>When the bootstrap method is invoked, it needs to create a
* {@link java.lang.invoke.CallSite} object. In Dynalink, these call sites need
* to additionally implement the {@link jdk.dynalink.RelinkableCallSite}
* interface. "Relinkable" here alludes to the fact that if the call site
* encounters objects of different types at run time, its target will be changed
* to a method handle that can perform the operation on the newly encountered
* type. {@link jdk.dynalink.support.SimpleRelinkableCallSite} and
* {@link jdk.dynalink.support.ChainedCallSite} (not used in the above example)
* are two implementations already provided by the library.</li>
* <li>Dynalink uses {@link jdk.dynalink.CallSiteDescriptor} objects to
* preserve the parameters to the bootstrap method: the lookup and the method type,
* as it will need them whenever it needs to relink a call site.</li>
* <li>Dynalink uses {@link jdk.dynalink.Operation} objects to express
* dynamic operations. It does not prescribe how would you encode the operations
* in your call site, though. That is why in the above example the
* {@code parseOperation} function is left empty, and you would be expected to
* provide the code to parse the string {@code "GET:PROPERTY:color"}
* in the call site's name into a named property getter operation object as
* {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}.
* </ul>
* <p>What can you already do with the above setup? {@code DynamicLinkerFactory}
* by default creates a {@code DynamicLinker} that can link Java objects with the
* usual Java semantics. If you have these three simple classes:
* <pre>
* public class A {
* public String color;
* public A(String color) { this.color = color; }
* }
*
* public class B {
* private String color;
* public B(String color) { this.color = color; }
* public String getColor() { return color; }
* }
*
* public class C {
* private int color;
* public C(int color) { this.color = color; }
* public int getColor() { return color; }
* }
* </pre>
* and you somehow create their instances and pass them to your call site in your
* programming language:
* <pre>
* for each(var obj in [new A("red"), new B("green"), new C(0x0000ff)]) {
* print(obj.color);
* }
* </pre>
* then on first invocation, Dynalink will link the {@code .color} getter
* operation to a field getter for {@code A.color}, on second invocation it will
* relink it to {@code B.getColor()} returning a {@code String}, and finally on
* third invocation it will relink it to {@code C.getColor()} returning an {@code int}.
* The {@code SimpleRelinkableCallSite} we used above only remembers the linkage
* for the last encountered type (it implements what is known as a <i>monomorphic
* inline cache</i>). Another already provided implementation,
* {@link jdk.dynalink.support.ChainedCallSite} will remember linkages for
* several different types (it is a <i>polymorphic inline cache</i>) and is
* probably a better choice in serious applications.
* <h2>Dynalink and bytecode creation</h2>
* {@code CallSite} objects are usually created as part of bootstrapping
* {@code invokedynamic} instructions in bytecode. Hence, Dynalink is typically
* used as part of language runtimes that compile programs into Java
* {@code .class} bytecode format. Dynalink does not address the aspects of
* either creating bytecode classes or loading them into the JVM. That said,
* Dynalink can also be used without bytecode compilation (e.g. in language
* interpreters) by creating {@code CallSite} objects explicitly and associating
* them with representations of dynamic operations in the interpreted program
* (e.g. a typical representation would be some node objects in a syntax tree).
* <h2>Available operations</h2>
* Dynalink defines several standard operations in its
* {@link jdk.dynalink.StandardOperation} class. The linker for Java
* objects can link all of these operations, and you are encouraged to at
* minimum support and use these operations in your language too. The
* standard operations {@code GET} and {@code SET} need to be combined with
* at least one {@link jdk.dynalink.Namespace} to be useful, e.g. to express a
* property getter, you'd use {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY)}.
* Dynalink defines three standard namespaces in the {@link jdk.dynalink.StandardNamespace} class.
* To associate a fixed name with an operation, you can use
* {@link jdk.dynalink.NamedOperation} as in the previous example:
* {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}
* expresses a getter for the property named "color".
* <h2>Operations on multiple namespaces</h2>
* Some languages might not have separate namespaces on objects for
* properties, elements, and methods, and a source language construct might
* address several of them at once. Dynalink supports specifying multiple
* {@link jdk.dynalink.Namespace} objects with {@link jdk.dynalink.NamespaceOperation}.
* <h2>Language-specific linkers</h2>
* Languages that define their own object model different than the JVM
* class-based model and/or use their own type conversions will need to create
* their own language-specific linkers. See the {@link jdk.dynalink.linker}
* package and specifically the {@link jdk.dynalink.linker.GuardingDynamicLinker}
* interface to get started.
* <h2>Dynalink and Java objects</h2>
* The {@code DynamicLinker} objects created by {@code DynamicLinkerFactory} by
* default contain an internal instance of
* {@code BeansLinker}, which is a language-specific linker
* that implements the usual Java semantics for all of the above operations and
* can link any Java object that no other language-specific linker has managed
* to link. This way, all language runtimes have built-in interoperability with
* ordinary Java objects. See {@link jdk.dynalink.beans.BeansLinker} for details
* on how it links the various operations.
* <h2>Cross-language interoperability</h2>
* A {@code DynamicLinkerFactory} can be configured with a
* {@link jdk.dynalink.DynamicLinkerFactory#setClassLoader(ClassLoader) class
* loader}. It will try to instantiate all
* {@link jdk.dynalink.linker.GuardingDynamicLinkerExporter} classes visible to
* that class loader and compose the linkers they provide into the
* {@code DynamicLinker} it creates. This allows for interoperability between
* languages: if you have two language runtimes A and B deployed in your JVM and
* they export their linkers through the above mechanism, language runtime A
* will have a language-specific linker instance from B and vice versa inside
* their {@code DynamicLinker} objects. This means that if an object from
* language runtime B gets passed to code from language runtime A, the linker
* from B will get a chance to link the call site in A when it encounters the
* object from B.
*/
module jdk.dynalink {
requires java.logging;

View File

@ -24,7 +24,71 @@
*/
/**
* Nashorn
<p>
Nashorn is a runtime environment for programs written in ECMAScript 5.1.
</p>
<h1>Usage</h1>
The recommended way to use Nashorn is through the <a href="http://jcp.org/en/jsr/detail?id=223" target="_top">JSR-223
"Scripting for the Java Platform"</a> APIs found in the {@link javax.script} package. Usually, you'll obtain a
{@link javax.script.ScriptEngine} instance for Nashorn using:
<pre>
import javax.script.*;
...
ScriptEngine nashornEngine = new ScriptEngineManager().getEngineByName("nashorn");
</pre>
and then use it just as you would any other JSR-223 script engine. See
<a href="jdk/nashorn/api/scripting/package-summary.html">{@code jdk.nashorn.api.scripting}</a> package
for details.
<h1>Compatibility</h1>
Nashorn is 100% compliant with the <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"
target="_top">ECMA-262 Standard, Edition 5.1</a>. It requires a Java Virtual Machine that implements the
<a href="http://jcp.org/en/jsr/detail?id=292" target="_top">JSR-292 "Supporting Dynamically Typed Languages on the Java
Platform"</a> specification (often referred to as "invokedynamic"), as well as the already mentioned JSR-223.
<h1>Interoperability with the Java platform</h1>
In addition to being a 100% ECMAScript 5.1 runtime, Nashorn provides features for interoperability of the ECMAScript
programs with the Java platform. In general, any Java object put into the script engine's context will be visible from
the script. In terms of the standard, such Java objects are not considered "native objects", but rather "host objects",
as defined in section 4.3.8. This distinction allows certain semantical differences in handling them compared to native
objects. For most purposes, Java objects behave just as native objects do: you can invoke their methods, get and set
their properties. In most cases, though, you can't add arbitrary properties to them, nor can you remove existing
properties.
<h2>Java collection handling</h2>
Native Java arrays and {@link java.util.List}s support indexed access to their elements through the property accessors,
and {@link java.util.Map}s support both property and element access through both dot and square-bracket property
accessors, with the difference being that dot operator gives precedence to object properties (its fields and properties
defined as {@code getXxx} and {@code setXxx} methods) while the square bracket operator gives precedence to map
elements. Native Java arrays expose the {@code length} property.
<h2>ECMAScript primitive types</h2>
ECMAScript primitive types for number, string, and boolean are represented with {@link java.lang.Number},
{@link java.lang.CharSequence}, and {@link java.lang.Boolean} objects. While the most often used number type is
{@link java.lang.Double} and the most often used string type is {@link java.lang.String}, don't rely on it as various
internal optimizations cause other subclasses of {@code Number} and internal implementations of {@code CharSequence} to
be used.
<h2>Type conversions</h2>
When a method on a Java object is invoked, the arguments are converted to the formal parameter types of the Java method
using all allowed ECMAScript conversions. This can be surprising, as in general, conversions from string to number will
succeed according to Standard's section 9.3 "ToNumber" and so on; string to boolean, number to boolean, Object to
number, Object to string all work. Note that if the Java method's declared parameter type is {@code java.lang.Object},
Nashorn objects are passed without any conversion whatsoever; specifically if the JavaScript value being passed is of
primitive string type, you can only rely on it being a {@code java.lang.CharSequence}, and if the value is a number, you
can only rely on it being a {@code java.lang.Number}. If the Java method declared parameter type is more specific (e.g.
{@code java.lang.String} or {@code java.lang.Double}), then Nashorn will of course ensure the required type is passed.
<h2>SAM types</h2>
As a special extension when invoking Java methods, ECMAScript function objects can be passed in place of an argument
whose Java type is so-called "single abstract method" or "SAM" type. While this name usually covers single-method
interfaces, Nashorn is a bit more versatile, and it recognizes a type as a SAM type if all its abstract methods are
overloads of the same name, and it is either an interface, or it is an abstract class with
a no-arg constructor. The type itself must be public, while the constructor and the methods can be either public or
protected. If there are multiple abstract overloads of the same name, the single function will serve as the shared
implementation for all of them, <em>and additionally it will also override any non-abstract methods of the same name</em>.
This is done to be consistent with the fact that ECMAScript does not have the concept of overloaded methods.
<h2>The {@code Java} object</h2>
Nashorn exposes a non-standard global object named {@code Java} that is the primary API entry point into Java
platform-specific functionality. You can use it to create instances of Java classes, convert from Java arrays to native
arrays and back, and so on.
<h2>Other non-standard built-in objects</h2>
In addition to {@code Java}, Nashorn also exposes some other non-standard built-in objects:
{@code JSAdapter}, {@code JavaImporter}, {@code Packages}
*/
module jdk.scripting.nashorn {
requires java.logging;
@ -47,4 +111,3 @@ module jdk.scripting.nashorn {
provides jdk.dynalink.linker.GuardingDynamicLinkerExporter
with jdk.nashorn.api.linker.NashornLinkerExporter;
}

View File

@ -1,113 +0,0 @@
<!--
Copyright (c) 2010, 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.
-->
<body>
<p>
Nashorn is a runtime environment for programs written in ECMAScript 5.1.
</p>
<h1>Usage</h1>
<p>
The recommended way to use Nashorn is through the <a href="http://jcp.org/en/jsr/detail?id=223" target="_top">JSR-223
"Scripting for the Java Platform"</a> APIs found in the {@link javax.script} package. Usually, you'll obtain a
{@link javax.script.ScriptEngine} instance for Nashorn using:
<pre>
import javax.script.*;
...
ScriptEngine nashornEngine = new ScriptEngineManager().getEngineByName("nashorn");
</pre>
and then use it just as you would any other JSR-223 script engine. See
<a href="jdk/nashorn/api/scripting/package-summary.html">{@code jdk.nashorn.api.scripting}</a> package
for details.
<p>
<h1>Compatibility</h1>
Nashorn is 100% compliant with the <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"
target="_top">ECMA-262 Standard, Edition 5.1</a>. It requires a Java Virtual Machine that implements the
<a href="http://jcp.org/en/jsr/detail?id=292" target="_top">JSR-292 "Supporting Dynamically Typed Languages on the Java
Platform"</a> specification (often referred to as "invokedynamic"), as well as the already mentioned JSR-223.
<h1>Interoperability with the Java platform</h1>
<p>
In addition to being a 100% ECMAScript 5.1 runtime, Nashorn provides features for interoperability of the ECMAScript
programs with the Java platform. In general, any Java object put into the script engine's context will be visible from
the script. In terms of the standard, such Java objects are not considered "native objects", but rather "host objects",
as defined in section 4.3.8. This distinction allows certain semantical differences in handling them compared to native
objects. For most purposes, Java objects behave just as native objects do: you can invoke their methods, get and set
their properties. In most cases, though, you can't add arbitrary properties to them, nor can you remove existing
properties.
<p>
<h2>Java collection handling</h2>
<p>
Native Java arrays and {@link java.util.List}s support indexed access to their elements through the property accessors,
and {@link java.util.Map}s support both property and element access through both dot and square-bracket property
accessors, with the difference being that dot operator gives precedence to object properties (its fields and properties
defined as {@code getXxx} and {@code setXxx} methods) while the square bracket operator gives precedence to map
elements. Native Java arrays expose the {@code length} property.
<p>
<h2>ECMAScript primitive types</h2>
<p>
ECMAScript primitive types for number, string, and boolean are represented with {@link java.lang.Number},
{@link java.lang.CharSequence}, and {@link java.lang.Boolean} objects. While the most often used number type is
{@link java.lang.Double} and the most often used string type is {@link java.lang.String}, don't rely on it as various
internal optimizations cause other subclasses of {@code Number} and internal implementations of {@code CharSequence} to
be used.
<p>
<h2>Type conversions</h2>
<p>
When a method on a Java object is invoked, the arguments are converted to the formal parameter types of the Java method
using all allowed ECMAScript conversions. This can be surprising, as in general, conversions from string to number will
succeed according to Standard's section 9.3 "ToNumber" and so on; string to boolean, number to boolean, Object to
number, Object to string all work. Note that if the Java method's declared parameter type is {@code java.lang.Object},
Nashorn objects are passed without any conversion whatsoever; specifically if the JavaScript value being passed is of
primitive string type, you can only rely on it being a {@code java.lang.CharSequence}, and if the value is a number, you
can only rely on it being a {@code java.lang.Number}. If the Java method declared parameter type is more specific (e.g.
{@code java.lang.String} or {@code java.lang.Double}), then Nashorn will of course ensure the required type is passed.
<p>
<h2>SAM types</h2>
<p>
As a special extension when invoking Java methods, ECMAScript function objects can be passed in place of an argument
whose Java type is so-called "single abstract method" or "SAM" type. While this name usually covers single-method
interfaces, Nashorn is a bit more versatile, and it recognizes a type as a SAM type if all its abstract methods are
overloads of the same name, and it is either an interface, or it is an abstract class with
a no-arg constructor. The type itself must be public, while the constructor and the methods can be either public or
protected. If there are multiple abstract overloads of the same name, the single function will serve as the shared
implementation for all of them, <em>and additionally it will also override any non-abstract methods of the same name</em>.
This is done to be consistent with the fact that ECMAScript does not have the concept of overloaded methods.
<p>
<h2>The {@code Java} object</h2>
Nashorn exposes a non-standard global object named {@code Java} that is the primary API entry point into Java
platform-specific functionality. You can use it to create instances of Java classes, convert from Java arrays to native
arrays and back, and so on. The methods on the objects are directly implemented by public static methods on the class
<a href="jdk/nashorn/internal/objects/NativeJava.html">{@code NativeJava}</a>, see that class for details on what
functionality is available.
<h2>Representations of Java types</h2>
The method <a href="jdk/nashorn/internal/objects/NativeJava.html#type(java.lang.Object,%20java.lang.Object)">
{@code Java.type(typeName)}</a> takes a name of a type, and returns an object representing a Java type. You can
use that object to both create new instances of Java classes, as well as to access static fields and methods on them.
The type object is distinct from the {@code java.lang.Class} object, which represents the reflective run-time type
identity and doesn't carry i.e. static members. Again, see the link for {@code NativeJava} above for details.
<h2>Other non-standard built-in objects</h2>
In addition to {@code Java}, Nashorn also exposes some other non-standard built-in objects:
<a href="jdk/nashorn/internal/objects/NativeJSAdapter.html">{@code JSAdapter}</a>,
<a href="jdk/nashorn/internal/objects/NativeJavaImporter.html">{@code JavaImporter}</a>,
<a href="jdk/nashorn/internal/runtime/NativeJavaPackage.html">{@code Packages}.</a>
</body>