This commit is contained in:
Lana Steuck 2016-06-09 19:07:27 +00:00
commit ffe5156969
45 changed files with 1500 additions and 850 deletions

View File

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

View File

@ -2204,15 +2204,7 @@ return mh1;
}
}
private static final Class<?> PUBLIC_LOOKUP_CLASS;
static {
PrivilegedAction<Class<?>> pa = new PrivilegedAction<Class<?>>() {
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

View File

@ -1733,41 +1733,32 @@ public final class StringConcatFactory {
// no instantiation
}
// This one is deliberately non-lambdified to optimize startup time:
private static final Function<Class<?>, MethodHandle> MOST = new Function<Class<?>, MethodHandle>() {
private static class StringifierMost extends ClassValue<MethodHandle> {
@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<Class<?>, MethodHandle> ANY = new Function<Class<?>, MethodHandle>() {
private static class StringifierAny extends ClassValue<MethodHandle> {
@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<Class<?>, MethodHandle> STRINGIFIERS_MOST = new ConcurrentHashMap<>();
private static final ConcurrentMap<Class<?>, MethodHandle> STRINGIFIERS_ANY = new ConcurrentHashMap<>();
private static final ClassValue<MethodHandle> STRINGIFIERS_MOST = new StringifierMost();
private static final ClassValue<MethodHandle> 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);
}
}

View File

@ -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:
*
* <blockquote>
* {@code http://java.sun.com/j2se/1.3/}<br>
* {@code docs/guide/collections/designfaq.html#28}<br>
* {@code ../../../demo/jfc/SwingSet2/src/SwingSet2.java}<br>
* {@code http://example.com/languages/java/}<br>
* {@code sample/a/index.html#28}<br>
* {@code ../../demo/b/index.html}<br>
* {@code file:///~/calendar}
* </blockquote>
*
@ -178,28 +178,28 @@ import java.lang.NullPointerException; // for javadoc
* normalized. The result, for example, of resolving
*
* <blockquote>
* {@code docs/guide/collections/designfaq.html#28}
* {@code sample/a/index.html#28}
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
* &nbsp;&nbsp;&nbsp;&nbsp;(1)
* </blockquote>
*
* 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
*
* <blockquote>
* {@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}
* </blockquote>
*
* Resolving the relative URI
*
* <blockquote>
* {@code ../../../demo/jfc/SwingSet2/src/SwingSet2.java}&nbsp;&nbsp;&nbsp;&nbsp;(2)
* {@code ../../demo/b/index.html}&nbsp;&nbsp;&nbsp;&nbsp;(2)
* </blockquote>
*
* against this result yields, in turn,
*
* <blockquote>
* {@code http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java}
* {@code http://example.com/languages/java/demo/b/index.html}
* </blockquote>
*
* Resolution of both absolute and relative URIs, and of both absolute and
@ -210,7 +210,7 @@ import java.lang.NullPointerException; // for javadoc
* URI
*
* <blockquote>
* {@code demo/jfc/SwingSet2/src/SwingSet2.java}
* {@code demo/b/index.html}
* </blockquote>
*
* <p> <i>Relativization</i>, finally, is the inverse of resolution: For any
@ -226,16 +226,16 @@ import java.lang.NullPointerException; // for javadoc
* possible. For example, relativizing the URI
*
* <blockquote>
* {@code http://docs.oracle.com/javase/1.3/docs/guide/index.html}
* {@code http://example.com/languages/java/sample/a/index.html#28}
* </blockquote>
*
* against the base URI
*
* <blockquote>
* {@code http://java.sun.com/j2se/1.3}
* {@code http://example.com/languages/java/}
* </blockquote>
*
* yields the relative URI {@code docs/guide/index.html}.
* yields the relative URI {@code sample/a/index.html#28}.
*
*
* <h4> Character categories </h4>

View File

@ -33,6 +33,7 @@ package java.security;
* can be passed to those implementations that support them.
*
* @see DrbgParameters
* @since 9
*/
public interface SecureRandomParameters {
}

View File

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

View File

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

View File

@ -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}.
* <p>
* 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:
* <ol>
* <li>{@link #generateAlgorithm(byte[], byte[])}
* <li>{@link #reseedAlgorithm(byte[], byte[])} (might not be supported)
* <li>{@link #reseedAlgorithm(byte[], byte[])} (In fact this is not an
* abstract method, but any DRBG supporting reseeding must override it.)
* <li>{@link #instantiateAlgorithm(byte[])}
* </ol>
* and 2 for implementation purpose:
@ -46,18 +47,19 @@ import static java.security.DrbgParameters.Capability.*;
* <li>{@link #initEngine()}
* <li>{@link #chooseAlgorithmAndStrength}
* </ol>
* 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.
* <p>
* 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.
* <p>
* 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) {

View File

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

View File

@ -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() + ","

View File

@ -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<String>)
() -> 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();
}
}

View File

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

View File

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

View File

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

View File

@ -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();

View File

@ -497,7 +497,8 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
String identificationProtocol,
AlgorithmConstraints algorithmConstraints,
Collection<SNIMatcher> 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);
/*

View File

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

View File

@ -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<Void> sendText(ByteBuffer message, boolean isLast) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public CompletableFuture<Void> sendText(CharSequence message, boolean isLast) {
public CompletableFuture<WebSocket> sendText(CharSequence message, boolean isLast) {
requireNonNull(message, "message");
synchronized (stateLock) {
checkState();
@ -109,7 +104,7 @@ final class WS implements WebSocket {
}
@Override
public CompletableFuture<Void> sendText(Stream<? extends CharSequence> message) {
public CompletableFuture<WebSocket> sendText(Stream<? extends CharSequence> message) {
requireNonNull(message, "message");
synchronized (stateLock) {
checkState();
@ -118,7 +113,7 @@ final class WS implements WebSocket {
}
@Override
public CompletableFuture<Void> sendBinary(ByteBuffer message, boolean isLast) {
public CompletableFuture<WebSocket> sendBinary(ByteBuffer message, boolean isLast) {
requireNonNull(message, "message");
synchronized (stateLock) {
checkState();
@ -127,7 +122,7 @@ final class WS implements WebSocket {
}
@Override
public CompletableFuture<Void> sendPing(ByteBuffer message) {
public CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
requireNonNull(message, "message");
synchronized (stateLock) {
checkState();
@ -136,7 +131,7 @@ final class WS implements WebSocket {
}
@Override
public CompletableFuture<Void> sendPong(ByteBuffer message) {
public CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
requireNonNull(message, "message");
synchronized (stateLock) {
checkState();
@ -145,7 +140,7 @@ final class WS implements WebSocket {
}
@Override
public CompletableFuture<Void> sendClose(CloseCode code, CharSequence reason) {
public CompletableFuture<WebSocket> 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<Void> sendClose() {
public CompletableFuture<WebSocket> sendClose() {
synchronized (stateLock) {
return doSendClose(() -> transmitter.sendClose());
}
}
private CompletableFuture<Void> doSendClose(Supplier<CompletableFuture<Void>> s) {
private CompletableFuture<WebSocket> doSendClose(Supplier<CompletableFuture<WebSocket>> s) {
checkState();
boolean closeChannel = false;
synchronized (stateLock) {
@ -170,7 +165,7 @@ final class WS implements WebSocket {
tryChangeState(State.CLOSED_LOCALLY);
}
}
CompletableFuture<Void> sent = s.get();
CompletableFuture<WebSocket> 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);

View File

@ -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<CharBuffer> text;
WSDisposableText(WSShared<CharBuffer> 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();
}
}

View File

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

View File

@ -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<CharBuffer> data);
void onBinary(MessagePart part, WSShared<ByteBuffer> data);

View File

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

View File

@ -51,15 +51,17 @@ import static java.net.http.Pair.pair;
*/
final class WSTransmitter {
private final BlockingQueue<Pair<WSOutgoingMessage, CompletableFuture<Void>>>
private final BlockingQueue<Pair<WSOutgoingMessage, CompletableFuture<WebSocket>>>
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<Throwable> errorHandler) {
WSTransmitter(WebSocket ws, Executor executor, RawChannel channel, Consumer<Throwable> errorHandler) {
this.webSocket = ws;
this.handler = new WSSignalHandler(executor, this::handleSignal);
Consumer<Throwable> sendCompletion = (error) -> {
synchronized (this) {
@ -76,41 +78,41 @@ final class WSTransmitter {
this.sender = new WSMessageSender(channel, sendCompletion);
}
CompletableFuture<Void> sendText(CharSequence message, boolean isLast) {
CompletableFuture<WebSocket> sendText(CharSequence message, boolean isLast) {
checkAndUpdateText(isLast);
return acceptMessage(new Text(isLast, message));
}
CompletableFuture<Void> sendText(Stream<? extends CharSequence> message) {
CompletableFuture<WebSocket> sendText(Stream<? extends CharSequence> message) {
checkAndUpdateText(true);
return acceptMessage(new StreamedText(message));
}
CompletableFuture<Void> sendBinary(ByteBuffer message, boolean isLast) {
CompletableFuture<WebSocket> sendBinary(ByteBuffer message, boolean isLast) {
checkAndUpdateBinary(isLast);
return acceptMessage(new Binary(isLast, message));
}
CompletableFuture<Void> sendPing(ByteBuffer message) {
CompletableFuture<WebSocket> sendPing(ByteBuffer message) {
checkSize(message.remaining(), 125);
return acceptMessage(new Ping(message));
}
CompletableFuture<Void> sendPong(ByteBuffer message) {
CompletableFuture<WebSocket> sendPong(ByteBuffer message) {
checkSize(message.remaining(), 125);
return acceptMessage(new Pong(message));
}
CompletableFuture<Void> sendClose(WebSocket.CloseCode code, CharSequence reason) {
CompletableFuture<WebSocket> sendClose(WebSocket.CloseCode code, CharSequence reason) {
return acceptMessage(createCloseMessage(code, reason));
}
CompletableFuture<Void> sendClose() {
CompletableFuture<WebSocket> sendClose() {
return acceptMessage(new Close(ByteBuffer.allocate(0)));
}
private CompletableFuture<Void> acceptMessage(WSOutgoingMessage m) {
CompletableFuture<Void> cf = new CompletableFuture<>();
private CompletableFuture<WebSocket> acceptMessage(WSOutgoingMessage m) {
CompletableFuture<WebSocket> 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<WSOutgoingMessage, CompletableFuture<Void>> p = backlog.peek();
Pair<WSOutgoingMessage, CompletableFuture<WebSocket>> p = backlog.peek();
boolean sent = sender.trySendFully(p.first);
if (sent) {
backlog.remove();
p.second.complete(null);
p.second.complete(webSocket);
previousMessageSent = true;
}
}

View File

@ -52,8 +52,8 @@ import java.util.stream.Stream;
*
* <p> 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.
*
* <p> 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}.
*
* <p> Returns immediately with a {@code CompletableFuture<WebSocket>}
* which completes with the {@code WebSocket} when it is connected, or
* completes exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally with the {@code WebSocket} when it is connected or completes
* exceptionally if an error occurs.
*
* <p> {@code CompletableFuture} may complete exceptionally with the
* following errors:
@ -252,7 +255,7 @@ public interface WebSocket {
* if the opening handshake fails
* </ul>
*
* @return a {@code CompletableFuture} of {@code WebSocket}
* @return a {@code CompletableFuture} with the {@code WebSocket}
*/
CompletableFuture<WebSocket> buildAsync();
}
@ -264,7 +267,7 @@ public interface WebSocket {
* <ul>
* <li> {@link #onOpen onOpen} <br>
* This method is always the first to be invoked.
* <li> {@link #onText(WebSocket, WebSocket.Text, WebSocket.MessagePart)
* <li> {@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} <br>
@ -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}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
*
* <p> 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.
*
* <p> The {@code ByteBuffer} should not be modified until the returned
* {@code CompletableFuture} completes (either normally or exceptionally).
*
* <p> The returned {@code CompletableFuture} can complete exceptionally
* with:
* <ul>
* <li> {@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
* </ul>
*
* @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<Void> sendText(ByteBuffer message, boolean isLast);
/**
* Sends a Text message with characters from the given {@code
* CharSequence}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
*
* <p> 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.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> 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:
* <ul>
* <li> {@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
* <li> {@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}
* </ul>
*
* @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<Void> sendText(CharSequence message, boolean isLast);
CompletableFuture<WebSocket> sendText(CharSequence message, boolean isLast);
/**
* Sends a whole Text message with characters from the given {@code
@ -689,9 +647,9 @@ public interface WebSocket {
* <p> This is a convenience method. For the general case, use {@link
* #sendText(CharSequence, boolean)}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> 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:
* <ul>
* <li> {@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
* <li> {@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}
* </ul>
*
* @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<Void> sendText(CharSequence message) {
default CompletableFuture<WebSocket> sendText(CharSequence message) {
return sendText(message, true);
}
@ -731,9 +685,9 @@ public interface WebSocket {
* <p> This is a convenience method. For the general case use {@link
* #sendText(CharSequence, boolean)}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> Streamed character sequences should not be modified until the
* returned {@code CompletableFuture} completes (either normally or
@ -743,41 +697,41 @@ public interface WebSocket {
* with:
* <ul>
* <li> {@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
* <li> {@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}
* </ul>
*
* @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<Void> sendText(Stream<? extends CharSequence> message);
CompletableFuture<WebSocket> sendText(Stream<? extends CharSequence> message);
/**
* Sends a Binary message with bytes from the given {@code ByteBuffer}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> The returned {@code CompletableFuture} can complete exceptionally
* with:
* <ul>
* <li> {@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
* <li> {@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}
* </ul>
*
* @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<Void> sendBinary(ByteBuffer message, boolean isLast);
CompletableFuture<WebSocket> sendBinary(ByteBuffer message, boolean isLast);
/**
* Sends a Binary message with bytes from the given {@code byte[]}.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> The returned {@code CompletableFuture} can complete exceptionally
* with:
* <ul>
* <li> {@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
* <li> {@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}
* </ul>
*
* @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<Void> sendBinary(byte[] message, boolean isLast) {
default CompletableFuture<WebSocket> 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.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> 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:
* <ul>
* <li> {@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
* <li> {@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
* </ul>
*
* @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<Void> sendPing(ByteBuffer message);
CompletableFuture<WebSocket> sendPing(ByteBuffer message);
/**
* Sends a Pong message.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> 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:
* <ul>
* <li> {@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
* <li> {@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
* </ul>
*
* @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<Void> sendPong(ByteBuffer message);
CompletableFuture<WebSocket> sendPong(ByteBuffer message);
/**
* Sends a Close message with the given close code and the reason.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> 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:
* <ul>
* <li> {@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
* <li> {@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
* </ul>
*
* @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<Void> sendClose(CloseCode code, CharSequence reason);
CompletableFuture<WebSocket> sendClose(CloseCode code, CharSequence reason);
/**
* Sends an empty Close message.
*
* <p> Returns immediately with a {@code CompletableFuture<Void>} which
* completes normally when the message has been sent, or completes
* exceptionally if an error occurs.
* <p> Returns a {@code CompletableFuture<WebSocket>} which completes
* normally when the message has been sent or completes exceptionally if an
* error occurs.
*
* <p> The returned {@code CompletableFuture} can complete exceptionally
* with:
* <ul>
* <li> {@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
* <li> {@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
* </ul>
*
* @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<Void> sendClose();
CompletableFuture<WebSocket> 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.
*
* <p> 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();
}
}

View File

@ -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 &quot;MULTITHREADED&quot;, and also, the engine maintains independent values
* for symbols in scripts executing on different threads.
* <li><code>&quot;STATELESS&quot;</code> - The implementation satisfies the requirements of
* <li><code>&quot;THREAD-ISOLATED&quot;</code>. In addition, script executions do not alter the
* <code>&quot;THREAD-ISOLATED&quot;</code>. In addition, script executions do not alter the
* mappings in the <code>Bindings</code> which is the engine scope of the
* <code>ScriptEngine</code>. In particular, the keys in the <code>Bindings</code>
* and their associated values are the same before and after the execution of the script.

View File

@ -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<Boolean> action) {

View File

@ -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<JImageTask>(true, (task, opt, arg) -> {
private static final Option<?>[] RECOGNIZED_OPTIONS = {
new Option<JImageTask>(true, (task, option, arg) -> {
task.options.directory = arg;
}, "--dir"),
new Option<JImageTask>(false, (task, opt, arg) -> {
new Option<JImageTask>(true, (task, option, arg) -> {
task.options.filters = arg;
}, "--filter"),
new Option<JImageTask>(false, (task, option, arg) -> {
task.options.fullVersion = true;
}, true, "--fullversion"),
new Option<JImageTask>(false, (task, opt, arg) -> {
new Option<JImageTask>(false, (task, option, arg) -> {
task.options.help = true;
}, "--help"),
new Option<JImageTask>(true, (task, opt, arg) -> {
task.options.flags = arg;
}, "--flags"),
new Option<JImageTask>(false, (task, opt, arg) -> {
new Option<JImageTask>(false, (task, option, arg) -> {
task.options.verbose = true;
}, "--verbose"),
new Option<JImageTask>(false, (task, opt, arg) -> {
new Option<JImageTask>(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<JImageTask> optionsHelper
= taskHelper.newOptionsHelper(JImageTask.class, recognizedOptions);
private static final OptionsHelper<JImageTask> 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<Predicate<String>> 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<File> 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<String> unhandled = optionsHelper.handleOptions(this, args);
List<String> 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", "<unspecified>");
} else if (!options.help && !options.version && !options.fullVersion) {
throw TASK_HELPER.newBadArgs("err.invalid.task", "<unspecified>");
}
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<String> 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<String> 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);
}
}

View File

@ -24,54 +24,67 @@
#
main.usage.summary=\
Usage: {0} <extract|info|list|set|verify> <options> jimage...\n\
use --help for a list of possible options
Usage: {0} <extract | info | list | verify> <options> jimage...\n\
use --help for a list of possible options.
main.usage=\
Usage: {0} <extract|info|list|set|verify> <options> jimage...\n\
Usage: {0} <extract | info | list | verify> <options> jimage...\n\
\n\
\ extract - Extract all jimage entries and place in a directory specified\n\
\ by the --dir=<directory> (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=<directory> (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=<directory> (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=\
\ @<filename> 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}
\ @<filename> Read options from file
err.not.a.task=task must be one of <extract | info | list | verify>: {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}

View File

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

View File

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

View File

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

View File

@ -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<ToIntFunction<String>> filters;
private final Map<String, Integer> orderedPaths;
@ -187,27 +191,11 @@ public final class OrderResourcesPlugin implements TransformerPlugin {
}
}
} else {
boolean endsWith = pattern.startsWith("*");
boolean startsWith = pattern.endsWith("*");
ToIntFunction<String> 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<String> function = (path)-> matcher.matches(JRT_FILE_SYSTEM.getPath(path)) ? result : Integer.MAX_VALUE;
filters.add(function);
}
}
}
}
}

View File

@ -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<String> {
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<PathMatcher> 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<String> 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<String> 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;
}
}

View File

@ -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<PathMatcher> {
static class PathMatcherConverter implements ValueConverter<PathMatcher> {
@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<PathMatcher> excludes
= parser.accepts("exclude", getMessage("main.opt.exclude"))
.withRequiredArg()
.withValuesConvertedBy(new GlobConverter());
.withValuesConvertedBy(new PathMatcherConverter());
OptionSpec<Pattern> hashModules
= parser.accepts("hash-modules", getMessage("main.opt.hash-modules"))

View File

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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -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;
}

View File

@ -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() {
};
}
}
}

View File

@ -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<Integer> 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");
}

View File

@ -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<? extends CharSequence>) null))
);
checkAndClose(
(ws) ->
TestKit.assertThrows(IllegalArgumentException.class,
"(?i).*reason.*",
() -> ws.sendClose(CloseCode.NORMAL_CLOSURE, CharBuffer.allocate(124)))
);
checkAndClose(
(ws) ->
TestKit.assertThrows(NullPointerException.class,

View File

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

View File

@ -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.*;

View File

@ -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<DataTuple> 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 {
}
}
}

View File

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

View File

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

View File

@ -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> T revive(T in) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
new ObjectOutputStream(bout).writeObject(in);
return (T) new ObjectInputStream(
new ByteArrayInputStream(bout.toByteArray())).readObject();
}
}