This commit is contained in:
Lana Steuck 2017-01-05 19:46:39 +00:00
commit a9dccaf0a2
41 changed files with 3012 additions and 1035 deletions

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

@ -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

@ -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

@ -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

@ -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

@ -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;
}
}