diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 7ac564d959a..250ff51b036 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1942,6 +1942,10 @@ public final class System { * the application classpath or modulepath. */ private static void initPhase3() { + // Initialize publicLookup early, to avoid bootstrapping circularities + // with security manager using java.lang.invoke infrastructure. + java.lang.invoke.MethodHandles.publicLookup(); + // set security manager String cn = System.getProperty("java.security.manager"); if (cn != null) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 7eda4908461..a525b1b9518 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2204,15 +2204,7 @@ return mh1; } } - private static final Class PUBLIC_LOOKUP_CLASS; - static { - PrivilegedAction> pa = new PrivilegedAction>() { - public Class run() { - return createClass(); - } - }; - PUBLIC_LOOKUP_CLASS = AccessController.doPrivileged(pa); - } + private static final Class PUBLIC_LOOKUP_CLASS = createClass(); /** * Lookup that is trusted minimally. It can only be used to create diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 7da455097b8..4702bd55ba4 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -1733,41 +1733,32 @@ public final class StringConcatFactory { // no instantiation } - // This one is deliberately non-lambdified to optimize startup time: - private static final Function, MethodHandle> MOST = new Function, MethodHandle>() { + private static class StringifierMost extends ClassValue { @Override - public MethodHandle apply(Class cl) { - MethodHandle mhObject = lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, Object.class); - - // We need the additional conversion here, because String.valueOf(Object) may return null. - // String conversion rules in Java state we need to produce "null" String in this case. - // It can be easily done with applying valueOf the second time. - MethodHandle mhObjectNoNulls = MethodHandles.filterReturnValue(mhObject, - mhObject.asType(MethodType.methodType(String.class, String.class))); - + protected MethodHandle computeValue(Class cl) { if (cl == String.class) { - return mhObject; + return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, Object.class); } else if (cl == float.class) { return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, float.class); } else if (cl == double.class) { return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, double.class); } else if (!cl.isPrimitive()) { - return mhObjectNoNulls; + MethodHandle mhObject = lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, Object.class); + + // We need the additional conversion here, because String.valueOf(Object) may return null. + // String conversion rules in Java state we need to produce "null" String in this case. + // It can be easily done with applying valueOf the second time. + return MethodHandles.filterReturnValue(mhObject, + mhObject.asType(MethodType.methodType(String.class, String.class))); } return null; } - }; + } - // This one is deliberately non-lambdified to optimize startup time: - private static final Function, MethodHandle> ANY = new Function, MethodHandle>() { + private static class StringifierAny extends ClassValue { @Override - public MethodHandle apply(Class cl) { - MethodHandle mh = MOST.apply(cl); - if (mh != null) { - return mh; - } - + protected MethodHandle computeValue(Class cl) { if (cl == byte.class || cl == short.class || cl == int.class) { return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, int.class); } else if (cl == boolean.class) { @@ -1777,13 +1768,18 @@ public final class StringConcatFactory { } else if (cl == long.class) { return lookupStatic(MethodHandles.publicLookup(), String.class, "valueOf", String.class, long.class); } else { - throw new IllegalStateException("Unknown class: " + cl); + MethodHandle mh = STRINGIFIERS_MOST.get(cl); + if (mh != null) { + return mh; + } else { + throw new IllegalStateException("Unknown class: " + cl); + } } } - }; + } - private static final ConcurrentMap, MethodHandle> STRINGIFIERS_MOST = new ConcurrentHashMap<>(); - private static final ConcurrentMap, MethodHandle> STRINGIFIERS_ANY = new ConcurrentHashMap<>(); + private static final ClassValue STRINGIFIERS_MOST = new StringifierMost(); + private static final ClassValue STRINGIFIERS_ANY = new StringifierAny(); /** * Returns a stringifier for references and floats/doubles only. @@ -1793,7 +1789,7 @@ public final class StringConcatFactory { * @return stringifier; null, if not available */ static MethodHandle forMost(Class t) { - return STRINGIFIERS_MOST.computeIfAbsent(t, MOST); + return STRINGIFIERS_MOST.get(t); } /** @@ -1803,7 +1799,7 @@ public final class StringConcatFactory { * @return stringifier */ static MethodHandle forAny(Class t) { - return STRINGIFIERS_ANY.computeIfAbsent(t, ANY); + return STRINGIFIERS_ANY.get(t); } } diff --git a/jdk/src/java.base/share/classes/java/net/URI.java b/jdk/src/java.base/share/classes/java/net/URI.java index 069aedb685f..97d8937f53d 100644 --- a/jdk/src/java.base/share/classes/java/net/URI.java +++ b/jdk/src/java.base/share/classes/java/net/URI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -92,9 +92,9 @@ import java.lang.NullPointerException; // for javadoc * URIs are: * *
- * {@code http://java.sun.com/j2se/1.3/}
- * {@code docs/guide/collections/designfaq.html#28}
- * {@code ../../../demo/jfc/SwingSet2/src/SwingSet2.java}
+ * {@code http://example.com/languages/java/}
+ * {@code sample/a/index.html#28}
+ * {@code ../../demo/b/index.html}
* {@code file:///~/calendar} *
* @@ -178,28 +178,28 @@ import java.lang.NullPointerException; // for javadoc * normalized. The result, for example, of resolving * *
- * {@code docs/guide/collections/designfaq.html#28} + * {@code sample/a/index.html#28} *              *     (1) *
* - * against the base URI {@code http://java.sun.com/j2se/1.3/} is the result + * against the base URI {@code http://example.com/languages/java/} is the result * URI * *
- * {@code http://docs.oracle.com/javase/1.3/docs/guide/collections/designfaq.html#28} + * {@code http://example.com/languages/java/sample/a/index.html#28} *
* * Resolving the relative URI * *
- * {@code ../../../demo/jfc/SwingSet2/src/SwingSet2.java}    (2) + * {@code ../../demo/b/index.html}    (2) *
* * against this result yields, in turn, * *
- * {@code http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java} + * {@code http://example.com/languages/java/demo/b/index.html} *
* * Resolution of both absolute and relative URIs, and of both absolute and @@ -210,7 +210,7 @@ import java.lang.NullPointerException; // for javadoc * URI * *
- * {@code demo/jfc/SwingSet2/src/SwingSet2.java} + * {@code demo/b/index.html} *
* *

Relativization, finally, is the inverse of resolution: For any @@ -226,16 +226,16 @@ import java.lang.NullPointerException; // for javadoc * possible. For example, relativizing the URI * *

- * {@code http://docs.oracle.com/javase/1.3/docs/guide/index.html} + * {@code http://example.com/languages/java/sample/a/index.html#28} *
* * against the base URI * *
- * {@code http://java.sun.com/j2se/1.3} + * {@code http://example.com/languages/java/} *
* - * yields the relative URI {@code docs/guide/index.html}. + * yields the relative URI {@code sample/a/index.html#28}. * * *

Character categories

diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandomParameters.java b/jdk/src/java.base/share/classes/java/security/SecureRandomParameters.java index bedf94e4ea5..f83491cf81a 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureRandomParameters.java +++ b/jdk/src/java.base/share/classes/java/security/SecureRandomParameters.java @@ -33,6 +33,7 @@ package java.security; * can be passed to those implementations that support them. * * @see DrbgParameters + * @since 9 */ public interface SecureRandomParameters { } diff --git a/jdk/src/java.base/share/classes/java/util/Locale.java b/jdk/src/java.base/share/classes/java/util/Locale.java index 23417394030..6567ab02bb4 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -2858,6 +2858,8 @@ public final class Locale implements Cloneable, Serializable { * @param range a language range * @throws NullPointerException if the given {@code range} is * {@code null} + * @throws IllegalArgumentException if the given {@code range} does not + * comply with the syntax of the language range mentioned in RFC 4647 */ public LanguageRange(String range) { this(range, MAX_WEIGHT); @@ -2873,8 +2875,10 @@ public final class Locale implements Cloneable, Serializable { * {@code MAX_WEIGHT} * @throws NullPointerException if the given {@code range} is * {@code null} - * @throws IllegalArgumentException if the given {@code weight} is less - * than {@code MIN_WEIGHT} or greater than {@code MAX_WEIGHT} + * @throws IllegalArgumentException if the given {@code range} does not + * comply with the syntax of the language range mentioned in RFC 4647 + * or if the given {@code weight} is less than {@code MIN_WEIGHT} + * or greater than {@code MAX_WEIGHT} */ public LanguageRange(String range, double weight) { if (range == null) { diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java index 7402560e45e..9da6546c04a 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,16 +118,22 @@ public class AnnotationType { members = new HashMap<>(methods.length+1, 1.0f); for (Method method : methods) { - if (method.getParameterTypes().length != 0) - throw new IllegalArgumentException(method + " has params"); - String name = method.getName(); - Class type = method.getReturnType(); - memberTypes.put(name, invocationHandlerReturnType(type)); - members.put(name, method); + if (Modifier.isPublic(method.getModifiers()) && + Modifier.isAbstract(method.getModifiers()) && + !method.isSynthetic()) { + if (method.getParameterTypes().length != 0) { + throw new IllegalArgumentException(method + " has params"); + } + String name = method.getName(); + Class type = method.getReturnType(); + memberTypes.put(name, invocationHandlerReturnType(type)); + members.put(name, method); - Object defaultValue = method.getDefaultValue(); - if (defaultValue != null) - memberDefaults.put(name, defaultValue); + Object defaultValue = method.getDefaultValue(); + if (defaultValue != null) { + memberDefaults.put(name, defaultValue); + } + } } // Initialize retention, & inherited fields. Special treatment diff --git a/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java b/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java index 8106ceaf644..ca2119ca7f9 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractDrbg.java @@ -33,12 +33,13 @@ import java.util.Objects; import static java.security.DrbgParameters.Capability.*; /** - * The abstract base class for all DRBGs. + * The abstract base class for all DRBGs. It is used as {@link DRBG#impl}. *

- * This class creates 5 new abstract methods. 3 are defined by the SP800-90A: + * This class has 5 abstract methods. 3 are defined by SP800-90A: *

    *
  1. {@link #generateAlgorithm(byte[], byte[])} - *
  2. {@link #reseedAlgorithm(byte[], byte[])} (might not be supported) + *
  3. {@link #reseedAlgorithm(byte[], byte[])} (In fact this is not an + * abstract method, but any DRBG supporting reseeding must override it.) *
  4. {@link #instantiateAlgorithm(byte[])} *
* and 2 for implementation purpose: @@ -46,18 +47,19 @@ import static java.security.DrbgParameters.Capability.*; *
  • {@link #initEngine()} *
  • {@link #chooseAlgorithmAndStrength} * - * All existing {@link SecureRandomSpi} methods are implemented based on the - * methods above as final. The initialization process is divided into 2 phases: - * configuration is eagerly called to set up parameters, and instantiation - * is lazily called only when nextBytes or reseed is called. + * Although this class is not a child class of {@link SecureRandomSpi}, it + * implements all abstract methods there as final. + *

    + * The initialization process of a DRBG is divided into 2 phases: + * {@link #configure configuration} is eagerly called to set up parameters, + * and {@link #instantiateIfNecessary instantiation} is lazily called only + * when nextBytes or reseed is called. *

    * SecureRandom methods like reseed and nextBytes are not thread-safe. * An implementation is required to protect shared access to instantiate states - * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter). + * (instantiated, nonce) and DRBG states (v, c, key, reseedCounter, etc). */ -public abstract class AbstractDrbg extends SecureRandomSpi { - - private static final long serialVersionUID = 9L; +public abstract class AbstractDrbg { /** * This field is not null if {@code -Djava.security.debug=securerandom} is @@ -69,7 +71,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { // Common working status - private transient boolean instantiated = false; + private boolean instantiated = false; /** * Reseed counter of a DRBG instance. A mechanism should increment it @@ -78,7 +80,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * * Volatile, will be used in a double checked locking. */ - protected transient volatile int reseedCounter = 0; + protected volatile int reseedCounter = 0; // Mech features. If not same as below, must be redefined in constructor. @@ -170,7 +172,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { /** * Algorithm used by this instance (SHA-512 or AES-256). Must be assigned * in {@link #chooseAlgorithmAndStrength}. This field is used in - * {@link #toString()} and {@link DRBG#algorithmName}. + * {@link #toString()}. */ protected String algorithm; @@ -217,7 +219,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * After instantiation, this field is not null. Do not modify it * in a mechanism. */ - protected transient byte[] nonce; + protected byte[] nonce; /** * Requested nonce in {@link MoreDrbgParameters}. If set to null, @@ -237,7 +239,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * {@link #configure(SecureRandomParameters)}. This field * can be null. {@link #getEntropyInput} will take care of null check. */ - private transient EntropySource es; + private EntropySource es; // Five abstract methods for SP 800-90A DRBG @@ -286,10 +288,7 @@ public abstract class AbstractDrbg extends SecureRandomSpi { /** * Initiates security engines ({@code MessageDigest}, {@code Mac}, - * or {@code Cipher}). Must be called in deserialization. Please note - * that before instantiation the algorithm might not be available yet. - * In this case, just return and this method will be called - * automatically at instantiation. + * or {@code Cipher}). This method is called during instantiation. */ protected abstract void initEngine(); @@ -331,13 +330,11 @@ public abstract class AbstractDrbg extends SecureRandomSpi { // SecureRandomSpi methods taken care of here. All final. - @Override protected final void engineNextBytes(byte[] result) { engineNextBytes(result, DrbgParameters.nextBytes( -1, predictionResistanceFlag, null)); } - @Override protected final void engineNextBytes( byte[] result, SecureRandomParameters params) { @@ -402,7 +399,6 @@ public abstract class AbstractDrbg extends SecureRandomSpi { } } - @Override public final void engineReseed(SecureRandomParameters params) { if (debug != null) { debug.println(this, "reseed with params"); @@ -454,7 +450,6 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * @param numBytes the number of seed bytes to generate. * @return the seed bytes. */ - @Override public final byte[] engineGenerateSeed(int numBytes) { byte[] b = new byte[numBytes]; SeedGenerator.generateSeed(b); @@ -469,7 +464,6 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * * @param input the seed */ - @Override public final synchronized void engineSetSeed(byte[] input) { if (debug != null) { debug.println(this, "setSeed"); @@ -598,7 +592,6 @@ public abstract class AbstractDrbg extends SecureRandomSpi { * * @return the curent configuration */ - @Override protected SecureRandomParameters engineGetParameters() { // Or read from variable. return DrbgParameters.instantiation( @@ -631,7 +624,8 @@ public abstract class AbstractDrbg extends SecureRandomSpi { this.es = m.es; this.requestedAlgorithm = m.algorithm; this.usedf = m.usedf; - params = m.config; + params = DrbgParameters.instantiation(m.strength, + m.capability, m.personalizationString); } if (params != null) { if (params instanceof DrbgParameters.Instantiation) { diff --git a/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java b/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java index 73d40b777da..e49f1349bf8 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/AbstractHashDrbg.java @@ -32,8 +32,6 @@ import java.util.Locale; public abstract class AbstractHashDrbg extends AbstractDrbg { - private static final long serialVersionUID = 9L; - protected int outLen; protected int seedLen; diff --git a/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java index 1d234172c95..683f5941c45 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/CtrDrbg.java @@ -28,14 +28,12 @@ package sun.security.provider; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; -import java.io.IOException; import java.security.*; import java.util.Arrays; import java.util.Locale; public class CtrDrbg extends AbstractDrbg { - private static final long serialVersionUID = 9L; private static final int AES_LIMIT; static { @@ -47,7 +45,7 @@ public class CtrDrbg extends AbstractDrbg { } } - private transient Cipher cipher; + private Cipher cipher; private String cipherAlg; private String keyAlg; @@ -57,8 +55,8 @@ public class CtrDrbg extends AbstractDrbg { private int keyLen; private int seedLen; - private transient byte[] v; - private transient byte[] k; + private byte[] v; + private byte[] k; public CtrDrbg(SecureRandomParameters params) { mechName = "CTR_DRBG"; @@ -165,7 +163,7 @@ public class CtrDrbg extends AbstractDrbg { protected void initEngine() { try { /* - * Use the local SUN implementation to avoid native + * Use the local SunJCE implementation to avoid native * performance overhead. */ cipher = Cipher.getInstance(cipherAlg, "SunJCE"); @@ -463,12 +461,6 @@ public class CtrDrbg extends AbstractDrbg { // Step 8. Return } - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject (); - initEngine(); - } - @Override public String toString() { return super.toString() + "," diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java b/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java index b5fa3c4c4d2..47d0f5cac06 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DRBG.java @@ -25,6 +25,7 @@ package sun.security.provider; +import java.io.IOException; import java.security.AccessController; import java.security.DrbgParameters; import java.security.PrivilegedAction; @@ -61,11 +62,12 @@ public final class DRBG extends SecureRandomSpi { private static final long serialVersionUID = 9L; - private final AbstractDrbg impl; + private transient AbstractDrbg impl; - private final String mechName; - - private final String algorithmName; + /** + * @serial + */ + private final MoreDrbgParameters mdp; public DRBG(SecureRandomParameters params) { @@ -91,7 +93,7 @@ public final class DRBG extends SecureRandomSpi { // Can be configured with a security property String config = AccessController.doPrivileged((PrivilegedAction) - () -> Security.getProperty(PROP_NAME)); + () -> Security.getProperty(PROP_NAME)); if (config != null && !config.isEmpty()) { for (String part : config.split(",")) { @@ -151,8 +153,9 @@ public final class DRBG extends SecureRandomSpi { if (params != null) { // MoreDrbgParameters is used for testing. if (params instanceof MoreDrbgParameters) { - MoreDrbgParameters m = (MoreDrbgParameters)params; - params = m.config; + MoreDrbgParameters m = (MoreDrbgParameters) params; + params = DrbgParameters.instantiation(m.strength, + m.capability, m.personalizationString); // No need to check null for es and nonce, they are still null es = m.es; @@ -197,26 +200,27 @@ public final class DRBG extends SecureRandomSpi { usedf = true; } - MoreDrbgParameters m = new MoreDrbgParameters( + mdp = new MoreDrbgParameters( es, mech, algorithm, nonce, usedf, DrbgParameters.instantiation(strength, cap, ps)); - switch (mech.toLowerCase(Locale.ROOT)) { + createImpl(); + } + + private void createImpl() { + switch (mdp.mech.toLowerCase(Locale.ROOT)) { case "hash_drbg": - impl = new HashDrbg(m); + impl = new HashDrbg(mdp); break; case "hmac_drbg": - impl = new HmacDrbg(m); + impl = new HmacDrbg(mdp); break; case "ctr_drbg": - impl = new CtrDrbg(m); + impl = new CtrDrbg(mdp); break; default: - throw new IllegalArgumentException("Unsupported mech: " + mech); + throw new IllegalArgumentException("Unsupported mech: " + mdp.mech); } - - mechName = mech; - algorithmName = impl.algorithm; } @Override @@ -268,4 +272,13 @@ public final class DRBG extends SecureRandomSpi { + " cannot be provided more than once in " + PROP_NAME); } } + + private void readObject(java.io.ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + if (mdp.mech == null) { + throw new IllegalArgumentException("Input data is corrupted"); + } + createImpl(); + } } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java b/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java index e3c676b8979..bf641227e85 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/HashDrbg.java @@ -25,7 +25,6 @@ package sun.security.provider; -import java.io.IOException; import java.math.BigInteger; import java.security.DigestException; import java.security.MessageDigest; @@ -36,15 +35,13 @@ import java.util.Arrays; public class HashDrbg extends AbstractHashDrbg { - private static final long serialVersionUID = 9L; - private static final byte[] ZERO = new byte[1]; private static final byte[] ONE = new byte[]{1}; - private transient MessageDigest digest; + private MessageDigest digest; - private transient byte[] v; - private transient byte[] c; + private byte[] v; + private byte[] c; public HashDrbg(SecureRandomParameters params) { mechName = "Hash_DRBG"; @@ -267,10 +264,4 @@ public class HashDrbg extends AbstractHashDrbg { // Step 5: No need to truncate // Step 6: Return } - - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject (); - initEngine(); - } } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java b/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java index 1ee07b02fee..40b43b00e6f 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/HmacDrbg.java @@ -27,7 +27,6 @@ package sun.security.provider; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; @@ -36,14 +35,12 @@ import java.util.Arrays; public class HmacDrbg extends AbstractHashDrbg { - private static final long serialVersionUID = 9L; - - private transient Mac mac; + private Mac mac; private String macAlg; - private transient byte[] v; - private transient byte[] k; + private byte[] v; + private byte[] k; public HmacDrbg(SecureRandomParameters params) { mechName = "HMAC_DRBG"; @@ -101,6 +98,10 @@ public class HmacDrbg extends AbstractHashDrbg { protected void initEngine() { macAlg = "HmacSHA" + algorithm.substring(4); try { + /* + * Use the local SunJCE implementation to avoid native + * performance overhead. + */ mac = Mac.getInstance(macAlg, "SunJCE"); } catch (NoSuchProviderException | NoSuchAlgorithmException e) { // Fallback to any available. @@ -194,10 +195,4 @@ public class HmacDrbg extends AbstractHashDrbg { // Step 8. Return } - - private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject (); - initEngine(); - } } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java b/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java index 7a2e8c75ca6..808909354d7 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/MoreDrbgParameters.java @@ -25,20 +25,30 @@ package sun.security.provider; +import java.io.IOException; +import java.io.Serializable; import java.security.DrbgParameters; import java.security.SecureRandomParameters; /** - * Extra non-standard parameters that can be used by DRBGs. + * Exported and non-exported parameters that can be used by DRBGs. */ -public class MoreDrbgParameters implements SecureRandomParameters { +public class MoreDrbgParameters implements SecureRandomParameters, Serializable { + + private static final long serialVersionUID = 9L; + + final transient EntropySource es; final String mech; final String algorithm; - final EntropySource es; - final byte[] nonce; final boolean usedf; - final DrbgParameters.Instantiation config; + final int strength; + final DrbgParameters.Capability capability; + + // The following 2 fields will be reassigned in readObject and + // thus cannot be final + byte[] nonce; + byte[] personalizationString; /** * Creates a new {@code MoreDrbgParameters} object. @@ -61,13 +71,31 @@ public class MoreDrbgParameters implements SecureRandomParameters { this.mech = mech; this.algorithm = algorithm; this.es = es; - this.nonce = nonce; + this.nonce = (nonce == null) ? null : nonce.clone(); this.usedf = usedf; - this.config = config; + + this.strength = config.getStrength(); + this.capability = config.getCapability(); + this.personalizationString = config.getPersonalizationString(); } @Override public String toString() { - return mech + "," + algorithm + "," + usedf + "," + config; + return mech + "," + algorithm + "," + usedf + "," + strength + + "," + capability + "," + personalizationString; + } + + private void readObject(java.io.ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + if (nonce != null) { + nonce = nonce.clone(); + } + if (personalizationString != null) { + personalizationString = personalizationString.clone(); + } + if (capability == null) { + throw new IllegalArgumentException("Input data is corrupted"); + } } } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java index f367df5d704..9a2b9600dee 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLServerSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -347,7 +347,7 @@ class SSLServerSocketImpl extends SSLServerSocket SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode, enabledCipherSuites, clientAuthType, enableSessionCreation, enabledProtocols, identificationProtocol, algorithmConstraints, - sniMatchers, preferLocalCipherSuites); + sniMatchers, preferLocalCipherSuites, applicationProtocols); implAccept(s); s.doneConnect(); diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 95258b2ec2b..880c98a80a4 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -497,7 +497,8 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { String identificationProtocol, AlgorithmConstraints algorithmConstraints, Collection sniMatchers, - boolean preferLocalCipherSuites) throws IOException { + boolean preferLocalCipherSuites, + String[] applicationProtocols) throws IOException { super(); doClientAuth = clientAuth; @@ -506,6 +507,7 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { this.algorithmConstraints = algorithmConstraints; this.sniMatchers = sniMatchers; this.preferLocalCipherSuites = preferLocalCipherSuites; + this.applicationProtocols = applicationProtocols; init(context, serverMode); /* diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 3a3d5cfe91d..1aa10f578d8 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -206,7 +206,7 @@ public final class Main { IMPORTKEYSTORE("Imports.one.or.all.entries.from.another.keystore", SRCKEYSTORE, DESTKEYSTORE, SRCSTORETYPE, DESTSTORETYPE, SRCSTOREPASS, DESTSTOREPASS, - SRCPROTECTED, SRCPROVIDERNAME, DESTPROVIDERNAME, + SRCPROTECTED, DESTPROTECTED, SRCPROVIDERNAME, DESTPROVIDERNAME, SRCALIAS, DESTALIAS, SRCKEYPASS, DESTKEYPASS, NOPROMPT, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V), diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java index d970b5ecd2f..7d51f646638 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java @@ -86,7 +86,7 @@ final class WS implements WebSocket { } } }; - transmitter = new WSTransmitter(executor, channel, errorHandler); + transmitter = new WSTransmitter(this, executor, channel, errorHandler); receiver = new WSReceiver(this.listener, this, executor, channel); } @@ -95,12 +95,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendText(ByteBuffer message, boolean isLast) { - throw new UnsupportedOperationException("Not implemented"); - } - - @Override - public CompletableFuture sendText(CharSequence message, boolean isLast) { + public CompletableFuture sendText(CharSequence message, boolean isLast) { requireNonNull(message, "message"); synchronized (stateLock) { checkState(); @@ -109,7 +104,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendText(Stream message) { + public CompletableFuture sendText(Stream message) { requireNonNull(message, "message"); synchronized (stateLock) { checkState(); @@ -118,7 +113,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendBinary(ByteBuffer message, boolean isLast) { + public CompletableFuture sendBinary(ByteBuffer message, boolean isLast) { requireNonNull(message, "message"); synchronized (stateLock) { checkState(); @@ -127,7 +122,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendPing(ByteBuffer message) { + public CompletableFuture sendPing(ByteBuffer message) { requireNonNull(message, "message"); synchronized (stateLock) { checkState(); @@ -136,7 +131,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendPong(ByteBuffer message) { + public CompletableFuture sendPong(ByteBuffer message) { requireNonNull(message, "message"); synchronized (stateLock) { checkState(); @@ -145,7 +140,7 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendClose(CloseCode code, CharSequence reason) { + public CompletableFuture sendClose(CloseCode code, CharSequence reason) { requireNonNull(code, "code"); requireNonNull(reason, "reason"); synchronized (stateLock) { @@ -154,13 +149,13 @@ final class WS implements WebSocket { } @Override - public CompletableFuture sendClose() { + public CompletableFuture sendClose() { synchronized (stateLock) { return doSendClose(() -> transmitter.sendClose()); } } - private CompletableFuture doSendClose(Supplier> s) { + private CompletableFuture doSendClose(Supplier> s) { checkState(); boolean closeChannel = false; synchronized (stateLock) { @@ -170,7 +165,7 @@ final class WS implements WebSocket { tryChangeState(State.CLOSED_LOCALLY); } } - CompletableFuture sent = s.get(); + CompletableFuture sent = s.get(); if (closeChannel) { sent.whenComplete((v, t) -> { try { @@ -239,7 +234,7 @@ final class WS implements WebSocket { } @Override - public CompletionStage onText(WebSocket webSocket, Text message, + public CompletionStage onText(WebSocket webSocket, CharSequence message, MessagePart part) { synchronized (visibilityLock) { return listener.onText(webSocket, message, part); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java deleted file mode 100644 index 08f71236f63..00000000000 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposableText.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 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 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.net.http; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; - -final class WSDisposableText implements WebSocket.Text, WSDisposable { - - private final WSShared text; - - WSDisposableText(WSShared text) { - this.text = text; - } - - @Override - public int length() { - return text.buffer().length(); - } - - @Override - public char charAt(int index) { - return text.buffer().charAt(index); - } - - @Override - public CharSequence subSequence(int start, int end) { - return text.buffer().subSequence(start, end); - } - - @Override - public ByteBuffer asByteBuffer() { - throw new UnsupportedOperationException("To be removed from the API"); - } - - @Override - public String toString() { - return text.buffer().toString(); - } - - @Override - public void dispose() { - text.dispose(); - } -} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java index 504d72ed462..9d0521e9700 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java @@ -214,7 +214,7 @@ final class WSFrameConsumer implements WSFrame.Consumer { if (!(binaryNonEmpty && !textData.hasRemaining())) { // If there's a binary data, that result in no text, then we // don't deliver anything - output.onText(part, new WSDisposableText(textData)); + output.onText(part, textData); } } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java index e80605df10e..69f46668cfb 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java @@ -27,10 +27,11 @@ package java.net.http; import java.net.http.WebSocket.CloseCode; import java.net.http.WebSocket.MessagePart; import java.nio.ByteBuffer; +import java.nio.CharBuffer; interface WSMessageConsumer { - void onText(MessagePart part, WSDisposableText data); + void onText(MessagePart part, WSShared data); void onBinary(MessagePart part, WSShared data); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java index da69958653d..7ce089b4a4a 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java @@ -29,6 +29,7 @@ import java.io.UncheckedIOException; import java.net.ProtocolException; import java.net.http.WebSocket.Listener; import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.util.Optional; import java.util.concurrent.CompletionStage; @@ -169,11 +170,11 @@ final class WSReceiver { private final class MessageConsumer implements WSMessageConsumer { @Override - public void onText(WebSocket.MessagePart part, WSDisposableText data) { + public void onText(WebSocket.MessagePart part, WSShared data) { decrementDemand(); CompletionStage cs; try { - cs = listener.onText(webSocket, data, part); + cs = listener.onText(webSocket, data.buffer(), part); } catch (Exception e) { closeExceptionally(new RuntimeException("onText threw an exception", e)); return; diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java b/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java index f9827306646..a9a8287478e 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java @@ -51,15 +51,17 @@ import static java.net.http.Pair.pair; */ final class WSTransmitter { - private final BlockingQueue>> + private final BlockingQueue>> backlog = new LinkedBlockingQueue<>(); private final WSMessageSender sender; private final WSSignalHandler handler; + private final WebSocket webSocket; private boolean previousMessageSent = true; private boolean canSendBinary = true; private boolean canSendText = true; - WSTransmitter(Executor executor, RawChannel channel, Consumer errorHandler) { + WSTransmitter(WebSocket ws, Executor executor, RawChannel channel, Consumer errorHandler) { + this.webSocket = ws; this.handler = new WSSignalHandler(executor, this::handleSignal); Consumer sendCompletion = (error) -> { synchronized (this) { @@ -76,41 +78,41 @@ final class WSTransmitter { this.sender = new WSMessageSender(channel, sendCompletion); } - CompletableFuture sendText(CharSequence message, boolean isLast) { + CompletableFuture sendText(CharSequence message, boolean isLast) { checkAndUpdateText(isLast); return acceptMessage(new Text(isLast, message)); } - CompletableFuture sendText(Stream message) { + CompletableFuture sendText(Stream message) { checkAndUpdateText(true); return acceptMessage(new StreamedText(message)); } - CompletableFuture sendBinary(ByteBuffer message, boolean isLast) { + CompletableFuture sendBinary(ByteBuffer message, boolean isLast) { checkAndUpdateBinary(isLast); return acceptMessage(new Binary(isLast, message)); } - CompletableFuture sendPing(ByteBuffer message) { + CompletableFuture sendPing(ByteBuffer message) { checkSize(message.remaining(), 125); return acceptMessage(new Ping(message)); } - CompletableFuture sendPong(ByteBuffer message) { + CompletableFuture sendPong(ByteBuffer message) { checkSize(message.remaining(), 125); return acceptMessage(new Pong(message)); } - CompletableFuture sendClose(WebSocket.CloseCode code, CharSequence reason) { + CompletableFuture sendClose(WebSocket.CloseCode code, CharSequence reason) { return acceptMessage(createCloseMessage(code, reason)); } - CompletableFuture sendClose() { + CompletableFuture sendClose() { return acceptMessage(new Close(ByteBuffer.allocate(0))); } - private CompletableFuture acceptMessage(WSOutgoingMessage m) { - CompletableFuture cf = new CompletableFuture<>(); + private CompletableFuture acceptMessage(WSOutgoingMessage m) { + CompletableFuture cf = new CompletableFuture<>(); synchronized (this) { backlog.offer(pair(m, cf)); } @@ -123,11 +125,11 @@ final class WSTransmitter { synchronized (this) { while (!backlog.isEmpty() && previousMessageSent) { previousMessageSent = false; - Pair> p = backlog.peek(); + Pair> p = backlog.peek(); boolean sent = sender.trySendFully(p.first); if (sent) { backlog.remove(); - p.second.complete(null); + p.second.complete(webSocket); previousMessageSent = true; } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java index 200f12332a9..dfc7f71dc3b 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java @@ -52,8 +52,8 @@ import java.util.stream.Stream; * *

    Messages of type {@code X} are sent through the {@code WebSocket.sendX} * methods and received through {@link WebSocket.Listener}{@code .onX} methods - * asynchronously. Each of the methods begins the operation and returns a {@link - * CompletionStage} which completes when the operation has completed. + * asynchronously. Each of the methods returns a {@link CompletionStage} which + * completes when the operation has completed. * *

    Messages are received only if {@linkplain #request(long) requested}. * @@ -79,6 +79,9 @@ import java.util.stream.Stream; * or method of this type will cause a {@link NullPointerException * NullPointerException} to be thrown. * + * @implNote The default implementation's methods do not block before returning + * a {@code CompletableFuture}. + * * @since 9 */ public interface WebSocket { @@ -234,9 +237,9 @@ public interface WebSocket { /** * Builds a {@code WebSocket}. * - *

    Returns immediately with a {@code CompletableFuture} - * which completes with the {@code WebSocket} when it is connected, or - * completes exceptionally if an error occurs. + *

    Returns a {@code CompletableFuture} which completes + * normally with the {@code WebSocket} when it is connected or completes + * exceptionally if an error occurs. * *

    {@code CompletableFuture} may complete exceptionally with the * following errors: @@ -252,7 +255,7 @@ public interface WebSocket { * if the opening handshake fails * * - * @return a {@code CompletableFuture} of {@code WebSocket} + * @return a {@code CompletableFuture} with the {@code WebSocket} */ CompletableFuture buildAsync(); } @@ -264,7 +267,7 @@ public interface WebSocket { *

      *
    • {@link #onOpen onOpen}
      * This method is always the first to be invoked. - *
    • {@link #onText(WebSocket, WebSocket.Text, WebSocket.MessagePart) + *
    • {@link #onText(WebSocket, CharSequence, WebSocket.MessagePart) * onText}, {@link #onBinary(WebSocket, ByteBuffer, WebSocket.MessagePart) * onBinary}, {@link #onPing(WebSocket, ByteBuffer) onPing} and {@link * #onPong(WebSocket, ByteBuffer) onPong}
      @@ -375,6 +378,9 @@ public interface WebSocket { * @implSpec The default implementation {@linkplain WebSocket#request(long) * requests one more message}. * + * @implNote This implementation passes only complete UTF-16 sequences + * to the {@code onText} method. + * * @param webSocket * the WebSocket * @param message @@ -386,7 +392,7 @@ public interface WebSocket { * is done; or {@code null} if already done */ default CompletionStage onText(WebSocket webSocket, - Text message, + CharSequence message, MessagePart part) { webSocket.request(1); return null; @@ -596,59 +602,11 @@ public interface WebSocket { } /** - * Sends a Text message with bytes from the given {@code ByteBuffer}. + * Sends a Text message with characters from the given {@code CharSequence}. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. - * - *

      This message may be a partial UTF-8 sequence. However, the - * concatenation of all messages through the last must be a whole UTF-8 - * sequence. - * - *

      The {@code ByteBuffer} should not be modified until the returned - * {@code CompletableFuture} completes (either normally or exceptionally). - * - *

      The returned {@code CompletableFuture} can complete exceptionally - * with: - *

        - *
      • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the {@code message} is a malformed UTF-8 sequence - *
      - * - * @param message - * the message - * @param isLast - * {@code true} if this is the final part of the message, - * {@code false} otherwise - * - * @return a CompletableFuture of Void - * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been sent already - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Binary message - * was not sent with {@code isLast == true} - */ - CompletableFuture sendText(ByteBuffer message, boolean isLast); - - /** - * Sends a Text message with characters from the given {@code - * CharSequence}. - * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. - * - *

      This message may be a partial UTF-16 sequence. However, the - * concatenation of all messages through the last must be a whole UTF-16 - * sequence. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      The {@code CharSequence} should not be modified until the returned * {@code CompletableFuture} completes (either normally or exceptionally). @@ -657,30 +615,30 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the {@code message} is a malformed UTF-16 sequence + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation; + * or if a previous Binary message was not sent with {@code isLast == true} *
      * + * @implNote This implementation does not accept partial UTF-16 + * sequences. In case such a sequence is passed, a returned {@code + * CompletableFuture} completes exceptionally. + * * @param message * the message * @param isLast - * {@code true} if this is the final part of the message + * {@code true} if this is the final part of the message, * {@code false} otherwise * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Binary message was not sent - * with {@code isLast == true} + * @throws IllegalArgumentException + * if {@code message} is a malformed (or an incomplete) UTF-16 sequence */ - CompletableFuture sendText(CharSequence message, boolean isLast); + CompletableFuture sendText(CharSequence message, boolean isLast); /** * Sends a whole Text message with characters from the given {@code @@ -689,9 +647,9 @@ public interface WebSocket { *

      This is a convenience method. For the general case, use {@link * #sendText(CharSequence, boolean)}. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      The {@code CharSequence} should not be modified until the returned * {@code CompletableFuture} completes (either normally or exceptionally). @@ -700,27 +658,23 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the message is a malformed UTF-16 sequence + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation; + * or if a previous Binary message was not sent with {@code isLast == true} *
      * * @param message * the message * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Binary message was not sent - * with {@code isLast == true} + * @throws IllegalArgumentException + * if {@code message} is a malformed (or an incomplete) UTF-16 sequence */ - default CompletableFuture sendText(CharSequence message) { + default CompletableFuture sendText(CharSequence message) { return sendText(message, true); } @@ -731,9 +685,9 @@ public interface WebSocket { *

      This is a convenience method. For the general case use {@link * #sendText(CharSequence, boolean)}. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      Streamed character sequences should not be modified until the * returned {@code CompletableFuture} completes (either normally or @@ -743,41 +697,41 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation; or the - * {@code WebSocket} closes while this operation is in progress; - * or the message is a malformed UTF-16 sequence + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation; + * or if a previous Binary message was not sent with {@code isLast == true} *
      * * @param message * the message * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Binary message was not sent - * with {@code isLast == true} + * @throws IllegalArgumentException + * if {@code message} is a malformed (or an incomplete) UTF-16 sequence */ - CompletableFuture sendText(Stream message); + CompletableFuture sendText(Stream message); /** * Sends a Binary message with bytes from the given {@code ByteBuffer}. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      The returned {@code CompletableFuture} can complete exceptionally * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation; + * or if a previous Text message was not sent with {@code isLast == true} *
      * * @param message @@ -786,33 +740,27 @@ public interface WebSocket { * {@code true} if this is the final part of the message, * {@code false} otherwise * - * @return a CompletableFuture of Void - * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Text message was not sent - * with {@code isLast == true} + * @return a CompletableFuture with this WebSocket */ - CompletableFuture sendBinary(ByteBuffer message, boolean isLast); + CompletableFuture sendBinary(ByteBuffer message, boolean isLast); /** * Sends a Binary message with bytes from the given {@code byte[]}. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      The returned {@code CompletableFuture} can complete exceptionally * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation; + * or if a previous Text message was not sent with {@code isLast == true} *
      * * @implSpec This is equivalent to: @@ -826,19 +774,9 @@ public interface WebSocket { * {@code true} if this is the final part of the message, * {@code false} otherwise * - * @return a CompletableFuture of Void - * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation - * @throws IllegalStateException - * if a previous Text message was not sent - * with {@code isLast == true} + * @return a CompletableFuture with this WebSocket */ - default CompletableFuture sendBinary(byte[] message, boolean isLast) { + default CompletableFuture sendBinary(byte[] message, boolean isLast) { Objects.requireNonNull(message, "message"); return sendBinary(ByteBuffer.wrap(message), isLast); } @@ -846,9 +784,9 @@ public interface WebSocket { /** * Sends a Ping message. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      A Ping message may be sent or received by either client or server. * It may serve either as a keepalive or as a means to verify that the @@ -861,32 +799,29 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation *
      * * @param message * the message * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation * @throws IllegalArgumentException * if {@code message.remaining() > 125} */ - CompletableFuture sendPing(ByteBuffer message); + CompletableFuture sendPing(ByteBuffer message); /** * Sends a Pong message. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      A Pong message may be unsolicited or may be sent in response to a * previously received Ping. In latter case the contents of the Pong is @@ -899,32 +834,29 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation *
      * * @param message * the message * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation * @throws IllegalArgumentException * if {@code message.remaining() > 125} */ - CompletableFuture sendPong(ByteBuffer message); + CompletableFuture sendPong(ByteBuffer message); /** * Sends a Close message with the given close code and the reason. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      A Close message may consist of a close code and a reason for closing. * The reason must have a valid UTF-8 representation not longer than {@code @@ -935,8 +867,11 @@ public interface WebSocket { * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation *
      * * @param code @@ -944,45 +879,35 @@ public interface WebSocket { * @param reason * the reason; can be empty * - * @return a CompletableFuture of Void + * @return a CompletableFuture with this WebSocket * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation * @throws IllegalArgumentException - * if the {@code reason} doesn't have a valid UTF-8 - * representation not longer than {@code 123} bytes + * if {@code reason} doesn't have an UTF-8 representation not longer + * than {@code 123} bytes */ - CompletableFuture sendClose(CloseCode code, CharSequence reason); + CompletableFuture sendClose(CloseCode code, CharSequence reason); /** * Sends an empty Close message. * - *

      Returns immediately with a {@code CompletableFuture} which - * completes normally when the message has been sent, or completes - * exceptionally if an error occurs. + *

      Returns a {@code CompletableFuture} which completes + * normally when the message has been sent or completes exceptionally if an + * error occurs. * *

      The returned {@code CompletableFuture} can complete exceptionally * with: *

        *
      • {@link IOException} - * if an I/O error occurs during this operation or the - * {@code WebSocket} closes while this operation is in progress + * if an I/O error occurs during this operation + *
      • {@link IllegalStateException} + * if the {@code WebSocket} closes while this operation is in progress; + * or if a Close message has been sent already; + * or if there is an outstanding send operation *
      * - * @return a CompletableFuture of Void - * - * @throws IllegalStateException - * if the WebSocket is closed - * @throws IllegalStateException - * if a Close message has been already sent - * @throws IllegalStateException - * if there is an outstanding send operation + * @return a CompletableFuture with this WebSocket */ - CompletableFuture sendClose(); + CompletableFuture sendClose(); /** * Requests {@code n} more messages to be received by the {@link Listener @@ -1001,6 +926,7 @@ public interface WebSocket { * @implNote This implementation does not distinguish between partial and * whole messages, because it's not known beforehand how a message will be * received. + * *

      If a server sends more messages than requested, the implementation * queues up these messages on the TCP connection and may eventually force * the sender to stop sending through TCP flow control. @@ -1242,47 +1168,4 @@ public interface WebSocket { return Map.entry(cc.getCode(), cc); } } - - /** - * A character sequence that provides access to the characters UTF-8 decoded - * from a message in a {@code ByteBuffer}. - * - * @since 9 - */ - interface Text extends CharSequence { - - // Methods from the CharSequence below are mentioned explicitly for the - // purpose of documentation, so when looking at javadoc it immediately - // obvious what methods Text has - - @Override - int length(); - - @Override - char charAt(int index); - - @Override - CharSequence subSequence(int start, int end); - - /** - * Returns a string containing the characters in this sequence in the - * same order as this sequence. The length of the string will be the - * length of this sequence. - * - * @return a string consisting of exactly this sequence of characters - */ - @Override - // TODO: remove the explicit javadoc above when: - // (JDK-8144034 has been resolved) AND (the comment is still identical - // to CharSequence#toString) - String toString(); - - /** - * Returns a read-only {@code ByteBuffer} containing the message encoded - * in UTF-8. - * - * @return a read-only ByteBuffer - */ - ByteBuffer asByteBuffer(); - } } diff --git a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java index f1071d760bd..6536c4e6e31 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java +++ b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -128,7 +128,7 @@ public interface ScriptEngineFactory { * of "MULTITHREADED", and also, the engine maintains independent values * for symbols in scripts executing on different threads. *

    • "STATELESS" - The implementation satisfies the requirements of - *
    • "THREAD-ISOLATED". In addition, script executions do not alter the + * "THREAD-ISOLATED". In addition, script executions do not alter the * mappings in the Bindings which is the engine scope of the * ScriptEngine. In particular, the keys in the Bindings * and their associated values are the same before and after the execution of the script. diff --git a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java index 7e4bbbff6a4..1bcccc0ded8 100644 --- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java @@ -54,7 +54,9 @@ public abstract class EditingHistory implements History { (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::previousSnippet)); bind(in, CTRL_DOWN, (Runnable) () -> moveHistoryToSnippet(in, ((EditingHistory) in.getHistory())::nextSnippet)); - load(originalHistory); + if (originalHistory != null) { + load(originalHistory); + } } private void moveHistoryToSnippet(ConsoleReader in, Supplier action) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index b8a2d58c7fc..2004c1630fa 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -28,19 +28,16 @@ package jdk.tools.jimage; import java.io.File; import java.io.IOException; import java.io.PrintWriter; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; +import java.nio.file.FileSystem; import java.nio.file.Files; -import static java.nio.file.StandardOpenOption.READ; -import static java.nio.file.StandardOpenOption.WRITE; +import java.nio.file.PathMatcher; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.MissingResourceException; +import java.util.function.Predicate; import jdk.internal.jimage.BasicImageReader; import jdk.internal.jimage.ImageHeader; -import static jdk.internal.jimage.ImageHeader.MAGIC; -import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION; -import static jdk.internal.jimage.ImageHeader.MINOR_VERSION; import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.ImageResourcesTree; import jdk.tools.jlink.internal.TaskHelper; @@ -48,53 +45,71 @@ import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE; import jdk.tools.jlink.internal.TaskHelper.Option; import jdk.tools.jlink.internal.TaskHelper.OptionsHelper; +import jdk.tools.jlink.internal.Utils; class JImageTask { - - static final Option[] recognizedOptions = { - new Option(true, (task, opt, arg) -> { + private static final Option[] RECOGNIZED_OPTIONS = { + new Option(true, (task, option, arg) -> { task.options.directory = arg; }, "--dir"), - new Option(false, (task, opt, arg) -> { + + new Option(true, (task, option, arg) -> { + task.options.filters = arg; + }, "--filter"), + + new Option(false, (task, option, arg) -> { task.options.fullVersion = true; }, true, "--fullversion"), - new Option(false, (task, opt, arg) -> { + + new Option(false, (task, option, arg) -> { task.options.help = true; }, "--help"), - new Option(true, (task, opt, arg) -> { - task.options.flags = arg; - }, "--flags"), - new Option(false, (task, opt, arg) -> { + + new Option(false, (task, option, arg) -> { task.options.verbose = true; }, "--verbose"), - new Option(false, (task, opt, arg) -> { + + new Option(false, (task, option, arg) -> { task.options.version = true; }, "--version") }; - private static final TaskHelper taskHelper + private static final TaskHelper TASK_HELPER = new TaskHelper(JIMAGE_BUNDLE); - private static final OptionsHelper optionsHelper - = taskHelper.newOptionsHelper(JImageTask.class, recognizedOptions); + private static final OptionsHelper OPTION_HELPER + = TASK_HELPER.newOptionsHelper(JImageTask.class, RECOGNIZED_OPTIONS); + private static final String PROGNAME = "jimage"; + private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem(); + + private final OptionsValues options; + private final List> filterPredicates; + private PrintWriter log; + + JImageTask() { + this.options = new OptionsValues(); + this.filterPredicates = new ArrayList<>(); + log = null; + } + + void setLog(PrintWriter out) { + log = out; + TASK_HELPER.setLog(log); + } static class OptionsValues { Task task = Task.LIST; String directory = "."; + String filters = ""; boolean fullVersion; boolean help; - String flags; boolean verbose; boolean version; List jimages = new LinkedList<>(); } - private static final String PROGNAME = "jimage"; - private final OptionsValues options = new OptionsValues(); - enum Task { EXTRACT, INFO, LIST, - SET, VERIFY }; @@ -145,50 +160,97 @@ class JImageTask { int run(String[] args) { if (log == null) { - setLog(new PrintWriter(System.out)); + setLog(new PrintWriter(System.out, true)); } if (args.length == 0) { - log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + log.println(TASK_HELPER.getMessage("main.usage.summary", PROGNAME)); return EXIT_ABNORMAL; } try { - List unhandled = optionsHelper.handleOptions(this, args); + List unhandled = OPTION_HELPER.handleOptions(this, args); + if(!unhandled.isEmpty()) { try { options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); } catch (IllegalArgumentException ex) { - throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0)); + throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0)); } + for(int i = 1; i < unhandled.size(); i++) { options.jimages.add(new File(unhandled.get(i))); } - } else { - throw taskHelper.newBadArgs("err.not.a.task", ""); + } else if (!options.help && !options.version && !options.fullVersion) { + throw TASK_HELPER.newBadArgs("err.invalid.task", ""); } + if (options.help) { - optionsHelper.showHelp(PROGNAME); + if (unhandled.isEmpty()) { + log.println(TASK_HELPER.getMessage("main.usage", PROGNAME)); + + for (Option o : RECOGNIZED_OPTIONS) { + String name = o.aliases()[0]; + + if (name.startsWith("--")) { + name = name.substring(2); + } else if (name.startsWith("-")) { + name = name.substring(1); + } + + log.println(TASK_HELPER.getMessage("main.opt." + name)); + } + } else { + try { + log.println(TASK_HELPER.getMessage("main.usage." + + options.task.toString().toLowerCase())); + } catch (MissingResourceException ex) { + throw TASK_HELPER.newBadArgs("err.not.a.task", unhandled.get(0)); + } + } + return EXIT_OK; } + if (options.version || options.fullVersion) { - taskHelper.showVersion(options.fullVersion); + TASK_HELPER.showVersion(options.fullVersion); + + if (unhandled.isEmpty()) { + return EXIT_OK; + } } - boolean ok = run(); - return ok ? EXIT_OK : EXIT_ERROR; + + processFilter(options.filters); + + return run() ? EXIT_OK : EXIT_ERROR; } catch (BadArgs e) { - taskHelper.reportError(e.key, e.args); + TASK_HELPER.reportError(e.key, e.args); + if (e.showUsage) { - log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + log.println(TASK_HELPER.getMessage("main.usage.summary", PROGNAME)); } + return EXIT_CMDERR; } catch (Exception x) { x.printStackTrace(); + return EXIT_ABNORMAL; } finally { log.flush(); } } + private void processFilter(String filters) { + if (filters.isEmpty()) { + return; + } + + for (String filter : filters.split(",")) { + final PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, filter); + Predicate predicate = (path) -> matcher.matches(JRT_FILE_SYSTEM.getPath(path)); + filterPredicates.add(predicate); + } + } + private void listTitle(File file, BasicImageReader reader) { log.println("jimage: " + file); } @@ -216,10 +278,12 @@ class JImageTask { if (parent.exists()) { if (!parent.isDirectory()) { - throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath()); + throw TASK_HELPER.newBadArgs("err.cannot.create.dir", + parent.getAbsolutePath()); } } else if (!parent.mkdirs()) { - throw taskHelper.newBadArgs("err.cannot.create.dir", parent.getAbsolutePath()); + throw TASK_HELPER.newBadArgs("err.cannot.create.dir", + parent.getAbsolutePath()); } if (!ImageResourcesTree.isTreeInfoResource(name)) { @@ -261,7 +325,7 @@ class JImageTask { log.println(" Major Version: " + header.getMajorVersion()); log.println(" Minor Version: " + header.getMinorVersion()); - log.println(" Flags: " + Integer.toHexString(header.getMinorVersion())); + log.println(" Flags: " + Integer.toHexString(header.getFlags())); log.println(" Resource Count: " + header.getResourceCount()); log.println(" Table Length: " + header.getTableLength()); log.println(" Offsets Size: " + header.getOffsetsSize()); @@ -287,36 +351,7 @@ class JImageTask { print(reader, name); } - void set(File file, BasicImageReader reader) throws BadArgs { - try { - ImageHeader oldHeader = reader.getHeader(); - - int value = 0; - try { - value = Integer.valueOf(options.flags); - } catch (NumberFormatException ex) { - throw taskHelper.newBadArgs("err.flags.not.int", options.flags); - } - - ImageHeader newHeader = new ImageHeader(MAGIC, MAJOR_VERSION, MINOR_VERSION, - value, - oldHeader.getResourceCount(), oldHeader.getTableLength(), - oldHeader.getLocationsSize(), oldHeader.getStringsSize()); - - ByteBuffer buffer = ByteBuffer.allocate(ImageHeader.getHeaderSize()); - buffer.order(ByteOrder.nativeOrder()); - newHeader.writeTo(buffer); - buffer.rewind(); - - try (FileChannel channel = FileChannel.open(file.toPath(), READ, WRITE)) { - channel.write(buffer, 0); - } - } catch (IOException ex) { - throw taskHelper.newBadArgs("err.cannot.update.file", file.getName()); - } - } - - void verify(BasicImageReader reader, String name, ImageLocation location) { + void verify(BasicImageReader reader, String name, ImageLocation location) { if (name.endsWith(".class")) { byte[] bytes = reader.getResource(location); @@ -335,12 +370,12 @@ class JImageTask { ModuleAction moduleAction, ResourceAction resourceAction) throws IOException, BadArgs { if (options.jimages.isEmpty()) { - throw taskHelper.newBadArgs("err.no.jimage"); + throw TASK_HELPER.newBadArgs("err.no.jimage"); } for (File file : options.jimages) { if (!file.exists() || !file.isFile()) { - throw taskHelper.newBadArgs("err.not.a.jimage", file.getName()); + throw TASK_HELPER.newBadArgs("err.not.a.jimage", file.getName()); } try (BasicImageReader reader = BasicImageReader.open(file.toPath())) { @@ -353,6 +388,19 @@ class JImageTask { String oldModule = ""; for (String name : entryNames) { + boolean match = filterPredicates.isEmpty(); + + for (Predicate predicate : filterPredicates) { + if (predicate.test(name)) { + match = true; + break; + } + } + + if (!match) { + continue; + } + if (!ImageResourcesTree.isTreeInfoResource(name)) { if (moduleAction != null) { int offset = name.indexOf('/', 1); @@ -387,21 +435,13 @@ class JImageTask { case LIST: iterate(this::listTitle, this::listModule, this::list); break; - case SET: - iterate(this::set, null, null); - break; case VERIFY: iterate(this::listTitle, null, this::verify); break; default: - throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true); + throw TASK_HELPER.newBadArgs("err.invalid.task", + options.task.name()).showUsage(true); } return true; } - - private PrintWriter log; - void setLog(PrintWriter out) { - log = out; - taskHelper.setLog(log); - } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index ef109232051..f0494be5763 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -24,54 +24,67 @@ # main.usage.summary=\ -Usage: {0} jimage...\n\ -use --help for a list of possible options +Usage: {0} jimage...\n\ +use --help for a list of possible options. main.usage=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ +\n\ +\ extract - Extract all jimage entries and place in a directory specified\n\ +\ by the --dir= (default='.') option.\n\ +\n\ +\ info - Prints detailed information contained in the jimage header.\n\ \n\ -\ extract - Extract all jimage entries into separate files into the directory\n\ -\ specified by --dir= (default='.')\n\ -\ info - Prints information specified in the jimage header.\n\ \ list - Prints the names of all the entries in the jimage. When used with\n\ -\ --verbose will also print entry attributes ex. size and offset.\n\ -\ set - sets the value of specific jimage header entries\n\ -\ verify - Reports errors on any .class entries that don't verify as classes.\n\ +\ --verbose, list will also print entry size and offset attributes.\n\ +\n\ +\ verify - Reports on any .class entries that don't verify as classes.\n\ \n\ Possible options include: +main.usage.extract=\ +\ extract - Extract all jimage entries and place in a directory specified\n\ +\ by the --dir= (default='.') option. + +main.usage.info=\ +\ info - Prints detailed information contained in the jimage header. + +main.usage.list=\ +\ list - Prints the names of all the entries in the jimage. When used with\n\ +\ --verbose, list will also print entry size and offset attributes. + +main.usage.verify=\ +\ verify - Reports errors on any .class entries that don't verify as classes. + error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract +\ --dir Target directory for extract directive -main.opt.flags=\ -\ --flags=value Set the jimage flags to value +main.opt.filter=\ +\ --filter Filter entries for list or extract\n\ +\ Ex. /java.base/*, */module-info.class + +main.opt.fullversion=\ +\ --fullversion Print full version information main.opt.help=\ -\ --help Print this usage message +\ --help Print usage message main.opt.verbose=\ -\ --verbose Verbose listing +\ --verbose Listing prints entry size and offset attributes main.opt.version=\ -\ --version Version information +\ --version Print version information main.command.files=\ -\ @ Read options from file -err.cannot.read.file=cannot read file: {0} -err.cannot.update.file=cannot update file: {0} -err.file.not.found=cannot find file: {0} -err.file.error=cannot access file: {0} -err.flags.not.int=--flags value not integer: {0} -err.internal.error=internal error: {0} {1} {2} -err.invalid.arg.for.option=invalid argument for option: {0} -err.invalid.task=task must be extract|info|list|verify: {0} +\ @ Read options from file + +err.not.a.task=task must be one of : {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} err.no.jimage=no jimage provided -err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index a5df2d71c06..e8b43855d12 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -186,7 +186,7 @@ public class JlinkTask { int run(String[] args) { if (log == null) { - setLog(new PrintWriter(System.err)); + setLog(new PrintWriter(System.err, true)); } try { optionsHelper.handleOptions(this, args); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index e8e69eeee81..5cc986f1bfd 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -136,6 +136,10 @@ public final class TaskHelper { void process(T task, String opt, String arg) throws BadArgs { processing.process(task, opt, arg); } + + public String[] aliases() { + return aliases; + } } private static class PlugOption extends Option { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java index 0e29969a034..62344efff4a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java @@ -25,6 +25,10 @@ package jdk.tools.jlink.internal; import java.lang.reflect.Module; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.PathMatcher; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -155,4 +159,20 @@ public class Utils { public static boolean isBuiltin(Plugin prov) { return THIS_MODULE.equals(prov.getClass().getModule()); } + + public static FileSystem jrtFileSystem() { + return FileSystems.getFileSystem(URI.create("jrt:/")); + } + + public static PathMatcher getPathMatcher(FileSystem fs, String pattern) { + if (!pattern.startsWith("glob:") && !pattern.startsWith("regex:")) { + pattern = "glob:" + pattern; + } + + return fs.getPathMatcher(pattern); + } + + public static PathMatcher getPathMatcher(String pattern) { + return getPathMatcher(jrtFileSystem(), pattern); + } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java index 5060bf5c519..c4ff910004a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java @@ -26,7 +26,9 @@ package jdk.tools.jlink.internal.plugins; import java.io.File; import java.io.IOException; +import java.nio.file.FileSystem; import java.nio.file.Files; +import java.nio.file.PathMatcher; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -47,6 +49,8 @@ import jdk.tools.jlink.internal.Utils; */ public final class OrderResourcesPlugin implements TransformerPlugin { public static final String NAME = "order-resources"; + private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem(); + private final List> filters; private final Map orderedPaths; @@ -187,27 +191,11 @@ public final class OrderResourcesPlugin implements TransformerPlugin { } } } else { - boolean endsWith = pattern.startsWith("*"); - boolean startsWith = pattern.endsWith("*"); - ToIntFunction function; final int result = ordinal++; - - if (startsWith && endsWith) { - final String string = pattern.substring(1, pattern.length() - 1); - function = (path)-> path.contains(string) ? result : Integer.MAX_VALUE; - } else if (startsWith) { - final String string = pattern.substring(0, pattern.length() - 1); - function = (path)-> path.startsWith(string) ? result : Integer.MAX_VALUE; - } else if (endsWith) { - final String string = pattern.substring(1); - function = (path)-> path.endsWith(string) ? result : Integer.MAX_VALUE; - } else { - final String string = pattern; - function = (path)-> path.equals(string) ? result : Integer.MAX_VALUE; - } - + final PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, pattern); + ToIntFunction function = (path)-> matcher.matches(JRT_FILE_SYSTEM.getPath(path)) ? result : Integer.MAX_VALUE; filters.add(function); - } + } } } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java index 10c9d3299bf..37287f19c94 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java @@ -24,113 +24,71 @@ */ package jdk.tools.jlink.internal.plugins; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import jdk.tools.jlink.internal.Utils; +import jdk.tools.jlink.plugin.PluginException; /** * - * Filter in or out a resource + * Filter resource resources using path matcher. */ public class ResourceFilter implements Predicate { + private static final FileSystem JRT_FILE_SYSTEM = Utils.jrtFileSystem(); - private final Pattern inPatterns; - private final Pattern outPatterns; - - static final String NEG = "^"; + final boolean negate; + final List matchers; public ResourceFilter(String[] patterns) throws IOException { this(patterns, false); } - public ResourceFilter(String[] patterns, boolean negateAll) throws IOException { + public ResourceFilter(String[] patterns, boolean negate) throws IOException { + this.negate = negate; + this.matchers = new ArrayList<>(); - // Get the patterns from a file - if (patterns != null && patterns.length == 1) { - String filePath = patterns[0]; - File f = new File(filePath); - if (f.exists()) { - List pats; - try (FileInputStream fis = new FileInputStream(f); - InputStreamReader ins = new InputStreamReader(fis, - StandardCharsets.UTF_8); - BufferedReader reader = new BufferedReader(ins)) { - pats = reader.lines().collect(Collectors.toList()); + for (String pattern : patterns) { + if (pattern.startsWith("@")) { + File file = new File(pattern.substring(1)); + + if (file.exists()) { + List lines; + + try { + lines = Files.readAllLines(file.toPath()); + } catch (IOException ex) { + throw new PluginException(ex); + } + + for (String line : lines) { + PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, line); + matchers.add(matcher); + } } - patterns = new String[pats.size()]; - pats.toArray(patterns); + } else { + PathMatcher matcher = Utils.getPathMatcher(JRT_FILE_SYSTEM, pattern); + matchers.add(matcher); } } - - if (patterns != null && negateAll) { - String[] excluded = new String[patterns.length]; - for (int i = 0; i < patterns.length; i++) { - excluded[i] = ResourceFilter.NEG + patterns[i]; - } - patterns = excluded; - } - - StringBuilder inPatternsBuilder = new StringBuilder(); - StringBuilder outPatternsBuilder = new StringBuilder(); - if (patterns != null) { - for (int i = 0; i < patterns.length; i++) { - String p = patterns[i]; - p = p.replaceAll(" ", ""); - StringBuilder builder = p.startsWith(NEG) - ? outPatternsBuilder : inPatternsBuilder; - String pat = p.startsWith(NEG) ? p.substring(NEG.length()) : p; - builder.append(escape(pat)); - if (i < patterns.length - 1) { - builder.append("|"); - } - } - } - this.inPatterns = inPatternsBuilder.length() == 0 ? null - : Pattern.compile(inPatternsBuilder.toString()); - this.outPatterns = outPatternsBuilder.length() == 0 ? null - : Pattern.compile(outPatternsBuilder.toString()); - } - - public static String escape(String s) { - s = s.replaceAll(" ", ""); - s = s.replaceAll("\\$", Matcher.quoteReplacement("\\$")); - s = s.replaceAll("\\.", Matcher.quoteReplacement("\\.")); - s = s.replaceAll("\\*", ".+"); - return s; - } - - private boolean accept(String path) { - if (outPatterns != null) { - Matcher mout = outPatterns.matcher(path); - if (mout.matches()) { - //System.out.println("Excluding file " + resource.getPath()); - return false; - } - } - boolean accepted = false; - // If the inPatterns is null, means that all resources are accepted. - if (inPatterns == null) { - accepted = true; - } else { - Matcher m = inPatterns.matcher(path); - if (m.matches()) { - //System.out.println("Including file " + resource.getPath()); - accepted = true; - } - } - return accepted; } @Override - public boolean test(String path) { - return accept(path); + public boolean test(String name) { + Path path = JRT_FILE_SYSTEM.getPath(name); + + for (PathMatcher matcher : matchers) { + if (matcher.matches(path)) { + return !negate; + } + } + + return negate; } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index 5cc8a8f649e..e73d91be0ca 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -1072,6 +1072,10 @@ public class JmodTask { @Override public Pattern convert(String value) { try { + if (value.startsWith("regex:")) { + value = value.substring("regex:".length()).trim(); + } + return Pattern.compile(value); } catch (PatternSyntaxException e) { throw new CommandException("err.bad.pattern", value); @@ -1083,10 +1087,15 @@ public class JmodTask { @Override public String valuePattern() { return "pattern"; } } - static class GlobConverter implements ValueConverter { + static class PathMatcherConverter implements ValueConverter { @Override public PathMatcher convert(String pattern) { try { + if (!pattern.startsWith("glob:") && + !pattern.startsWith("regex:")) { + pattern = "glob:" + pattern; + } + return FileSystems.getDefault() .getPathMatcher("glob:" + pattern); } catch (PatternSyntaxException e) { @@ -1194,7 +1203,7 @@ public class JmodTask { OptionSpec excludes = parser.accepts("exclude", getMessage("main.opt.exclude")) .withRequiredArg() - .withValuesConvertedBy(new GlobConverter()); + .withValuesConvertedBy(new PathMatcherConverter()); OptionSpec hashModules = parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index ce5beab2b06..0141163a0f4 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -167,6 +167,8 @@ java/net/MulticastSocket/Test.java 7145658 macosx-a java/net/DatagramSocket/SendDatagramToBadAddress.java 7143960 macosx-all +sun/net/www/http/ChunkedOutputStream/checkError.java 8041924 linux-all + ############################################################################ # jdk_nio @@ -199,6 +201,8 @@ java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic- sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all +java/rmi/transport/dgcDeadLock/DGCDeadLock.java 8029360 macosx-all + ############################################################################ # jdk_security diff --git a/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java index a232aaaec92..9cb25c739bc 100644 --- a/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java +++ b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,11 +150,6 @@ public abstract class TestCipher { } // Encryption - int PAD_LEN = 0; - if (pad.equalsIgnoreCase("PKCS5Padding")) { - // Need to consider pad bytes - PAD_LEN = 8; - } byte[] plainText = INPUT_TEXT.clone(); @@ -162,12 +157,13 @@ public abstract class TestCipher { byte[] cipherText = ci.doFinal(INPUT_TEXT, ENC_OFFSET, TEXT_LEN); // Generate cipher and save to same buffer - int offset = ci.update( + int enc_bytes = ci.update( INPUT_TEXT, ENC_OFFSET, TEXT_LEN, INPUT_TEXT, STORAGE_OFFSET); - ci.doFinal(INPUT_TEXT, offset + STORAGE_OFFSET); + enc_bytes += ci.doFinal(INPUT_TEXT, enc_bytes + STORAGE_OFFSET); if (!equalsBlock( - INPUT_TEXT, STORAGE_OFFSET, cipherText, 0, cipherText.length)) { + INPUT_TEXT, STORAGE_OFFSET, enc_bytes, + cipherText, 0, cipherText.length)) { throw new RuntimeException( "Different ciphers generated with same buffer"); } @@ -183,8 +179,8 @@ public abstract class TestCipher { byte[] recoveredText = ci.doFinal(cipherText, 0, cipherText.length); if (!equalsBlock( - plainText, ENC_OFFSET, recoveredText, 0, - recoveredText.length)) { + plainText, ENC_OFFSET, TEXT_LEN, + recoveredText, 0, recoveredText.length)) { throw new RuntimeException( "Recovered text not same as plain text"); } else { @@ -192,13 +188,13 @@ public abstract class TestCipher { } // Recover text from cipher and save to same buffer - ci.update(INPUT_TEXT, STORAGE_OFFSET, TEXT_LEN + PAD_LEN, INPUT_TEXT, - ENC_OFFSET); - ci.doFinal(INPUT_TEXT, ENC_OFFSET); + int dec_bytes = ci.update( + INPUT_TEXT, STORAGE_OFFSET, enc_bytes, INPUT_TEXT, ENC_OFFSET); + dec_bytes += ci.doFinal(INPUT_TEXT, dec_bytes + ENC_OFFSET); if (!equalsBlock( - plainText, ENC_OFFSET, recoveredText, 0, - recoveredText.length)) { + plainText, ENC_OFFSET, TEXT_LEN, + INPUT_TEXT, ENC_OFFSET, dec_bytes)) { throw new RuntimeException( "Recovered text not same as plain text with same buffer"); } else { @@ -208,9 +204,12 @@ public abstract class TestCipher { out.println("Test Passed."); } - private static boolean equalsBlock(byte[] b1, int off1, byte[] b2, int off2, - int len) { - for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) { + private static boolean equalsBlock(byte[] b1, int off1, int len1, + byte[] b2, int off2, int len2) { + if (len1 != len2) { + return false; + } + for (int i = off1, j = off2, k = 0; k < len1; i++, j++, k++) { if (b1[i] != b2[j]) { return false; } diff --git a/jdk/test/java/lang/String/concat/WithSecurityManager.java b/jdk/test/java/lang/String/concat/WithSecurityManager.java index 17fc437ff3f..d4aaeeaf131 100644 --- a/jdk/test/java/lang/String/concat/WithSecurityManager.java +++ b/jdk/test/java/lang/String/concat/WithSecurityManager.java @@ -26,7 +26,7 @@ import java.security.Permission; /** * @test * @summary String concatenation fails with a custom SecurityManager that uses concatenation - * @bug 8155090 + * @bug 8155090 8158851 * * @compile WithSecurityManager.java * @@ -37,17 +37,43 @@ import java.security.Permission; * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager + * + * @run main/othervm -Xverify:all -limitmods java.base WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager + * @run main/othervm -Xverify:all -limitmods java.base -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager */ public class WithSecurityManager { public static void main(String[] args) throws Throwable { - SecurityManager sm = new SecurityManager() { - @Override - public void checkPermission(Permission perm) { - String abc = "abc"; - String full = abc + "def"; - } - }; - System.setSecurityManager(sm); - ClassLoader cl = new ClassLoader() {}; + // First time should succeed to bootstrap everything + { + SecurityManager sm = new SecurityManager() { + @Override + public void checkPermission(Permission perm) { + String abc = "abc"; + String full = abc + "def"; + } + }; + System.setSecurityManager(sm); + ClassLoader cl = new ClassLoader() { + }; + } + + // Second time should succeed to run after bootstrapping + { + SecurityManager sm = new SecurityManager() { + @Override + public void checkPermission(Permission perm) { + String abc = "abc"; + String full = abc + "def"; + } + }; + System.setSecurityManager(sm); + ClassLoader cl = new ClassLoader() { + }; + } } } diff --git a/jdk/test/java/lang/annotation/AnnotationWithLambda.java b/jdk/test/java/lang/annotation/AnnotationWithLambda.java new file mode 100644 index 00000000000..ac213522923 --- /dev/null +++ b/jdk/test/java/lang/annotation/AnnotationWithLambda.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8147585 + * @summary Check Annotation with Lambda, with or without parameter + * @run testng AnnotationWithLambda + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.util.function.Consumer; + +import org.testng.annotations.*; +import static org.testng.Assert.*; + +public class AnnotationWithLambda { + + @Test + void testAnnotationWithLambda() { + Method[] methods = AnnotationWithLambda.MethodsWithAnnotations.class.getDeclaredMethods(); + for (Method method : methods) { + assertTrue((method.isAnnotationPresent(LambdaWithParameter.class)) && + (method.isAnnotationPresent(LambdaWithoutParameter.class))); + + } + } + + static class MethodsWithAnnotations { + + @LambdaWithParameter + @LambdaWithoutParameter + public void testAnnotationLambda() { + } + } +} + +@Target(value = ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@interface LambdaWithParameter { + Consumer f1 = a -> { + System.out.println("lambda has parameter"); + }; +} + +@Target(value = ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@interface LambdaWithoutParameter { + Runnable r = () -> System.out.println("lambda without parameter"); +} + diff --git a/jdk/test/java/net/httpclient/BasicWebSocketAPITest.java b/jdk/test/java/net/httpclient/BasicWebSocketAPITest.java index 4e454c0a533..0ee412450ed 100644 --- a/jdk/test/java/net/httpclient/BasicWebSocketAPITest.java +++ b/jdk/test/java/net/httpclient/BasicWebSocketAPITest.java @@ -30,6 +30,7 @@ import java.net.http.HttpClient; import java.net.http.WebSocket; import java.net.http.WebSocket.CloseCode; import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.channels.SocketChannel; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -90,12 +91,24 @@ public class BasicWebSocketAPITest { "message", () -> ws.sendBinary((ByteBuffer) null, true)) ); + checkAndClose( + (ws) -> + TestKit.assertThrows(IllegalArgumentException.class, + ".*message.*", + () -> ws.sendPing(ByteBuffer.allocate(126))) + ); checkAndClose( (ws) -> TestKit.assertThrows(NullPointerException.class, "message", () -> ws.sendPing(null)) ); + checkAndClose( + (ws) -> + TestKit.assertThrows(IllegalArgumentException.class, + ".*message.*", + () -> ws.sendPong(ByteBuffer.allocate(126))) + ); checkAndClose( (ws) -> TestKit.assertThrows(NullPointerException.class, @@ -106,7 +119,7 @@ public class BasicWebSocketAPITest { (ws) -> TestKit.assertThrows(NullPointerException.class, "message", - () -> ws.sendText((CharSequence) null, true)) + () -> ws.sendText(null, true)) ); checkAndClose( (ws) -> @@ -120,6 +133,12 @@ public class BasicWebSocketAPITest { "message", () -> ws.sendText((Stream) null)) ); + checkAndClose( + (ws) -> + TestKit.assertThrows(IllegalArgumentException.class, + "(?i).*reason.*", + () -> ws.sendClose(CloseCode.NORMAL_CLOSURE, CharBuffer.allocate(124))) + ); checkAndClose( (ws) -> TestKit.assertThrows(NullPointerException.class, diff --git a/jdk/test/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java b/jdk/test/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java new file mode 100644 index 00000000000..a310cbb0336 --- /dev/null +++ b/jdk/test/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java @@ -0,0 +1,494 @@ +/* + * 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 + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8051498 8145849 8158978 + * @summary JEP 244: TLS Application-Layer Protocol Negotiation Extension + * @compile MyX509ExtendedKeyManager.java + * @run main/othervm SSLServerSocketAlpnTest h2 h2 h2 + * @run main/othervm SSLServerSocketAlpnTest h2 h2,http/1.1 h2 + * @run main/othervm SSLServerSocketAlpnTest h2,http/1.1 h2,http/1.1 h2 + * @run main/othervm SSLServerSocketAlpnTest http/1.1,h2 h2,http/1.1 http/1.1 + * @run main/othervm SSLServerSocketAlpnTest h4,h3,h2 h1,h2 h2 + * @run main/othervm SSLServerSocketAlpnTest EMPTY h2,http/1.1 NONE + * @run main/othervm SSLServerSocketAlpnTest h2 EMPTY NONE + * @run main/othervm SSLServerSocketAlpnTest H2 h2 ERROR + * @run main/othervm SSLServerSocketAlpnTest h2 http/1.1 ERROR + * @author Brad Wetmore + */ +import java.io.*; +import java.security.KeyStore; + +import javax.net.ssl.*; + +public class SSLServerSocketAlpnTest { + + /* + * ============================================================= + * 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 = false; + + /* + * Where do we find the keystores? + */ + static String pathToStores = "../etc"; + static String keyStoreFile = "keystore"; + static String trustStoreFile = "truststore"; + static String passwd = "passphrase"; + + static String keyFilename = System.getProperty("test.src", ".") + "/" + + pathToStores + "/" + keyStoreFile; + static String trustFilename = System.getProperty("test.src", ".") + "/" + + pathToStores + "/" + trustStoreFile; + + /* + * SSLContext + */ + SSLContext mySSLContext = null; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + static String[] serverAPs; + static String[] clientAPs; + static String expectedAP; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * 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 { + SSLServerSocketFactory sslssf = mySSLContext.getServerSocketFactory(); + SSLServerSocket sslServerSocket + = (SSLServerSocket) sslssf.createServerSocket(serverPort); + sslServerSocket.setNeedClientAuth(true); + + SSLParameters sslp = sslServerSocket.getSSLParameters(); + + // for both client/server to call into X509KM + sslp.setNeedClientAuth(true); + + /* + * The default ciphersuite ordering from the SSLContext may not + * reflect "h2" ciphersuites as being preferred, additionally the + * client may not send them in an appropriate order. We could resort + * the suite list if so desired. + */ + String[] suites = sslp.getCipherSuites(); + sslp.setCipherSuites(suites); + sslp.setUseCipherSuitesOrder(true); // Set server side order + + // Set the ALPN selection. + sslp.setApplicationProtocols(serverAPs); + sslServerSocket.setSSLParameters(sslp); + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); + + if (sslSocket.getHandshakeApplicationProtocol() != null) { + throw new Exception ("getHandshakeApplicationProtocol() should " + + "return null before the handshake starts"); + } + + sslSocket.startHandshake(); + + if (sslSocket.getHandshakeApplicationProtocol() != null) { + throw new Exception ("getHandshakeApplicationProtocol() should " + + "return null after the handshake is completed"); + } + + String ap = sslSocket.getApplicationProtocol(); + System.out.println("Application Protocol: \"" + ap + "\""); + + if (ap == null) { + throw new Exception( + "Handshake was completed but null was received"); + } + if (expectedAP.equals("NONE")) { + if (!ap.isEmpty()) { + throw new Exception("Expected no ALPN value"); + } else { + System.out.println("No ALPN value negotiated, as expected"); + } + } else if (!expectedAP.equals(ap)) { + throw new Exception(expectedAP + + " ALPN value not available on negotiated connection"); + } + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + sslSocket.close(); + } + + /* + * 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 { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = mySSLContext.getSocketFactory(); + SSLSocket sslSocket + = (SSLSocket) sslsf.createSocket("localhost", serverPort); + + SSLParameters sslp = sslSocket.getSSLParameters(); + + /* + * The default ciphersuite ordering from the SSLContext may not + * reflect "h2" ciphersuites as being preferred, additionally the + * client may not send them in an appropriate order. We could resort + * the suite list if so desired. + */ + String[] suites = sslp.getCipherSuites(); + sslp.setCipherSuites(suites); + sslp.setUseCipherSuitesOrder(true); // Set server side order + + // Set the ALPN selection. + sslp.setApplicationProtocols(clientAPs); + sslSocket.setSSLParameters(sslp); + + if (sslSocket.getHandshakeApplicationProtocol() != null) { + throw new Exception ("getHandshakeApplicationProtocol() should " + + "return null before the handshake starts"); + } + + sslSocket.startHandshake(); + + if (sslSocket.getHandshakeApplicationProtocol() != null) { + throw new Exception ("getHandshakeApplicationProtocol() should " + + "return null after the handshake is completed"); + } + + /* + * Check that the resulting connection meets our defined ALPN + * criteria. If we were connecting to a non-JSSE implementation, + * the server might have negotiated something we shouldn't accept. + */ + String ap = sslSocket.getApplicationProtocol(); + System.out.println("Application Protocol: \"" + ap + "\""); + + if (ap == null) { + throw new Exception( + "Handshake was completed but null was received"); + } + if (expectedAP.equals("NONE")) { + if (!ap.isEmpty()) { + throw new Exception("Expected no ALPN value"); + } else { + System.out.println("No ALPN value negotiated, as expected"); + } + } else if (!expectedAP.equals(ap)) { + throw new Exception(expectedAP + + " ALPN value not available on negotiated connection"); + } + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + // 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"); + } + + // Validate parameters + if (args.length != 3) { + throw new Exception("Invalid number of test parameters"); + } + serverAPs = convert(args[0]); + clientAPs = convert(args[1]); + expectedAP = args[2]; + + /* + * Start the tests. + */ + try { + new SSLServerSocketAlpnTest(); + } catch (SSLHandshakeException she) { + if (args[2].equals("ERROR")) { + System.out.println("Caught the expected exception: " + she); + } else { + throw she; + } + } + + System.out.println("Test Passed."); + } + + SSLContext getSSLContext(String keyFilename, String trustFilename) + throws Exception { + SSLContext ctx = SSLContext.getInstance("TLS"); + + // Keystores + KeyStore keyKS = KeyStore.getInstance("JKS"); + keyKS.load(new FileInputStream(keyFilename), passwd.toCharArray()); + + KeyStore trustKS = KeyStore.getInstance("JKS"); + trustKS.load(new FileInputStream(trustFilename), passwd.toCharArray()); + + // Generate KeyManager and TrustManager + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(keyKS, passwd.toCharArray()); + + KeyManager[] kms = kmf.getKeyManagers(); + if (!(kms[0] instanceof X509ExtendedKeyManager)) { + throw new Exception("kms[0] not X509ExtendedKeyManager"); + } + + kms = new KeyManager[] { new MyX509ExtendedKeyManager( + (X509ExtendedKeyManager) kms[0], expectedAP) }; + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(trustKS); + TrustManager[] tms = tmf.getTrustManagers(); + + // initial SSLContext + ctx.init(kms, tms, null); + + return ctx; + } + + /* + * Convert a comma-separated list into an array of strings. + */ + private static String[] convert(String list) { + String[] strings; + + if (list.equals("EMPTY")) { + return new String[0]; + } + + if (list.indexOf(',') > 0) { + strings = list.split(","); + } else { + strings = new String[]{ list }; + } + + return strings; + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + SSLServerSocketAlpnTest() throws Exception { + Exception startException = null; + mySSLContext = getSSLContext(keyFilename, trustFilename); + 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() { + @Override + 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() { + @Override + 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; + } + } + } +} diff --git a/jdk/test/sun/security/provider/DSA/SupportedDSAParamGen.java b/jdk/test/sun/security/provider/DSA/SupportedDSAParamGen.java index 1a10b4ce272..7b770a993cf 100644 --- a/jdk/test/sun/security/provider/DSA/SupportedDSAParamGen.java +++ b/jdk/test/sun/security/provider/DSA/SupportedDSAParamGen.java @@ -28,7 +28,7 @@ * @run main/timeout=300 SupportedDSAParamGen 1024 160 * @run main/timeout=300 SupportedDSAParamGen 2048 224 * @run main/timeout=300 SupportedDSAParamGen 2048 256 - * @run main/timeout=450 SupportedDSAParamGen 3072 256 + * @run main/timeout=700 SupportedDSAParamGen 3072 256 */ import java.security.*; import java.security.spec.*; diff --git a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java index 45a7c178455..f2be9ed9ad8 100644 --- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java +++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java @@ -31,9 +31,6 @@ import java.security.NoSuchProviderException; import java.security.spec.DSAGenParameterSpec; import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; /* * @test @@ -43,8 +40,15 @@ import java.util.stream.Collectors; * DSA within some certain range of key sizes as described in the class * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and * (3072, 256) should be OK for DSAGenParameterSpec. - * @run main TestDSAGenParameterSpec 2048,256,true 2048,224,true 1024,160,true 4096,256 3072,224 2048,160 1024,224 512,160 - * @run main TestDSAGenParameterSpec 3072,256,true + * @run main TestDSAGenParameterSpec 512 160 + * @run main TestDSAGenParameterSpec 1024 160 true + * @run main TestDSAGenParameterSpec 1024 224 + * @run main TestDSAGenParameterSpec 2048 160 + * @run main/timeout=300 TestDSAGenParameterSpec 2048 224 true + * @run main/timeout=300 TestDSAGenParameterSpec 2048 256 true + * @run main TestDSAGenParameterSpec 3072 224 + * @run main/timeout=700 TestDSAGenParameterSpec 3072 256 true + * @run main TestDSAGenParameterSpec 4096 256 */ public class TestDSAGenParameterSpec { @@ -57,8 +61,8 @@ public class TestDSAGenParameterSpec { System.out.printf("Test case: primePLen=%d, " + "subprimeQLen=%d%n", dataTuple.primePLen, dataTuple.subprimeQLen); - AlgorithmParameterGenerator apg = - AlgorithmParameterGenerator.getInstance(ALGORITHM_NAME, + AlgorithmParameterGenerator apg + = AlgorithmParameterGenerator.getInstance(ALGORITHM_NAME, PROVIDER_NAME); DSAGenParameterSpec genParamSpec = createGenParameterSpec(dataTuple); @@ -80,8 +84,8 @@ public class TestDSAGenParameterSpec { private static void checkParam(AlgorithmParameters param, DSAGenParameterSpec genParam) throws InvalidParameterSpecException, - NoSuchAlgorithmException, NoSuchProviderException, - InvalidAlgorithmParameterException { + NoSuchAlgorithmException, NoSuchProviderException, + InvalidAlgorithmParameterException { String algorithm = param.getAlgorithm(); if (!algorithm.equalsIgnoreCase(ALGORITHM_NAME)) { throw new RuntimeException( @@ -139,21 +143,25 @@ public class TestDSAGenParameterSpec { } public static void main(String[] args) throws Exception { - List dataTuples = Arrays.stream(args) - .map(arg -> arg.split(",")).map(params -> { - int primePLen = Integer.valueOf(params[0]); - int subprimeQLen = Integer.valueOf(params[1]); - boolean isDSASpecSupported = false; - if (params.length == 3) { - isDSASpecSupported = Boolean.valueOf(params[2]); - } - return new DataTuple(primePLen, subprimeQLen, - isDSASpecSupported); - }).collect(Collectors.toList()); - - for (DataTuple dataTuple : dataTuples) { - testDSAGenParameterSpec(dataTuple); + if (args == null || args.length < 2) { + throw new RuntimeException("Invalid number of arguments to generate" + + " DSA parameter."); } + DataTuple dataTuple = null; + switch (args.length) { + case 3: + dataTuple = new DataTuple(Integer.valueOf(args[0]), + Integer.valueOf(args[1]), Boolean.valueOf(args[2])); + break; + case 2: + dataTuple = new DataTuple(Integer.valueOf(args[0]), + Integer.valueOf(args[1]), false); + break; + default: + throw new RuntimeException("Unsupported arguments found."); + } + testDSAGenParameterSpec(dataTuple); + } private static class DataTuple { @@ -170,4 +178,3 @@ public class TestDSAGenParameterSpec { } } } - diff --git a/jdk/test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java similarity index 77% rename from jdk/test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java rename to jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java index a0caa26091e..65a876e4a78 100644 --- a/jdk/test/sun/security/provider/SecureRandom/AbstractDrbgSpec.java +++ b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java @@ -22,20 +22,25 @@ */ /* @test - * @bug 8051408 + * @bug 8051408 8157308 * @modules java.base/sun.security.provider + * @build java.base/sun.security.provider.S + * @run main SpecTest * @summary check the AbstractDrbg API etc */ import java.security.*; -import sun.security.provider.AbstractDrbg; +import sun.security.provider.S; import static java.security.DrbgParameters.Capability.*; /** * This test makes sure the AbstractDrbg API works as specified. It also * checks the SecureRandom API. + * + * The implementations must be patched into java.base/sun.security.provider + * because AbstractDrbg is not a public interface. */ -public class AbstractDrbgSpec { +public class SpecTest { public static void main(String args[]) throws Exception { @@ -170,9 +175,9 @@ public class AbstractDrbgSpec { public static class All extends Provider { protected All(String name, double version, String info) { super(name, version, info); - put("SecureRandom.S1", S1.class.getName()); - put("SecureRandom.S2", S2.class.getName()); - put("SecureRandom.S3", S3.class.getName()); + put("SecureRandom.S1", S.S1.class.getName()); + put("SecureRandom.S2", S.S2.class.getName()); + put("SecureRandom.S3", S.S3.class.getName()); } } @@ -180,92 +185,21 @@ public class AbstractDrbgSpec { public static class Legacy extends Provider { protected Legacy(String name, double version, String info) { super(name, version, info); - put("SecureRandom.S", S1.class.getName()); + put("SecureRandom.S", S.S1.class.getName()); } } public static class Weak extends Provider { protected Weak(String name, double version, String info) { super(name, version, info); - put("SecureRandom.S", S2.class.getName()); + put("SecureRandom.S", S.S2.class.getName()); } } public static class Strong extends Provider { protected Strong(String name, double version, String info) { super(name, version, info); - put("SecureRandom.S", S3.class.getName()); - } - } - - // This is not a DRBG. - public static class S1 extends SecureRandomSpi { - @Override - protected void engineSetSeed(byte[] seed) { - } - - @Override - protected void engineNextBytes(byte[] bytes) { - } - - @Override - protected byte[] engineGenerateSeed(int numBytes) { - return new byte[numBytes]; - } - } - - // This is a strong DRBG. - public static class S3 extends AbstractDrbg { - - public S3(SecureRandomParameters params) { - supportPredictionResistance = true; - supportReseeding = true; - highestSupportedSecurityStrength = 192; - mechName = "S3"; - algorithm = "SQUEEZE"; - configure(params); - } - protected void chooseAlgorithmAndStrength() { - if (requestedInstantiationSecurityStrength < 0) { - securityStrength = DEFAULT_STRENGTH; - } else { - securityStrength = requestedInstantiationSecurityStrength; - } - minLength = securityStrength / 8; - maxAdditionalInputLength = maxPersonalizationStringLength = 100; - } - - @Override - protected void initEngine() { - - } - - @Override - protected void instantiateAlgorithm(byte[] ei) { - - } - - @Override - protected void generateAlgorithm(byte[] result, byte[] additionalInput) { - - } - - @Override - protected void reseedAlgorithm(byte[] ei, byte[] additionalInput) { - - } - } - - // This is a weak DRBG. maximum strength is 128 and does - // not support prediction resistance or reseed. - public static class S2 extends S3 { - public S2(SecureRandomParameters params) { - super(null); - mechName = "S2"; - highestSupportedSecurityStrength = 128; - supportPredictionResistance = false; - supportReseeding = false; - configure(params); + put("SecureRandom.S", S.S3.class.getName()); } } diff --git a/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/java.base/sun/security/provider/S.java b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/java.base/sun/security/provider/S.java new file mode 100644 index 00000000000..e9bdd4f530f --- /dev/null +++ b/jdk/test/sun/security/provider/SecureRandom/AbstractDrbg/java.base/sun/security/provider/S.java @@ -0,0 +1,155 @@ +/* + * 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 sun.security.provider; + +import java.security.SecureRandomParameters; +import java.security.SecureRandomSpi; + +/** + * Read ../../../../SpecTest.java for details. + */ +public class S extends SecureRandomSpi { + + protected AbstractDrbg impl; + + // This is not a DRBG. + public static class S1 extends SecureRandomSpi { + @Override + protected void engineSetSeed(byte[] seed) { + } + + @Override + protected void engineNextBytes(byte[] bytes) { + } + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + return new byte[numBytes]; + } + } + + // This is a weak DRBG. maximum strength is 128 and does + // not support prediction resistance or reseed. + public static class S2 extends S { + public S2(SecureRandomParameters params) { + impl = new Impl2(params); + } + } + + // This is a strong DRBG. + public static class S3 extends S { + public S3(SecureRandomParameters params) { + impl = new Impl3(params); + } + } + + // AbstractDrbg Implementations + + static class Impl3 extends AbstractDrbg { + + public Impl3(SecureRandomParameters params) { + supportPredictionResistance = true; + supportReseeding = true; + highestSupportedSecurityStrength = 192; + mechName = "S3"; + algorithm = "SQUEEZE"; + configure(params); + } + + protected void chooseAlgorithmAndStrength() { + if (requestedInstantiationSecurityStrength < 0) { + securityStrength = DEFAULT_STRENGTH; + } else { + securityStrength = requestedInstantiationSecurityStrength; + } + minLength = securityStrength / 8; + maxAdditionalInputLength = maxPersonalizationStringLength = 100; + } + + @Override + protected void initEngine() { + } + + @Override + protected void instantiateAlgorithm(byte[] ei) { + } + + @Override + protected void generateAlgorithm(byte[] result, byte[] additionalInput) { + } + + @Override + protected void reseedAlgorithm(byte[] ei, byte[] additionalInput) { + } + } + + static class Impl2 extends Impl3 { + public Impl2(SecureRandomParameters params) { + super(null); + mechName = "S2"; + highestSupportedSecurityStrength = 128; + supportPredictionResistance = false; + supportReseeding = false; + configure(params); + } + } + + // Overridden SecureRandomSpi methods + + @Override + protected void engineSetSeed(byte[] seed) { + impl.engineSetSeed(seed); + } + + @Override + protected void engineNextBytes(byte[] bytes) { + impl.engineNextBytes(bytes); + } + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + return impl.engineGenerateSeed(numBytes); + } + + @Override + protected void engineNextBytes( + byte[] bytes, SecureRandomParameters params) { + impl.engineNextBytes(bytes, params); + } + + @Override + protected void engineReseed(SecureRandomParameters params) { + impl.engineReseed(params); + } + + @Override + protected SecureRandomParameters engineGetParameters() { + return impl.engineGetParameters(); + } + + @Override + public String toString() { + return impl.toString(); + } +} diff --git a/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java b/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java new file mode 100644 index 00000000000..aaf005d44bb --- /dev/null +++ b/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java @@ -0,0 +1,70 @@ +/* + * 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 sun.security.provider.DRBG; +import sun.security.provider.MoreDrbgParameters; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; + +/** + * @test + * @bug 8157308 + * @modules java.base/sun.security.provider + * @summary Make AbstractDrbg non-Serializable + * @run main DRBGS11n mech + * @run main DRBGS11n capability + */ +public class DRBGS11n { + + public static void main(String[] args) throws Exception { + + DRBG d = new DRBG(null); + Field f = DRBG.class.getDeclaredField("mdp"); + f.setAccessible(true); + MoreDrbgParameters mdp = (MoreDrbgParameters)f.get(d); + + // Corrupt the mech or capability fields inside DRBG#mdp. + f = MoreDrbgParameters.class.getDeclaredField(args[0]); + f.setAccessible(true); + f.set(mdp, null); + + try { + revive(d); + } catch (IllegalArgumentException iae) { + // Expected + return; + } + + throw new Exception("revive should fail"); + } + + static T revive(T in) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + new ObjectOutputStream(bout).writeObject(in); + return (T) new ObjectInputStream( + new ByteArrayInputStream(bout.toByteArray())).readObject(); + } +}