--- a/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138
65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139
0875007901f7d364a08220b052f0c81003e9c8c5 jdk-9+140
+9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141
--- a/.hgtags-top-repo Thu Oct 27 09:38:46 2016 -0700
+++ b/.hgtags-top-repo Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
67c4388142bdf58aec8fefa4475faaa8a5d7380c jdk-9+138
7dcf453eacae79ee86a6bcc75fd0b546fc99b48a jdk-9+139
a5815c6098a241d3a1df64d22b84b3524e4a77df jdk-9+140
+f64afae7f1a5608e438585bbf0bc23785e69cba0 jdk-9+141
--- a/common/autoconf/flags.m4 Thu Oct 27 09:38:46 2016 -0700
+++ b/common/autoconf/flags.m4 Thu Oct 27 09:42:08 2016 -0700
@@ -895,7 +895,7 @@
elif test "x$OPENJDK_$1_OS" = xsolaris; then
$2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS"
$2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \
- -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except"
+ -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except"
elif test "x$OPENJDK_$1_OS" = xmacosx; then
$2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
$2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE"
--- a/common/autoconf/generated-configure.sh Thu Oct 27 09:38:46 2016 -0700
+++ b/common/autoconf/generated-configure.sh Thu Oct 27 09:42:08 2016 -0700
@@ -5093,7 +5093,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1476275292
+DATE_WHEN_GENERATED=1477108079
###############################################################################
#
@@ -50077,7 +50077,7 @@
elif test "x$OPENJDK_TARGET_OS" = xsolaris; then
JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS"
JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \
- -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except"
+ -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except"
elif test "x$OPENJDK_TARGET_OS" = xmacosx; then
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE"
@@ -50892,7 +50892,7 @@
elif test "x$OPENJDK_BUILD_OS" = xsolaris; then
OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS"
OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \
- -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except"
+ -D_Crun_inline_placement -library=%none -KPIC -mt -features=no%except"
elif test "x$OPENJDK_BUILD_OS" = xmacosx; then
OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT"
OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE"
--- a/corba/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
27bb44be32076861a0951bcefb07a1d92509a4b6 jdk-9+138
8c9da7fc5b07c606afd571c7012441b77dda83b2 jdk-9+139
9f3fc931bc230f44f2a58d75f7f6360af98bb113 jdk-9+140
+b32f998da32b488ec7c4e9dbb3c750841b48e74d jdk-9+141
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,22 +31,17 @@
package com.sun.corba.se.impl.io;
-import java.io.InputStream;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.io.ObjectInputValidation;
import java.io.NotActiveException;
import java.io.InvalidObjectException;
import java.io.InvalidClassException;
-import java.io.DataInputStream;
import java.io.OptionalDataException;
-import java.io.WriteAbortedException;
import java.io.Externalizable;
import java.io.EOFException;
import java.lang.reflect.*;
import java.util.Vector;
-import java.util.Stack;
-import java.util.Hashtable;
import java.util.Enumeration;
import sun.corba.Bridge ;
@@ -54,7 +49,6 @@
import java.security.AccessController ;
import java.security.PrivilegedAction ;
-import com.sun.corba.se.impl.io.ObjectStreamClass;
import com.sun.corba.se.impl.util.Utility;
import org.omg.CORBA.portable.ValueInputStream;
@@ -71,14 +65,12 @@
import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
import com.sun.org.omg.SendingContext.CodeBase;
-import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandler;
import java.security.*;
import java.util.*;
-import com.sun.corba.se.impl.orbutil.ObjectUtility ;
import com.sun.corba.se.impl.logging.OMGSystemException ;
import com.sun.corba.se.impl.logging.UtilSystemException ;
@@ -182,75 +174,6 @@
private byte streamFormatVersion;
- // Since java.io.OptionalDataException's constructors are
- // package private, but we need to throw it in some special
- // cases, we try to do it by reflection.
- private static final Constructor OPT_DATA_EXCEPTION_CTOR;
-
- private Object[] readObjectArgList = { this } ;
-
- static {
- OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
- }
-
- // Grab the OptionalDataException boolean ctor and make
- // it accessible. Note that any exceptions
- // will be wrapped in ExceptionInInitializerErrors.
- private static Constructor getOptDataExceptionCtor() {
-
- try {
-
- Constructor result =
-
- (Constructor) AccessController.doPrivileged(
- new PrivilegedExceptionAction() {
- public java.lang.Object run()
- throws NoSuchMethodException,
- SecurityException {
-
- Constructor boolCtor
- = OptionalDataException.class.getDeclaredConstructor(
- new Class[] {
- Boolean.TYPE });
-
- boolCtor.setAccessible(true);
-
- return boolCtor;
- }});
-
- if (result == null)
- // XXX I18N, logging needed.
- throw new Error("Unable to find OptionalDataException constructor");
-
- return result;
-
- } catch (Exception ex) {
- // XXX I18N, logging needed.
- throw new ExceptionInInitializerError(ex);
- }
- }
-
- // Create a new OptionalDataException with the EOF marker
- // set to true. See handleOptionalDataMarshalException.
- private OptionalDataException createOptionalDataException() {
- try {
- OptionalDataException result
- = (OptionalDataException)
- OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] {
- Boolean.TRUE });
-
- if (result == null)
- // XXX I18N, logging needed.
- throw new Error("Created null OptionalDataException");
-
- return result;
-
- } catch (Exception ex) {
- // XXX I18N, logging needed.
- throw new Error("Couldn't create OptionalDataException", ex);
- }
- }
-
// Return the stream format version currently being used
// to deserialize an object
protected byte getStreamFormatVersion() {
@@ -395,7 +318,6 @@
int offset)
/* throws OptionalDataException, ClassNotFoundException, IOException */
{
-
/* Save the current state and get ready to read an object. */
Object prevObject = currentObject;
ObjectStreamClass prevClassDesc = currentClassDesc;
@@ -947,7 +869,7 @@
if (!objectRead)
result = new EOFException("No more optional data");
else
- result = createOptionalDataException();
+ result = bridge.newOptionalDataExceptionForSerialization(true);
result.initCause(marshalException);
@@ -1230,8 +1152,7 @@
readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject,
- (currentClassDesc.readObjectMethod
- != null));
+ currentClassDesc.hasReadObject());
} else {
if (currentClassDesc.hasReadObject())
setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
@@ -1556,8 +1477,7 @@
readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject,
- (currentClassDesc.readObjectMethod
- != null));
+ currentClassDesc.hasReadObject());
}
boolean usedReadObject = false;
@@ -1714,13 +1634,8 @@
throws InvalidClassException, StreamCorruptedException,
ClassNotFoundException, IOException
{
- if (osc.readObjectMethod == null) {
- return false;
- }
-
try {
- osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
- return true;
+ return osc.invokeReadObject( obj, this ) ;
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof ClassNotFoundException)
@@ -1734,8 +1649,6 @@
else
// XXX I18N, logging needed.
throw new Error("internal error");
- } catch (IllegalAccessException e) {
- return false;
}
}
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,33 +31,23 @@
package com.sun.corba.se.impl.io;
-import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.portable.OutputStream;
import java.security.AccessController ;
import java.security.PrivilegedAction ;
import java.io.IOException;
-import java.io.DataOutputStream;
-import java.io.Serializable;
import java.io.InvalidClassException;
-import java.io.StreamCorruptedException;
import java.io.Externalizable;
-import java.io.ObjectStreamException;
import java.io.NotSerializableException;
import java.io.NotActiveException;
import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Field;
-
-import java.util.Stack;
import javax.rmi.CORBA.Util;
-import javax.rmi.CORBA.ValueHandlerMultiFormat;
import sun.corba.Bridge ;
-import com.sun.corba.se.impl.io.ObjectStreamClass;
import com.sun.corba.se.impl.util.Utility;
import com.sun.corba.se.impl.util.RepositoryId;
@@ -621,7 +611,7 @@
writeObjectState.enterWriteObject(this);
// writeObject(obj, c, this);
- osc.writeObjectMethod.invoke( obj, writeObjectArgList ) ;
+ osc.invokeWriteObject( obj, this ) ;
writeObjectState.exitWriteObject(this);
@@ -636,8 +626,6 @@
else
// XXX I18N, Logging needed.
throw new Error("invokeObjectWriter internal error",e);
- } catch (IllegalAccessException e) {
- // cannot happen
}
}
@@ -761,59 +749,52 @@
*/
private void outputClassFields(Object o, Class cl,
ObjectStreamField[] fields)
- throws IOException, InvalidClassException {
+ throws IOException {
for (int i = 0; i < fields.length; i++) {
if (fields[i].getField() == null)
- // XXX I18N, Logging needed.
throw new InvalidClassException(cl.getName(),
"Nonexistent field " + fields[i].getName());
-
- try {
- switch (fields[i].getTypeCode()) {
- case 'B':
- byte byteValue = fields[i].getField().getByte( o ) ;
- orbStream.write_octet(byteValue);
- break;
- case 'C':
- char charValue = fields[i].getField().getChar( o ) ;
- orbStream.write_wchar(charValue);
- break;
- case 'F':
- float floatValue = fields[i].getField().getFloat( o ) ;
- orbStream.write_float(floatValue);
- break;
- case 'D' :
- double doubleValue = fields[i].getField().getDouble( o ) ;
- orbStream.write_double(doubleValue);
- break;
- case 'I':
- int intValue = fields[i].getField().getInt( o ) ;
- orbStream.write_long(intValue);
- break;
- case 'J':
- long longValue = fields[i].getField().getLong( o ) ;
- orbStream.write_longlong(longValue);
- break;
- case 'S':
- short shortValue = fields[i].getField().getShort( o ) ;
- orbStream.write_short(shortValue);
- break;
- case 'Z':
- boolean booleanValue = fields[i].getField().getBoolean( o ) ;
- orbStream.write_boolean(booleanValue);
- break;
- case '[':
- case 'L':
- Object objectValue = fields[i].getField().get( o ) ;
- writeObjectField(fields[i], objectValue);
- break;
- default:
- // XXX I18N, Logging needed.
- throw new InvalidClassException(cl.getName());
- }
- } catch (IllegalAccessException exc) {
- throw wrapper.illegalFieldAccess( exc, fields[i].getName() ) ;
+ switch (fields[i].getTypeCode()) {
+ case 'B':
+ byte byteValue = bridge.getByte(o, fields[i].getFieldID()) ;
+ orbStream.write_octet(byteValue);
+ break;
+ case 'C':
+ char charValue = bridge.getChar(o, fields[i].getFieldID()) ;
+ orbStream.write_wchar(charValue);
+ break;
+ case 'F':
+ float floatValue = bridge.getFloat(o, fields[i].getFieldID()) ;
+ orbStream.write_float(floatValue);
+ break;
+ case 'D' :
+ double doubleValue = bridge.getDouble(o, fields[i].getFieldID()) ;
+ orbStream.write_double(doubleValue);
+ break;
+ case 'I':
+ int intValue = bridge.getInt(o, fields[i].getFieldID()) ;
+ orbStream.write_long(intValue);
+ break;
+ case 'J':
+ long longValue = bridge.getLong(o, fields[i].getFieldID()) ;
+ orbStream.write_longlong(longValue);
+ break;
+ case 'S':
+ short shortValue = bridge.getShort(o, fields[i].getFieldID()) ;
+ orbStream.write_short(shortValue);
+ break;
+ case 'Z':
+ boolean booleanValue = bridge.getBoolean(o, fields[i].getFieldID()) ;
+ orbStream.write_boolean(booleanValue);
+ break;
+ case '[':
+ case 'L':
+ Object objectValue = bridge.getObject(o, fields[i].getFieldID()) ;
+ writeObjectField(fields[i], objectValue);
+ break;
+ default:
+ throw new InvalidClassException(cl.getName());
}
}
}
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,16 +31,16 @@
package com.sun.corba.se.impl.io;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.invoke.MethodHandle;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.DigestOutputStream;
import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
import java.security.PrivilegedAction;
import java.lang.reflect.Modifier;
-import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@@ -80,9 +80,6 @@
public static final long kDefaultUID = -1;
- private static Object noArgsList[] = {};
- private static Class<?> noTypesList[] = {};
-
/** true if represents enum type */
private boolean isEnum;
@@ -311,12 +308,37 @@
return null;
}
+ public final boolean invokeWriteObject(Object obj, ObjectOutputStream ois) throws InvocationTargetException {
+ if (!hasWriteObject()) {
+ return false;
+ }
+ try {
+ writeObjectMethod.invoke(obj, ois);
+ } catch (Throwable t) {
+ throw new InvocationTargetException(t, "writeObject");
+ }
+ return true;
+ }
+
+ public final boolean invokeReadObject(Object obj, ObjectInputStream ois) throws InvocationTargetException {
+ if (hasReadObject()) {
+ try {
+ readObjectMethod.invoke(obj, ois);
+ return true;
+ } catch (Throwable t) {
+ throw new InvocationTargetException(t, "readObject");
+ }
+ } else {
+ return false;
+ }
+ }
+
public Serializable writeReplace(Serializable value) {
if (writeReplaceObjectMethod != null) {
try {
- return (Serializable) writeReplaceObjectMethod.invoke(value,noArgsList);
- } catch(Throwable t) {
- throw new RuntimeException(t);
+ return (Serializable) writeReplaceObjectMethod.invoke(value);
+ } catch (Throwable t) {
+ throw new InternalError("unexpected error", t);
}
}
else return value;
@@ -325,9 +347,9 @@
public Object readResolve(Object value) {
if (readResolveObjectMethod != null) {
try {
- return readResolveObjectMethod.invoke(value,noArgsList);
- } catch(Throwable t) {
- throw new RuntimeException(t);
+ return readResolveObjectMethod.invoke(value);
+ } catch (Throwable t) {
+ throw new InternalError("unexpected error", t);
}
}
else return value;
@@ -382,31 +404,34 @@
*/
}
- private static final class PersistentFieldsValue
+ static final class PersistentFieldsValue
extends ClassValue<ObjectStreamField[]> {
PersistentFieldsValue() { }
protected ObjectStreamField[] computeValue(Class<?> type) {
try {
+ bridge.ensureClassInitialized(type);
Field pf = type.getDeclaredField("serialPersistentFields");
int mods = pf.getModifiers();
if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) &&
Modifier.isFinal(mods)) {
- pf.setAccessible(true);
+ long offset = bridge.staticFieldOffset(pf);
java.io.ObjectStreamField[] fields =
- (java.io.ObjectStreamField[])pf.get(type);
+ (java.io.ObjectStreamField[])bridge.getObject(type, offset);
return translateFields(fields);
}
- } catch (NoSuchFieldException | IllegalAccessException |
+ } catch (NoSuchFieldException |
IllegalArgumentException | ClassCastException e) {
}
return null;
}
- private static ObjectStreamField[] translateFields(
- java.io.ObjectStreamField[] fields) {
+ private static ObjectStreamField[] translateFields(java.io.ObjectStreamField[] fields) {
+ if (fields == null) {
+ return null;
+ }
ObjectStreamField[] translation =
- new ObjectStreamField[fields.length];
+ new ObjectStreamField[fields.length];
for (int i = 0; i < fields.length; i++) {
translation[i] = new ObjectStreamField(fields[i].getName(),
fields[i].getType());
@@ -450,13 +475,11 @@
* If it is declared, use the declared serialPersistentFields.
* Otherwise, extract the fields from the class itself.
*/
- fields = persistentFieldsValue.get(cl);
+ fields = persistentFieldsValue.get(cl);
if (fields == null) {
- /* Get all of the declared fields for this
- * Class. setAccessible on all fields so they
- * can be accessed later. Create a temporary
- * ObjectStreamField array to hold each
+ /* Get all of the declared fields for this Class.
+ * Create a temporary ObjectStreamField array to hold each
* non-static, non-transient field. Then copy the
* temporary array into an array of the correct
* size once the number of fields is known.
@@ -471,7 +494,6 @@
int modifiers = fld.getModifiers();
if (!Modifier.isStatic(modifiers) &&
!Modifier.isTransient(modifiers)) {
- fld.setAccessible(true) ;
tempFields[numFields++] = new ObjectStreamField(fld);
}
}
@@ -487,7 +509,6 @@
try {
Field reflField = cl.getDeclaredField(fields[j].getName());
if (fields[j].getType() == reflField.getType()) {
- reflField.setAccessible(true);
fields[j].setField(reflField);
}
} catch (NoSuchFieldException e) {
@@ -527,8 +548,8 @@
int mods = f.getModifiers();
// SerialBug 5: static final SUID should be read
if (Modifier.isStatic(mods) && Modifier.isFinal(mods) ) {
- f.setAccessible(true);
- suid = f.getLong(cl);
+ long offset = bridge.staticFieldOffset(f);
+ suid = bridge.getLong(cl, offset);
// SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl);
} else {
@@ -540,16 +561,12 @@
suid = _computeSerialVersionUID(cl);
// SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl);
- } catch (IllegalAccessException ex) {
- suid = _computeSerialVersionUID(cl);
}
}
- writeReplaceObjectMethod = ObjectStreamClass.getInheritableMethod(cl,
- "writeReplace", noTypesList, Object.class);
+ writeReplaceObjectMethod = bridge.writeReplaceForSerialization(cl);
- readResolveObjectMethod = ObjectStreamClass.getInheritableMethod(cl,
- "readResolve", noTypesList, Object.class);
+ readResolveObjectMethod = bridge.readResolveForSerialization(cl);
if (externalizable)
cons = getExternalizableConstructor(cl) ;
@@ -557,14 +574,8 @@
cons = getSerializableConstructor(cl) ;
if (serializable && !forProxyClass) {
- /* Look for the writeObject method
- * Set the accessible flag on it here. ObjectOutputStream
- * will call it as necessary.
- */
- writeObjectMethod = getPrivateMethod( cl, "writeObject",
- new Class<?>[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ;
- readObjectMethod = getPrivateMethod( cl, "readObject",
- new Class<?>[] { java.io.ObjectInputStream.class }, Void.TYPE ) ;
+ writeObjectMethod = bridge.writeObjectForSerialization(cl) ;
+ readObjectMethod = bridge.readObjectForSerialization(cl);
}
return null;
}
@@ -585,27 +596,6 @@
}
}
- /**
- * Returns non-static private method with given signature defined by given
- * class, or null if none found. Access checks are disabled on the
- * returned method (if any).
- */
- private static Method getPrivateMethod(Class<?> cl, String name,
- Class<?>[] argTypes,
- Class<?> returnType)
- {
- try {
- Method meth = cl.getDeclaredMethod(name, argTypes);
- meth.setAccessible(true);
- int mods = meth.getModifiers();
- return ((meth.getReturnType() == returnType) &&
- ((mods & Modifier.STATIC) == 0) &&
- ((mods & Modifier.PRIVATE) != 0)) ? meth : null;
- } catch (NoSuchMethodException ex) {
- return null;
- }
- }
-
// Specific to RMI-IIOP
/**
* Java to IDL ptc-02-01-12 1.5.1
@@ -849,6 +839,22 @@
}
/**
+ * Returns true if represented class is serializable or externalizable and
+ * defines a conformant writeReplace method. Otherwise, returns false.
+ */
+ boolean hasWriteReplaceMethod() {
+ return (writeReplaceObjectMethod != null);
+ }
+
+ /**
+ * Returns true if represented class is serializable or externalizable and
+ * defines a conformant readResolve method. Otherwise, returns false.
+ */
+ boolean hasReadResolveMethod() {
+ return (readResolveObjectMethod != null);
+ }
+
+ /**
* Returns when or not this class should be custom
* marshaled (use chunking). This should happen if
* it is Externalizable OR if it or
@@ -904,7 +910,7 @@
{
if (cons != null) {
try {
- return cons.newInstance(new Object[0]);
+ return cons.newInstance();
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
InternalError ie = new InternalError();
@@ -912,7 +918,7 @@
throw ie ;
}
} else {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException("no constructor for " + ofClass);
}
}
@@ -921,15 +927,8 @@
* Access checks are disabled on the returned constructor (if any), since
* the defining class may still be non-public.
*/
- private static Constructor getExternalizableConstructor(Class<?> cl) {
- try {
- Constructor cons = cl.getDeclaredConstructor(new Class<?>[0]);
- cons.setAccessible(true);
- return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
- cons : null;
- } catch (NoSuchMethodException ex) {
- return null;
- }
+ private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
+ return bridge.newConstructorForExternalization(cl);
}
/**
@@ -937,28 +936,8 @@
* superclass, or null if none found. Access checks are disabled on the
* returned constructor (if any).
*/
- private static Constructor getSerializableConstructor(Class<?> cl) {
- Class<?> initCl = cl;
- while (Serializable.class.isAssignableFrom(initCl)) {
- if ((initCl = initCl.getSuperclass()) == null) {
- return null;
- }
- }
- try {
- Constructor cons = initCl.getDeclaredConstructor(new Class<?>[0]);
- int mods = cons.getModifiers();
- if ((mods & Modifier.PRIVATE) != 0 ||
- ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
- !packageEquals(cl, initCl)))
- {
- return null;
- }
- cons = bridge.newConstructorForSerialization(cl, cons);
- cons.setAccessible(true);
- return cons;
- } catch (NoSuchMethodException ex) {
- return null;
- }
+ private static Constructor<?> getSerializableConstructor(Class<?> cl) {
+ return bridge.newConstructorForSerialization(cl);
}
/*
@@ -1522,11 +1501,11 @@
* @since JDK 1.2
*/
private boolean hasExternalizableBlockData;
- Method writeObjectMethod;
- Method readObjectMethod;
- private transient Method writeReplaceObjectMethod;
- private transient Method readResolveObjectMethod;
- private Constructor cons ;
+ private transient MethodHandle writeObjectMethod;
+ private transient MethodHandle readObjectMethod;
+ private transient MethodHandle writeReplaceObjectMethod;
+ private transient MethodHandle readResolveObjectMethod;
+ private transient Constructor<?> cons;
/**
* Beginning in Java to IDL ptc/02-01-12, RMI-IIOP has a
@@ -1543,44 +1522,12 @@
*/
private ObjectStreamClass localClassDesc;
- /* Find out if the class has a static class initializer <clinit> */
- private static Method hasStaticInitializerMethod = null;
/**
* Returns true if the given class defines a static initializer method,
* false otherwise.
*/
private static boolean hasStaticInitializer(Class<?> cl) {
- if (hasStaticInitializerMethod == null) {
- Class<?> classWithThisMethod = null;
-
- try {
- if (classWithThisMethod == null)
- classWithThisMethod = java.io.ObjectStreamClass.class;
-
- hasStaticInitializerMethod =
- classWithThisMethod.getDeclaredMethod("hasStaticInitializer",
- new Class<?>[] { Class.class });
- } catch (NoSuchMethodException ex) {
- }
-
- if (hasStaticInitializerMethod == null) {
- // XXX I18N, logging needed
- throw new InternalError("Can't find hasStaticInitializer method on "
- + classWithThisMethod.getName());
- }
- hasStaticInitializerMethod.setAccessible(true);
- }
-
- try {
- Boolean retval = (Boolean)
- hasStaticInitializerMethod.invoke(null, new Object[] { cl });
- return retval.booleanValue();
- } catch (Exception ex) {
- // XXX I18N, logging needed
- InternalError ie = new InternalError( "Error invoking hasStaticInitializer" ) ;
- ie.initCause( ex ) ;
- throw ie ;
- }
+ return bridge.hasStaticInitializerForSerialization(cl);
}
@@ -1754,7 +1701,6 @@
if ((meth == null) || (meth.getReturnType() != returnType)) {
return null;
}
- meth.setAccessible(true);
int mods = meth.getModifiers();
if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
return null;
--- a/corba/src/java.corba/share/classes/module-info.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/module-info.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,6 +32,7 @@
requires java.logging;
requires java.naming;
requires java.transaction;
+ requires jdk.unsupported;
exports javax.activity;
exports javax.rmi;
--- a/corba/src/java.corba/share/classes/sun/corba/Bridge.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/sun/corba/Bridge.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,25 +25,24 @@
package sun.corba ;
+import java.io.OptionalDataException;
+import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field ;
-import java.lang.reflect.Method ;
import java.lang.reflect.Constructor ;
-import java.lang.reflect.InvocationTargetException ;
-
-import java.io.ObjectInputStream ;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
-import jdk.internal.misc.Unsafe ;
-import jdk.internal.reflect.ReflectionFactory;
+import sun.misc.Unsafe;
+import sun.reflect.ReflectionFactory;
/** This class provides the methods for fundamental JVM operations
* needed in the ORB that are not part of the public Java API. This includes:
* <ul>
* <li>throwException, which can throw undeclared checked exceptions.
- * This is needed to handle throwing arbitrary exceptions across a standardized OMG interface that (incorrectly) does not specify appropriate exceptions.</li>
+ * This is needed to handle throwing arbitrary exceptions across a standardized
+ * OMG interface that (incorrectly) does not specify appropriate exceptions.</li>
* <li>putXXX/getXXX methods that allow unchecked access to fields of objects.
* This is used for setting uninitialzed non-static final fields (which is
* impossible with reflection) and for speed.</li>
@@ -71,88 +70,28 @@
*/
public final class Bridge
{
- private static final Class[] NO_ARGS = new Class[] {};
private static final Permission getBridgePermission =
- new BridgePermission( "getBridge" ) ;
+ new BridgePermission("getBridge");
private static Bridge bridge = null ;
- // latestUserDefinedLoader() is a private static method
- // in ObjectInputStream in JDK 1.3 through 1.5.
- // We use reflection in a doPrivileged block to get a
- // Method reference and make it accessible.
- private final Method latestUserDefinedLoaderMethod ;
- private final Unsafe unsafe ;
- private final ReflectionFactory reflectionFactory ;
+ /** Access to Unsafe to read/write fields. */
+ private static final Unsafe unsafe = AccessController.doPrivileged(
+ (PrivilegedAction<Unsafe>)() -> {
+ try {
+ Field field = Unsafe.class.getDeclaredField("theUnsafe");
+ field.setAccessible(true);
+ return (Unsafe)field.get(null);
- private Method getLatestUserDefinedLoaderMethod()
- {
- return (Method) AccessController.doPrivileged(
- new PrivilegedAction()
- {
- public Object run()
- {
- Method result = null;
-
- try {
- Class io = ObjectInputStream.class;
- result = io.getDeclaredMethod(
- "latestUserDefinedLoader", NO_ARGS);
- result.setAccessible(true);
- } catch (NoSuchMethodException nsme) {
- Error err = new Error( "java.io.ObjectInputStream" +
- " latestUserDefinedLoader " + nsme );
- err.initCause(nsme) ;
- throw err ;
- }
-
- return result;
+ } catch (NoSuchFieldException |IllegalAccessException ex) {
+ throw new InternalError("Unsafe.theUnsafe field not available", ex);
}
}
- );
- }
-
- private Unsafe getUnsafe() {
- Field fld = (Field)AccessController.doPrivileged(
- new PrivilegedAction()
- {
- public Object run()
- {
- Field fld = null ;
+ ) ;
- try {
- Class unsafeClass = jdk.internal.misc.Unsafe.class ;
- fld = unsafeClass.getDeclaredField( "theUnsafe" ) ;
- fld.setAccessible( true ) ;
- return fld ;
- } catch (NoSuchFieldException exc) {
- Error err = new Error( "Could not access Unsafe" ) ;
- err.initCause( exc ) ;
- throw err ;
- }
- }
- }
- ) ;
-
- Unsafe unsafe = null;
+ private final ReflectionFactory reflectionFactory ;
- try {
- unsafe = (Unsafe)(fld.get( null )) ;
- } catch (Throwable t) {
- Error err = new Error( "Could not access Unsafe" ) ;
- err.initCause( t ) ;
- throw err ;
- }
-
- return unsafe ;
- }
-
-
- private Bridge()
- {
- latestUserDefinedLoaderMethod = getLatestUserDefinedLoaderMethod();
- unsafe = getUnsafe() ;
- reflectionFactory = (ReflectionFactory)AccessController.doPrivileged(
- new ReflectionFactory.GetReflectionFactoryAction());
+ private Bridge() {
+ reflectionFactory = ReflectionFactory.getReflectionFactory();
}
/** Fetch the Bridge singleton. This requires the following
@@ -182,23 +121,8 @@
/** Obtain the latest user defined ClassLoader from the call stack.
* This is required by the RMI-IIOP specification.
*/
- public final ClassLoader getLatestUserDefinedLoader()
- {
- try {
- // Invoke the ObjectInputStream.latestUserDefinedLoader method
- return (ClassLoader)latestUserDefinedLoaderMethod.invoke(null,
- (Object[])NO_ARGS);
- } catch (InvocationTargetException ite) {
- Error err = new Error(
- "sun.corba.Bridge.latestUserDefinedLoader: " + ite ) ;
- err.initCause( ite ) ;
- throw err ;
- } catch (IllegalAccessException iae) {
- Error err = new Error(
- "sun.corba.Bridge.latestUserDefinedLoader: " + iae ) ;
- err.initCause( iae ) ;
- throw err ;
- }
+ public final ClassLoader getLatestUserDefinedLoader() {
+ return jdk.internal.misc.VM.latestUserDefinedLoader();
}
/**
@@ -345,6 +269,23 @@
return unsafe.objectFieldOffset( f ) ;
}
+ /**
+ * Returns the offset of a static field.
+ */
+ public final long staticFieldOffset(Field f)
+ {
+ return unsafe.staticFieldOffset( f ) ;
+ }
+
+ /**
+ * Ensure that the class has been initalized.
+ * @param cl the class to ensure is initialized
+ */
+ public final void ensureClassInitialized(Class<?> cl) {
+ unsafe.ensureClassInitialized(cl);
+ }
+
+
/** Throw the exception.
* The exception may be an undeclared checked exception.
*/
@@ -353,16 +294,55 @@
unsafe.throwException( ee ) ;
}
- /** Obtain a constructor for Class cl using constructor cons which
- * may be the constructor defined in a superclass of cl. This is
- * used to create a constructor for Serializable classes that
- * constructs an instance of the Serializable class using the
+ /**
+ * Obtain a constructor for Class cl.
+ * This is used to create a constructor for Serializable classes that
+ * construct an instance of the Serializable class using the
* no args constructor of the first non-Serializable superclass
* of the Serializable class.
*/
- public final Constructor newConstructorForSerialization( Class cl,
- Constructor cons )
- {
- return reflectionFactory.newConstructorForSerialization( cl, cons ) ;
+ public final Constructor<?> newConstructorForSerialization( Class<?> cl ) {
+ return reflectionFactory.newConstructorForSerialization( cl ) ;
+ }
+
+ public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+ return reflectionFactory.newConstructorForExternalization( cl ) ;
+ }
+
+ /**
+ * Returns true if the given class defines a static initializer method,
+ * false otherwise.
+ */
+ public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+ return reflectionFactory.hasStaticInitializerForSerialization(cl);
+ }
+
+ public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+ return reflectionFactory.writeObjectForSerialization(cl);
+ }
+
+ public final MethodHandle readObjectForSerialization(Class<?> cl) {
+ return reflectionFactory.readObjectForSerialization(cl);
}
+
+ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+ return reflectionFactory.readObjectNoDataForSerialization(cl);
+ }
+
+ public final MethodHandle readResolveForSerialization(Class<?> cl) {
+ return reflectionFactory.readResolveForSerialization(cl);
+ }
+
+ public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+ return reflectionFactory.writeReplaceForSerialization(cl);
+ }
+
+ /**
+ * Return a new OptionalDataException instance.
+ * @return a new OptionalDataException instance
+ */
+ public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+ return reflectionFactory.newOptionalDataExceptionForSerialization(bool);
+ }
+
}
--- a/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java Thu Oct 27 09:38:46 2016 -0700
+++ b/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,13 +25,13 @@
package sun.corba;
-import com.sun.corba.se.impl.io.ValueUtility;
-import jdk.internal.misc.Unsafe;
-
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import com.sun.corba.se.impl.io.ValueUtility;
+import sun.misc.Unsafe;
+
/** A repository of "shared secrets", which are a mechanism for
calling implementation-private methods in another package without
using reflection. A package-private class implements a public
@@ -43,22 +43,22 @@
// SharedSecrets cloned in corba repo to avoid build issues
public class SharedSecrets {
- private static final Unsafe unsafe = getUnsafe();
- private static JavaCorbaAccess javaCorbaAccess;
- private static Unsafe getUnsafe() {
- PrivilegedAction<Unsafe> pa = () -> {
- Class<?> unsafeClass = jdk.internal.misc.Unsafe.class ;
- try {
- Field f = unsafeClass.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- return (Unsafe) f.get(null);
- } catch (Exception e) {
- throw new Error(e);
- }
- };
- return AccessController.doPrivileged(pa);
- }
+ /** Access to Unsafe to read/write fields. */
+ private static final Unsafe unsafe = AccessController.doPrivileged(
+ (PrivilegedAction<Unsafe>)() -> {
+ try {
+ Field field = Unsafe.class.getDeclaredField("theUnsafe");
+ field.setAccessible(true);
+ return (Unsafe)field.get(null);
+
+ } catch (NoSuchFieldException |IllegalAccessException ex) {
+ throw new InternalError("Unsafe.theUnsafe field not available", ex);
+ }
+ }
+ );
+
+ private static JavaCorbaAccess javaCorbaAccess;
public static JavaCorbaAccess getJavaCorbaAccess() {
if (javaCorbaAccess == null) {
--- a/hotspot/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -543,3 +543,4 @@
fc0956308c7a586267c5dd35dff74f773aa9c3eb jdk-9+138
08492e67bf3226784dab3bf9ae967382ddbc1af5 jdk-9+139
fec31089c2ef5a12dd64f401b0bf2e00f56ee0d0 jdk-9+140
+160a00bc6ed0af1fdf8418fc65e6bddbbc0c536d jdk-9+141
--- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -1894,6 +1894,22 @@
__ beq(combined_check, slow);
}
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(tmp, dst);
+ __ lwz(tmp2, in_bytes(Klass::layout_helper_offset()), tmp);
+ __ cmpwi(CCR0, tmp2, Klass::_lh_neutral_value);
+ __ bge(CCR0, slow);
+ }
+
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(tmp, src);
+ __ lwz(tmp2, in_bytes(Klass::layout_helper_offset()), tmp);
+ __ cmpwi(CCR0, tmp2, Klass::_lh_neutral_value);
+ __ bge(CCR0, slow);
+ }
+ }
+
// Higher 32bits must be null.
__ extsw(length, length);
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -2034,6 +2034,27 @@
__ delayed()->nop();
}
+ // If the compiler was not able to prove that exact type of the source or the destination
+ // of the arraycopy is an array type, check at runtime if the source or the destination is
+ // an instance type.
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(dst, tmp);
+ __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2);
+ __ cmp(tmp2, Klass::_lh_neutral_value);
+ __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry());
+ __ delayed()->nop();
+ }
+
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(src, tmp);
+ __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2);
+ __ cmp(tmp2, Klass::_lh_neutral_value);
+ __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry());
+ __ delayed()->nop();
+ }
+ }
+
if (flags & LIR_OpArrayCopy::src_pos_positive_check) {
// test src_pos register
__ cmp_zero_and_br(Assembler::less, src_pos, *stub->entry());
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -3146,6 +3146,23 @@
__ jcc(Assembler::zero, *stub->entry());
}
+ // If the compiler was not able to prove that exact type of the source or the destination
+ // of the arraycopy is an array type, check at runtime if the source or the destination is
+ // an instance type.
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(tmp, dst);
+ __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value);
+ __ jcc(Assembler::greaterEqual, *stub->entry());
+ }
+
+ if (!(flags & LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(tmp, src);
+ __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value);
+ __ jcc(Assembler::greaterEqual, *stub->entry());
+ }
+ }
+
// check if negative
if (flags & LIR_OpArrayCopy::src_pos_positive_check) {
__ testl(src_pos, src_pos);
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -5859,6 +5859,11 @@
assert(cp != NULL, "invariant");
assert(_loader_data != NULL, "invariant");
+ if (_class_name == vmSymbols::java_lang_Object()) {
+ check_property(_local_interfaces == Universe::the_empty_klass_array(),
+ "java.lang.Object cannot implement an interface in class file %s",
+ CHECK);
+ }
// We check super class after class file is parsed and format is checked
if (_super_class_index > 0 && NULL ==_super_klass) {
Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
--- a/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -203,6 +203,7 @@
inline bool verify(address start, address end) const;
inline void print_on(outputStream* st, int current_offset) const;
+ inline void print_truncated(outputStream* st, int current_offset) const;
// Create as_xxx and is_xxx methods for the subtypes
#define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
@@ -263,6 +264,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame(@%d)", offset_delta() + current_offset);
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class same_frame_extended : public stack_map_frame {
@@ -309,6 +314,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame_extended(@%d)", offset_delta() + current_offset);
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class same_locals_1_stack_item_frame : public stack_map_frame {
@@ -381,6 +390,11 @@
types()->print_on(st);
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("same_locals_1_stack_item_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class same_locals_1_stack_item_extended : public stack_map_frame {
@@ -446,6 +460,11 @@
types()->print_on(st);
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("same_locals_1_stack_item_extended(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class chop_frame : public stack_map_frame {
@@ -511,6 +530,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops());
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class append_frame : public stack_map_frame {
@@ -619,6 +642,11 @@
}
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("append_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class full_frame : public stack_map_frame {
@@ -784,6 +812,11 @@
}
st->print("})");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("full_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
#define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
@@ -841,6 +874,10 @@
FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs));
}
+void stack_map_frame::print_truncated(outputStream* st, int offs = -1) const {
+ FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_truncated, (st, offs));
+}
+
#undef VIRTUAL_DISPATCH
#undef VOID_VIRTUAL_DISPATCH
--- a/hotspot/src/share/vm/classfile/verifier.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -541,8 +541,19 @@
stack_map_frame* sm_frame = sm_table->entries();
streamIndentor si2(ss);
int current_offset = -1;
+ // Subtract two from StackMapAttribute length because the length includes
+ // two bytes for number of table entries.
+ size_t sm_table_space = method->stackmap_data()->length() - 2;
for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
ss->indent();
+ size_t sm_frame_size = sm_frame->size();
+ // If the size of the next stackmap exceeds the length of the entire
+ // stackmap table then print a truncated message and return.
+ if (sm_frame_size > sm_table_space) {
+ sm_frame->print_truncated(ss, current_offset);
+ return;
+ }
+ sm_table_space -= sm_frame_size;
sm_frame->print_on(ss, current_offset);
ss->cr();
current_offset += sm_frame->offset_delta();
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -2524,7 +2524,6 @@
switch (cp->tag_at(cp_index).value()) {
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
- case JVM_CONSTANT_NameAndType: // for invokedynamic
return cp->uncached_name_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodNameUTF: illegal constant");
@@ -2542,7 +2541,6 @@
switch (cp->tag_at(cp_index).value()) {
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
- case JVM_CONSTANT_NameAndType: // for invokedynamic
return cp->uncached_signature_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodSignatureUTF: illegal constant");
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -794,9 +794,10 @@
} else if (new_len == 0) {
value = old_value;
} else {
- char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtArguments);
+ size_t length = old_len + 1 + new_len + 1;
+ char* buf = NEW_C_HEAP_ARRAY(char, length, mtArguments);
// each new setting adds another LINE to the switch:
- sprintf(buf, "%s\n%s", old_value, new_value);
+ jio_snprintf(buf, length, "%s\n%s", old_value, new_value);
value = buf;
free_this_too = buf;
}
@@ -1014,15 +1015,17 @@
if (args == NULL || count == 0) {
return NULL;
}
- size_t length = strlen(args[0]) + 1; // add 1 for the null terminator
- for (int i = 1; i < count; i++) {
- length += strlen(args[i]) + 1; // add 1 for a space
+ size_t length = 0;
+ for (int i = 0; i < count; i++) {
+ length += strlen(args[i]) + 1; // add 1 for a space or NULL terminating character
}
char* s = NEW_RESOURCE_ARRAY(char, length);
- strcpy(s, args[0]);
- for (int j = 1; j < count; j++) {
- strcat(s, " ");
- strcat(s, args[j]);
+ char* dst = s;
+ for (int j = 0; j < count; j++) {
+ size_t offset = strlen(args[j]) + 1; // add 1 for a space or NULL terminating character
+ jio_snprintf(dst, length, "%s ", args[j]); // jio_snprintf will replace the last space character with NULL character
+ dst += offset;
+ length -= offset;
}
return (const char*) s;
}
@@ -1106,9 +1109,8 @@
// Only make the obsolete check for valid arguments.
if (arg_len <= BUFLEN) {
// Construct a string which consists only of the argument name without '+', '-', or '='.
- char stripped_argname[BUFLEN+1];
- strncpy(stripped_argname, argname, arg_len);
- stripped_argname[arg_len] = '\0'; // strncpy may not null terminate.
+ char stripped_argname[BUFLEN+1]; // +1 for '\0'
+ jio_snprintf(stripped_argname, arg_len+1, "%s", argname); // +1 for '\0'
if (is_obsolete_flag(stripped_argname, &since)) {
char version[256];
since.to_string(version, sizeof(version));
@@ -1260,8 +1262,7 @@
size_t key_len = eq - prop;
char* tmp_key = AllocateHeap(key_len + 1, mtArguments);
- strncpy(tmp_key, prop, key_len);
- tmp_key[key_len] = '\0';
+ jio_snprintf(tmp_key, key_len + 1, "%s", prop);
key = tmp_key;
value = &prop[key_len + 1];
@@ -2256,7 +2257,7 @@
// Feed the cache size setting into the JDK
char buffer[1024];
- sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
+ jio_snprintf(buffer, 1024, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
if (!add_property(buffer)) {
return JNI_ENOMEM;
}
@@ -2777,8 +2778,8 @@
if (tail != NULL) {
const char* pos = strchr(tail, ':');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
- char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len);
- name[len] = '\0';
+ char* name = NEW_C_HEAP_ARRAY(char, len + 1, mtArguments);
+ jio_snprintf(name, len + 1, "%s", tail);
char *options = NULL;
if(pos != NULL) {
@@ -2854,7 +2855,9 @@
return JNI_ERR;
#else
if (tail != NULL) {
- char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
+ size_t length = strlen(tail) + 1;
+ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
+ jio_snprintf(options, length, "%s", tail);
add_init_agent("instrument", options, false);
// java agents need module java.instrument
if (!create_numbered_property("jdk.module.addmods", "java.instrument", addmods_count++)) {
@@ -3512,7 +3515,7 @@
// check if the default lib/endorsed directory exists; if so, error
char path[JVM_MAXPATHLEN];
const char* fileSep = os::file_separator();
- sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
+ jio_snprintf(path, JVM_MAXPATHLEN, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
if (CheckEndorsedAndExtDirs) {
int nonEmptyDirs = 0;
@@ -3534,7 +3537,7 @@
return JNI_ERR;
}
- sprintf(path, "%s%slib%sext", Arguments::get_java_home(), fileSep, fileSep);
+ jio_snprintf(path, JVM_MAXPATHLEN, "%s%slib%sext", Arguments::get_java_home(), fileSep, fileSep);
dir = os::opendir(path);
if (dir != NULL) {
jio_fprintf(defaultStream::output_stream(),
@@ -3899,6 +3902,13 @@
void Arguments::set_shared_spaces_flags() {
if (DumpSharedSpaces) {
+ if (FailOverToOldVerifier) {
+ // Don't fall back to the old verifier on verification failure. If a
+ // class fails verification with the split verifier, it might fail the
+ // CDS runtime verifier constraint check. In that case, we don't want
+ // to share the class. We only archive classes that pass the split verifier.
+ FLAG_SET_DEFAULT(FailOverToOldVerifier, false);
+ }
if (RequireSharedSpaces) {
warning("Cannot dump shared archive while using shared archive");
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -2881,8 +2881,6 @@
char *s = sig->as_C_string();
int len = (int)strlen(s);
s++; len--; // Skip opening paren
- char *t = s+len;
- while (*(--t) != ')'); // Find close paren
BasicType *sig_bt = NEW_RESOURCE_ARRAY(BasicType, 256);
VMRegPair *regs = NEW_RESOURCE_ARRAY(VMRegPair, 256);
@@ -2891,7 +2889,7 @@
sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature
}
- while (s < t) {
+ while (*s != ')') { // Find closing right paren
switch (*s++) { // Switch on signature character
case 'B': sig_bt[cnt++] = T_BYTE; break;
case 'C': sig_bt[cnt++] = T_CHAR; break;
--- a/hotspot/src/share/vm/runtime/signature.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/hotspot/src/share/vm/runtime/signature.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -224,7 +224,49 @@
_index = 0;
expect('(');
Symbol* sig = _signature;
- while (sig->byte_at(_index) != ')') _index++;
+ // Need to skip over each type in the signature's argument list until a
+ // closing ')' is found., then get the return type. We cannot just scan
+ // for the first ')' because ')' is a legal character in a type name.
+ while (sig->byte_at(_index) != ')') {
+ switch(sig->byte_at(_index)) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
+ case 'V':
+ {
+ _index++;
+ }
+ break;
+ case 'L':
+ {
+ while (sig->byte_at(_index++) != ';') ;
+ }
+ break;
+ case '[':
+ {
+ int begin = ++_index;
+ skip_optional_size();
+ while (sig->byte_at(_index) == '[') {
+ _index++;
+ skip_optional_size();
+ }
+ if (sig->byte_at(_index) == 'L') {
+ while (sig->byte_at(_index++) != ';') ;
+ } else {
+ _index++;
+ }
+ }
+ break;
+ default:
+ ShouldNotReachHere();
+ break;
+ }
+ }
expect(')');
// Parse return type
_parameter_index = -1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c1/TestArrayCopyToFromObject.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8160591
+ * @summary C1-generated code for System.arraycopy() does not throw an ArrayStoreException if 'dst' is no a "proper" array (i.e., it is java.lang.Object)
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:-UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:+UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject
+ */
+public class TestArrayCopyToFromObject {
+
+ public void test(Object aArray[]) {
+ Object a = new Object();
+
+ try {
+ System.arraycopy(aArray, 0, a, 0, 1);
+ throw new RuntimeException ("FAILED: Expected ArrayStoreException " +
+ "(due to destination not being an array) " +
+ "was not thrown");
+ } catch (ArrayStoreException e) {
+ System.out.println("PASSED: Expected ArrayStoreException was thrown");
+ }
+
+ try {
+ System.arraycopy(a, 0, aArray, 0, 1);
+ throw new RuntimeException ("FAILED: Expected ArrayStoreException " +
+ "(due to source not being an array) " +
+ "was not thrown");
+ } catch (ArrayStoreException e) {
+ System.out.println("PASSED: Expected ArrayStoreException was thrown");
+ }
+
+ }
+
+ public static void main(String args[]) {
+ System.out.println("TestArrayCopyToFromObject");
+ Object aArray[] = new Object[10];
+ for (int i = 0; i < 10; i++) {
+ aArray[i] = new Object();
+ }
+ new TestArrayCopyToFromObject().test(aArray);
+ }
+}
--- a/jaxp/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/jaxp/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
69c3b12ba75b2e321dee731ac545e7fbff608451 jdk-9+138
8991d71c5316bde259e6a417c1199b008ca3cdf0 jdk-9+139
8d100cb9b04819b5bd09f33c7fd5b8628d1a456f jdk-9+140
+037c095ba0c345edbeaaab52fda913a76c3930c0 jdk-9+141
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -31,6 +31,7 @@
import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
+import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
import com.sun.org.apache.bcel.internal.generic.ISTORE;
import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
@@ -1252,6 +1253,10 @@
classGen.getConstantPool());
transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
+ // call resetPrefixIndex at the beginning of transform
+ final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "resetPrefixIndex", "()V");
+ il.append(new INVOKESTATIC(check));
+
// Define and initialize current with the root node
final LocalVariableGen current =
transf.addLocalVariable("current",
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -31,6 +31,7 @@
import java.text.NumberFormat;
import java.util.Locale;
import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.xml.transform.dom.DOMSource;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
@@ -1533,16 +1534,25 @@
}
/**
- * This function is used in the execution of xsl:element
+ * These functions are used in the execution of xsl:element to generate
+ * and reset namespace prefix index local to current transformation process
*/
- private static int prefixIndex = 0;
-
public static String generatePrefix() {
- synchronized (BasisLibrary.class) {
- return ("ns" + prefixIndex++);
- }
+ return ("ns" + threadLocalPrefixIndex.get().getAndIncrement());
+ }
+
+ public static void resetPrefixIndex() {
+ threadLocalPrefixIndex.get().set(0);
}
+ private static final ThreadLocal<AtomicInteger> threadLocalPrefixIndex =
+ new ThreadLocal<AtomicInteger>() {
+ @Override
+ protected AtomicInteger initialValue() {
+ return new AtomicInteger();
+ }
+ };
+
public static final String RUN_TIME_INTERNAL_ERR =
"RUN_TIME_INTERNAL_ERR";
public static final String RUN_TIME_COPY_ERR =
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/NamespacePrefixTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,193 @@
+/*
+ * 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 transform;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+import static jaxp.library.JAXPTestUtilities.runWithAllPerm;
+
+/*
+ * @test
+ * @bug 8167179
+ * @library /javax/xml/jaxp/libs
+ * @run testng/othervm -DrunSecMngr=true transform.NamespacePrefixTest
+ * @run testng/othervm transform.NamespacePrefixTest
+ * @summary This class tests the generation of namespace prefixes
+ */
+public class NamespacePrefixTest {
+
+ @Test
+ public void testReuseTemplates() throws Exception {
+ final TransformerFactory tf = TransformerFactory.newInstance();
+ final Source xslsrc = new StreamSource(new StringReader(XSL));
+ final Templates tmpl = tf.newTemplates(xslsrc);
+ for (int i = 0; i < TRANSF_COUNT; i++) {
+ checkResult(doTransformation(tmpl.newTransformer()));
+ }
+ }
+
+ @Test
+ public void testReuseTransformer() throws Exception {
+ final TransformerFactory tf = TransformerFactory.newInstance();
+ final Source xslsrc = new StreamSource(new StringReader(XSL));
+ final Transformer t = tf.newTransformer(xslsrc);
+ for (int i = 0; i < TRANSF_COUNT; i++) {
+ checkResult(doTransformation(t));
+ }
+ }
+
+ @Test
+ public void testConcurrentTransformations() throws Exception {
+ final TransformerFactory tf = TransformerFactory.newInstance();
+ final Source xslsrc = new StreamSource(new StringReader(XSL));
+ final Templates tmpl = tf.newTemplates(xslsrc);
+ concurrentTestPassed.set(true);
+
+ // Execute multiple TestWorker tasks
+ for (int id = 0; id < THREADS_COUNT; id++) {
+ EXECUTOR.execute(new TransformerThread(tmpl.newTransformer(), id));
+ }
+ // Initiate shutdown of previously submitted task
+ runWithAllPerm(EXECUTOR::shutdown);
+ // Wait for termination of submitted tasks
+ if (!EXECUTOR.awaitTermination(THREADS_COUNT, TimeUnit.SECONDS)) {
+ // If not all tasks terminates during the time out force them to shutdown
+ runWithAllPerm(EXECUTOR::shutdownNow);
+ }
+ // Check if all transformation threads generated the correct namespace prefix
+ assertTrue(concurrentTestPassed.get());
+ }
+
+ // Do one transformation with the provided transformer
+ private static String doTransformation(Transformer t) throws Exception {
+ StringWriter resWriter = new StringWriter();
+ Source xmlSrc = new StreamSource(new StringReader(XML));
+ t.transform(xmlSrc, new StreamResult(resWriter));
+ return resWriter.toString();
+ }
+
+ // Check if the transformation result string contains the
+ // element with the exact namespace prefix generated.
+ private static void checkResult(String result) {
+ // Check prefix of 'Element2' element, it should always be the same
+ assertTrue(result.contains(EXPECTED_CONTENT));
+ }
+
+ // Check if the transformation result string contains the element with
+ // the exact namespace prefix generated by current thread.
+ // If the expected prefix is not found and there was no failures observed by
+ // other test threads then mark concurrent test as failed.
+ private static void checkThreadResult(String result, int id) {
+ boolean res = result.contains(EXPECTED_CONTENT);
+ System.out.printf("%d: transformation result: %s%n", id, res ? "Pass" : "Fail");
+ if (!res) {
+ System.out.printf("%d result:%s%n", id, result);
+ }
+ concurrentTestPassed.compareAndSet(true, res);
+ }
+
+ // TransformerThread task that does the transformation similar
+ // to testReuseTransformer test method
+ private class TransformerThread implements Runnable {
+
+ private final Transformer transformer;
+ private final int id;
+
+ TransformerThread(Transformer transformer, int id) {
+ this.transformer = transformer;
+ this.id = id;
+ }
+
+ @Override
+ public void run() {
+ try {
+ System.out.printf("%d: waiting for barrier%n", id);
+ //Synchronize startup of all tasks
+ BARRIER.await();
+ System.out.printf("%d: starting transformation%n", id);
+ checkThreadResult(doTransformation(transformer), id);
+ } catch (Exception ex) {
+ throw new RuntimeException("TransformerThread " + id + " failed", ex);
+ }
+ }
+ }
+
+ // Number of subsequent transformations
+ private static final int TRANSF_COUNT = 10;
+
+ // Number of transformer threads running concurently
+ private static final int THREADS_COUNT = 10;
+
+ // Variable for storing the concurrent transformation test result. It is
+ // updated by transformer threads
+ private static final AtomicBoolean concurrentTestPassed = new AtomicBoolean(true);
+
+ // Cyclic barrier for threads startup synchronization
+ private static final CyclicBarrier BARRIER = new CyclicBarrier(THREADS_COUNT);
+
+ // Thread pool
+ private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
+
+ // XSL that transforms XML and produces unique namespace prefixes for each element
+ private final static String XSL = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
+ + " <xsl:template match=\"node()|@*\" priority=\"1\">\n"
+ + " <xsl:copy>\n"
+ + " <xsl:apply-templates select=\"node()|@*\"/>\n"
+ + " </xsl:copy>\n"
+ + " </xsl:template>\n"
+ + " <xsl:template match=\"*\" priority=\"2\">\n"
+ + " <xsl:element name=\"{name()}\" namespace=\"{namespace-uri()}\">\n"
+ + " <xsl:apply-templates select=\"node()|@*\"/>\n"
+ + " </xsl:element>\n"
+ + " </xsl:template>\n"
+ + "</xsl:stylesheet>";
+
+ // Simple XML content with root and two child elements
+ private final static String XML = "<TestRoot xmlns=\"test.xmlns\">\n"
+ + " <Element1 xmlns=\"test.xmlns\">\n"
+ + " </Element1>\n"
+ + " <Element2 xmlns=\"test.xmlns\">\n"
+ + " </Element2>\n"
+ + "</TestRoot>";
+
+ // With thread local namespace prefix index each transformation result should
+ // be the same and contain the same prefix for Element2
+ private final static String EXPECTED_CONTENT = "</ns2:Element2>";
+
+}
--- a/jaxws/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/jaxws/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -386,3 +386,4 @@
7d3a8f52b124db26ba8425c2931b748dd9d2791b jdk-9+138
7a7aadf3c4500cc273c889aa1172d4fe3844bb6b jdk-9+139
9004617323fe99cbe4fad48f373cb2ed4fc50aa6 jdk-9+140
+b2c18f755228d1d19a86cd7d5fa1abb6b1495dfb jdk-9+141
--- a/jdk/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
665096863382bf23ce891307cf2a7511e77c1c88 jdk-9+138
5518ac2f2ead5e594bd983f2047178136aafdfd0 jdk-9+139
e93b7ea559759f036c9f69fd2ddaf47bb4e98385 jdk-9+140
+8d752af5f61d41f226adf2cda72a20faa9ad620a jdk-9+141
--- a/jdk/make/gendata/GendataBreakIterator.gmk Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/make/gendata/GendataBreakIterator.gmk Thu Oct 27 09:42:08 2016 -0700
@@ -55,7 +55,6 @@
$(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(JDK_TOPDIR)/src/jdk.localedata/share/classes, \
- INCLUDES := $(TEXT_PKG_LD), \
INCLUDE_FILES := \
$(TEXT_PKG_LD)/BreakIteratorRules_th.java \
$(TEXT_PKG_LD)/BreakIteratorInfo_th.java, \
--- a/jdk/src/java.base/share/classes/java/io/FileInputStream.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/FileInputStream.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -26,7 +26,6 @@
package java.io;
import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
import sun.nio.ch.FileChannelImpl;
@@ -60,7 +59,9 @@
private volatile FileChannel channel;
- private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final Object closeLock = new Object();
+
+ private volatile boolean closed;
/**
* Creates a <code>FileInputStream</code> by
@@ -313,14 +314,21 @@
* @spec JSR-51
*/
public void close() throws IOException {
- if (!closed.compareAndSet(false, true)) {
- // if compareAndSet() returns false closed was already true
+ if (closed) {
return;
}
+ synchronized (closeLock) {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
FileChannel fc = channel;
if (fc != null) {
- fc.close();
+ // possible race with getChannel(), benign since
+ // FileChannel.close is final and idempotent
+ fc.close();
}
fd.closeAll(new Closeable() {
@@ -370,8 +378,10 @@
fc = this.channel;
if (fc == null) {
this.channel = fc = FileChannelImpl.open(fd, path, true, false, this);
- if (closed.get()) {
+ if (closed) {
try {
+ // possible race with close(), benign since
+ // FileChannel.close is final and idempotent
fc.close();
} catch (IOException ioe) {
throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -26,7 +26,6 @@
package java.io;
import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaIOFileDescriptorAccess;
import sun.nio.ch.FileChannelImpl;
@@ -77,7 +76,9 @@
*/
private final String path;
- private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final Object closeLock = new Object();
+
+ private volatile boolean closed;
/**
* Creates a file output stream to write to the file with the
@@ -341,14 +342,21 @@
* @spec JSR-51
*/
public void close() throws IOException {
- if (!closed.compareAndSet(false, true)) {
- // if compareAndSet() returns false closed was already true
+ if (closed) {
return;
}
+ synchronized (closeLock) {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
FileChannel fc = channel;
if (fc != null) {
- fc.close();
+ // possible race with getChannel(), benign since
+ // FileChannel.close is final and idempotent
+ fc.close();
}
fd.closeAll(new Closeable() {
@@ -399,8 +407,10 @@
fc = this.channel;
if (fc == null) {
this.channel = fc = FileChannelImpl.open(fd, path, false, true, this);
- if (closed.get()) {
+ if (closed) {
try {
+ // possible race with close(), benign since
+ // FileChannel.close is final and idempotent
fc.close();
} catch (IOException ioe) {
throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java Thu Oct 27 09:42:08 2016 -0700
@@ -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
@@ -1413,27 +1413,7 @@
* returned constructor (if any).
*/
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
- Class<?> initCl = cl;
- while (Serializable.class.isAssignableFrom(initCl)) {
- if ((initCl = initCl.getSuperclass()) == null) {
- return null;
- }
- }
- try {
- Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
- int mods = cons.getModifiers();
- if ((mods & Modifier.PRIVATE) != 0 ||
- ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
- !packageEquals(cl, initCl)))
- {
- return null;
- }
- cons = reflFactory.newConstructorForSerialization(cl, cons);
- cons.setAccessible(true);
- return cons;
- } catch (NoSuchMethodException ex) {
- return null;
- }
+ return reflFactory.newConstructorForSerialization(cl);
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Thu Oct 27 09:42:08 2016 -0700
@@ -104,9 +104,9 @@
* class or resource itself.
*
* <p> Class loaders that support concurrent loading of classes are known as
- * <em>parallel capable</em> class loaders and are required to register
- * themselves at their class initialization time by invoking the
- * {@link
+ * <em>{@linkplain #isParallelCapable() parallel capable}</em> class loaders and
+ * are required to register themselves at their class initialization time by
+ * invoking the {@link
* #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
* method. Note that the <tt>ClassLoader</tt> class is registered as parallel
* capable by default. However, its subclasses still need to register themselves
@@ -1437,7 +1437,7 @@
}
/**
- * Registers the caller as parallel capable.
+ * Registers the caller as {@linkplain #isParallelCapable() parallel capable}.
* The registration succeeds if and only if all of the following
* conditions are met:
* <ol>
@@ -1448,8 +1448,10 @@
* <p>Note that once a class loader is registered as parallel capable, there
* is no way to change it back.</p>
*
- * @return true if the caller is successfully registered as
- * parallel capable and false if otherwise.
+ * @return {@code true} if the caller is successfully registered as
+ * parallel capable and {@code false} if otherwise.
+ *
+ * @see #isParallelCapable()
*
* @since 1.7
*/
@@ -1461,6 +1463,22 @@
}
/**
+ * Returns {@code true} if this class loader is
+ * {@linkplain #registerAsParallelCapable parallel capable}, otherwise
+ * {@code false}.
+ *
+ * @return {@code true} if this class loader is parallel capable,
+ * otherwise {@code false}.
+ *
+ * @see #registerAsParallelCapable()
+ *
+ * @since 9
+ */
+ public final boolean isParallelCapable() {
+ return ParallelLoaders.isRegistered(this.getClass());
+ }
+
+ /**
* Find a resource of the specified name from the search path used to load
* classes. This method locates the resource through the system class
* loader (see {@link #getSystemClassLoader()}).
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java Thu Oct 27 09:42:08 2016 -0700
@@ -201,13 +201,13 @@
* Specify the address family: Internet Protocol, Version 4
* @since 1.4
*/
- static final int IPv4 = 1;
+ @Native static final int IPv4 = 1;
/**
* Specify the address family: Internet Protocol, Version 6
* @since 1.4
*/
- static final int IPv6 = 2;
+ @Native static final int IPv6 = 2;
/* Specify address family preference */
static transient final int preferIPv6Address;
@@ -321,6 +321,13 @@
public String getOriginalHostName(InetAddress ia) {
return ia.holder.getOriginalHostName();
}
+
+ public InetAddress getByName(String hostName,
+ InetAddress hostAddress)
+ throws UnknownHostException
+ {
+ return InetAddress.getByName(hostName, hostAddress);
+ }
}
);
init();
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,8 @@
import jdk.internal.loader.Resource;
import jdk.internal.loader.URLClassPath;
+import jdk.internal.misc.JavaNetURLClassLoaderAccess;
+import jdk.internal.misc.SharedSecrets;
import jdk.internal.perf.PerfCounter;
import sun.net.www.ParseUtil;
import sun.security.util.SecurityConstants;
@@ -765,6 +767,14 @@
}
static {
+ SharedSecrets.setJavaNetURLClassLoaderAccess(
+ new JavaNetURLClassLoaderAccess() {
+ @Override
+ public AccessControlContext getAccessControlContext(URLClassLoader u) {
+ return u.acc;
+ }
+ }
+ );
ClassLoader.registerAsParallelCapable();
}
}
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Thu Oct 27 09:42:08 2016 -0700
@@ -89,6 +89,11 @@
AccessController.getContext(), context);
}
+ @Override
+ public ProtectionDomain[] getProtectDomains(AccessControlContext context) {
+ return context.getContext();
+ }
+
private static AccessControlContext getCombinedACC(
AccessControlContext context, AccessControlContext stack) {
AccessControlContext acc =
--- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java Thu Oct 27 09:42:08 2016 -0700
@@ -368,7 +368,7 @@
if (field instanceof ChronoField) {
switch ((ChronoField) field) {
case DAY_OF_WEEK: return getDayOfWeek();
- case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((getDayOfWeek() - 1) % 7) + 1;
+ case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((dayOfMonth - 1) % 7) + 1;
case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
case DAY_OF_MONTH: return this.dayOfMonth;
case DAY_OF_YEAR: return this.getDayOfYear();
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -349,25 +349,40 @@
if (field == MONTH_OF_YEAR) {
for (TextStyle textStyle : TextStyle.values()) {
- Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
- "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale);
Map<Long, String> map = new HashMap<>();
- if (displayNames != null) {
- for (Entry<String, Integer> entry : displayNames.entrySet()) {
- map.put((long) (entry.getValue() + 1), entry.getKey());
- }
-
- } else {
- // Narrow names may have duplicated names, such as "J" for January, Jun, July.
- // Get names one by one in that case.
+ // Narrow names may have duplicated names, such as "J" for January, June, July.
+ // Get names one by one in that case.
+ if ((textStyle.equals(TextStyle.NARROW) ||
+ textStyle.equals(TextStyle.NARROW_STANDALONE))) {
for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
String name;
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
- "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale);
+ "gregory", Calendar.MONTH,
+ month, textStyle.toCalendarStyle(), locale);
if (name == null) {
break;
}
- map.put((long) (month + 1), name);
+ map.put((month + 1L), name);
+ }
+ } else {
+ Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
+ "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale);
+ if (displayNames != null) {
+ for (Entry<String, Integer> entry : displayNames.entrySet()) {
+ map.put((long)(entry.getValue() + 1), entry.getKey());
+ }
+ } else {
+ // Although probability is very less, but if other styles have duplicate names.
+ // Get names one by one in that case.
+ for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
+ String name;
+ name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
+ "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale);
+ if (name == null) {
+ break;
+ }
+ map.put((month + 1L), name);
+ }
}
}
if (!map.isEmpty()) {
@@ -379,26 +394,41 @@
if (field == DAY_OF_WEEK) {
for (TextStyle textStyle : TextStyle.values()) {
- Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
- "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale);
Map<Long, String> map = new HashMap<>();
- if (displayNames != null) {
- for (Entry<String, Integer> entry : displayNames.entrySet()) {
- map.put((long)toWeekDay(entry.getValue()), entry.getKey());
- }
-
- } else {
- // Narrow names may have duplicated names, such as "S" for Sunday and Saturday.
- // Get names one by one in that case.
+ // Narrow names may have duplicated names, such as "S" for Sunday and Saturday.
+ // Get names one by one in that case.
+ if ((textStyle.equals(TextStyle.NARROW) ||
+ textStyle.equals(TextStyle.NARROW_STANDALONE))) {
for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
String name;
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
- "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale);
+ "gregory", Calendar.DAY_OF_WEEK,
+ wday, textStyle.toCalendarStyle(), locale);
if (name == null) {
break;
}
map.put((long)toWeekDay(wday), name);
}
+ } else {
+ Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
+ "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale);
+ if (displayNames != null) {
+ for (Entry<String, Integer> entry : displayNames.entrySet()) {
+ map.put((long)toWeekDay(entry.getValue()), entry.getKey());
+ }
+ } else {
+ // Although probability is very less, but if other styles have duplicate names.
+ // Get names one by one in that case.
+ for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
+ String name;
+ name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
+ "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale);
+ if (name == null) {
+ break;
+ }
+ map.put((long)toWeekDay(wday), name);
+ }
+ }
}
if (!map.isEmpty()) {
styleMap.put(textStyle, map);
--- a/jdk/src/java.base/share/classes/java/util/Optional.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Optional.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -236,7 +236,7 @@
* present, otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is {@code null}
*/
- public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
+ public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
@@ -264,12 +264,14 @@
* @throws NullPointerException if the mapping function is {@code null} or
* returns a {@code null} result
*/
- public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
+ public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
- return Objects.requireNonNull(mapper.apply(value));
+ @SuppressWarnings("unchecked")
+ Optional<U> r = (Optional<U>) mapper.apply(value);
+ return Objects.requireNonNull(r);
}
}
@@ -286,12 +288,14 @@
* produces a {@code null} result
* @since 9
*/
- public Optional<T> or(Supplier<Optional<T>> supplier) {
+ public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
Objects.requireNonNull(supplier);
if (isPresent()) {
return this;
} else {
- return Objects.requireNonNull(supplier.get());
+ @SuppressWarnings("unchecked")
+ Optional<T> r = (Optional<T>) supplier.get();
+ return Objects.requireNonNull(r);
}
}
--- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Thu Oct 27 09:42:08 2016 -0700
@@ -63,7 +63,7 @@
* files containing the resource data. <code>ResourceBundle.getBundle</code>
* will automatically look for the appropriate properties file and create a
* <code>PropertyResourceBundle</code> that refers to it. See
- * {@link ResourceBundle#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) ResourceBundle.getBundle}
+ * {@link ResourceBundle#getBundle(String, Locale, ClassLoader) ResourceBundle.getBundle}
* for a complete description of the search and instantiation strategy.
*
* <p>
@@ -105,19 +105,14 @@
* </pre>
* </blockquote>
*
- * <p>
- * The implementation of a {@code PropertyResourceBundle} subclass must be
- * thread-safe if it's simultaneously used by multiple threads. The default
- * implementations of the non-abstract methods in this class are thread-safe.
- *
- * <p>
- * <strong>Note:</strong> PropertyResourceBundle can be constructed either
- * from an InputStream or a Reader, which represents a property file.
- * Constructing a PropertyResourceBundle instance from an InputStream requires
- * that the input stream be encoded in UTF-8. By default, if a
+ * @apiNote
+ * {@code PropertyResourceBundle} can be constructed either
+ * from an {@code InputStream} or a {@code Reader}, which represents a property file.
+ * Constructing a {@code PropertyResourceBundle} instance from an {@code InputStream}
+ * requires that the input stream be encoded in {@code UTF-8}. By default, if a
* {@link java.nio.charset.MalformedInputException} or an
* {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
- * input stream, then the PropertyResourceBundle instance resets to the state
+ * input stream, then the {@code PropertyResourceBundle} instance resets to the state
* before the exception, re-reads the input stream in {@code ISO-8859-1}, and
* continues reading. If the system property
* {@code java.util.PropertyResourceBundle.encoding} is set to either
@@ -126,8 +121,15 @@
* If "ISO-8859-1" is specified, characters that cannot be represented in
* ISO-8859-1 encoding must be represented by Unicode Escapes as defined in section
* 3.3 of <cite>The Java™ Language Specification</cite>
- * whereas the other constructor which takes a Reader does not have that limitation.
+ * whereas the other constructor which takes a {@code Reader} does not have that limitation.
* Other encoding values are ignored for this system property.
+ * The system property is read and evaluated when initializing this class.
+ * Changing or removing the property has no effect after the initialization.
+ *
+ * @implSpec
+ * The implementation of a {@code PropertyResourceBundle} subclass must be
+ * thread-safe if it's simultaneously used by multiple threads. The default
+ * implementations of the non-abstract methods in this class are thread-safe.
*
* @see ResourceBundle
* @see ListResourceBundle
@@ -144,16 +146,18 @@
/**
* Creates a property resource bundle from an {@link java.io.InputStream
- * InputStream}. This constructor reads the property file in UTF-8 by default.
- * If a {@link java.nio.charset.MalformedInputException} or an
- * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
- * input stream, then the PropertyResourceBundle instance resets to the state
- * before the exception, re-reads the input stream in {@code ISO-8859-1} and
- * continues reading. If the system property
- * {@code java.util.PropertyResourceBundle.encoding} is set to either
- * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
- * and throws the exception if it encounters an invalid sequence. Other
- * encoding values are ignored for this system property.
+ * InputStream}. This constructor reads the property file in UTF-8 by default.
+ * If a {@link java.nio.charset.MalformedInputException} or an
+ * {@link java.nio.charset.UnmappableCharacterException} occurs on reading the
+ * input stream, then the PropertyResourceBundle instance resets to the state
+ * before the exception, re-reads the input stream in {@code ISO-8859-1} and
+ * continues reading. If the system property
+ * {@code java.util.PropertyResourceBundle.encoding} is set to either
+ * "ISO-8859-1" or "UTF-8", the input stream is solely read in that encoding,
+ * and throws the exception if it encounters an invalid sequence. Other
+ * encoding values are ignored for this system property.
+ * The system property is read and evaluated when initializing this class.
+ * Changing or removing the property has no effect after the initialization.
*
* @param stream an InputStream that represents a property file
* to read from.
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetInetAddressAccess.java Thu Oct 27 09:42:08 2016 -0700
@@ -26,6 +26,7 @@
package jdk.internal.misc;
import java.net.InetAddress;
+import java.net.UnknownHostException;
public interface JavaNetInetAddressAccess {
/**
@@ -33,4 +34,13 @@
* the given InetAddress object.
*/
String getOriginalHostName(InetAddress ia);
+
+ /**
+ * Get the InetAddress of the provided host. If an InetAddress is provided
+ * then it will be the default address returned for all calls to either
+ * form of getByName. This is required to maintain consistency when
+ * caching addresses and hostnames.
+ */
+ InetAddress getByName(String hostName, InetAddress hostAddress)
+ throws UnknownHostException;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaNetURLClassLoaderAccess.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+
+public interface JavaNetURLClassLoaderAccess {
+ AccessControlContext getAccessControlContext(URLClassLoader u);;
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaSecurityAccess.java Thu Oct 27 09:42:08 2016 -0700
@@ -27,6 +27,7 @@
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
public interface JavaSecurityAccess {
@@ -37,4 +38,5 @@
<T> T doIntersectionPrivilege(PrivilegedAction<T> action,
AccessControlContext context);
+ ProtectionDomain[] getProtectDomains(AccessControlContext context);
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Thu Oct 27 09:42:08 2016 -0700
@@ -57,6 +57,7 @@
private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
private static JavaNetSocketAccess javaNetSocketAccess;
private static JavaNetUriAccess javaNetUriAccess;
+ private static JavaNetURLClassLoaderAccess javaNetURLClassLoaderAccess;
private static JavaNioAccess javaNioAccess;
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
@@ -144,6 +145,16 @@
return javaNetUriAccess;
}
+ public static void setJavaNetURLClassLoaderAccess(JavaNetURLClassLoaderAccess jnua) {
+ javaNetURLClassLoaderAccess = jnua;
+ }
+
+ public static JavaNetURLClassLoaderAccess getJavaNetURLClassLoaderAccess() {
+ if (javaNetURLClassLoaderAccess == null)
+ unsafe.ensureClassInitialized(java.net.URLClassLoader.class);
+ return javaNetURLClassLoaderAccess;
+ }
+
public static void setJavaNetInetAddressAccess(JavaNetInetAddressAccess jna) {
javaNetInetAddressAccess = jna;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,14 +25,25 @@
package jdk.internal.reflect;
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.security.Permission;
import java.security.PrivilegedAction;
+import java.util.Objects;
import java.util.Properties;
+
import sun.reflect.misc.ReflectUtil;
import sun.security.action.GetPropertyAction;
@@ -57,6 +68,9 @@
// Provides access to package-private mechanisms in java.lang.reflect
private static volatile LangReflectAccess langReflectAccess;
+ /* Method for static class initializer <clinit>, or null */
+ private static volatile Method hasStaticInitializerMethod;
+
//
// "Inflation" mechanism. Loading bytecodes to implement
// Method.invoke() and Constructor.newInstance() currently costs
@@ -337,16 +351,41 @@
//
//
- public Constructor<?> newConstructorForSerialization
- (Class<?> classToInstantiate, Constructor<?> constructorToCall)
- {
- // Fast path
- if (constructorToCall.getDeclaringClass() == classToInstantiate) {
- return constructorToCall;
+ public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+ if (!Externalizable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+ try {
+ Constructor<?> cons = cl.getConstructor();
+ cons.setAccessible(true);
+ return cons;
+ } catch (NoSuchMethodException ex) {
+ return null;
+ }
+ }
+
+ public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
+ Class<?> initCl = cl;
+ while (Serializable.class.isAssignableFrom(initCl)) {
+ if ((initCl = initCl.getSuperclass()) == null) {
+ return null;
+ }
+ }
+ Constructor<?> constructorToCall;
+ try {
+ constructorToCall = initCl.getDeclaredConstructor();
+ int mods = constructorToCall.getModifiers();
+ if ((mods & Modifier.PRIVATE) != 0 ||
+ ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
+ !packageEquals(cl, initCl))) {
+ return null;
+ }
+ } catch (NoSuchMethodException ex) {
+ return null;
}
ConstructorAccessor acc = new MethodAccessorGenerator().
- generateSerializationConstructor(classToInstantiate,
+ generateSerializationConstructor(cl,
constructorToCall.getParameterTypes(),
constructorToCall.getExceptionTypes(),
constructorToCall.getModifiers(),
@@ -364,9 +403,151 @@
langReflectAccess().
getConstructorParameterAnnotations(constructorToCall));
setConstructorAccessor(c, acc);
+ c.setAccessible(true);
return c;
}
+ public final MethodHandle readObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
+ }
+
+ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
+ }
+
+ public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+ return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
+ }
+
+ private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
+ String methodName,
+ Class<?> streamClass) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ try {
+ Method meth = cl.getDeclaredMethod(methodName, streamClass);
+ int mods = meth.getModifiers();
+ if (meth.getReturnType() != Void.TYPE ||
+ Modifier.isStatic(mods) ||
+ !Modifier.isPrivate(mods)) {
+ return null;
+ }
+ meth.setAccessible(true);
+ return MethodHandles.lookup().unreflect(meth);
+ } catch (NoSuchMethodException ex) {
+ return null;
+ } catch (IllegalAccessException ex1) {
+ throw new InternalError("Error", ex1);
+ }
+ }
+
+ /**
+ * Returns a MethodHandle for {@code writeReplace} on the serializable class
+ * or null if no match found.
+ * @param cl a serializable class
+ * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
+ */
+ public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "writeReplace");
+ }
+
+ /**
+ * Returns a MethodHandle for {@code readResolve} on the serializable class
+ * or null if no match found.
+ * @param cl a serializable class
+ * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
+ */
+ public final MethodHandle readResolveForSerialization(Class<?> cl) {
+ return getReplaceResolveForSerialization(cl, "readResolve");
+ }
+
+ /**
+ * Lookup readResolve or writeReplace on a class with specified
+ * signature constraints.
+ * @param cl a serializable class
+ * @param methodName the method name to find
+ * @returns a MethodHandle for the method or {@code null} if not found or
+ * has the wrong signature.
+ */
+ private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
+ String methodName) {
+ if (!Serializable.class.isAssignableFrom(cl)) {
+ return null;
+ }
+
+ Class<?> defCl = cl;
+ while (defCl != null) {
+ try {
+ Method m = defCl.getDeclaredMethod(methodName);
+ if (m.getReturnType() != Object.class) {
+ return null;
+ }
+ int mods = m.getModifiers();
+ if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
+ return null;
+ } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
+ // fall through
+ } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
+ return null;
+ } else if (!packageEquals(cl, defCl)) {
+ return null;
+ }
+ try {
+ // Normal return
+ m.setAccessible(true);
+ return MethodHandles.lookup().unreflect(m);
+ } catch (IllegalAccessException ex0) {
+ // setAccessible should prevent IAE
+ throw new InternalError("Error", ex0);
+ }
+ } catch (NoSuchMethodException ex) {
+ defCl = defCl.getSuperclass();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the given class defines a static initializer method,
+ * false otherwise.
+ */
+ public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+ Method m = hasStaticInitializerMethod;
+ if (m == null) {
+ try {
+ m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
+ new Class<?>[]{Class.class});
+ m.setAccessible(true);
+ hasStaticInitializerMethod = m;
+ } catch (NoSuchMethodException ex) {
+ throw new InternalError("No such method hasStaticInitializer on "
+ + ObjectStreamClass.class, ex);
+ }
+ }
+ try {
+ return (Boolean) m.invoke(null, cl);
+ } catch (InvocationTargetException | IllegalAccessException ex) {
+ throw new InternalError("Exception invoking hasStaticInitializer", ex);
+ }
+ }
+
+ /**
+ * Return the accessible constructor for OptionalDataException signaling eof.
+ * @returns the eof constructor for OptionalDataException
+ */
+ public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
+ try {
+ Constructor<OptionalDataException> boolCtor =
+ OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
+ boolCtor.setAccessible(true);
+ return boolCtor;
+ } catch (NoSuchMethodException ex) {
+ throw new InternalError("Constructor not found", ex);
+ }
+ }
+
//--------------------------------------------------------------------------
//
// Internals only below this point
@@ -426,4 +607,17 @@
}
return langReflectAccess;
}
+
+ /**
+ * Returns true if classes are defined in the classloader and same package, false
+ * otherwise.
+ * @param cl1 a class
+ * @param cl2 another class
+ * @returns true if the two classes are in the same classloader and package
+ */
+ private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
+ return cl1.getClassLoader() == cl2.getClassLoader() &&
+ Objects.equals(cl1.getPackage(), cl2.getPackage());
+ }
+
}
--- a/jdk/src/java.base/share/classes/module-info.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/module-info.java Thu Oct 27 09:42:08 2016 -0700
@@ -240,8 +240,7 @@
java.xml.ws;
exports sun.security.action to
java.desktop,
- java.security.jgss,
- jdk.crypto.pkcs11;
+ java.security.jgss;
exports sun.security.internal.interfaces to
jdk.crypto.pkcs11;
exports sun.security.internal.spec to
@@ -267,6 +266,8 @@
jdk.crypto.pkcs11;
exports sun.security.ssl to
java.security.jgss;
+ exports sun.security.timestamp to
+ jdk.jartool;
exports sun.security.tools to
jdk.jartool;
exports sun.security.util to
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Thu Oct 27 09:42:08 2016 -0700
@@ -498,6 +498,23 @@
return unauthenticatedAttributes;
}
+ /**
+ * Returns the timestamp PKCS7 data unverified.
+ * @return a PKCS7 object
+ */
+ public PKCS7 getTsToken() throws IOException {
+ if (unauthenticatedAttributes == null) {
+ return null;
+ }
+ PKCS9Attribute tsTokenAttr =
+ unauthenticatedAttributes.getAttribute(
+ PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+ if (tsTokenAttr == null) {
+ return null;
+ }
+ return new PKCS7((byte[])tsTokenAttr.getValue());
+ }
+
/*
* Extracts a timestamp from a PKCS7 SignerInfo.
*
@@ -525,19 +542,12 @@
if (timestamp != null || !hasTimestamp)
return timestamp;
- if (unauthenticatedAttributes == null) {
- hasTimestamp = false;
- return null;
- }
- PKCS9Attribute tsTokenAttr =
- unauthenticatedAttributes.getAttribute(
- PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
- if (tsTokenAttr == null) {
+ PKCS7 tsToken = getTsToken();
+ if (tsToken == null) {
hasTimestamp = false;
return null;
}
- PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
// Extract the content (an encoded timestamp token info)
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/BreakDictionary.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+package sun.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * This is the class that represents the list of known words used by
+ * DictionaryBasedBreakIterator. The conceptual data structure used
+ * here is a trie: there is a node hanging off the root node for every
+ * letter that can start a word. Each of these nodes has a node hanging
+ * off of it for every letter that can be the second letter of a word
+ * if this node is the first letter, and so on. The trie is represented
+ * as a two-dimensional array that can be treated as a table of state
+ * transitions. Indexes are used to compress this array, taking
+ * advantage of the fact that this array will always be very sparse.
+ */
+class BreakDictionary {
+
+ //=========================================================================
+ // data members
+ //=========================================================================
+
+ /**
+ * The version of the dictionary that was read in.
+ */
+ private static int supportedVersion = 1;
+
+ /**
+ * Maps from characters to column numbers. The main use of this is to
+ * avoid making room in the array for empty columns.
+ */
+ private CompactByteArray columnMap = null;
+ private SupplementaryCharacterData supplementaryCharColumnMap = null;
+
+ /**
+ * The number of actual columns in the table
+ */
+ private int numCols;
+
+ /**
+ * Columns are organized into groups of 32. This says how many
+ * column groups. (We could calculate this, but we store the
+ * value to avoid having to repeatedly calculate it.)
+ */
+ private int numColGroups;
+
+ /**
+ * The actual compressed state table. Each conceptual row represents
+ * a state, and the cells in it contain the row numbers of the states
+ * to transition to for each possible letter. 0 is used to indicate
+ * an illegal combination of letters (i.e., the error state). The
+ * table is compressed by eliminating all the unpopulated (i.e., zero)
+ * cells. Multiple conceptual rows can then be doubled up in a single
+ * physical row by sliding them up and possibly shifting them to one
+ * side or the other so the populated cells don't collide. Indexes
+ * are used to identify unpopulated cells and to locate populated cells.
+ */
+ private short[] table = null;
+
+ /**
+ * This index maps logical row numbers to physical row numbers
+ */
+ private short[] rowIndex = null;
+
+ /**
+ * A bitmap is used to tell which cells in the comceptual table are
+ * populated. This array contains all the unique bit combinations
+ * in that bitmap. If the table is more than 32 columns wide,
+ * successive entries in this array are used for a single row.
+ */
+ private int[] rowIndexFlags = null;
+
+ /**
+ * This index maps from a logical row number into the bitmap table above.
+ * (This keeps us from storing duplicate bitmap combinations.) Since there
+ * are a lot of rows with only one populated cell, instead of wasting space
+ * in the bitmap table, we just store a negative number in this index for
+ * rows with one populated cell. The absolute value of that number is
+ * the column number of the populated cell.
+ */
+ private short[] rowIndexFlagsIndex = null;
+
+ /**
+ * For each logical row, this index contains a constant that is added to
+ * the logical column number to get the physical column number
+ */
+ private byte[] rowIndexShifts = null;
+
+ //=========================================================================
+ // deserialization
+ //=========================================================================
+
+ BreakDictionary(String dictionaryName, byte[] dictionaryData) {
+ try {
+ setupDictionary(dictionaryName, dictionaryData);
+ } catch (BufferUnderflowException bue) {
+ MissingResourceException e;
+ e = new MissingResourceException("Corrupted dictionary data",
+ dictionaryName, "");
+ e.initCause(bue);
+ throw e;
+ }
+ }
+
+ private void setupDictionary(String dictionaryName, byte[] dictionaryData) {
+ ByteBuffer bb = ByteBuffer.wrap(dictionaryData);
+
+ // check version
+ int version = bb.getInt();
+ if (version != supportedVersion) {
+ throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
+ dictionaryName, "");
+ }
+
+ // Check data size
+ int len = bb.getInt();
+ if (bb.position() + len != bb.limit()) {
+ throw new MissingResourceException("Dictionary size is wrong: " + bb.limit(),
+ dictionaryName, "");
+ }
+
+ // read in the column map for BMP characteres (this is serialized in
+ // its internal form: an index array followed by a data array)
+ len = bb.getInt();
+ short[] temp = new short[len];
+ for (int i = 0; i < len; i++) {
+ temp[i] = bb.getShort();
+ }
+ len = bb.getInt();
+ byte[] temp2 = new byte[len];
+ bb.get(temp2);
+ columnMap = new CompactByteArray(temp, temp2);
+
+ // read in numCols and numColGroups
+ numCols = bb.getInt();
+ numColGroups = bb.getInt();
+
+ // read in the row-number index
+ len = bb.getInt();
+ rowIndex = new short[len];
+ for (int i = 0; i < len; i++) {
+ rowIndex[i] = bb.getShort();
+ }
+
+ // load in the populated-cells bitmap: index first, then bitmap list
+ len = bb.getInt();
+ rowIndexFlagsIndex = new short[len];
+ for (int i = 0; i < len; i++) {
+ rowIndexFlagsIndex[i] = bb.getShort();
+ }
+ len = bb.getInt();
+ rowIndexFlags = new int[len];
+ for (int i = 0; i < len; i++) {
+ rowIndexFlags[i] = bb.getInt();
+ }
+
+ // load in the row-shift index
+ len = bb.getInt();
+ rowIndexShifts = new byte[len];
+ bb.get(rowIndexShifts);
+
+ // load in the actual state table
+ len = bb.getInt();
+ table = new short[len];
+ for (int i = 0; i < len; i++) {
+ table[i] = bb.getShort();
+ }
+
+ // finally, prepare the column map for supplementary characters
+ len = bb.getInt();
+ int[] temp3 = new int[len];
+ for (int i = 0; i < len; i++) {
+ temp3[i] = bb.getInt();
+ }
+ assert bb.position() == bb.limit();
+
+ supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
+ }
+
+ //=========================================================================
+ // access to the words
+ //=========================================================================
+
+ /**
+ * Uses the column map to map the character to a column number, then
+ * passes the row and column number to getNextState()
+ * @param row The current state
+ * @param ch The character whose column we're interested in
+ * @return The new state to transition to
+ */
+ public final short getNextStateFromCharacter(int row, int ch) {
+ int col;
+ if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ col = columnMap.elementAt((char)ch);
+ } else {
+ col = supplementaryCharColumnMap.getValue(ch);
+ }
+ return getNextState(row, col);
+ }
+
+ /**
+ * Returns the value in the cell with the specified (logical) row and
+ * column numbers. In DictionaryBasedBreakIterator, the row number is
+ * a state number, the column number is an input, and the return value
+ * is the row number of the new state to transition to. (0 is the
+ * "error" state, and -1 is the "end of word" state in a dictionary)
+ * @param row The row number of the current state
+ * @param col The column number of the input character (0 means "not a
+ * dictionary character")
+ * @return The row number of the new state to transition to
+ */
+ public final short getNextState(int row, int col) {
+ if (cellIsPopulated(row, col)) {
+ // we map from logical to physical row number by looking up the
+ // mapping in rowIndex; we map from logical column number to
+ // physical column number by looking up a shift value for this
+ // logical row and offsetting the logical column number by
+ // the shift amount. Then we can use internalAt() to actually
+ // get the value out of the table.
+ return internalAt(rowIndex[row], col + rowIndexShifts[row]);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /**
+ * Given (logical) row and column numbers, returns true if the
+ * cell in that position is populated
+ */
+ private boolean cellIsPopulated(int row, int col) {
+ // look up the entry in the bitmap index for the specified row.
+ // If it's a negative number, it's the column number of the only
+ // populated cell in the row
+ if (rowIndexFlagsIndex[row] < 0) {
+ return col == -rowIndexFlagsIndex[row];
+ }
+
+ // if it's a positive number, it's the offset of an entry in the bitmap
+ // list. If the table is more than 32 columns wide, the bitmap is stored
+ // successive entries in the bitmap list, so we have to divide the column
+ // number by 32 and offset the number we got out of the index by the result.
+ // Once we have the appropriate piece of the bitmap, test the appropriate
+ // bit and return the result.
+ else {
+ int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
+ return (flags & (1 << (col & 0x1f))) != 0;
+ }
+ }
+
+ /**
+ * Implementation of getNextState() when we know the specified cell is
+ * populated.
+ * @param row The PHYSICAL row number of the cell
+ * @param col The PHYSICAL column number of the cell
+ * @return The value stored in the cell
+ */
+ private short internalAt(int row, int col) {
+ // the table is a one-dimensional array, so this just does the math necessary
+ // to treat it as a two-dimensional array (we don't just use a two-dimensional
+ // array because two-dimensional arrays are inefficient in Java)
+ return table[row * numCols + col];
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+
+package sun.text;
+
+import java.text.CharacterIterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
+ * to further subdivide ranges of text beyond what is possible using just the
+ * state-table-based algorithm. This is necessary, for example, to handle
+ * word and line breaking in Thai, which doesn't use spaces between words. The
+ * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
+ * up text as far as possible, and then contiguous ranges of letters are
+ * repeatedly compared against a list of known words (i.e., the dictionary)
+ * to divide them up into words.
+ *
+ * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
+ * but adds one more special substitution name: <dictionary>. This substitution
+ * name is used to identify characters in words in the dictionary. The idea is that
+ * if the iterator passes over a chunk of text that includes two or more characters
+ * in a row that are included in <dictionary>, it goes back through that range and
+ * derives additional break positions (if possible) using the dictionary.
+ *
+ * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
+ * file. It follows a prescribed search path to locate the dictionary (right now,
+ * it looks for it in /com/ibm/text/resources in each directory in the classpath,
+ * and won't find it in JAR files, but this location is likely to change). The
+ * dictionary file is in a serialized binary format. We have a very primitive (and
+ * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
+ * currently making it public. Contact us for help.
+ */
+public class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
+
+ /**
+ * a list of known words that is used to divide up contiguous ranges of letters,
+ * stored in a compressed, indexed, format that offers fast access
+ */
+ private BreakDictionary dictionary;
+
+ /**
+ * a list of flags indicating which character categories are contained in
+ * the dictionary file (this is used to determine which ranges of characters
+ * to apply the dictionary to)
+ */
+ private boolean[] categoryFlags;
+
+ /**
+ * a temporary hiding place for the number of dictionary characters in the
+ * last range passed over by next()
+ */
+ private int dictionaryCharCount;
+
+ /**
+ * when a range of characters is divided up using the dictionary, the break
+ * positions that are discovered are stored here, preventing us from having
+ * to use either the dictionary or the state table again until the iterator
+ * leaves this range of text
+ */
+ private int[] cachedBreakPositions;
+
+ /**
+ * if cachedBreakPositions is not null, this indicates which item in the
+ * cache the current iteration position refers to
+ */
+ private int positionInCache;
+
+ /**
+ * Constructs a DictionaryBasedBreakIterator.
+ *
+ * @param ruleFile the name of the rule data file
+ * @param ruleData the rule data loaded from the rule data file
+ * @param dictionaryFile the name of the dictionary file
+ * @param dictionartData the dictionary data loaded from the dictionary file
+ * @throws MissingResourceException if rule data or dictionary initialization failed
+ */
+ public DictionaryBasedBreakIterator(String ruleFile, byte[] ruleData,
+ String dictionaryFile, byte[] dictionaryData) {
+ super(ruleFile, ruleData);
+ byte[] tmp = super.getAdditionalData();
+ if (tmp != null) {
+ prepareCategoryFlags(tmp);
+ super.setAdditionalData(null);
+ }
+ dictionary = new BreakDictionary(dictionaryFile, dictionaryData);
+ }
+
+ private void prepareCategoryFlags(byte[] data) {
+ categoryFlags = new boolean[data.length];
+ for (int i = 0; i < data.length; i++) {
+ categoryFlags[i] = (data[i] == (byte)1) ? true : false;
+ }
+ }
+
+ @Override
+ public void setText(CharacterIterator newText) {
+ super.setText(newText);
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ }
+
+ /**
+ * Sets the current iteration position to the beginning of the text.
+ * (i.e., the CharacterIterator's starting offset).
+ * @return The offset of the beginning of the text.
+ */
+ @Override
+ public int first() {
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ return super.first();
+ }
+
+ /**
+ * Sets the current iteration position to the end of the text.
+ * (i.e., the CharacterIterator's ending offset).
+ * @return The text's past-the-end offset.
+ */
+ @Override
+ public int last() {
+ cachedBreakPositions = null;
+ dictionaryCharCount = 0;
+ positionInCache = 0;
+ return super.last();
+ }
+
+ /**
+ * Advances the iterator one step backwards.
+ * @return The position of the last boundary position before the
+ * current iteration position
+ */
+ @Override
+ public int previous() {
+ CharacterIterator text = getText();
+
+ // if we have cached break positions and we're still in the range
+ // covered by them, just move one step backward in the cache
+ if (cachedBreakPositions != null && positionInCache > 0) {
+ --positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return cachedBreakPositions[positionInCache];
+ }
+
+ // otherwise, dump the cache and use the inherited previous() method to move
+ // backward. This may fill up the cache with new break positions, in which
+ // case we have to mark our position in the cache
+ else {
+ cachedBreakPositions = null;
+ int result = super.previous();
+ if (cachedBreakPositions != null) {
+ positionInCache = cachedBreakPositions.length - 2;
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Sets the current iteration position to the last boundary position
+ * before the specified position.
+ * @param offset The position to begin searching from
+ * @return The position of the last boundary before "offset"
+ */
+ @Override
+ public int preceding(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // if we have no cached break positions, or "offset" is outside the
+ // range covered by the cache, we can just call the inherited routine
+ // (which will eventually call other routines in this class that may
+ // refresh the cache)
+ if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
+ offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
+ cachedBreakPositions = null;
+ return super.preceding(offset);
+ }
+
+ // on the other hand, if "offset" is within the range covered by the cache,
+ // then all we have to do is search the cache for the last break position
+ // before "offset"
+ else {
+ positionInCache = 0;
+ while (positionInCache < cachedBreakPositions.length
+ && offset > cachedBreakPositions[positionInCache]) {
+ ++positionInCache;
+ }
+ --positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return text.getIndex();
+ }
+ }
+
+ /**
+ * Sets the current iteration position to the first boundary position after
+ * the specified position.
+ * @param offset The position to begin searching forward from
+ * @return The position of the first boundary after "offset"
+ */
+ @Override
+ public int following(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // if we have no cached break positions, or if "offset" is outside the
+ // range covered by the cache, then dump the cache and call our
+ // inherited following() method. This will call other methods in this
+ // class that may refresh the cache.
+ if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
+ offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
+ cachedBreakPositions = null;
+ return super.following(offset);
+ }
+
+ // on the other hand, if "offset" is within the range covered by the
+ // cache, then just search the cache for the first break position
+ // after "offset"
+ else {
+ positionInCache = 0;
+ while (positionInCache < cachedBreakPositions.length
+ && offset >= cachedBreakPositions[positionInCache]) {
+ ++positionInCache;
+ }
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return text.getIndex();
+ }
+ }
+
+ /**
+ * This is the implementation function for next().
+ */
+ @Override
+ protected int handleNext() {
+ CharacterIterator text = getText();
+
+ // if there are no cached break positions, or if we've just moved
+ // off the end of the range covered by the cache, we have to dump
+ // and possibly regenerate the cache
+ if (cachedBreakPositions == null ||
+ positionInCache == cachedBreakPositions.length - 1) {
+
+ // start by using the inherited handleNext() to find a tentative return
+ // value. dictionaryCharCount tells us how many dictionary characters
+ // we passed over on our way to the tentative return value
+ int startPos = text.getIndex();
+ dictionaryCharCount = 0;
+ int result = super.handleNext();
+
+ // if we passed over more than one dictionary character, then we use
+ // divideUpDictionaryRange() to regenerate the cached break positions
+ // for the new range
+ if (dictionaryCharCount > 1 && result - startPos > 1) {
+ divideUpDictionaryRange(startPos, result);
+ }
+
+ // otherwise, the value we got back from the inherited fuction
+ // is our return value, and we can dump the cache
+ else {
+ cachedBreakPositions = null;
+ return result;
+ }
+ }
+
+ // if the cache of break positions has been regenerated (or existed all
+ // along), then just advance to the next break position in the cache
+ // and return it
+ if (cachedBreakPositions != null) {
+ ++positionInCache;
+ text.setIndex(cachedBreakPositions[positionInCache]);
+ return cachedBreakPositions[positionInCache];
+ }
+ return -9999; // SHOULD NEVER GET HERE!
+ }
+
+ /**
+ * Looks up a character category for a character.
+ */
+ @Override
+ protected int lookupCategory(int c) {
+ // this override of lookupCategory() exists only to keep track of whether we've
+ // passed over any dictionary characters. It calls the inherited lookupCategory()
+ // to do the real work, and then checks whether its return value is one of the
+ // categories represented in the dictionary. If it is, bump the dictionary-
+ // character count.
+ int result = super.lookupCategory(c);
+ if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
+ ++dictionaryCharCount;
+ }
+ return result;
+ }
+
+ /**
+ * This is the function that actually implements the dictionary-based
+ * algorithm. Given the endpoints of a range of text, it uses the
+ * dictionary to determine the positions of any boundaries in this
+ * range. It stores all the boundary positions it discovers in
+ * cachedBreakPositions so that we only have to do this work once
+ * for each time we enter the range.
+ */
+ @SuppressWarnings("unchecked")
+ private void divideUpDictionaryRange(int startPos, int endPos) {
+ CharacterIterator text = getText();
+
+ // the range we're dividing may begin or end with non-dictionary characters
+ // (i.e., for line breaking, we may have leading or trailing punctuation
+ // that needs to be kept with the word). Seek from the beginning of the
+ // range to the first dictionary character
+ text.setIndex(startPos);
+ int c = getCurrent();
+ int category = lookupCategory(c);
+ while (category == IGNORE || !categoryFlags[category]) {
+ c = getNext();
+ category = lookupCategory(c);
+ }
+
+ // initialize. We maintain two stacks: currentBreakPositions contains
+ // the list of break positions that will be returned if we successfully
+ // finish traversing the whole range now. possibleBreakPositions lists
+ // all other possible word ends we've passed along the way. (Whenever
+ // we reach an error [a sequence of characters that can't begin any word
+ // in the dictionary], we back up, possibly delete some breaks from
+ // currentBreakPositions, move a break from possibleBreakPositions
+ // to currentBreakPositions, and start over from there. This process
+ // continues in this way until we either successfully make it all the way
+ // across the range, or exhaust all of our combinations of break
+ // positions.)
+ Stack<Integer> currentBreakPositions = new Stack<>();
+ Stack<Integer> possibleBreakPositions = new Stack<>();
+ List<Integer> wrongBreakPositions = new ArrayList<>();
+
+ // the dictionary is implemented as a trie, which is treated as a state
+ // machine. -1 represents the end of a legal word. Every word in the
+ // dictionary is represented by a path from the root node to -1. A path
+ // that ends in state 0 is an illegal combination of characters.
+ int state = 0;
+
+ // these two variables are used for error handling. We keep track of the
+ // farthest we've gotten through the range being divided, and the combination
+ // of breaks that got us that far. If we use up all possible break
+ // combinations, the text contains an error or a word that's not in the
+ // dictionary. In this case, we "bless" the break positions that got us the
+ // farthest as real break positions, and then start over from scratch with
+ // the character where the error occurred.
+ int farthestEndPoint = text.getIndex();
+ Stack<Integer> bestBreakPositions = null;
+
+ // initialize (we always exit the loop with a break statement)
+ c = getCurrent();
+ while (true) {
+
+ // if we can transition to state "-1" from our current state, we're
+ // on the last character of a legal word. Push that position onto
+ // the possible-break-positions stack
+ if (dictionary.getNextState(state, 0) == -1) {
+ possibleBreakPositions.push(text.getIndex());
+ }
+
+ // look up the new state to transition to in the dictionary
+ state = dictionary.getNextStateFromCharacter(state, c);
+
+ // if the character we're sitting on causes us to transition to
+ // the "end of word" state, then it was a non-dictionary character
+ // and we've successfully traversed the whole range. Drop out
+ // of the loop.
+ if (state == -1) {
+ currentBreakPositions.push(text.getIndex());
+ break;
+ }
+
+ // if the character we're sitting on causes us to transition to
+ // the error state, or if we've gone off the end of the range
+ // without transitioning to the "end of word" state, we've hit
+ // an error...
+ else if (state == 0 || text.getIndex() >= endPos) {
+
+ // if this is the farthest we've gotten, take note of it in
+ // case there's an error in the text
+ if (text.getIndex() > farthestEndPoint) {
+ farthestEndPoint = text.getIndex();
+
+ @SuppressWarnings("unchecked")
+ Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
+
+ bestBreakPositions = currentBreakPositionsCopy;
+ }
+
+ // wrongBreakPositions is a list of all break positions
+ // we've tried starting that didn't allow us to traverse
+ // all the way through the text. Every time we pop a
+ // break position off of currentBreakPositions, we put it
+ // into wrongBreakPositions to avoid trying it again later.
+ // If we make it to this spot, we're either going to back
+ // up to a break in possibleBreakPositions and try starting
+ // over from there, or we've exhausted all possible break
+ // positions and are going to do the fallback procedure.
+ // This loop prevents us from messing with anything in
+ // possibleBreakPositions that didn't work as a starting
+ // point the last time we tried it (this is to prevent a bunch of
+ // repetitive checks from slowing down some extreme cases)
+ while (!possibleBreakPositions.isEmpty()
+ && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
+ possibleBreakPositions.pop();
+ }
+
+ // if we've used up all possible break-position combinations, there's
+ // an error or an unknown word in the text. In this case, we start
+ // over, treating the farthest character we've reached as the beginning
+ // of the range, and "blessing" the break positions that got us that
+ // far as real break positions
+ if (possibleBreakPositions.isEmpty()) {
+ if (bestBreakPositions != null) {
+ currentBreakPositions = bestBreakPositions;
+ if (farthestEndPoint < endPos) {
+ text.setIndex(farthestEndPoint + 1);
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ if ((currentBreakPositions.size() == 0 ||
+ currentBreakPositions.peek().intValue() != text.getIndex())
+ && text.getIndex() != startPos) {
+ currentBreakPositions.push(text.getIndex());
+ }
+ getNext();
+ currentBreakPositions.push(text.getIndex());
+ }
+ }
+
+ // if we still have more break positions we can try, then promote the
+ // last break in possibleBreakPositions into currentBreakPositions,
+ // and get rid of all entries in currentBreakPositions that come after
+ // it. Then back up to that position and start over from there (i.e.,
+ // treat that position as the beginning of a new word)
+ else {
+ Integer temp = possibleBreakPositions.pop();
+ Integer temp2 = null;
+ while (!currentBreakPositions.isEmpty() && temp.intValue() <
+ currentBreakPositions.peek().intValue()) {
+ temp2 = currentBreakPositions.pop();
+ wrongBreakPositions.add(temp2);
+ }
+ currentBreakPositions.push(temp);
+ text.setIndex(currentBreakPositions.peek().intValue());
+ }
+
+ // re-sync "c" for the next go-round, and drop out of the loop if
+ // we've made it off the end of the range
+ c = getCurrent();
+ if (text.getIndex() >= endPos) {
+ break;
+ }
+ }
+
+ // if we didn't hit any exceptional conditions on this last iteration,
+ // just advance to the next character and loop
+ else {
+ c = getNext();
+ }
+ }
+
+ // dump the last break position in the list, and replace it with the actual
+ // end of the range (which may be the same character, or may be further on
+ // because the range actually ended with non-dictionary characters we want to
+ // keep with the word)
+ if (!currentBreakPositions.isEmpty()) {
+ currentBreakPositions.pop();
+ }
+ currentBreakPositions.push(endPos);
+
+ // create a regular array to hold the break positions and copy
+ // the break positions from the stack to the array (in addition,
+ // our starting position goes into this array as a break position).
+ // This array becomes the cache of break positions used by next()
+ // and previous(), so this is where we actually refresh the cache.
+ cachedBreakPositions = new int[currentBreakPositions.size() + 1];
+ cachedBreakPositions[0] = startPos;
+
+ for (int i = 0; i < currentBreakPositions.size(); i++) {
+ cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
+ }
+ positionInCache = 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,1144 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ */
+
+package sun.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
+ *
+ * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
+ * and <i>regular expressions.</i></p>
+ *
+ * <p>A substitution rule defines a name that can be used in place of an expression. It
+ * consists of a name, which is a string of characters contained in angle brackets, an equals
+ * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
+ * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
+ * square brackets. A substitution is visible after its definition, and is filled in using
+ * simple textual substitution. Substitution definitions can contain other substitutions, as
+ * long as those substitutions have been defined first. Substitutions are generally used to
+ * make the regular expressions (which can get quite complex) shorted and easier to read.
+ * They typically define either character categories or commonly-used subexpressions.</p>
+ *
+ * <p>There is one special substitution. If the description defines a substitution
+ * called "<ignore>", the expression must be a [] expression, and the
+ * expression defines a set of characters (the "<em>ignore characters</em>") that
+ * will be transparent to the BreakIterator. A sequence of characters will break the
+ * same way it would if any ignore characters it contains are taken out. Break
+ * positions never occur befoer ignore characters.</p>
+ *
+ * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
+ * defines a sequence of characters to be kept together. With one significant exception, the
+ * iterator uses a longest-possible-match algorithm when matching text to regular
+ * expressions. The iterator also treats descriptions containing multiple regular expressions
+ * as if they were ORed together (i.e., as if they were separated by |).</p>
+ *
+ * <p>The special characters recognized by the regular-expression parser are as follows:</p>
+ *
+ * <blockquote>
+ * <table border="1" width="100%">
+ * <tr>
+ * <td width="6%">*</td>
+ * <td width="94%">Specifies that the expression preceding the asterisk may occur any number
+ * of times (including not at all).</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">{}</td>
+ * <td width="94%">Encloses a sequence of characters that is optional.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">()</td>
+ * <td width="94%">Encloses a sequence of characters. If followed by *, the sequence
+ * repeats. Otherwise, the parentheses are just a grouping device and a way to delimit
+ * the ends of expressions containing |.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">|</td>
+ * <td width="94%">Separates two alternative sequences of characters. Either one
+ * sequence or the other, but not both, matches this expression. The | character can
+ * only occur inside ().</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">.</td>
+ * <td width="94%">Matches any character.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">*?</td>
+ * <td width="94%">Specifies a non-greedy asterisk. *? works the same way as *, except
+ * when there is overlap between the last group of characters in the expression preceding the
+ * * and the first group of characters following the *. When there is this kind of
+ * overlap, * will match the longest sequence of characters that match the expression before
+ * the *, and *? will match the shortest sequence of characters matching the expression
+ * before the *?. For example, if you have "xxyxyyyxyxyxxyxyxyy" in the text,
+ * "x[xy]*x" will match through to the last x (i.e., "<strong>xxyxyyyxyxyxxyxyx</strong>yy",
+ * but "x[xy]*?x" will only match the first two xes ("<strong>xx</strong>yxyyyxyxyxxyxyxyy").</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">[]</td>
+ * <td width="94%">Specifies a group of alternative characters. A [] expression will
+ * match any single character that is specified in the [] expression. For more on the
+ * syntax of [] expressions, see below.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">/</td>
+ * <td width="94%">Specifies where the break position should go if text matches this
+ * expression. (e.g., "[a-z]*/[:Zs:]*[1-0]" will match if the iterator sees a run
+ * of letters, followed by a run of whitespace, followed by a digit, but the break position
+ * will actually go before the whitespace). Expressions that don't contain / put the
+ * break position at the end of the matching text.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">\</td>
+ * <td width="94%">Escape character. The \ itself is ignored, but causes the next
+ * character to be treated as literal character. This has no effect for many
+ * characters, but for the characters listed above, this deprives them of their special
+ * meaning. (There are no special escape sequences for Unicode characters, or tabs and
+ * newlines; these are all handled by a higher-level protocol. In a Java string,
+ * "\n" will be converted to a literal newline character by the time the
+ * regular-expression parser sees it. Of course, this means that \ sequences that are
+ * visible to the regexp parser must be written as \\ when inside a Java string.) All
+ * characters in the ASCII range except for letters, digits, and control characters are
+ * reserved characters to the parser and must be preceded by \ even if they currently don't
+ * mean anything.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">!</td>
+ * <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
+ * parser that this expression specifies the backwards-iteration behavior of the iterator,
+ * and not its normal iteration behavior. This is generally only used in situations
+ * where the automatically-generated backwards-iteration brhavior doesn't produce
+ * satisfactory results and must be supplemented with extra client-specified rules.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%"><em>(all others)</em></td>
+ * <td width="94%">All other characters are treated as literal characters, which must match
+ * the corresponding character(s) in the text exactly.</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * <p>Within a [] expression, a number of other special characters can be used to specify
+ * groups of characters:</p>
+ *
+ * <blockquote>
+ * <table border="1" width="100%">
+ * <tr>
+ * <td width="6%">-</td>
+ * <td width="94%">Specifies a range of matching characters. For example
+ * "[a-p]" matches all lowercase Latin letters from a to p (inclusive). The -
+ * sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
+ * language's alphabetical order: "[a-z]" doesn't include capital letters, nor does
+ * it include accented letters such as a-umlaut.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">::</td>
+ * <td width="94%">A pair of colons containing a one- or two-letter code matches all
+ * characters in the corresponding Unicode category. The two-letter codes are the same
+ * as the two-letter codes in the Unicode database (for example, "[:Sc::Sm:]"
+ * matches all currency symbols and all math symbols). Specifying a one-letter code is
+ * the same as specifying all two-letter codes that begin with that letter (for example,
+ * "[:L:]" matches all letters, and is equivalent to
+ * "[:Lu::Ll::Lo::Lm::Lt:]"). Anything other than a valid two-letter Unicode
+ * category code or a single letter that begins a Unicode category code is illegal within
+ * colons.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">[]</td>
+ * <td width="94%">[] expressions can nest. This has no effect, except when used in
+ * conjunction with the ^ token.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%">^</td>
+ * <td width="94%">Excludes the character (or the characters in the [] expression) following
+ * it from the group of characters. For example, "[a-z^p]" matches all Latin
+ * lowercase letters except p. "[:L:^[\u4e00-\u9fff]]" matches all letters
+ * except the Han ideographs.</td>
+ * </tr>
+ * <tr>
+ * <td width="6%"><em>(all others)</em></td>
+ * <td width="94%">All other characters are treated as literal characters. (For
+ * example, "[aeiou]" specifies just the letters a, e, i, o, and u.)</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * <p>For a more complete explanation, see <a
+ * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
+ * For examples, see the resource data (which is annotated).</p>
+ *
+ * @author Richard Gillam
+ */
+public class RuleBasedBreakIterator extends BreakIterator {
+
+ /**
+ * A token used as a character-category value to identify ignore characters
+ */
+ protected static final byte IGNORE = -1;
+
+ /**
+ * The state number of the starting state
+ */
+ private static final short START_STATE = 1;
+
+ /**
+ * The state-transition value indicating "stop"
+ */
+ private static final short STOP_STATE = 0;
+
+ /**
+ * Magic number for the BreakIterator data file format.
+ */
+ static final byte[] LABEL = {
+ (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
+ (byte)'\0'
+ };
+ static final int LABEL_LENGTH = LABEL.length;
+
+ /**
+ * Version number of the dictionary that was read in.
+ */
+ static final byte supportedVersion = 1;
+
+ /**
+ * An array length of indices for BMP characters
+ */
+ private static final int BMP_INDICES_LENGTH = 512;
+
+ /**
+ * Tables that indexes from character values to character category numbers
+ */
+ private CompactByteArray charCategoryTable = null;
+ private SupplementaryCharacterData supplementaryCharCategoryTable = null;
+
+ /**
+ * The table of state transitions used for forward iteration
+ */
+ private short[] stateTable = null;
+
+ /**
+ * The table of state transitions used to sync up the iterator with the
+ * text in backwards and random-access iteration
+ */
+ private short[] backwardsStateTable = null;
+
+ /**
+ * A list of flags indicating which states in the state table are accepting
+ * ("end") states
+ */
+ private boolean[] endStates = null;
+
+ /**
+ * A list of flags indicating which states in the state table are
+ * lookahead states (states which turn lookahead on and off)
+ */
+ private boolean[] lookaheadStates = null;
+
+ /**
+ * A table for additional data. May be used by a subclass of
+ * RuleBasedBreakIterator.
+ */
+ private byte[] additionalData = null;
+
+ /**
+ * The number of character categories (and, thus, the number of columns in
+ * the state tables)
+ */
+ private int numCategories;
+
+ /**
+ * The character iterator through which this BreakIterator accesses the text
+ */
+ private CharacterIterator text = null;
+
+ /**
+ * A CRC32 value of all data in datafile
+ */
+ private long checksum;
+
+ //=======================================================================
+ // constructors
+ //=======================================================================
+
+ /**
+ * Constructs a RuleBasedBreakIterator using the given rule data.
+ *
+ * @throws MissingResourceException if the rule data is invalid or corrupted
+ */
+ public RuleBasedBreakIterator(String ruleFile, byte[] ruleData) {
+ ByteBuffer bb = ByteBuffer.wrap(ruleData);
+ try {
+ validateRuleData(ruleFile, bb);
+ setupTables(ruleFile, bb);
+ } catch (BufferUnderflowException bue) {
+ MissingResourceException e;
+ e = new MissingResourceException("Corrupted rule data file", ruleFile, "");
+ e.initCause(bue);
+ throw e;
+ }
+ }
+
+ /**
+ * Initializes the fields with the given rule data.
+ * The data format is as follows:
+ * <pre>
+ * BreakIteratorData {
+ * u1 magic[7];
+ * u1 version;
+ * u4 totalDataSize;
+ * header_info header;
+ * body value;
+ * }
+ * </pre>
+ * <code>totalDataSize</code> is the summation of the size of
+ * <code>header_info</code> and <code>body</code> in byte count.
+ * <p>
+ * In <code>header</code>, each field except for checksum implies the
+ * length of each field. Since <code>BMPdataLength</code> is a fixed-length
+ * data(512 entries), its length isn't included in <code>header</code>.
+ * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
+ * <pre>
+ * header_info {
+ * u4 stateTableLength;
+ * u4 backwardsStateTableLength;
+ * u4 endStatesLength;
+ * u4 lookaheadStatesLength;
+ * u4 BMPdataLength;
+ * u4 nonBMPdataLength;
+ * u4 additionalDataLength;
+ * u8 checksum;
+ * }
+ * </pre>
+ * <p>
+ *
+ * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
+ * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
+ * <code>supplementaryCharCategoryTable</code>.
+ * <pre>
+ * body {
+ * u2 stateTable[stateTableLength];
+ * u2 backwardsStateTable[backwardsStateTableLength];
+ * u1 endStates[endStatesLength];
+ * u1 lookaheadStates[lookaheadStatesLength];
+ * u2 BMPindices[512];
+ * u1 BMPdata[BMPdataLength];
+ * u4 nonBMPdata[numNonBMPdataLength];
+ * u1 additionalData[additionalDataLength];
+ * }
+ * </pre>
+ *
+ * @throws BufferUnderflowException if the end-of-data is reached before
+ * setting up all the tables
+ */
+ private void setupTables(String ruleFile, ByteBuffer bb) {
+ /* Read header_info. */
+ int stateTableLength = bb.getInt();
+ int backwardsStateTableLength = bb.getInt();
+ int endStatesLength = bb.getInt();
+ int lookaheadStatesLength = bb.getInt();
+ int BMPdataLength = bb.getInt();
+ int nonBMPdataLength = bb.getInt();
+ int additionalDataLength = bb.getInt();
+ checksum = bb.getLong();
+
+ /* Read stateTable[numCategories * numRows] */
+ stateTable = new short[stateTableLength];
+ for (int i = 0; i < stateTableLength; i++) {
+ stateTable[i] = bb.getShort();
+ }
+
+ /* Read backwardsStateTable[numCategories * numRows] */
+ backwardsStateTable = new short[backwardsStateTableLength];
+ for (int i = 0; i < backwardsStateTableLength; i++) {
+ backwardsStateTable[i] = bb.getShort();
+ }
+
+ /* Read endStates[numRows] */
+ endStates = new boolean[endStatesLength];
+ for (int i = 0; i < endStatesLength; i++) {
+ endStates[i] = bb.get() == 1;
+ }
+
+ /* Read lookaheadStates[numRows] */
+ lookaheadStates = new boolean[lookaheadStatesLength];
+ for (int i = 0; i < lookaheadStatesLength; i++) {
+ lookaheadStates[i] = bb.get() == 1;
+ }
+
+ /* Read a category table and indices for BMP characters. */
+ short[] temp1 = new short[BMP_INDICES_LENGTH]; // BMPindices
+ for (int i = 0; i < BMP_INDICES_LENGTH; i++) {
+ temp1[i] = bb.getShort();
+ }
+ byte[] temp2 = new byte[BMPdataLength]; // BMPdata
+ bb.get(temp2);
+ charCategoryTable = new CompactByteArray(temp1, temp2);
+
+ /* Read a category table for non-BMP characters. */
+ int[] temp3 = new int[nonBMPdataLength];
+ for (int i = 0; i < nonBMPdataLength; i++) {
+ temp3[i] = bb.getInt();
+ }
+ supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
+
+ /* Read additional data */
+ if (additionalDataLength > 0) {
+ additionalData = new byte[additionalDataLength];
+ bb.get(additionalData);
+ }
+ assert bb.position() == bb.limit();
+
+ /* Set numCategories */
+ numCategories = stateTable.length / endStates.length;
+ }
+
+ /**
+ * Validates the magic number, version, and the length of the given data.
+ *
+ * @throws BufferUnderflowException if the end-of-data is reached while
+ * validating data
+ * @throws MissingResourceException if valification failed
+ */
+ void validateRuleData(String ruleFile, ByteBuffer bb) {
+ /* Verify the magic number. */
+ for (int i = 0; i < LABEL_LENGTH; i++) {
+ if (bb.get() != LABEL[i]) {
+ throw new MissingResourceException("Wrong magic number",
+ ruleFile, "");
+ }
+ }
+
+ /* Verify the version number. */
+ byte version = bb.get();
+ if (version != supportedVersion) {
+ throw new MissingResourceException("Unsupported version(" + version + ")",
+ ruleFile, "");
+ }
+
+ // Check the length of the rest of data
+ int len = bb.getInt();
+ if (bb.position() + len != bb.limit()) {
+ throw new MissingResourceException("Wrong data length",
+ ruleFile, "");
+ }
+ }
+
+ byte[] getAdditionalData() {
+ return additionalData;
+ }
+
+ void setAdditionalData(byte[] b) {
+ additionalData = b;
+ }
+
+ //=======================================================================
+ // boilerplate
+ //=======================================================================
+ /**
+ * Clones this iterator.
+ * @return A newly-constructed RuleBasedBreakIterator with the same
+ * behavior as this one.
+ */
+ @Override
+ public Object clone() {
+ RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
+ if (text != null) {
+ result.text = (CharacterIterator) text.clone();
+ }
+ return result;
+ }
+
+ /**
+ * Returns true if both BreakIterators are of the same class, have the same
+ * rules, and iterate over the same text.
+ */
+ @Override
+ public boolean equals(Object that) {
+ try {
+ if (that == null) {
+ return false;
+ }
+
+ RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
+ if (checksum != other.checksum) {
+ return false;
+ }
+ if (text == null) {
+ return other.text == null;
+ } else {
+ return text.equals(other.text);
+ }
+ }
+ catch(ClassCastException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns text
+ */
+ @Override
+ public String toString() {
+ return "[checksum=0x" + Long.toHexString(checksum) + ']';
+ }
+
+ /**
+ * Compute a hashcode for this BreakIterator
+ * @return A hash code
+ */
+ @Override
+ public int hashCode() {
+ return (int)checksum;
+ }
+
+ //=======================================================================
+ // BreakIterator overrides
+ //=======================================================================
+
+ /**
+ * Sets the current iteration position to the beginning of the text.
+ * (i.e., the CharacterIterator's starting offset).
+ * @return The offset of the beginning of the text.
+ */
+ @Override
+ public int first() {
+ CharacterIterator t = getText();
+
+ t.first();
+ return t.getIndex();
+ }
+
+ /**
+ * Sets the current iteration position to the end of the text.
+ * (i.e., the CharacterIterator's ending offset).
+ * @return The text's past-the-end offset.
+ */
+ @Override
+ public int last() {
+ CharacterIterator t = getText();
+
+ // I'm not sure why, but t.last() returns the offset of the last character,
+ // rather than the past-the-end offset
+ t.setIndex(t.getEndIndex());
+ return t.getIndex();
+ }
+
+ /**
+ * Advances the iterator either forward or backward the specified number of steps.
+ * Negative values move backward, and positive values move forward. This is
+ * equivalent to repeatedly calling next() or previous().
+ * @param n The number of steps to move. The sign indicates the direction
+ * (negative is backwards, and positive is forwards).
+ * @return The character offset of the boundary position n boundaries away from
+ * the current one.
+ */
+ @Override
+ public int next(int n) {
+ int result = current();
+ while (n > 0) {
+ result = handleNext();
+ --n;
+ }
+ while (n < 0) {
+ result = previous();
+ ++n;
+ }
+ return result;
+ }
+
+ /**
+ * Advances the iterator to the next boundary position.
+ * @return The position of the first boundary after this one.
+ */
+ @Override
+ public int next() {
+ return handleNext();
+ }
+
+ private int cachedLastKnownBreak = BreakIterator.DONE;
+
+ /**
+ * Advances the iterator backwards, to the last boundary preceding this one.
+ * @return The position of the last boundary position preceding this one.
+ */
+ @Override
+ public int previous() {
+ // if we're already sitting at the beginning of the text, return DONE
+ CharacterIterator text = getText();
+ if (current() == text.getBeginIndex()) {
+ return BreakIterator.DONE;
+ }
+
+ // set things up. handlePrevious() will back us up to some valid
+ // break position before the current position (we back our internal
+ // iterator up one step to prevent handlePrevious() from returning
+ // the current position), but not necessarily the last one before
+ // where we started
+ int start = current();
+ int lastResult = cachedLastKnownBreak;
+ if (lastResult >= start || lastResult <= BreakIterator.DONE) {
+ getPrevious();
+ lastResult = handlePrevious();
+ } else {
+ //it might be better to check if handlePrevious() give us closer
+ //safe value but handlePrevious() is slow too
+ //So, this has to be done carefully
+ text.setIndex(lastResult);
+ }
+ int result = lastResult;
+
+ // iterate forward from the known break position until we pass our
+ // starting point. The last break position before the starting
+ // point is our return value
+ while (result != BreakIterator.DONE && result < start) {
+ lastResult = result;
+ result = handleNext();
+ }
+
+ // set the current iteration position to be the last break position
+ // before where we started, and then return that value
+ text.setIndex(lastResult);
+ cachedLastKnownBreak = lastResult;
+ return lastResult;
+ }
+
+ /**
+ * Returns previous character
+ */
+ private int getPrevious() {
+ char c2 = text.previous();
+ if (Character.isLowSurrogate(c2) &&
+ text.getIndex() > text.getBeginIndex()) {
+ char c1 = text.previous();
+ if (Character.isHighSurrogate(c1)) {
+ return Character.toCodePoint(c1, c2);
+ } else {
+ text.next();
+ }
+ }
+ return (int)c2;
+ }
+
+ /**
+ * Returns current character
+ */
+ int getCurrent() {
+ char c1 = text.current();
+ if (Character.isHighSurrogate(c1) &&
+ text.getIndex() < text.getEndIndex()) {
+ char c2 = text.next();
+ text.previous();
+ if (Character.isLowSurrogate(c2)) {
+ return Character.toCodePoint(c1, c2);
+ }
+ }
+ return (int)c1;
+ }
+
+ /**
+ * Returns the count of next character.
+ */
+ private int getCurrentCodePointCount() {
+ char c1 = text.current();
+ if (Character.isHighSurrogate(c1) &&
+ text.getIndex() < text.getEndIndex()) {
+ char c2 = text.next();
+ text.previous();
+ if (Character.isLowSurrogate(c2)) {
+ return 2;
+ }
+ }
+ return 1;
+ }
+
+ /**
+ * Returns next character
+ */
+ int getNext() {
+ int index = text.getIndex();
+ int endIndex = text.getEndIndex();
+ if (index == endIndex ||
+ (index += getCurrentCodePointCount()) >= endIndex) {
+ return CharacterIterator.DONE;
+ }
+ text.setIndex(index);
+ return getCurrent();
+ }
+
+ /**
+ * Returns the position of next character.
+ */
+ private int getNextIndex() {
+ int index = text.getIndex() + getCurrentCodePointCount();
+ int endIndex = text.getEndIndex();
+ if (index > endIndex) {
+ return endIndex;
+ } else {
+ return index;
+ }
+ }
+
+ /**
+ * Throw IllegalArgumentException unless begin <= offset < end.
+ */
+ protected static final void checkOffset(int offset, CharacterIterator text) {
+ if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
+ throw new IllegalArgumentException("offset out of bounds");
+ }
+ }
+
+ /**
+ * Sets the iterator to refer to the first boundary position following
+ * the specified position.
+ * @offset The position from which to begin searching for a break position.
+ * @return The position of the first break after the current position.
+ */
+ @Override
+ public int following(int offset) {
+
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+
+ // Set our internal iteration position (temporarily)
+ // to the position passed in. If this is the _beginning_ position,
+ // then we can just use next() to get our return value
+ text.setIndex(offset);
+ if (offset == text.getBeginIndex()) {
+ cachedLastKnownBreak = handleNext();
+ return cachedLastKnownBreak;
+ }
+
+ // otherwise, we have to sync up first. Use handlePrevious() to back
+ // us up to a known break position before the specified position (if
+ // we can determine that the specified position is a break position,
+ // we don't back up at all). This may or may not be the last break
+ // position at or before our starting position. Advance forward
+ // from here until we've passed the starting position. The position
+ // we stop on will be the first break position after the specified one.
+ int result = cachedLastKnownBreak;
+ if (result >= offset || result <= BreakIterator.DONE) {
+ result = handlePrevious();
+ } else {
+ //it might be better to check if handlePrevious() give us closer
+ //safe value but handlePrevious() is slow too
+ //So, this has to be done carefully
+ text.setIndex(result);
+ }
+ while (result != BreakIterator.DONE && result <= offset) {
+ result = handleNext();
+ }
+ cachedLastKnownBreak = result;
+ return result;
+ }
+
+ /**
+ * Sets the iterator to refer to the last boundary position before the
+ * specified position.
+ * @offset The position to begin searching for a break from.
+ * @return The position of the last boundary before the starting position.
+ */
+ @Override
+ public int preceding(int offset) {
+ // if we start by updating the current iteration position to the
+ // position specified by the caller, we can just use previous()
+ // to carry out this operation
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+ text.setIndex(offset);
+ return previous();
+ }
+
+ /**
+ * Returns true if the specified position is a boundary position. As a side
+ * effect, leaves the iterator pointing to the first boundary position at
+ * or after "offset".
+ * @param offset the offset to check.
+ * @return True if "offset" is a boundary position.
+ */
+ @Override
+ public boolean isBoundary(int offset) {
+ CharacterIterator text = getText();
+ checkOffset(offset, text);
+ if (offset == text.getBeginIndex()) {
+ return true;
+ }
+
+ // to check whether this is a boundary, we can use following() on the
+ // position before the specified one and return true if the position we
+ // get back is the one the user specified
+ else {
+ return following(offset - 1) == offset;
+ }
+ }
+
+ /**
+ * Returns the current iteration position.
+ * @return The current iteration position.
+ */
+ @Override
+ public int current() {
+ return getText().getIndex();
+ }
+
+ /**
+ * Return a CharacterIterator over the text being analyzed. This version
+ * of this method returns the actual CharacterIterator we're using internally.
+ * Changing the state of this iterator can have undefined consequences. If
+ * you need to change it, clone it first.
+ * @return An iterator over the text being analyzed.
+ */
+ @Override
+ public CharacterIterator getText() {
+ // The iterator is initialized pointing to no text at all, so if this
+ // function is called while we're in that state, we have to fudge an
+ // iterator to return.
+ if (text == null) {
+ text = new StringCharacterIterator("");
+ }
+ return text;
+ }
+
+ /**
+ * Set the iterator to analyze a new piece of text. This function resets
+ * the current iteration position to the beginning of the text.
+ * @param newText An iterator over the text to analyze.
+ */
+ @Override
+ public void setText(CharacterIterator newText) {
+ // Test iterator to see if we need to wrap it in a SafeCharIterator.
+ // The correct behavior for CharacterIterators is to allow the
+ // position to be set to the endpoint of the iterator. Many
+ // CharacterIterators do not uphold this, so this is a workaround
+ // to permit them to use this class.
+ int end = newText.getEndIndex();
+ boolean goodIterator;
+ try {
+ newText.setIndex(end); // some buggy iterators throw an exception here
+ goodIterator = newText.getIndex() == end;
+ }
+ catch(IllegalArgumentException e) {
+ goodIterator = false;
+ }
+
+ if (goodIterator) {
+ text = newText;
+ }
+ else {
+ text = new SafeCharIterator(newText);
+ }
+ text.first();
+
+ cachedLastKnownBreak = BreakIterator.DONE;
+ }
+
+
+ //=======================================================================
+ // implementation
+ //=======================================================================
+
+ /**
+ * This method is the actual implementation of the next() method. All iteration
+ * vectors through here. This method initializes the state machine to state 1
+ * and advances through the text character by character until we reach the end
+ * of the text or the state machine transitions to state 0. We update our return
+ * value every time the state machine passes through a possible end state.
+ */
+ protected int handleNext() {
+ // if we're already at the end of the text, return DONE.
+ CharacterIterator text = getText();
+ if (text.getIndex() == text.getEndIndex()) {
+ return BreakIterator.DONE;
+ }
+
+ // no matter what, we always advance at least one character forward
+ int result = getNextIndex();
+ int lookaheadResult = 0;
+
+ // begin in state 1
+ int state = START_STATE;
+ int category;
+ int c = getCurrent();
+
+ // loop until we reach the end of the text or transition to state 0
+ while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+ // look up the current character's character category (which tells us
+ // which column in the state table to look at)
+ category = lookupCategory(c);
+
+ // if the character isn't an ignore character, look up a state
+ // transition in the state table
+ if (category != IGNORE) {
+ state = lookupState(state, category);
+ }
+
+ // if the state we've just transitioned to is a lookahead state,
+ // (but not also an end state), save its position. If it's
+ // both a lookahead state and an end state, update the break position
+ // to the last saved lookup-state position
+ if (lookaheadStates[state]) {
+ if (endStates[state]) {
+ result = lookaheadResult;
+ }
+ else {
+ lookaheadResult = getNextIndex();
+ }
+ }
+
+ // otherwise, if the state we've just transitioned to is an accepting
+ // state, update the break position to be the current iteration position
+ else {
+ if (endStates[state]) {
+ result = getNextIndex();
+ }
+ }
+
+ c = getNext();
+ }
+
+ // if we've run off the end of the text, and the very last character took us into
+ // a lookahead state, advance the break position to the lookahead position
+ // (the theory here is that if there are no characters at all after the lookahead
+ // position, that always matches the lookahead criteria)
+ if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
+ result = lookaheadResult;
+ }
+
+ text.setIndex(result);
+ return result;
+ }
+
+ /**
+ * This method backs the iterator back up to a "safe position" in the text.
+ * This is a position that we know, without any context, must be a break position.
+ * The various calling methods then iterate forward from this safe position to
+ * the appropriate position to return. (For more information, see the description
+ * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
+ */
+ protected int handlePrevious() {
+ CharacterIterator text = getText();
+ int state = START_STATE;
+ int category = 0;
+ int lastCategory = 0;
+ int c = getCurrent();
+
+ // loop until we reach the beginning of the text or transition to state 0
+ while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+ // save the last character's category and look up the current
+ // character's category
+ lastCategory = category;
+ category = lookupCategory(c);
+
+ // if the current character isn't an ignore character, look up a
+ // state transition in the backwards state table
+ if (category != IGNORE) {
+ state = lookupBackwardState(state, category);
+ }
+
+ // then advance one character backwards
+ c = getPrevious();
+ }
+
+ // if we didn't march off the beginning of the text, we're either one or two
+ // positions away from the real break position. (One because of the call to
+ // previous() at the end of the loop above, and another because the character
+ // that takes us into the stop state will always be the character BEFORE
+ // the break position.)
+ if (c != CharacterIterator.DONE) {
+ if (lastCategory != IGNORE) {
+ getNext();
+ getNext();
+ }
+ else {
+ getNext();
+ }
+ }
+ return text.getIndex();
+ }
+
+ /**
+ * Looks up a character's category (i.e., its category for breaking purposes,
+ * not its Unicode category)
+ */
+ protected int lookupCategory(int c) {
+ if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ return charCategoryTable.elementAt((char)c);
+ } else {
+ return supplementaryCharCategoryTable.getValue(c);
+ }
+ }
+
+ /**
+ * Given a current state and a character category, looks up the
+ * next state to transition to in the state table.
+ */
+ protected int lookupState(int state, int category) {
+ return stateTable[state * numCategories + category];
+ }
+
+ /**
+ * Given a current state and a character category, looks up the
+ * next state to transition to in the backwards state table.
+ */
+ protected int lookupBackwardState(int state, int category) {
+ return backwardsStateTable[state * numCategories + category];
+ }
+
+ /*
+ * This class exists to work around a bug in incorrect implementations
+ * of CharacterIterator, which incorrectly handle setIndex(endIndex).
+ * This iterator relies only on base.setIndex(n) where n is less than
+ * endIndex.
+ *
+ * One caveat: if the base iterator's begin and end indices change
+ * the change will not be reflected by this wrapper. Does that matter?
+ */
+ // TODO: Review this class to see if it's still required.
+ private static final class SafeCharIterator implements CharacterIterator,
+ Cloneable {
+
+ private CharacterIterator base;
+ private int rangeStart;
+ private int rangeLimit;
+ private int currentIndex;
+
+ SafeCharIterator(CharacterIterator base) {
+ this.base = base;
+ this.rangeStart = base.getBeginIndex();
+ this.rangeLimit = base.getEndIndex();
+ this.currentIndex = base.getIndex();
+ }
+
+ @Override
+ public char first() {
+ return setIndex(rangeStart);
+ }
+
+ @Override
+ public char last() {
+ return setIndex(rangeLimit - 1);
+ }
+
+ @Override
+ public char current() {
+ if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char next() {
+
+ currentIndex++;
+ if (currentIndex >= rangeLimit) {
+ currentIndex = rangeLimit;
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char previous() {
+
+ currentIndex--;
+ if (currentIndex < rangeStart) {
+ currentIndex = rangeStart;
+ return DONE;
+ }
+ else {
+ return base.setIndex(currentIndex);
+ }
+ }
+
+ @Override
+ public char setIndex(int i) {
+
+ if (i < rangeStart || i > rangeLimit) {
+ throw new IllegalArgumentException("Invalid position");
+ }
+ currentIndex = i;
+ return current();
+ }
+
+ @Override
+ public int getBeginIndex() {
+ return rangeStart;
+ }
+
+ @Override
+ public int getEndIndex() {
+ return rangeLimit;
+ }
+
+ @Override
+ public int getIndex() {
+ return currentIndex;
+ }
+
+ @Override
+ public Object clone() {
+
+ SafeCharIterator copy = null;
+ try {
+ copy = (SafeCharIterator) super.clone();
+ }
+ catch(CloneNotSupportedException e) {
+ throw new Error("Clone not supported: " + e);
+ }
+
+ CharacterIterator copyOfBase = (CharacterIterator) base.clone();
+ copy.base = copyOfBase;
+ return copy;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorResources.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources;
+
+import java.util.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources extends BreakIteratorResourceBundle {
+ @Override
+ protected ResourceBundle getBreakIteratorInfo() {
+ return new BreakIteratorInfo();
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-package sun.util.locale.provider;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * This is the class that represents the list of known words used by
- * DictionaryBasedBreakIterator. The conceptual data structure used
- * here is a trie: there is a node hanging off the root node for every
- * letter that can start a word. Each of these nodes has a node hanging
- * off of it for every letter that can be the second letter of a word
- * if this node is the first letter, and so on. The trie is represented
- * as a two-dimensional array that can be treated as a table of state
- * transitions. Indexes are used to compress this array, taking
- * advantage of the fact that this array will always be very sparse.
- */
-class BreakDictionary {
-
- //=========================================================================
- // data members
- //=========================================================================
-
- /**
- * The version of the dictionary that was read in.
- */
- private static int supportedVersion = 1;
-
- /**
- * Maps from characters to column numbers. The main use of this is to
- * avoid making room in the array for empty columns.
- */
- private CompactByteArray columnMap = null;
- private SupplementaryCharacterData supplementaryCharColumnMap = null;
-
- /**
- * The number of actual columns in the table
- */
- private int numCols;
-
- /**
- * Columns are organized into groups of 32. This says how many
- * column groups. (We could calculate this, but we store the
- * value to avoid having to repeatedly calculate it.)
- */
- private int numColGroups;
-
- /**
- * The actual compressed state table. Each conceptual row represents
- * a state, and the cells in it contain the row numbers of the states
- * to transition to for each possible letter. 0 is used to indicate
- * an illegal combination of letters (i.e., the error state). The
- * table is compressed by eliminating all the unpopulated (i.e., zero)
- * cells. Multiple conceptual rows can then be doubled up in a single
- * physical row by sliding them up and possibly shifting them to one
- * side or the other so the populated cells don't collide. Indexes
- * are used to identify unpopulated cells and to locate populated cells.
- */
- private short[] table = null;
-
- /**
- * This index maps logical row numbers to physical row numbers
- */
- private short[] rowIndex = null;
-
- /**
- * A bitmap is used to tell which cells in the comceptual table are
- * populated. This array contains all the unique bit combinations
- * in that bitmap. If the table is more than 32 columns wide,
- * successive entries in this array are used for a single row.
- */
- private int[] rowIndexFlags = null;
-
- /**
- * This index maps from a logical row number into the bitmap table above.
- * (This keeps us from storing duplicate bitmap combinations.) Since there
- * are a lot of rows with only one populated cell, instead of wasting space
- * in the bitmap table, we just store a negative number in this index for
- * rows with one populated cell. The absolute value of that number is
- * the column number of the populated cell.
- */
- private short[] rowIndexFlagsIndex = null;
-
- /**
- * For each logical row, this index contains a constant that is added to
- * the logical column number to get the physical column number
- */
- private byte[] rowIndexShifts = null;
-
- //=========================================================================
- // deserialization
- //=========================================================================
-
- BreakDictionary(Module module, String dictionaryName)
- throws IOException, MissingResourceException {
-
- readDictionaryFile(module, dictionaryName);
- }
-
- private void readDictionaryFile(final Module module, final String dictionaryName)
- throws IOException, MissingResourceException {
-
- BufferedInputStream in;
- try {
- PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
- String pathName = "jdk.localedata".equals(module.getName()) ?
- "sun/text/resources/ext/" :
- "sun/text/resources/";
- InputStream is = module.getResourceAsStream(pathName + dictionaryName);
- if (is == null) {
- // Try to load the file with "java.base" module instance. Assumption
- // here is that the fall back data files to be read should reside in
- // java.base.
- is = BreakDictionary.class.getModule().getResourceAsStream("sun/text/resources/" + dictionaryName);
- }
-
- return new BufferedInputStream(is);
- };
- in = AccessController.doPrivileged(pa);
- }
- catch (PrivilegedActionException e) {
- throw new InternalError(e.toString(), e);
- }
-
- byte[] buf = new byte[8];
- if (in.read(buf) != 8) {
- throw new MissingResourceException("Wrong data length",
- dictionaryName, "");
- }
-
- // check version
- int version = RuleBasedBreakIterator.getInt(buf, 0);
- if (version != supportedVersion) {
- throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
- dictionaryName, "");
- }
-
- // get data size
- int len = RuleBasedBreakIterator.getInt(buf, 4);
- buf = new byte[len];
- if (in.read(buf) != len) {
- throw new MissingResourceException("Wrong data length",
- dictionaryName, "");
- }
-
- // close the stream
- in.close();
-
- int l;
- int offset = 0;
-
- // read in the column map for BMP characteres (this is serialized in
- // its internal form: an index array followed by a data array)
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- short[] temp = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- temp[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- byte[] temp2 = new byte[l];
- for (int i = 0; i < l; i++, offset++) {
- temp2[i] = buf[offset];
- }
- columnMap = new CompactByteArray(temp, temp2);
-
- // read in numCols and numColGroups
- numCols = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- numColGroups = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
-
- // read in the row-number index
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndex = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- rowIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
-
- // load in the populated-cells bitmap: index first, then bitmap list
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexFlagsIndex = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- rowIndexFlagsIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexFlags = new int[l];
- for (int i = 0; i < l; i++, offset+=4) {
- rowIndexFlags[i] = RuleBasedBreakIterator.getInt(buf, offset);
- }
-
- // load in the row-shift index
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- rowIndexShifts = new byte[l];
- for (int i = 0; i < l; i++, offset++) {
- rowIndexShifts[i] = buf[offset];
- }
-
- // load in the actual state table
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- table = new short[l];
- for (int i = 0; i < l; i++, offset+=2) {
- table[i] = RuleBasedBreakIterator.getShort(buf, offset);
- }
-
- // finally, prepare the column map for supplementary characters
- l = RuleBasedBreakIterator.getInt(buf, offset);
- offset += 4;
- int[] temp3 = new int[l];
- for (int i = 0; i < l; i++, offset+=4) {
- temp3[i] = RuleBasedBreakIterator.getInt(buf, offset);
- }
- supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
- }
-
- //=========================================================================
- // access to the words
- //=========================================================================
-
- /**
- * Uses the column map to map the character to a column number, then
- * passes the row and column number to getNextState()
- * @param row The current state
- * @param ch The character whose column we're interested in
- * @return The new state to transition to
- */
- public final short getNextStateFromCharacter(int row, int ch) {
- int col;
- if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- col = columnMap.elementAt((char)ch);
- } else {
- col = supplementaryCharColumnMap.getValue(ch);
- }
- return getNextState(row, col);
- }
-
- /**
- * Returns the value in the cell with the specified (logical) row and
- * column numbers. In DictionaryBasedBreakIterator, the row number is
- * a state number, the column number is an input, and the return value
- * is the row number of the new state to transition to. (0 is the
- * "error" state, and -1 is the "end of word" state in a dictionary)
- * @param row The row number of the current state
- * @param col The column number of the input character (0 means "not a
- * dictionary character")
- * @return The row number of the new state to transition to
- */
- public final short getNextState(int row, int col) {
- if (cellIsPopulated(row, col)) {
- // we map from logical to physical row number by looking up the
- // mapping in rowIndex; we map from logical column number to
- // physical column number by looking up a shift value for this
- // logical row and offsetting the logical column number by
- // the shift amount. Then we can use internalAt() to actually
- // get the value out of the table.
- return internalAt(rowIndex[row], col + rowIndexShifts[row]);
- }
- else {
- return 0;
- }
- }
-
- /**
- * Given (logical) row and column numbers, returns true if the
- * cell in that position is populated
- */
- private boolean cellIsPopulated(int row, int col) {
- // look up the entry in the bitmap index for the specified row.
- // If it's a negative number, it's the column number of the only
- // populated cell in the row
- if (rowIndexFlagsIndex[row] < 0) {
- return col == -rowIndexFlagsIndex[row];
- }
-
- // if it's a positive number, it's the offset of an entry in the bitmap
- // list. If the table is more than 32 columns wide, the bitmap is stored
- // successive entries in the bitmap list, so we have to divide the column
- // number by 32 and offset the number we got out of the index by the result.
- // Once we have the appropriate piece of the bitmap, test the appropriate
- // bit and return the result.
- else {
- int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
- return (flags & (1 << (col & 0x1f))) != 0;
- }
- }
-
- /**
- * Implementation of getNextState() when we know the specified cell is
- * populated.
- * @param row The PHYSICAL row number of the cell
- * @param col The PHYSICAL column number of the cell
- * @return The value stored in the cell
- */
- private short internalAt(int row, int col) {
- // the table is a one-dimensional array, so this just does the math necessary
- // to treat it as a two-dimensional array (we don't just use a two-dimensional
- // array because two-dimensional arrays are inefficient in Java)
- return table[row * numCols + col];
- }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Set;
+import sun.text.DictionaryBasedBreakIterator;
+import sun.text.RuleBasedBreakIterator;
/**
* Concrete implementation of the {@link java.text.spi.BreakIteratorProvider
@@ -153,29 +155,31 @@
}
private BreakIterator getBreakInstance(Locale locale,
- int type,
- String dataName,
- String dictionaryName) {
+ int type,
+ String ruleName,
+ String dictionaryName) {
Objects.requireNonNull(locale);
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
- String dataFile = (String) lr.getBreakIteratorInfo(dataName);
+ String ruleFile = (String) lr.getBreakIteratorInfo(ruleName);
+ byte[] ruleData = lr.getBreakIteratorResources(ruleName);
try {
switch (classNames[type]) {
case "RuleBasedBreakIterator":
- return new RuleBasedBreakIterator(
- lr.getBreakIteratorDataModule(), dataFile);
+ return new RuleBasedBreakIterator(ruleFile, ruleData);
+
case "DictionaryBasedBreakIterator":
String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
- return new DictionaryBasedBreakIterator(
- lr.getBreakIteratorDataModule(), dataFile, dictionaryFile);
+ byte[] dictionaryData = lr.getBreakIteratorResources(dictionaryName);
+ return new DictionaryBasedBreakIterator(ruleFile, ruleData,
+ dictionaryFile, dictionaryData);
default:
throw new IllegalArgumentException("Invalid break iterator class \"" +
classNames[type] + "\"");
}
- } catch (IOException | MissingResourceException | IllegalArgumentException e) {
+ } catch (MissingResourceException | IllegalArgumentException e) {
throw new InternalError(e.toString(), e);
}
}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,524 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-
-package sun.util.locale.provider;
-
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.text.CharacterIterator;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-
-/**
- * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
- * to further subdivide ranges of text beyond what is possible using just the
- * state-table-based algorithm. This is necessary, for example, to handle
- * word and line breaking in Thai, which doesn't use spaces between words. The
- * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
- * up text as far as possible, and then contiguous ranges of letters are
- * repeatedly compared against a list of known words (i.e., the dictionary)
- * to divide them up into words.
- *
- * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
- * but adds one more special substitution name: <dictionary>. This substitution
- * name is used to identify characters in words in the dictionary. The idea is that
- * if the iterator passes over a chunk of text that includes two or more characters
- * in a row that are included in <dictionary>, it goes back through that range and
- * derives additional break positions (if possible) using the dictionary.
- *
- * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
- * file. It follows a prescribed search path to locate the dictionary (right now,
- * it looks for it in /com/ibm/text/resources in each directory in the classpath,
- * and won't find it in JAR files, but this location is likely to change). The
- * dictionary file is in a serialized binary format. We have a very primitive (and
- * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
- * currently making it public. Contact us for help.
- */
-class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
-
- /**
- * a list of known words that is used to divide up contiguous ranges of letters,
- * stored in a compressed, indexed, format that offers fast access
- */
- private BreakDictionary dictionary;
-
- /**
- * a list of flags indicating which character categories are contained in
- * the dictionary file (this is used to determine which ranges of characters
- * to apply the dictionary to)
- */
- private boolean[] categoryFlags;
-
- /**
- * a temporary hiding place for the number of dictionary characters in the
- * last range passed over by next()
- */
- private int dictionaryCharCount;
-
- /**
- * when a range of characters is divided up using the dictionary, the break
- * positions that are discovered are stored here, preventing us from having
- * to use either the dictionary or the state table again until the iterator
- * leaves this range of text
- */
- private int[] cachedBreakPositions;
-
- /**
- * if cachedBreakPositions is not null, this indicates which item in the
- * cache the current iteration position refers to
- */
- private int positionInCache;
-
- /**
- * Constructs a DictionaryBasedBreakIterator.
- * @param module The module where the dictionary file resides
- * @param dictionaryFilename The filename of the dictionary file to use
- */
- DictionaryBasedBreakIterator(Module module, String dataFile, String dictionaryFile)
- throws IOException {
- super(module, dataFile);
- byte[] tmp = super.getAdditionalData();
- if (tmp != null) {
- prepareCategoryFlags(tmp);
- super.setAdditionalData(null);
- }
- dictionary = new BreakDictionary(module, dictionaryFile);
- }
-
- private void prepareCategoryFlags(byte[] data) {
- categoryFlags = new boolean[data.length];
- for (int i = 0; i < data.length; i++) {
- categoryFlags[i] = (data[i] == (byte)1) ? true : false;
- }
- }
-
- @Override
- public void setText(CharacterIterator newText) {
- super.setText(newText);
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- }
-
- /**
- * Sets the current iteration position to the beginning of the text.
- * (i.e., the CharacterIterator's starting offset).
- * @return The offset of the beginning of the text.
- */
- @Override
- public int first() {
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- return super.first();
- }
-
- /**
- * Sets the current iteration position to the end of the text.
- * (i.e., the CharacterIterator's ending offset).
- * @return The text's past-the-end offset.
- */
- @Override
- public int last() {
- cachedBreakPositions = null;
- dictionaryCharCount = 0;
- positionInCache = 0;
- return super.last();
- }
-
- /**
- * Advances the iterator one step backwards.
- * @return The position of the last boundary position before the
- * current iteration position
- */
- @Override
- public int previous() {
- CharacterIterator text = getText();
-
- // if we have cached break positions and we're still in the range
- // covered by them, just move one step backward in the cache
- if (cachedBreakPositions != null && positionInCache > 0) {
- --positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return cachedBreakPositions[positionInCache];
- }
-
- // otherwise, dump the cache and use the inherited previous() method to move
- // backward. This may fill up the cache with new break positions, in which
- // case we have to mark our position in the cache
- else {
- cachedBreakPositions = null;
- int result = super.previous();
- if (cachedBreakPositions != null) {
- positionInCache = cachedBreakPositions.length - 2;
- }
- return result;
- }
- }
-
- /**
- * Sets the current iteration position to the last boundary position
- * before the specified position.
- * @param offset The position to begin searching from
- * @return The position of the last boundary before "offset"
- */
- @Override
- public int preceding(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // if we have no cached break positions, or "offset" is outside the
- // range covered by the cache, we can just call the inherited routine
- // (which will eventually call other routines in this class that may
- // refresh the cache)
- if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
- offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
- cachedBreakPositions = null;
- return super.preceding(offset);
- }
-
- // on the other hand, if "offset" is within the range covered by the cache,
- // then all we have to do is search the cache for the last break position
- // before "offset"
- else {
- positionInCache = 0;
- while (positionInCache < cachedBreakPositions.length
- && offset > cachedBreakPositions[positionInCache]) {
- ++positionInCache;
- }
- --positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return text.getIndex();
- }
- }
-
- /**
- * Sets the current iteration position to the first boundary position after
- * the specified position.
- * @param offset The position to begin searching forward from
- * @return The position of the first boundary after "offset"
- */
- @Override
- public int following(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // if we have no cached break positions, or if "offset" is outside the
- // range covered by the cache, then dump the cache and call our
- // inherited following() method. This will call other methods in this
- // class that may refresh the cache.
- if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
- offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
- cachedBreakPositions = null;
- return super.following(offset);
- }
-
- // on the other hand, if "offset" is within the range covered by the
- // cache, then just search the cache for the first break position
- // after "offset"
- else {
- positionInCache = 0;
- while (positionInCache < cachedBreakPositions.length
- && offset >= cachedBreakPositions[positionInCache]) {
- ++positionInCache;
- }
- text.setIndex(cachedBreakPositions[positionInCache]);
- return text.getIndex();
- }
- }
-
- /**
- * This is the implementation function for next().
- */
- @Override
- protected int handleNext() {
- CharacterIterator text = getText();
-
- // if there are no cached break positions, or if we've just moved
- // off the end of the range covered by the cache, we have to dump
- // and possibly regenerate the cache
- if (cachedBreakPositions == null ||
- positionInCache == cachedBreakPositions.length - 1) {
-
- // start by using the inherited handleNext() to find a tentative return
- // value. dictionaryCharCount tells us how many dictionary characters
- // we passed over on our way to the tentative return value
- int startPos = text.getIndex();
- dictionaryCharCount = 0;
- int result = super.handleNext();
-
- // if we passed over more than one dictionary character, then we use
- // divideUpDictionaryRange() to regenerate the cached break positions
- // for the new range
- if (dictionaryCharCount > 1 && result - startPos > 1) {
- divideUpDictionaryRange(startPos, result);
- }
-
- // otherwise, the value we got back from the inherited fuction
- // is our return value, and we can dump the cache
- else {
- cachedBreakPositions = null;
- return result;
- }
- }
-
- // if the cache of break positions has been regenerated (or existed all
- // along), then just advance to the next break position in the cache
- // and return it
- if (cachedBreakPositions != null) {
- ++positionInCache;
- text.setIndex(cachedBreakPositions[positionInCache]);
- return cachedBreakPositions[positionInCache];
- }
- return -9999; // SHOULD NEVER GET HERE!
- }
-
- /**
- * Looks up a character category for a character.
- */
- @Override
- protected int lookupCategory(int c) {
- // this override of lookupCategory() exists only to keep track of whether we've
- // passed over any dictionary characters. It calls the inherited lookupCategory()
- // to do the real work, and then checks whether its return value is one of the
- // categories represented in the dictionary. If it is, bump the dictionary-
- // character count.
- int result = super.lookupCategory(c);
- if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
- ++dictionaryCharCount;
- }
- return result;
- }
-
- /**
- * This is the function that actually implements the dictionary-based
- * algorithm. Given the endpoints of a range of text, it uses the
- * dictionary to determine the positions of any boundaries in this
- * range. It stores all the boundary positions it discovers in
- * cachedBreakPositions so that we only have to do this work once
- * for each time we enter the range.
- */
- @SuppressWarnings("unchecked")
- private void divideUpDictionaryRange(int startPos, int endPos) {
- CharacterIterator text = getText();
-
- // the range we're dividing may begin or end with non-dictionary characters
- // (i.e., for line breaking, we may have leading or trailing punctuation
- // that needs to be kept with the word). Seek from the beginning of the
- // range to the first dictionary character
- text.setIndex(startPos);
- int c = getCurrent();
- int category = lookupCategory(c);
- while (category == IGNORE || !categoryFlags[category]) {
- c = getNext();
- category = lookupCategory(c);
- }
-
- // initialize. We maintain two stacks: currentBreakPositions contains
- // the list of break positions that will be returned if we successfully
- // finish traversing the whole range now. possibleBreakPositions lists
- // all other possible word ends we've passed along the way. (Whenever
- // we reach an error [a sequence of characters that can't begin any word
- // in the dictionary], we back up, possibly delete some breaks from
- // currentBreakPositions, move a break from possibleBreakPositions
- // to currentBreakPositions, and start over from there. This process
- // continues in this way until we either successfully make it all the way
- // across the range, or exhaust all of our combinations of break
- // positions.)
- Stack<Integer> currentBreakPositions = new Stack<>();
- Stack<Integer> possibleBreakPositions = new Stack<>();
- List<Integer> wrongBreakPositions = new ArrayList<>();
-
- // the dictionary is implemented as a trie, which is treated as a state
- // machine. -1 represents the end of a legal word. Every word in the
- // dictionary is represented by a path from the root node to -1. A path
- // that ends in state 0 is an illegal combination of characters.
- int state = 0;
-
- // these two variables are used for error handling. We keep track of the
- // farthest we've gotten through the range being divided, and the combination
- // of breaks that got us that far. If we use up all possible break
- // combinations, the text contains an error or a word that's not in the
- // dictionary. In this case, we "bless" the break positions that got us the
- // farthest as real break positions, and then start over from scratch with
- // the character where the error occurred.
- int farthestEndPoint = text.getIndex();
- Stack<Integer> bestBreakPositions = null;
-
- // initialize (we always exit the loop with a break statement)
- c = getCurrent();
- while (true) {
-
- // if we can transition to state "-1" from our current state, we're
- // on the last character of a legal word. Push that position onto
- // the possible-break-positions stack
- if (dictionary.getNextState(state, 0) == -1) {
- possibleBreakPositions.push(text.getIndex());
- }
-
- // look up the new state to transition to in the dictionary
- state = dictionary.getNextStateFromCharacter(state, c);
-
- // if the character we're sitting on causes us to transition to
- // the "end of word" state, then it was a non-dictionary character
- // and we've successfully traversed the whole range. Drop out
- // of the loop.
- if (state == -1) {
- currentBreakPositions.push(text.getIndex());
- break;
- }
-
- // if the character we're sitting on causes us to transition to
- // the error state, or if we've gone off the end of the range
- // without transitioning to the "end of word" state, we've hit
- // an error...
- else if (state == 0 || text.getIndex() >= endPos) {
-
- // if this is the farthest we've gotten, take note of it in
- // case there's an error in the text
- if (text.getIndex() > farthestEndPoint) {
- farthestEndPoint = text.getIndex();
-
- @SuppressWarnings("unchecked")
- Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
-
- bestBreakPositions = currentBreakPositionsCopy;
- }
-
- // wrongBreakPositions is a list of all break positions
- // we've tried starting that didn't allow us to traverse
- // all the way through the text. Every time we pop a
- // break position off of currentBreakPositions, we put it
- // into wrongBreakPositions to avoid trying it again later.
- // If we make it to this spot, we're either going to back
- // up to a break in possibleBreakPositions and try starting
- // over from there, or we've exhausted all possible break
- // positions and are going to do the fallback procedure.
- // This loop prevents us from messing with anything in
- // possibleBreakPositions that didn't work as a starting
- // point the last time we tried it (this is to prevent a bunch of
- // repetitive checks from slowing down some extreme cases)
- while (!possibleBreakPositions.isEmpty()
- && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
- possibleBreakPositions.pop();
- }
-
- // if we've used up all possible break-position combinations, there's
- // an error or an unknown word in the text. In this case, we start
- // over, treating the farthest character we've reached as the beginning
- // of the range, and "blessing" the break positions that got us that
- // far as real break positions
- if (possibleBreakPositions.isEmpty()) {
- if (bestBreakPositions != null) {
- currentBreakPositions = bestBreakPositions;
- if (farthestEndPoint < endPos) {
- text.setIndex(farthestEndPoint + 1);
- }
- else {
- break;
- }
- }
- else {
- if ((currentBreakPositions.size() == 0 ||
- currentBreakPositions.peek().intValue() != text.getIndex())
- && text.getIndex() != startPos) {
- currentBreakPositions.push(text.getIndex());
- }
- getNext();
- currentBreakPositions.push(text.getIndex());
- }
- }
-
- // if we still have more break positions we can try, then promote the
- // last break in possibleBreakPositions into currentBreakPositions,
- // and get rid of all entries in currentBreakPositions that come after
- // it. Then back up to that position and start over from there (i.e.,
- // treat that position as the beginning of a new word)
- else {
- Integer temp = possibleBreakPositions.pop();
- Integer temp2 = null;
- while (!currentBreakPositions.isEmpty() && temp.intValue() <
- currentBreakPositions.peek().intValue()) {
- temp2 = currentBreakPositions.pop();
- wrongBreakPositions.add(temp2);
- }
- currentBreakPositions.push(temp);
- text.setIndex(currentBreakPositions.peek().intValue());
- }
-
- // re-sync "c" for the next go-round, and drop out of the loop if
- // we've made it off the end of the range
- c = getCurrent();
- if (text.getIndex() >= endPos) {
- break;
- }
- }
-
- // if we didn't hit any exceptional conditions on this last iteration,
- // just advance to the next character and loop
- else {
- c = getNext();
- }
- }
-
- // dump the last break position in the list, and replace it with the actual
- // end of the range (which may be the same character, or may be further on
- // because the range actually ended with non-dictionary characters we want to
- // keep with the word)
- if (!currentBreakPositions.isEmpty()) {
- currentBreakPositions.pop();
- }
- currentBreakPositions.push(endPos);
-
- // create a regular array to hold the break positions and copy
- // the break positions from the stack to the array (in addition,
- // our starting position goes into this array as a break position).
- // This array becomes the cache of break positions used by next()
- // and previous(), so this is where we actually refresh the cache.
- cachedBreakPositions = new int[currentBreakPositions.size() + 1];
- cachedBreakPositions[0] = startPos;
-
- for (int i = 0; i < currentBreakPositions.size(); i++) {
- cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
- }
- positionInCache = 0;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -42,7 +42,6 @@
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Module;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.LinkedHashSet;
@@ -113,13 +112,14 @@
if (data == null || ((biInfo = data.get()) == null)) {
biInfo = localeData.getBreakIteratorInfo(locale).getObject(key);
cache.put(cacheKey, new ResourceReference(cacheKey, biInfo, referenceQueue));
- }
+ }
return biInfo;
}
- Module getBreakIteratorDataModule() {
- return localeData.getBreakIteratorInfo(locale).getClass().getModule();
+ @SuppressWarnings("unchecked")
+ byte[] getBreakIteratorResources(String key) {
+ return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
}
int getCalendarData(String key) {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1198 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, 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.
- */
-
-/*
- *
- * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
- * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved
- *
- * The original version of this source code and documentation
- * is copyrighted and owned by Taligent, Inc., a wholly-owned
- * subsidiary of IBM. These materials are provided under terms
- * of a License Agreement between Taligent and Sun. This technology
- * is protected by multiple US and International patents.
- *
- * This notice and attribution to Taligent may not be removed.
- * Taligent is a registered trademark of Taligent, Inc.
- */
-
-package sun.util.locale.provider;
-
-import java.io.BufferedInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.text.BreakIterator;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
- *
- * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
- * and <i>regular expressions.</i></p>
- *
- * <p>A substitution rule defines a name that can be used in place of an expression. It
- * consists of a name, which is a string of characters contained in angle brackets, an equals
- * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
- * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
- * square brackets. A substitution is visible after its definition, and is filled in using
- * simple textual substitution. Substitution definitions can contain other substitutions, as
- * long as those substitutions have been defined first. Substitutions are generally used to
- * make the regular expressions (which can get quite complex) shorted and easier to read.
- * They typically define either character categories or commonly-used subexpressions.</p>
- *
- * <p>There is one special substitution. If the description defines a substitution
- * called "<ignore>", the expression must be a [] expression, and the
- * expression defines a set of characters (the "<em>ignore characters</em>") that
- * will be transparent to the BreakIterator. A sequence of characters will break the
- * same way it would if any ignore characters it contains are taken out. Break
- * positions never occur befoer ignore characters.</p>
- *
- * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
- * defines a sequence of characters to be kept together. With one significant exception, the
- * iterator uses a longest-possible-match algorithm when matching text to regular
- * expressions. The iterator also treats descriptions containing multiple regular expressions
- * as if they were ORed together (i.e., as if they were separated by |).</p>
- *
- * <p>The special characters recognized by the regular-expression parser are as follows:</p>
- *
- * <blockquote>
- * <table border="1" width="100%">
- * <tr>
- * <td width="6%">*</td>
- * <td width="94%">Specifies that the expression preceding the asterisk may occur any number
- * of times (including not at all).</td>
- * </tr>
- * <tr>
- * <td width="6%">{}</td>
- * <td width="94%">Encloses a sequence of characters that is optional.</td>
- * </tr>
- * <tr>
- * <td width="6%">()</td>
- * <td width="94%">Encloses a sequence of characters. If followed by *, the sequence
- * repeats. Otherwise, the parentheses are just a grouping device and a way to delimit
- * the ends of expressions containing |.</td>
- * </tr>
- * <tr>
- * <td width="6%">|</td>
- * <td width="94%">Separates two alternative sequences of characters. Either one
- * sequence or the other, but not both, matches this expression. The | character can
- * only occur inside ().</td>
- * </tr>
- * <tr>
- * <td width="6%">.</td>
- * <td width="94%">Matches any character.</td>
- * </tr>
- * <tr>
- * <td width="6%">*?</td>
- * <td width="94%">Specifies a non-greedy asterisk. *? works the same way as *, except
- * when there is overlap between the last group of characters in the expression preceding the
- * * and the first group of characters following the *. When there is this kind of
- * overlap, * will match the longest sequence of characters that match the expression before
- * the *, and *? will match the shortest sequence of characters matching the expression
- * before the *?. For example, if you have "xxyxyyyxyxyxxyxyxyy" in the text,
- * "x[xy]*x" will match through to the last x (i.e., "<strong>xxyxyyyxyxyxxyxyx</strong>yy",
- * but "x[xy]*?x" will only match the first two xes ("<strong>xx</strong>yxyyyxyxyxxyxyxyy").</td>
- * </tr>
- * <tr>
- * <td width="6%">[]</td>
- * <td width="94%">Specifies a group of alternative characters. A [] expression will
- * match any single character that is specified in the [] expression. For more on the
- * syntax of [] expressions, see below.</td>
- * </tr>
- * <tr>
- * <td width="6%">/</td>
- * <td width="94%">Specifies where the break position should go if text matches this
- * expression. (e.g., "[a-z]*/[:Zs:]*[1-0]" will match if the iterator sees a run
- * of letters, followed by a run of whitespace, followed by a digit, but the break position
- * will actually go before the whitespace). Expressions that don't contain / put the
- * break position at the end of the matching text.</td>
- * </tr>
- * <tr>
- * <td width="6%">\</td>
- * <td width="94%">Escape character. The \ itself is ignored, but causes the next
- * character to be treated as literal character. This has no effect for many
- * characters, but for the characters listed above, this deprives them of their special
- * meaning. (There are no special escape sequences for Unicode characters, or tabs and
- * newlines; these are all handled by a higher-level protocol. In a Java string,
- * "\n" will be converted to a literal newline character by the time the
- * regular-expression parser sees it. Of course, this means that \ sequences that are
- * visible to the regexp parser must be written as \\ when inside a Java string.) All
- * characters in the ASCII range except for letters, digits, and control characters are
- * reserved characters to the parser and must be preceded by \ even if they currently don't
- * mean anything.</td>
- * </tr>
- * <tr>
- * <td width="6%">!</td>
- * <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
- * parser that this expression specifies the backwards-iteration behavior of the iterator,
- * and not its normal iteration behavior. This is generally only used in situations
- * where the automatically-generated backwards-iteration brhavior doesn't produce
- * satisfactory results and must be supplemented with extra client-specified rules.</td>
- * </tr>
- * <tr>
- * <td width="6%"><em>(all others)</em></td>
- * <td width="94%">All other characters are treated as literal characters, which must match
- * the corresponding character(s) in the text exactly.</td>
- * </tr>
- * </table>
- * </blockquote>
- *
- * <p>Within a [] expression, a number of other special characters can be used to specify
- * groups of characters:</p>
- *
- * <blockquote>
- * <table border="1" width="100%">
- * <tr>
- * <td width="6%">-</td>
- * <td width="94%">Specifies a range of matching characters. For example
- * "[a-p]" matches all lowercase Latin letters from a to p (inclusive). The -
- * sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
- * language's alphabetical order: "[a-z]" doesn't include capital letters, nor does
- * it include accented letters such as a-umlaut.</td>
- * </tr>
- * <tr>
- * <td width="6%">::</td>
- * <td width="94%">A pair of colons containing a one- or two-letter code matches all
- * characters in the corresponding Unicode category. The two-letter codes are the same
- * as the two-letter codes in the Unicode database (for example, "[:Sc::Sm:]"
- * matches all currency symbols and all math symbols). Specifying a one-letter code is
- * the same as specifying all two-letter codes that begin with that letter (for example,
- * "[:L:]" matches all letters, and is equivalent to
- * "[:Lu::Ll::Lo::Lm::Lt:]"). Anything other than a valid two-letter Unicode
- * category code or a single letter that begins a Unicode category code is illegal within
- * colons.</td>
- * </tr>
- * <tr>
- * <td width="6%">[]</td>
- * <td width="94%">[] expressions can nest. This has no effect, except when used in
- * conjunction with the ^ token.</td>
- * </tr>
- * <tr>
- * <td width="6%">^</td>
- * <td width="94%">Excludes the character (or the characters in the [] expression) following
- * it from the group of characters. For example, "[a-z^p]" matches all Latin
- * lowercase letters except p. "[:L:^[\u4e00-\u9fff]]" matches all letters
- * except the Han ideographs.</td>
- * </tr>
- * <tr>
- * <td width="6%"><em>(all others)</em></td>
- * <td width="94%">All other characters are treated as literal characters. (For
- * example, "[aeiou]" specifies just the letters a, e, i, o, and u.)</td>
- * </tr>
- * </table>
- * </blockquote>
- *
- * <p>For a more complete explanation, see <a
- * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
- * For examples, see the resource data (which is annotated).</p>
- *
- * @author Richard Gillam
- */
-class RuleBasedBreakIterator extends BreakIterator {
-
- /**
- * A token used as a character-category value to identify ignore characters
- */
- protected static final byte IGNORE = -1;
-
- /**
- * The state number of the starting state
- */
- private static final short START_STATE = 1;
-
- /**
- * The state-transition value indicating "stop"
- */
- private static final short STOP_STATE = 0;
-
- /**
- * Magic number for the BreakIterator data file format.
- */
- static final byte[] LABEL = {
- (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
- (byte)'\0'
- };
- static final int LABEL_LENGTH = LABEL.length;
-
- /**
- * Version number of the dictionary that was read in.
- */
- static final byte supportedVersion = 1;
-
- /**
- * Header size in byte count
- */
- private static final int HEADER_LENGTH = 36;
-
- /**
- * An array length of indices for BMP characters
- */
- private static final int BMP_INDICES_LENGTH = 512;
-
- /**
- * Tables that indexes from character values to character category numbers
- */
- private CompactByteArray charCategoryTable = null;
- private SupplementaryCharacterData supplementaryCharCategoryTable = null;
-
- /**
- * The table of state transitions used for forward iteration
- */
- private short[] stateTable = null;
-
- /**
- * The table of state transitions used to sync up the iterator with the
- * text in backwards and random-access iteration
- */
- private short[] backwardsStateTable = null;
-
- /**
- * A list of flags indicating which states in the state table are accepting
- * ("end") states
- */
- private boolean[] endStates = null;
-
- /**
- * A list of flags indicating which states in the state table are
- * lookahead states (states which turn lookahead on and off)
- */
- private boolean[] lookaheadStates = null;
-
- /**
- * A table for additional data. May be used by a subclass of
- * RuleBasedBreakIterator.
- */
- private byte[] additionalData = null;
-
- /**
- * The number of character categories (and, thus, the number of columns in
- * the state tables)
- */
- private int numCategories;
-
- /**
- * The character iterator through which this BreakIterator accesses the text
- */
- private CharacterIterator text = null;
-
- /**
- * A CRC32 value of all data in datafile
- */
- private long checksum;
-
- //=======================================================================
- // constructors
- //=======================================================================
-
- /**
- * Constructs a RuleBasedBreakIterator according to the module and the datafile
- * provided.
- */
- RuleBasedBreakIterator(Module module, String datafile)
- throws IOException, MissingResourceException {
- readTables(module, datafile);
- }
-
- /**
- * Read datafile. The datafile's format is as follows:
- * <pre>
- * BreakIteratorData {
- * u1 magic[7];
- * u1 version;
- * u4 totalDataSize;
- * header_info header;
- * body value;
- * }
- * </pre>
- * <code>totalDataSize</code> is the summation of the size of
- * <code>header_info</code> and <code>body</code> in byte count.
- * <p>
- * In <code>header</code>, each field except for checksum implies the
- * length of each field. Since <code>BMPdataLength</code> is a fixed-length
- * data(512 entries), its length isn't included in <code>header</code>.
- * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
- * <pre>
- * header_info {
- * u4 stateTableLength;
- * u4 backwardsStateTableLength;
- * u4 endStatesLength;
- * u4 lookaheadStatesLength;
- * u4 BMPdataLength;
- * u4 nonBMPdataLength;
- * u4 additionalDataLength;
- * u8 checksum;
- * }
- * </pre>
- * <p>
- *
- * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
- * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
- * <code>supplementaryCharCategoryTable</code>.
- * <pre>
- * body {
- * u2 stateTable[stateTableLength];
- * u2 backwardsStateTable[backwardsStateTableLength];
- * u1 endStates[endStatesLength];
- * u1 lookaheadStates[lookaheadStatesLength];
- * u2 BMPindices[512];
- * u1 BMPdata[BMPdataLength];
- * u4 nonBMPdata[numNonBMPdataLength];
- * u1 additionalData[additionalDataLength];
- * }
- * </pre>
- */
- protected final void readTables(Module module, String datafile)
- throws IOException, MissingResourceException {
-
- byte[] buffer = readFile(module, datafile);
-
- /* Read header_info. */
- int stateTableLength = getInt(buffer, 0);
- int backwardsStateTableLength = getInt(buffer, 4);
- int endStatesLength = getInt(buffer, 8);
- int lookaheadStatesLength = getInt(buffer, 12);
- int BMPdataLength = getInt(buffer, 16);
- int nonBMPdataLength = getInt(buffer, 20);
- int additionalDataLength = getInt(buffer, 24);
- checksum = getLong(buffer, 28);
-
- /* Read stateTable[numCategories * numRows] */
- stateTable = new short[stateTableLength];
- int offset = HEADER_LENGTH;
- for (int i = 0; i < stateTableLength; i++, offset+=2) {
- stateTable[i] = getShort(buffer, offset);
- }
-
- /* Read backwardsStateTable[numCategories * numRows] */
- backwardsStateTable = new short[backwardsStateTableLength];
- for (int i = 0; i < backwardsStateTableLength; i++, offset+=2) {
- backwardsStateTable[i] = getShort(buffer, offset);
- }
-
- /* Read endStates[numRows] */
- endStates = new boolean[endStatesLength];
- for (int i = 0; i < endStatesLength; i++, offset++) {
- endStates[i] = buffer[offset] == 1;
- }
-
- /* Read lookaheadStates[numRows] */
- lookaheadStates = new boolean[lookaheadStatesLength];
- for (int i = 0; i < lookaheadStatesLength; i++, offset++) {
- lookaheadStates[i] = buffer[offset] == 1;
- }
-
- /* Read a category table and indices for BMP characters. */
- short[] temp1 = new short[BMP_INDICES_LENGTH]; // BMPindices
- for (int i = 0; i < BMP_INDICES_LENGTH; i++, offset+=2) {
- temp1[i] = getShort(buffer, offset);
- }
- byte[] temp2 = new byte[BMPdataLength]; // BMPdata
- System.arraycopy(buffer, offset, temp2, 0, BMPdataLength);
- offset += BMPdataLength;
- charCategoryTable = new CompactByteArray(temp1, temp2);
-
- /* Read a category table for non-BMP characters. */
- int[] temp3 = new int[nonBMPdataLength];
- for (int i = 0; i < nonBMPdataLength; i++, offset+=4) {
- temp3[i] = getInt(buffer, offset);
- }
- supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
-
- /* Read additional data */
- if (additionalDataLength > 0) {
- additionalData = new byte[additionalDataLength];
- System.arraycopy(buffer, offset, additionalData, 0, additionalDataLength);
- }
-
- /* Set numCategories */
- numCategories = stateTable.length / endStates.length;
- }
-
- protected byte[] readFile(final Module module, final String datafile)
- throws IOException, MissingResourceException {
-
- BufferedInputStream is;
- try {
- PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
- String pathName = "jdk.localedata".equals(module.getName()) ?
- "sun/text/resources/ext/" :
- "sun/text/resources/";
- InputStream in = module.getResourceAsStream(pathName + datafile);
- if (in == null) {
- // Try to load the file with "java.base" module instance. Assumption
- // here is that the fall back data files to be read should reside in
- // java.base.
- in = RuleBasedBreakIterator.class.getModule().getResourceAsStream("sun/text/resources/" + datafile);
- }
-
- return new BufferedInputStream(in);
- };
- is = AccessController.doPrivileged(pa);
- } catch (PrivilegedActionException e) {
- throw new InternalError(e.toString(), e);
- }
-
- int offset = 0;
-
- /* First, read magic, version, and header_info. */
- int len = LABEL_LENGTH + 5;
- byte[] buf = new byte[len];
- if (is.read(buf) != len) {
- throw new MissingResourceException("Wrong header length",
- datafile, "");
- }
-
- /* Validate the magic number. */
- for (int i = 0; i < LABEL_LENGTH; i++, offset++) {
- if (buf[offset] != LABEL[offset]) {
- throw new MissingResourceException("Wrong magic number",
- datafile, "");
- }
- }
-
- /* Validate the version number. */
- if (buf[offset] != supportedVersion) {
- throw new MissingResourceException("Unsupported version(" + buf[offset] + ")",
- datafile, "");
- }
-
- /* Read data: totalDataSize + 8(for checksum) */
- len = getInt(buf, ++offset);
- buf = new byte[len];
- if (is.read(buf) != len) {
- throw new MissingResourceException("Wrong data length",
- datafile, "");
- }
-
- is.close();
-
- return buf;
- }
-
- byte[] getAdditionalData() {
- return additionalData;
- }
-
- void setAdditionalData(byte[] b) {
- additionalData = b;
- }
-
- //=======================================================================
- // boilerplate
- //=======================================================================
- /**
- * Clones this iterator.
- * @return A newly-constructed RuleBasedBreakIterator with the same
- * behavior as this one.
- */
- @Override
- public Object clone() {
- RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
- if (text != null) {
- result.text = (CharacterIterator) text.clone();
- }
- return result;
- }
-
- /**
- * Returns true if both BreakIterators are of the same class, have the same
- * rules, and iterate over the same text.
- */
- @Override
- public boolean equals(Object that) {
- try {
- if (that == null) {
- return false;
- }
-
- RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
- if (checksum != other.checksum) {
- return false;
- }
- if (text == null) {
- return other.text == null;
- } else {
- return text.equals(other.text);
- }
- }
- catch(ClassCastException e) {
- return false;
- }
- }
-
- /**
- * Returns text
- */
- @Override
- public String toString() {
- return "[checksum=0x" + Long.toHexString(checksum) + ']';
- }
-
- /**
- * Compute a hashcode for this BreakIterator
- * @return A hash code
- */
- @Override
- public int hashCode() {
- return (int)checksum;
- }
-
- //=======================================================================
- // BreakIterator overrides
- //=======================================================================
-
- /**
- * Sets the current iteration position to the beginning of the text.
- * (i.e., the CharacterIterator's starting offset).
- * @return The offset of the beginning of the text.
- */
- @Override
- public int first() {
- CharacterIterator t = getText();
-
- t.first();
- return t.getIndex();
- }
-
- /**
- * Sets the current iteration position to the end of the text.
- * (i.e., the CharacterIterator's ending offset).
- * @return The text's past-the-end offset.
- */
- @Override
- public int last() {
- CharacterIterator t = getText();
-
- // I'm not sure why, but t.last() returns the offset of the last character,
- // rather than the past-the-end offset
- t.setIndex(t.getEndIndex());
- return t.getIndex();
- }
-
- /**
- * Advances the iterator either forward or backward the specified number of steps.
- * Negative values move backward, and positive values move forward. This is
- * equivalent to repeatedly calling next() or previous().
- * @param n The number of steps to move. The sign indicates the direction
- * (negative is backwards, and positive is forwards).
- * @return The character offset of the boundary position n boundaries away from
- * the current one.
- */
- @Override
- public int next(int n) {
- int result = current();
- while (n > 0) {
- result = handleNext();
- --n;
- }
- while (n < 0) {
- result = previous();
- ++n;
- }
- return result;
- }
-
- /**
- * Advances the iterator to the next boundary position.
- * @return The position of the first boundary after this one.
- */
- @Override
- public int next() {
- return handleNext();
- }
-
- private int cachedLastKnownBreak = BreakIterator.DONE;
-
- /**
- * Advances the iterator backwards, to the last boundary preceding this one.
- * @return The position of the last boundary position preceding this one.
- */
- @Override
- public int previous() {
- // if we're already sitting at the beginning of the text, return DONE
- CharacterIterator text = getText();
- if (current() == text.getBeginIndex()) {
- return BreakIterator.DONE;
- }
-
- // set things up. handlePrevious() will back us up to some valid
- // break position before the current position (we back our internal
- // iterator up one step to prevent handlePrevious() from returning
- // the current position), but not necessarily the last one before
- // where we started
- int start = current();
- int lastResult = cachedLastKnownBreak;
- if (lastResult >= start || lastResult <= BreakIterator.DONE) {
- getPrevious();
- lastResult = handlePrevious();
- } else {
- //it might be better to check if handlePrevious() give us closer
- //safe value but handlePrevious() is slow too
- //So, this has to be done carefully
- text.setIndex(lastResult);
- }
- int result = lastResult;
-
- // iterate forward from the known break position until we pass our
- // starting point. The last break position before the starting
- // point is our return value
- while (result != BreakIterator.DONE && result < start) {
- lastResult = result;
- result = handleNext();
- }
-
- // set the current iteration position to be the last break position
- // before where we started, and then return that value
- text.setIndex(lastResult);
- cachedLastKnownBreak = lastResult;
- return lastResult;
- }
-
- /**
- * Returns previous character
- */
- private int getPrevious() {
- char c2 = text.previous();
- if (Character.isLowSurrogate(c2) &&
- text.getIndex() > text.getBeginIndex()) {
- char c1 = text.previous();
- if (Character.isHighSurrogate(c1)) {
- return Character.toCodePoint(c1, c2);
- } else {
- text.next();
- }
- }
- return (int)c2;
- }
-
- /**
- * Returns current character
- */
- int getCurrent() {
- char c1 = text.current();
- if (Character.isHighSurrogate(c1) &&
- text.getIndex() < text.getEndIndex()) {
- char c2 = text.next();
- text.previous();
- if (Character.isLowSurrogate(c2)) {
- return Character.toCodePoint(c1, c2);
- }
- }
- return (int)c1;
- }
-
- /**
- * Returns the count of next character.
- */
- private int getCurrentCodePointCount() {
- char c1 = text.current();
- if (Character.isHighSurrogate(c1) &&
- text.getIndex() < text.getEndIndex()) {
- char c2 = text.next();
- text.previous();
- if (Character.isLowSurrogate(c2)) {
- return 2;
- }
- }
- return 1;
- }
-
- /**
- * Returns next character
- */
- int getNext() {
- int index = text.getIndex();
- int endIndex = text.getEndIndex();
- if (index == endIndex ||
- (index += getCurrentCodePointCount()) >= endIndex) {
- return CharacterIterator.DONE;
- }
- text.setIndex(index);
- return getCurrent();
- }
-
- /**
- * Returns the position of next character.
- */
- private int getNextIndex() {
- int index = text.getIndex() + getCurrentCodePointCount();
- int endIndex = text.getEndIndex();
- if (index > endIndex) {
- return endIndex;
- } else {
- return index;
- }
- }
-
- /**
- * Throw IllegalArgumentException unless begin <= offset < end.
- */
- protected static final void checkOffset(int offset, CharacterIterator text) {
- if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
- throw new IllegalArgumentException("offset out of bounds");
- }
- }
-
- /**
- * Sets the iterator to refer to the first boundary position following
- * the specified position.
- * @offset The position from which to begin searching for a break position.
- * @return The position of the first break after the current position.
- */
- @Override
- public int following(int offset) {
-
- CharacterIterator text = getText();
- checkOffset(offset, text);
-
- // Set our internal iteration position (temporarily)
- // to the position passed in. If this is the _beginning_ position,
- // then we can just use next() to get our return value
- text.setIndex(offset);
- if (offset == text.getBeginIndex()) {
- cachedLastKnownBreak = handleNext();
- return cachedLastKnownBreak;
- }
-
- // otherwise, we have to sync up first. Use handlePrevious() to back
- // us up to a known break position before the specified position (if
- // we can determine that the specified position is a break position,
- // we don't back up at all). This may or may not be the last break
- // position at or before our starting position. Advance forward
- // from here until we've passed the starting position. The position
- // we stop on will be the first break position after the specified one.
- int result = cachedLastKnownBreak;
- if (result >= offset || result <= BreakIterator.DONE) {
- result = handlePrevious();
- } else {
- //it might be better to check if handlePrevious() give us closer
- //safe value but handlePrevious() is slow too
- //So, this has to be done carefully
- text.setIndex(result);
- }
- while (result != BreakIterator.DONE && result <= offset) {
- result = handleNext();
- }
- cachedLastKnownBreak = result;
- return result;
- }
-
- /**
- * Sets the iterator to refer to the last boundary position before the
- * specified position.
- * @offset The position to begin searching for a break from.
- * @return The position of the last boundary before the starting position.
- */
- @Override
- public int preceding(int offset) {
- // if we start by updating the current iteration position to the
- // position specified by the caller, we can just use previous()
- // to carry out this operation
- CharacterIterator text = getText();
- checkOffset(offset, text);
- text.setIndex(offset);
- return previous();
- }
-
- /**
- * Returns true if the specified position is a boundary position. As a side
- * effect, leaves the iterator pointing to the first boundary position at
- * or after "offset".
- * @param offset the offset to check.
- * @return True if "offset" is a boundary position.
- */
- @Override
- public boolean isBoundary(int offset) {
- CharacterIterator text = getText();
- checkOffset(offset, text);
- if (offset == text.getBeginIndex()) {
- return true;
- }
-
- // to check whether this is a boundary, we can use following() on the
- // position before the specified one and return true if the position we
- // get back is the one the user specified
- else {
- return following(offset - 1) == offset;
- }
- }
-
- /**
- * Returns the current iteration position.
- * @return The current iteration position.
- */
- @Override
- public int current() {
- return getText().getIndex();
- }
-
- /**
- * Return a CharacterIterator over the text being analyzed. This version
- * of this method returns the actual CharacterIterator we're using internally.
- * Changing the state of this iterator can have undefined consequences. If
- * you need to change it, clone it first.
- * @return An iterator over the text being analyzed.
- */
- @Override
- public CharacterIterator getText() {
- // The iterator is initialized pointing to no text at all, so if this
- // function is called while we're in that state, we have to fudge an
- // iterator to return.
- if (text == null) {
- text = new StringCharacterIterator("");
- }
- return text;
- }
-
- /**
- * Set the iterator to analyze a new piece of text. This function resets
- * the current iteration position to the beginning of the text.
- * @param newText An iterator over the text to analyze.
- */
- @Override
- public void setText(CharacterIterator newText) {
- // Test iterator to see if we need to wrap it in a SafeCharIterator.
- // The correct behavior for CharacterIterators is to allow the
- // position to be set to the endpoint of the iterator. Many
- // CharacterIterators do not uphold this, so this is a workaround
- // to permit them to use this class.
- int end = newText.getEndIndex();
- boolean goodIterator;
- try {
- newText.setIndex(end); // some buggy iterators throw an exception here
- goodIterator = newText.getIndex() == end;
- }
- catch(IllegalArgumentException e) {
- goodIterator = false;
- }
-
- if (goodIterator) {
- text = newText;
- }
- else {
- text = new SafeCharIterator(newText);
- }
- text.first();
-
- cachedLastKnownBreak = BreakIterator.DONE;
- }
-
-
- //=======================================================================
- // implementation
- //=======================================================================
-
- /**
- * This method is the actual implementation of the next() method. All iteration
- * vectors through here. This method initializes the state machine to state 1
- * and advances through the text character by character until we reach the end
- * of the text or the state machine transitions to state 0. We update our return
- * value every time the state machine passes through a possible end state.
- */
- protected int handleNext() {
- // if we're already at the end of the text, return DONE.
- CharacterIterator text = getText();
- if (text.getIndex() == text.getEndIndex()) {
- return BreakIterator.DONE;
- }
-
- // no matter what, we always advance at least one character forward
- int result = getNextIndex();
- int lookaheadResult = 0;
-
- // begin in state 1
- int state = START_STATE;
- int category;
- int c = getCurrent();
-
- // loop until we reach the end of the text or transition to state 0
- while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
- // look up the current character's character category (which tells us
- // which column in the state table to look at)
- category = lookupCategory(c);
-
- // if the character isn't an ignore character, look up a state
- // transition in the state table
- if (category != IGNORE) {
- state = lookupState(state, category);
- }
-
- // if the state we've just transitioned to is a lookahead state,
- // (but not also an end state), save its position. If it's
- // both a lookahead state and an end state, update the break position
- // to the last saved lookup-state position
- if (lookaheadStates[state]) {
- if (endStates[state]) {
- result = lookaheadResult;
- }
- else {
- lookaheadResult = getNextIndex();
- }
- }
-
- // otherwise, if the state we've just transitioned to is an accepting
- // state, update the break position to be the current iteration position
- else {
- if (endStates[state]) {
- result = getNextIndex();
- }
- }
-
- c = getNext();
- }
-
- // if we've run off the end of the text, and the very last character took us into
- // a lookahead state, advance the break position to the lookahead position
- // (the theory here is that if there are no characters at all after the lookahead
- // position, that always matches the lookahead criteria)
- if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
- result = lookaheadResult;
- }
-
- text.setIndex(result);
- return result;
- }
-
- /**
- * This method backs the iterator back up to a "safe position" in the text.
- * This is a position that we know, without any context, must be a break position.
- * The various calling methods then iterate forward from this safe position to
- * the appropriate position to return. (For more information, see the description
- * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
- */
- protected int handlePrevious() {
- CharacterIterator text = getText();
- int state = START_STATE;
- int category = 0;
- int lastCategory = 0;
- int c = getCurrent();
-
- // loop until we reach the beginning of the text or transition to state 0
- while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
- // save the last character's category and look up the current
- // character's category
- lastCategory = category;
- category = lookupCategory(c);
-
- // if the current character isn't an ignore character, look up a
- // state transition in the backwards state table
- if (category != IGNORE) {
- state = lookupBackwardState(state, category);
- }
-
- // then advance one character backwards
- c = getPrevious();
- }
-
- // if we didn't march off the beginning of the text, we're either one or two
- // positions away from the real break position. (One because of the call to
- // previous() at the end of the loop above, and another because the character
- // that takes us into the stop state will always be the character BEFORE
- // the break position.)
- if (c != CharacterIterator.DONE) {
- if (lastCategory != IGNORE) {
- getNext();
- getNext();
- }
- else {
- getNext();
- }
- }
- return text.getIndex();
- }
-
- /**
- * Looks up a character's category (i.e., its category for breaking purposes,
- * not its Unicode category)
- */
- protected int lookupCategory(int c) {
- if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
- return charCategoryTable.elementAt((char)c);
- } else {
- return supplementaryCharCategoryTable.getValue(c);
- }
- }
-
- /**
- * Given a current state and a character category, looks up the
- * next state to transition to in the state table.
- */
- protected int lookupState(int state, int category) {
- return stateTable[state * numCategories + category];
- }
-
- /**
- * Given a current state and a character category, looks up the
- * next state to transition to in the backwards state table.
- */
- protected int lookupBackwardState(int state, int category) {
- return backwardsStateTable[state * numCategories + category];
- }
-
- static long getLong(byte[] buf, int offset) {
- long num = buf[offset]&0xFF;
- for (int i = 1; i < 8; i++) {
- num = num<<8 | (buf[offset+i]&0xFF);
- }
- return num;
- }
-
- static int getInt(byte[] buf, int offset) {
- int num = buf[offset]&0xFF;
- for (int i = 1; i < 4; i++) {
- num = num<<8 | (buf[offset+i]&0xFF);
- }
- return num;
- }
-
- static short getShort(byte[] buf, int offset) {
- short num = (short)(buf[offset]&0xFF);
- num = (short)(num<<8 | (buf[offset+1]&0xFF));
- return num;
- }
-
- /*
- * This class exists to work around a bug in incorrect implementations
- * of CharacterIterator, which incorrectly handle setIndex(endIndex).
- * This iterator relies only on base.setIndex(n) where n is less than
- * endIndex.
- *
- * One caveat: if the base iterator's begin and end indices change
- * the change will not be reflected by this wrapper. Does that matter?
- */
- // TODO: Review this class to see if it's still required.
- private static final class SafeCharIterator implements CharacterIterator,
- Cloneable {
-
- private CharacterIterator base;
- private int rangeStart;
- private int rangeLimit;
- private int currentIndex;
-
- SafeCharIterator(CharacterIterator base) {
- this.base = base;
- this.rangeStart = base.getBeginIndex();
- this.rangeLimit = base.getEndIndex();
- this.currentIndex = base.getIndex();
- }
-
- @Override
- public char first() {
- return setIndex(rangeStart);
- }
-
- @Override
- public char last() {
- return setIndex(rangeLimit - 1);
- }
-
- @Override
- public char current() {
- if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char next() {
-
- currentIndex++;
- if (currentIndex >= rangeLimit) {
- currentIndex = rangeLimit;
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char previous() {
-
- currentIndex--;
- if (currentIndex < rangeStart) {
- currentIndex = rangeStart;
- return DONE;
- }
- else {
- return base.setIndex(currentIndex);
- }
- }
-
- @Override
- public char setIndex(int i) {
-
- if (i < rangeStart || i > rangeLimit) {
- throw new IllegalArgumentException("Invalid position");
- }
- currentIndex = i;
- return current();
- }
-
- @Override
- public int getBeginIndex() {
- return rangeStart;
- }
-
- @Override
- public int getEndIndex() {
- return rangeLimit;
- }
-
- @Override
- public int getIndex() {
- return currentIndex;
- }
-
- @Override
- public Object clone() {
-
- SafeCharIterator copy = null;
- try {
- copy = (SafeCharIterator) super.clone();
- }
- catch(CloneNotSupportedException e) {
- throw new Error("Clone not supported: " + e);
- }
-
- CharacterIterator copyOfBase = (CharacterIterator) base.clone();
- copy.base = copyOfBase;
- return copy;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/resources/BreakIteratorResourceBundle.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.util.resources;
+
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+/**
+ * BreakIteratorResourceBundle is an abstract class for loading BreakIterator
+ * data (rules or dictionary) from each module. An implementation class must
+ * implement getBreakIteratorInfo() that returns an instance of the
+ * corresponding BreakIteratorInfo (basename). The data name is taken from the
+ * BreakIteratorInfo instance.
+ *
+ * <p>For example, if the given key is "WordDictionary" and Locale is "th", the
+ * data name is taken from a BreakIteratorInfo_th and the key's value is
+ * "thai_dict". Its data thai_dict is loaded from the Module of the
+ * implementation class of this class.
+ */
+
+public abstract class BreakIteratorResourceBundle extends ResourceBundle {
+ // If any keys that are not for data names are added to BreakIteratorInfo*,
+ // those keys must be added to NON_DATA_KEYS.
+ private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
+
+ private volatile Set<String> keys;
+
+ /**
+ * Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
+ * The instance shouldn't have its parent.
+ */
+ protected abstract ResourceBundle getBreakIteratorInfo();
+
+ @Override
+ protected Object handleGetObject(String key) {
+ if (NON_DATA_KEYS.contains(key)) {
+ return null;
+ }
+ ResourceBundle info = getBreakIteratorInfo();
+ if (!info.containsKey(key)) {
+ return null;
+ }
+ String path = getClass().getPackage().getName().replace('.', '/')
+ + '/' + info.getString(key);
+ byte[] data;
+ try (InputStream is = getResourceAsStream(path)) {
+ data = is.readAllBytes();
+ } catch (Exception e) {
+ throw new InternalError("Can't load " + path, e);
+ }
+ return data;
+ }
+
+ private InputStream getResourceAsStream(String path) throws Exception {
+ PrivilegedExceptionAction<InputStream> pa;
+ pa = () -> getClass().getModule().getResourceAsStream(path);
+ InputStream is;
+ try {
+ is = AccessController.doPrivileged(pa);
+ } catch (PrivilegedActionException e) {
+ throw e.getException();
+ }
+ return is;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(keySet());
+ }
+
+ @Override
+ protected Set<String> handleKeySet() {
+ if (keys == null) {
+ ResourceBundle info = getBreakIteratorInfo();
+ Set<String> k = info.keySet();
+ k.removeAll(NON_DATA_KEYS);
+ synchronized (this) {
+ if (keys == null) {
+ keys = k;
+ }
+ }
+ }
+ return keys;
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Thu Oct 27 09:42:08 2016 -0700
@@ -123,6 +123,14 @@
}
/**
+ * Gets a break iterator resources resource bundle, using
+ * privileges to allow accessing a sun.* package.
+ */
+ public ResourceBundle getBreakIteratorResources(Locale locale) {
+ return getBundle(type.getTextResourcesPackage() + ".BreakIteratorResources", locale);
+ }
+
+ /**
* Gets a collation data resource bundle, using privileges
* to allow accessing a sun.* package.
*/
--- a/jdk/src/java.base/share/conf/security/java.security Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/conf/security/java.security Thu Oct 27 09:42:08 2016 -0700
@@ -655,6 +655,44 @@
jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & denyAfter 2017-01-01, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation. For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm. This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+# DisabledAlgorithms:
+# " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+# DisabledAlgorithm:
+# AlgorithmName [Constraint]
+#
+# AlgorithmName:
+# (see below)
+#
+# Constraint:
+# KeySizeConstraint
+#
+# KeySizeConstraint:
+# keySize Operator KeyLength
+#
+# Operator:
+# <= | < | == | != | >= | >
+#
+# KeyLength:
+# Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+ DSA keySize < 1024
+
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS/DTLS) processing
#
@@ -936,41 +974,3 @@
#
#jdk.serialFilter=pattern;pattern
-# Algorithm restrictions for signed JAR files
-#
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation. For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm. This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
-#
-# The syntax of the disabled algorithm string is described as follows:
-# DisabledAlgorithms:
-# " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-# DisabledAlgorithm:
-# AlgorithmName [Constraint]
-#
-# AlgorithmName:
-# (see below)
-#
-# Constraint:
-# KeySizeConstraint
-#
-# KeySizeConstraint:
-# keySize Operator KeyLength
-#
-# Operator:
-# <= | < | == | != | >= | >
-#
-# KeyLength:
-# Integer value of the algorithm's key length in bits
-#
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
-#
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024, \
- DSA keySize < 1024
-
--- a/jdk/src/java.base/share/lib/security/default.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/lib/security/default.policy Thu Oct 27 09:42:08 2016 -0700
@@ -111,11 +111,11 @@
grant codeBase "jrt:/jdk.crypto.pkcs11" {
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.*";
- permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
permission java.lang.RuntimePermission "loadLibrary.j2pkcs11";
- // needs "security.pkcs11.allowSingleThreadedModules"
- permission java.util.PropertyPermission "*", "read";
+ permission java.util.PropertyPermission "sun.security.pkcs11.allowSingleThreadedModules", "read";
+ permission java.util.PropertyPermission "os.name", "read";
+ permission java.util.PropertyPermission "os.arch", "read";
permission java.security.SecurityPermission "putProviderProperty.*";
permission java.security.SecurityPermission "clearProviderProperties.*";
permission java.security.SecurityPermission "removeProviderProperty.*";
--- a/jdk/src/java.base/share/native/libnet/net_util.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/native/libnet/net_util.c Thu Oct 27 09:42:08 2016 -0700
@@ -23,20 +23,19 @@
* questions.
*/
-#include "jni.h"
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
-int IPv6_supported() ;
-int reuseport_supported() ;
+#include "java_net_InetAddress.h"
+
+int IPv6_supported();
+int reuseport_supported();
static int IPv6_available;
static int REUSEPORT_available;
JNIEXPORT jint JNICALL ipv6_available()
{
- return IPv6_available ;
+ return IPv6_available;
}
JNIEXPORT jint JNICALL reuseport_available()
@@ -206,11 +205,7 @@
jobject iaObj;
#ifdef AF_INET6
if (him->sa_family == AF_INET6) {
-#ifdef WIN32
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
jbyte *caddr = (jbyte *)&(him6->sin6_addr);
if (NET_IsIPv4Mapped(caddr)) {
int address;
@@ -218,7 +213,7 @@
CHECK_NULL_RETURN(iaObj, NULL);
address = NET_IPv4MappedToIPv4(caddr);
setInetAddress_addr(env, iaObj, address);
- setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
} else {
jint scope;
jboolean ret;
@@ -227,7 +222,7 @@
ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
if (ret == JNI_FALSE)
return NULL;
- setInetAddress_family(env, iaObj, IPv6);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
scope = getScopeID(him);
setInet6Address_scopeid(env, iaObj, scope);
}
@@ -238,7 +233,7 @@
struct sockaddr_in *him4 = (struct sockaddr_in *)him;
iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL);
- setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
*port = ntohs(him4->sin_port);
}
@@ -251,13 +246,10 @@
jint family = AF_INET;
#ifdef AF_INET6
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
if (him->sa_family == AF_INET6) {
-#ifdef WIN32
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
if (NET_IsIPv4Mapped(caddrNew)) {
int addrNew;
--- a/jdk/src/java.base/share/native/libnet/net_util.h Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Thu Oct 27 09:42:08 2016 -0700
@@ -36,12 +36,6 @@
#define MAX_PACKET_LEN 65536
-#define IPv4 1
-#define IPv6 2
-
-#define NET_ERROR(env, ex, msg) \
-{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
-
#define NET_WAIT_READ 0x01
#define NET_WAIT_WRITE 0x02
#define NET_WAIT_CONNECT 0x04
@@ -127,45 +121,43 @@
JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL NET_ThrowNew(JNIEnv *env, int errorNum, char *msg);
+
int NET_GetError();
void NET_ThrowCurrent(JNIEnv *env, char *msg);
jfieldID NET_GetFileDescriptorID(JNIEnv *env);
-JNIEXPORT jint JNICALL ipv6_available() ;
+JNIEXPORT jint JNICALL ipv6_available();
-JNIEXPORT jint JNICALL reuseport_available() ;
+JNIEXPORT jint JNICALL reuseport_available();
JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress);
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+ struct sockaddr *him, int *len,
+ jboolean v4MappedAddress);
JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
void platformInit();
+
void parseExclusiveBindProperty(JNIEnv *env);
-void
-NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+void NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him);
+JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him);
JNIEXPORT jint JNICALL
NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
-int
-NET_IsIPv4Mapped(jbyte* caddr);
+int NET_IsIPv4Mapped(jbyte* caddr);
-int
-NET_IPv4MappedToIPv4(jbyte* caddr);
+int NET_IPv4MappedToIPv4(jbyte* caddr);
-int
-NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
+int NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
-int
-NET_IsZeroAddr(jbyte* caddr);
+int NET_IsZeroAddr(jbyte* caddr);
/* Socket operations
*
@@ -191,9 +183,9 @@
JNIEXPORT jint JNICALL
NET_EnableFastTcpLoopback(int fd);
-int getScopeID (struct sockaddr *);
+int getScopeID(struct sockaddr *);
-int cmpScopeID (unsigned int, struct sockaddr *);
+int cmpScopeID(unsigned int, struct sockaddr *);
unsigned short in_cksum(unsigned short *addr, int len);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/conf/s390x/jvm.cfg Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,34 @@
+# Copyright (c) 2011, 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.
+#
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
--- a/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,27 +22,17 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <ctype.h>
#include <errno.h>
-#include <sys/time.h>
#include <sys/types.h>
-#include <sys/socket.h>
+#include <netinet/in.h>
#include <netinet/in_systm.h>
-#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
-#include <netdb.h>
+#include <stdlib.h>
#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include <sys/time.h>
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_Inet4AddressImpl.h"
@@ -293,13 +283,12 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
@@ -443,7 +432,7 @@
if (!skip) {
struct addrinfo *next
- = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+ = (struct addrinfo *)malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
ret = NULL;
@@ -528,13 +517,12 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((void *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,29 +22,21 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <ctype.h>
#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netinet/in.h>
-#include <netdb.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifdef MACOSX
+#include <netinet/icmp6.h>
+
+#if defined(_ALLBSD_SOURCE)
#include <ifaddrs.h>
#include <net/if.h>
-#include <unistd.h> /* gethostname */
#endif
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
-#ifndef IPV6_DEFS_H
-#include <netinet/icmp6.h>
-#endif
#include "java_net_Inet4AddressImpl.h"
#include "java_net_Inet6AddressImpl.h"
@@ -504,24 +496,23 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((void *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
- sa = (struct sockaddr *) &him4;
+ sa = (struct sockaddr *)&him4;
len = sizeof(him4);
} else {
/*
* For IPv6 address construct a sockaddr_in6 structure.
*/
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
- memset((void *) &him6, 0, sizeof(him6));
- memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+ memset((void *)&him6, 0, sizeof(him6));
+ memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr));
him6.sin6_family = AF_INET6;
- sa = (struct sockaddr *) &him6 ;
- len = sizeof(him6) ;
+ sa = (struct sockaddr *)&him6;
+ len = sizeof(him6);
}
- error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
- NI_NAMEREQD);
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
if (!error) {
ret = (*env)->NewStringUTF(env, host);
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,55 +22,36 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <arpa/inet.h>
#include <errno.h>
-#include <strings.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_arp.h>
-
-#if defined(__solaris__)
-#include <sys/dlpi.h>
-#include <fcntl.h>
-#include <stropts.h>
-#include <sys/sockio.h>
-#endif
-
-#if defined(__linux__)
+#include <stdlib.h>
+#include <string.h>
#include <sys/ioctl.h>
-#include <sys/utsname.h>
-#include <stdio.h>
-#endif
#if defined(_AIX)
-#include <sys/ioctl.h>
#include <netinet/in6_var.h>
#include <sys/ndd_var.h>
#include <sys/kinfo.h>
#endif
-#if defined(_ALLBSD_SOURCE)
-#include <sys/param.h>
-#include <sys/ioctl.h>
+#if defined(__solaris__)
+#include <stropts.h>
+#include <sys/dlpi.h>
#include <sys/sockio.h>
-#if defined(__APPLE__)
+#endif
+
+#if defined(_ALLBSD_SOURCE)
#include <net/ethernet.h>
-#include <net/if_var.h>
#include <net/if_dl.h>
-#include <netinet/in_var.h>
#include <ifaddrs.h>
#endif
-#endif
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
+#include "java_net_InetAddress.h"
+
#if defined(__linux__)
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
#elif defined(__solaris__)
@@ -332,7 +313,7 @@
{
netif *ifs, *curr;
#if defined(AF_INET6)
- int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
+ int family = (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) ? AF_INET : AF_INET6;
#else
int family = AF_INET;
#endif
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,29 +22,23 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
#include <errno.h>
-#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/ioctl.h>
-#ifdef __solaris__
-#include <fcntl.h>
-#include <unistd.h>
-#include <stropts.h>
+#if defined(__solaris__)
+#include <sys/filio.h>
+#endif
-#ifndef BSD_COMP
-#define BSD_COMP
-#endif
-#endif
+#include "net_util.h"
+
+#include "java_net_PlainDatagramSocketImpl.h"
+#include "java_net_InetAddress.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_SocketOptions.h"
+
#ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#include <sys/utsname.h>
-#include <netinet/ip.h>
-
#define IPV6_MULTICAST_IF 17
#ifndef SO_BSDCOMPAT
#define SO_BSDCOMPAT 14
@@ -58,7 +52,11 @@
#endif
#endif // __linux__
-#include <sys/ioctl.h>
+#ifdef __solaris__
+#ifndef BSD_COMP
+#define BSD_COMP
+#endif
+#endif
#ifndef IPTOS_TOS_MASK
#define IPTOS_TOS_MASK 0x1e
@@ -67,12 +65,6 @@
#define IPTOS_PREC_MASK 0xe0
#endif
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_PlainDatagramSocketImpl.h"
-#include "java_net_NetworkInterface.h"
/************************************************************************
* PlainDatagramSocketImpl
*/
@@ -151,9 +143,6 @@
JNIEXPORT void JNICALL
Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
-#ifdef __linux__
- struct utsname sysinfo;
-#endif
pdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
"Ljava/io/FileDescriptor;");
CHECK_NULL(pdsi_fdID);
@@ -550,7 +539,8 @@
iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
#ifdef AF_INET6
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
#else
family = AF_INET;
#endif
@@ -1071,7 +1061,7 @@
*/
for (i = 0; i < len; i++) {
addr = (*env)->GetObjectArrayElement(env, addrArray, i);
- if (getInetAddress_family(env, addr) == IPv4) {
+ if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) {
in.s_addr = htonl(getInetAddress_addr(env, addr));
break;
}
@@ -1970,7 +1960,7 @@
ipv6_join_leave = ipv6_available();
#ifdef __linux__
- if (getInetAddress_family(env, iaObj) == IPv4) {
+ if (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) {
ipv6_join_leave = JNI_FALSE;
}
#endif
@@ -2162,7 +2152,8 @@
jbyte caddr[16];
jint family;
jint address;
- family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+ AF_INET : AF_INET6;
if (family == AF_INET) { /* will convert to IPv4-mapped address */
memset((char *) caddr, 0, 16);
address = getInetAddress_addr(env, iaObj);
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,32 +22,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <errno.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if defined(__linux__)
-#include <sys/poll.h>
-#endif
-#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#ifdef __linux__
-#include <netinet/ip.h>
-#endif
-#include <netdb.h>
-#include <stdlib.h>
-
-#ifdef __solaris__
-#include <fcntl.h>
-#endif
-#ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_SocketOptions.h"
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,20 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <errno.h>
#include <stdlib.h>
-#include <errno.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "jvm.h"
-#include "jni_util.h"
#include "net_util.h"
#include "java_net_SocketInputStream.h"
-/************************************************************************
+/*
* SocketInputStream
*/
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,15 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <errno.h>
#include <stdlib.h>
-#include <errno.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include "jni_util.h"
-#include "jvm.h"
#include "net_util.h"
#include "java_net_SocketOutputStream.h"
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,60 +22,42 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+#include <dlfcn.h>
#include <errno.h>
+#include <net/if.h>
+#include <netinet/tcp.h> // defines TCP_NODELAY
+#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <dlfcn.h>
+#include <sys/ioctl.h>
#include <sys/time.h>
-#ifndef _ALLBSD_SOURCE
-#include <values.h>
-#else
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#ifndef MAXINT
-#define MAXINT INT_MAX
-#endif
-#endif
-
-#ifdef __solaris__
-#include <sys/filio.h>
-#include <sys/sockio.h>
-#include <stropts.h>
-#include <inet/nd.h>
-#endif
-
-#ifdef __linux__
-#include <sys/ioctl.h>
+#if defined(__linux__)
#include <arpa/inet.h>
#include <net/route.h>
#include <sys/utsname.h>
+#endif
-#ifndef IPV6_FLOWINFO_SEND
+#if defined(__solaris__)
+#include <inet/nd.h>
+#include <limits.h>
+#include <stropts.h>
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#endif
+
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
+
+#if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
#define IPV6_FLOWINFO_SEND 33
#endif
-#endif
-
-#ifdef _AIX
-#include <sys/ioctl.h>
+#if defined(__solaris__) && !defined(MAXINT)
+#define MAXINT INT_MAX
#endif
-#include "jni_util.h"
-#include "jvm.h"
-#include "net_util.h"
-
-#include "java_net_SocketOptions.h"
-
/*
* EXCLBIND socket options only on Solaris
*/
@@ -806,13 +788,15 @@
family = getInetAddress_family(env, iaObj);
#ifdef AF_INET6
/* needs work. 1. family 2. clean up him6 etc deallocate memory */
- if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
+ if (ipv6_available() && !(family == java_net_InetAddress_IPv4 &&
+ v4MappedAddress == JNI_FALSE)) {
struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
jbyte caddr[16];
jint address;
- if (family == IPv4) { /* will convert to IPv4-mapped address */
+ if (family == java_net_InetAddress_IPv4) {
+ // convert to IPv4-mapped address
memset((char *) caddr, 0, 16);
address = getInetAddress_addr(env, iaObj);
if (address == INADDR_ANY) {
@@ -906,7 +890,7 @@
#else
/* handle scope_id for solaris */
- if (family != IPv4) {
+ if (family != java_net_InetAddress_IPv4) {
if (ia6_scopeidID) {
him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
}
@@ -917,14 +901,14 @@
{
struct sockaddr_in *him4 = (struct sockaddr_in*)him;
jint address;
- if (family == IPv6) {
+ if (family == java_net_InetAddress_IPv6) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
return -1;
}
memset((char *) him4, 0, sizeof(struct sockaddr_in));
address = getInetAddress_addr(env, iaObj);
him4->sin_port = htons((short) port);
- him4->sin_addr.s_addr = (uint32_t) htonl(address);
+ him4->sin_addr.s_addr = htonl(address);
him4->sin_family = AF_INET;
*len = sizeof(struct sockaddr_in);
}
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h Thu Oct 27 09:42:08 2016 -0700
@@ -26,13 +26,9 @@
#ifndef NET_UTILS_MD_H
#define NET_UTILS_MD_H
+#include <netdb.h>
+#include <sys/poll.h>
#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <sys/poll.h>
int NET_Timeout(int s, long timeout);
int NET_Timeout0(int s, long timeout, long currentTime);
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,10 +22,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
#include "net_util.h"
+
#include "java_net_DualStackPlainDatagramSocketImpl.h"
/*
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,11 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
#include "net_util.h"
+
#include "java_net_DualStackPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
#define SET_BLOCKING 0
#define SET_NONBLOCKING 1
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, 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
@@ -22,24 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
-#include <WinError.h>
+#include "net_util.h"
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
/*
* Returns true if hostname is in dotted IP address format. Note that this
--- a/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,38 +22,13 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
+#include "net_util.h"
#include "java_net_InetAddress.h"
#include "java_net_Inet4AddressImpl.h"
#include "java_net_Inet6AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
-#ifdef WIN32
-#ifndef _WIN64
-
-/* Retain this code a little longer to support building in
- * old environments. _MSC_VER is defined as:
- * 1200 for MSVC++ 6.0
- * 1310 for Vc7
- */
-#if defined(_MSC_VER) && _MSC_VER < 1310
-#define sockaddr_in6 SOCKADDR_IN6
-#endif
-#endif
-#define uint32_t UINT32
-#endif
/*
* Inet6AddressImpl
@@ -300,7 +275,7 @@
addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff);
memset((char *) &him4, 0, sizeof(him4));
- him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_addr.s_addr = htonl(addr);
him4.sin_family = AF_INET;
sa = (struct sockaddr *) &him4;
len = sizeof(him4);
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,17 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h> /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
#include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
/*
* Windows implementation of the java.net.NetworkInterface native methods.
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.h Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.h Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
#ifndef NETWORK_INTERFACE_H
#define NETWORK_INTERFACE_H
-#include <iphlpapi.h>
#include "net_util.h"
/*
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,19 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h> /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
-#include <limits.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
#include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
-#include "net_util.h"
/*
* Windows implementation of the java.net.NetworkInterface native methods.
@@ -554,14 +545,20 @@
* Create a NetworkInterface object and populate it
*/
netifObj = (*env)->NewObject(env, ni_class, ni_ctor);
+ if (netifObj == NULL) {
+ return NULL;
+ }
name = (*env)->NewStringUTF(env, ifs->name);
+ if (name == NULL) {
+ return NULL;
+ }
if (ifs->dNameIsUnicode) {
displayName = (*env)->NewString(env, (PWCHAR)ifs->displayName,
(jsize)wcslen ((PWCHAR)ifs->displayName));
} else {
displayName = (*env)->NewStringUTF(env, ifs->displayName);
}
- if (netifObj == NULL || name == NULL || displayName == NULL) {
+ if (displayName == NULL) {
return NULL;
}
(*env)->SetObjectField(env, netifObj, ni_nameID, name);
@@ -621,26 +618,28 @@
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
} else /* AF_INET6 */ {
int scope;
+ jboolean ret;
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
- if (iaObj) {
- jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));
- if (ret == JNI_FALSE) {
- return NULL;
- }
- scope = addrs->addr.sa6.sin6_scope_id;
- if (scope != 0) { /* zero is default value, no need to set */
- setInet6Address_scopeid(env, iaObj, scope);
- setInet6Address_scopeifname(env, iaObj, netifObj);
- }
- ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
- if (ibObj == NULL) {
- free_netaddr(netaddrP);
- return NULL;
- }
- (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
- (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
- (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
+ if (iaObj == NULL) {
+ return NULL;
+ }
+ ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));
+ if (ret == JNI_FALSE) {
+ return NULL;
}
+ scope = addrs->addr.sa6.sin6_scope_id;
+ if (scope != 0) { /* zero is default value, no need to set */
+ setInet6Address_scopeid(env, iaObj, scope);
+ setInet6Address_scopeifname(env, iaObj, netifObj);
+ }
+ ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
+ if (ibObj == NULL) {
+ free_netaddr(netaddrP);
+ return NULL;
+ }
+ (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+ (*env)->SetShortField(env, ibObj, ni_ibmaskID, addrs->mask);
+ (*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
}
(*env)->SetObjectArrayElement(env, addrArr, addr_index, iaObj);
addrs = addrs->next;
--- a/jdk/src/java.base/windows/native/libnet/SocketInputStream.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/SocketInputStream.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,24 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
#include "java_net_SocketInputStream.h"
-#include "net_util.h"
-#include "jni_util.h"
-
/*************************************************************************
* SocketInputStream
*/
-
static jfieldID IO_fd_fdID;
/*
--- a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,20 +22,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
#include "java_net_SocketOutputStream.h"
-#include "net_util.h"
-#include "jni_util.h"
-
/************************************************************************
* SocketOutputStream
*/
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,15 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include <malloc.h>
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
+
+#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_InetAddress.h"
#ifndef IPTOS_TOS_MASK
#define IPTOS_TOS_MASK 0x1e
@@ -39,14 +39,6 @@
#define IPTOS_PREC_MASK 0xe0
#endif
-#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_NetworkInterface.h"
-
-#include "NetworkInterface.h"
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(i) IN_CLASSD(i)
@@ -439,7 +431,7 @@
memset((char *)&lcladdr, 0, sizeof(lcladdr));
family = getInetAddress_family(env, addressObj);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -561,13 +553,13 @@
addr = getInetAddress_addr(env, address);
family = getInetAddress_family(env, address);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
}
- fdc = family == IPv4? fd: fd1;
+ fdc = family == java_net_InetAddress_IPv4 ? fd : fd1;
if (xp_or_later) {
/* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
@@ -605,12 +597,12 @@
jint fd, len;
SOCKETADDRESS addr;
- if (family == IPv4) {
+ if (family == java_net_InetAddress_IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
} else {
fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
if (IS_NULL(fdObj)) {
@@ -678,7 +670,7 @@
}
family = getInetAddress_family(env, iaObj);
- if (family == IPv4) {
+ if (family == java_net_InetAddress_IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
} else {
if (!ipv6_available()) {
@@ -830,6 +822,7 @@
}
if (IS_NULL(addressObj)) {
JNU_ThrowNullPointerException(env, "Null address in peek()");
+ return -1;
} else {
address = getInetAddress_addr(env, addressObj);
/* We only handle IPv4 for now. Will support IPv6 once its in the os */
@@ -905,7 +898,7 @@
return 0;
}
setInetAddress_addr(env, addressObj, ntohl(remote_addr.sa4.sin_addr.s_addr));
- setInetAddress_family(env, addressObj, IPv4);
+ setInetAddress_family(env, addressObj, java_net_InetAddress_IPv4);
/* return port */
return ntohs(remote_addr.sa4.sin_port);
@@ -1127,11 +1120,23 @@
}
if (n == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+ free(fullPacket);
+ }
+ return -1;
} else if (n == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
"operation interrupted");
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+ free(fullPacket);
+ }
+ return -1;
} else if (n < 0) {
NET_ThrowCurrent(env, "Datagram receive failed");
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+ free(fullPacket);
+ }
+ return -1;
} else {
jobject packetAddress;
@@ -1597,7 +1602,7 @@
{
jobject addr;
- int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
+ int ret = getInetAddrFromIf(env, java_net_InetAddress_IPv4, nif, &addr);
if (ret == -1) {
return -1;
}
@@ -1882,7 +1887,7 @@
default :
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket option not supported by PlainDatagramSocketImp");
- break;
+ return;
}
@@ -2272,9 +2277,9 @@
len = sizeof(struct sockaddr_in);
/* family==-1 when socket is not connected */
- if ((family == IPv6) || (family == -1 && fd == -1)) {
+ if ((family == java_net_InetAddress_IPv6) || (family == -1 && fd == -1)) {
fd = fd1; /* must be IPv6 only */
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
if (fd == -1) {
@@ -2325,6 +2330,7 @@
if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl,
sizeof (ittl)) < 0) {
NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed");
+ return;
}
}
@@ -2518,6 +2524,9 @@
} else {
ifindex = getIndexFromIf (env, niObj);
if (ifindex == -1) {
+ if ((*env)->ExceptionOccurred(env)) {
+ return;
+ }
NET_ThrowCurrent(env, "get ifindex failed");
return;
}
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,23 +22,13 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <malloc.h>
-#include <sys/types.h>
-
-#include "java_net_SocketOptions.h"
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_InetAddress.h"
-#include "java_io_FileDescriptor.h"
-#include "java_lang_Integer.h"
#include "net_util.h"
-#include "jni_util.h"
+
+#include "java_net_TwoStacksPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
/************************************************************************
* TwoStacksPlainSocketImpl
@@ -108,7 +98,7 @@
psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
CHECK_NULL(psi_portID);
psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
- CHECK_NULL(psi_portID);
+ CHECK_NULL(psi_lastfdID);
psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
CHECK_NULL(psi_localportID);
psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
@@ -153,17 +143,17 @@
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
if (IS_NULL(fd1Obj)) {
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+ NET_SocketClose(fd);
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"null fd1 object");
- (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
- NET_SocketClose(fd);
return;
}
fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
if (fd1 == -1) {
- NET_ThrowCurrent(env, "create");
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
NET_SocketClose(fd);
+ NET_ThrowCurrent(env, "create");
return;
} else {
/* Set socket attribute so it is not passed to any child process */
@@ -413,7 +403,7 @@
family = getInetAddress_family(env, iaObj);
- if (family == IPv6 && !ipv6_supported) {
+ if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
@@ -655,18 +645,18 @@
return;
}
if (fd2 == fd) { /* v4 */
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
} else {
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
}
fd = fd2;
} else {
int ret;
if (fd1 != -1) {
fd = fd1;
- len = sizeof (struct SOCKADDR_IN6);
+ len = sizeof(struct sockaddr_in6);
} else {
- len = sizeof (struct sockaddr_in);
+ len = sizeof(struct sockaddr_in);
}
if (timeout) {
ret = NET_Timeout(fd, timeout);
@@ -728,7 +718,7 @@
}
setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr));
- setInetAddress_family(env, socketAddressObj, IPv4);
+ setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
} else {
/* AF_INET6 -> Inet6Address */
@@ -754,7 +744,7 @@
return;
}
setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr);
- setInetAddress_family(env, socketAddressObj, IPv6);
+ setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id);
}
@@ -907,6 +897,7 @@
isRcvTimeoutSupported = JNI_FALSE;
} else {
NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
+ return;
}
}
if (fd1 != -1) {
--- a/jdk/src/java.base/windows/native/libnet/icmp.h Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef ICMP_H
-#define ICMP_H
-
-/*
- * Structure of an internet header, naked of options.
- *
- * We declare ip_len and ip_off to be short, rather than ushort_t
- * pragmatically since otherwise unsigned comparisons can result
- * against negative integers quite easily, and fail in subtle ways.
- */
-struct ip {
- unsigned char ip_hl:4, /* header length */
- ip_v:4; /* version */
- unsigned char ip_tos; /* type of service */
- short ip_len; /* total length */
- unsigned short ip_id; /* identification */
- short ip_off; /* fragment offset field */
-#define IP_DF 0x4000 /* don't fragment flag */
-#define IP_MF 0x2000 /* more fragments flag */
- unsigned char ip_ttl; /* time to live */
- unsigned char ip_p; /* protocol */
- unsigned short ip_sum; /* checksum */
- struct in_addr ip_src, ip_dst; /* source and dest address */
-};
-
-/*
- * Structure of an icmp header.
- */
-struct icmp {
- unsigned char icmp_type; /* type of message, see below */
- unsigned char icmp_code; /* type sub code */
- unsigned short icmp_cksum; /* ones complement cksum of struct */
- union {
- unsigned char ih_pptr; /* ICMP_PARAMPROB */
- struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
- struct ih_idseq {
- unsigned short icd_id;
- unsigned short icd_seq;
- } ih_idseq;
- int ih_void;
-
- /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
- struct ih_pmtu {
- unsigned short ipm_void;
- unsigned short ipm_nextmtu;
- } ih_pmtu;
-
- struct ih_rtradv {
- unsigned char irt_num_addrs;
- unsigned char irt_wpa;
- unsigned short irt_lifetime;
- } ih_rtradv;
- } icmp_hun;
-#define icmp_pptr icmp_hun.ih_pptr
-#define icmp_gwaddr icmp_hun.ih_gwaddr
-#define icmp_id icmp_hun.ih_idseq.icd_id
-#define icmp_seq icmp_hun.ih_idseq.icd_seq
-#define icmp_void icmp_hun.ih_void
-#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
-#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
- union {
- struct id_ts {
- unsigned int its_otime;
- unsigned int its_rtime;
- unsigned int its_ttime;
- } id_ts;
- struct id_ip {
- struct ip idi_ip;
- /* options and then 64 bits of data */
- } id_ip;
- unsigned int id_mask;
- char id_data[1];
- } icmp_dun;
-#define icmp_otime icmp_dun.id_ts.its_otime
-#define icmp_rtime icmp_dun.id_ts.its_rtime
-#define icmp_ttime icmp_dun.id_ts.its_ttime
-#define icmp_ip icmp_dun.id_ip.idi_ip
-#define icmp_mask icmp_dun.id_mask
-#define icmp_data icmp_dun.id_data
-};
-
-#define ICMP_ECHOREPLY 0 /* echo reply */
-#define ICMP_ECHO 8 /* echo service */
-
-/*
- * ICMPv6 structures & constants
- */
-
-typedef struct icmp6_hdr {
- u_char icmp6_type; /* type field */
- u_char icmp6_code; /* code field */
- u_short icmp6_cksum; /* checksum field */
- union {
- u_int icmp6_un_data32[1]; /* type-specific field */
- u_short icmp6_un_data16[2]; /* type-specific field */
- u_char icmp6_un_data8[4]; /* type-specific field */
- } icmp6_dataun;
-} icmp6_t;
-
-#define icmp6_data32 icmp6_dataun.icmp6_un_data32
-#define icmp6_data16 icmp6_dataun.icmp6_un_data16
-#define icmp6_data8 icmp6_dataun.icmp6_un_data8
-#define icmp6_pptr icmp6_data32[0] /* parameter prob */
-#define icmp6_mtu icmp6_data32[0] /* packet too big */
-#define icmp6_id icmp6_data16[0] /* echo request/reply */
-#define icmp6_seq icmp6_data16[1] /* echo request/reply */
-#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
-
-struct ip6_pseudo_hdr /* for calculate the ICMPv6 checksum */
-{
- struct in6_addr ip6_src;
- struct in6_addr ip6_dst;
- u_int ip6_plen;
- u_int ip6_nxt;
-};
-
-#define ICMP6_ECHO_REQUEST 128
-#define ICMP6_ECHO_REPLY 129
-#define IPPROTO_ICMPV6 58
-#define IPV6_UNICAST_HOPS 4 /* Set/get IP unicast hop limit */
-
-
-#endif
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Thu Oct 27 09:42:08 2016 -0700
@@ -22,12 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+#include "net_util.h"
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "net_util.h"
-#include "jni.h"
+#include "java_net_InetAddress.h"
+#include "java_net_SocketOptions.h"
// Taken from mstcpip.h in Windows SDK 8.0 or newer.
#define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)
@@ -593,7 +591,7 @@
void dumpAddr (char *str, void *addr) {
- struct SOCKADDR_IN6 *a = (struct SOCKADDR_IN6 *)addr;
+ struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr;
int family = a->sin6_family;
printf ("%s\n", str);
if (family == AF_INET) {
@@ -812,7 +810,7 @@
* 0 if error
* > 0 interface index to use
*/
-jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
+jint getDefaultIPv6Interface(JNIEnv *env, struct sockaddr_in6 *target_addr)
{
int ret;
DWORD b;
@@ -866,9 +864,9 @@
int *len, jboolean v4MappedAddress) {
jint family, iafam;
iafam = getInetAddress_family(env, iaObj);
- family = (iafam == IPv4)? AF_INET : AF_INET6;
+ family = (iafam == java_net_InetAddress_IPv4)? AF_INET : AF_INET6;
if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
jbyte caddr[16];
jint address, scopeid = 0;
jint cached_scope_id = 0;
@@ -894,7 +892,7 @@
cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
}
- memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6));
+ memset((char *)him6, 0, sizeof(struct sockaddr_in6));
him6->sin6_port = (u_short) htons((u_short)port);
memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
him6->sin6_family = AF_INET6;
@@ -904,7 +902,7 @@
(*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
}
him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
- *len = sizeof(struct SOCKADDR_IN6) ;
+ *len = sizeof(struct sockaddr_in6) ;
} else {
struct sockaddr_in *him4 = (struct sockaddr_in *)him;
jint address;
@@ -964,12 +962,12 @@
}
int getScopeID(struct sockaddr *him) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
return him6->sin6_scope_id;
}
int cmpScopeID(unsigned int scope, struct sockaddr *him) {
- struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
return him6->sin6_scope_id == scope;
}
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h Thu Oct 27 09:42:08 2016 -0700
@@ -22,195 +22,10 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
#include <winsock2.h>
#include <WS2tcpip.h>
-
-/* typedefs that were defined correctly for the first time
- * in Nov. 2001 SDK, which we need to include here.
- * Specifically, in6_addr and sockaddr_in6 (which is defined but
- * not correctly). When moving to a later SDK remove following
- * code between START and END
- */
-
-/* --- START --- */
-
-/* WIN64 already uses newer SDK */
-#ifdef _WIN64
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-#ifdef _MSC_VER
-#define WS2TCPIP_INLINE __inline
-#else
-#define WS2TCPIP_INLINE extern inline /* GNU style */
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1310
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-/*SO_REUSEPORT is not supported on Windows, define it to 0*/
-#define SO_REUSEPORT 0
-
-/* Retain this code a little longer to support building in
- * old environments. _MSC_VER is defined as:
- * 1200 for MSVC++ 6.0
- * 1310 for Vc7
- */
-
-#define IPPROTO_IPV6 41
-#define IPV6_MULTICAST_IF 9
-
-struct in6_addr {
- union {
- u_char Byte[16];
- u_short Word[8];
- } u;
-};
-
-/*
-** Defines to match RFC 2553.
-*/
-#define _S6_un u
-#define _S6_u8 Byte
-#define s6_addr _S6_un._S6_u8
-
-/*
-** Defines for our implementation.
-*/
-#define s6_bytes u.Byte
-#define s6_words u.Word
-
-/* IPv6 socket address structure, RFC 2553 */
-
-struct SOCKADDR_IN6 {
- short sin6_family; /* AF_INET6 */
- u_short sin6_port; /* Transport level port number */
- u_long sin6_flowinfo; /* IPv6 flow information */
- struct in6_addr sin6_addr; /* IPv6 address */
- u_long sin6_scope_id; /* set of interfaces for a scope */
-};
-
-
-/* Error codes from getaddrinfo() */
-
-#define EAI_AGAIN WSATRY_AGAIN
-#define EAI_BADFLAGS WSAEINVAL
-#define EAI_FAIL WSANO_RECOVERY
-#define EAI_FAMILY WSAEAFNOSUPPORT
-#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
-//#define EAI_NODATA WSANO_DATA
-#define EAI_NONAME WSAHOST_NOT_FOUND
-#define EAI_SERVICE WSATYPE_NOT_FOUND
-#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
-
-#define EAI_NODATA EAI_NONAME
-
-/* Structure used in getaddrinfo() call */
-
-typedef struct addrinfo {
- int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- size_t ai_addrlen; /* Length of ai_addr */
- char *ai_canonname; /* Canonical name for nodename */
- struct sockaddr *ai_addr; /* Binary address */
- struct addrinfo *ai_next; /* Next structure in linked list */
-} ADDRINFO, FAR * LPADDRINFO;
-
-/* Flags used in "hints" argument to getaddrinfo() */
-
-#define AI_PASSIVE 0x1 /* Socket address will be used in bind() call */
-#define AI_CANONNAME 0x2 /* Return canonical name in first ai_canonname */
-#define AI_NUMERICHOST 0x4 /* Nodename must be a numeric address string */
-
-/* IPv6 Multicasting definitions */
-
-/* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP */
-
-typedef struct ipv6_mreq {
- struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast address */
- unsigned int ipv6mr_interface; /* Interface index */
-} IPV6_MREQ;
-
-#define IPV6_ADD_MEMBERSHIP 12 /* Add an IP group membership */
-#define IPV6_DROP_MEMBERSHIP 13 /* Drop an IP group membership */
-#define IPV6_MULTICAST_LOOP 11 /* Set/get IP multicast loopback */
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_MULTICAST(const struct in6_addr *a)
-{
- return (a->s6_bytes[0] == 0xff);
-}
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *a)
-{
- return (a->s6_bytes[0] == 0xfe
- && a->s6_bytes[1] == 0x80);
-}
-
-#define NI_MAXHOST 1025 /* Max size of a fully-qualified domain name */
-#define NI_MAXSERV 32 /* Max size of a service name */
-
-#define INET_ADDRSTRLEN 16 /* Max size of numeric form of IPv4 address */
-#define INET6_ADDRSTRLEN 46 /* Max size of numeric form of IPv6 address */
-
-/* Flags for getnameinfo() */
-
-#define NI_NOFQDN 0x01 /* Only return nodename portion for local hosts */
-#define NI_NUMERICHOST 0x02 /* Return numeric form of the host's address */
-#define NI_NAMEREQD 0x04 /* Error if the host's name not in DNS */
-#define NI_NUMERICSERV 0x08 /* Return numeric form of the service (port #) */
-#define NI_DGRAM 0x10 /* Service is a datagram service */
-
-
-#define IN6_IS_ADDR_V4MAPPED(a) \
- (((a)->s6_words[0] == 0) && ((a)->s6_words[1] == 0) && \
- ((a)->s6_words[2] == 0) && ((a)->s6_words[3] == 0) && \
- ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0xffff))
-
-
-/* --- END --- */
-#endif /* end 'else older build environment' */
-
-#endif
-
-#if !INCL_WINSOCK_API_TYPEDEFS
-
-typedef
-int
-(WSAAPI * LPFN_GETADDRINFO)(
- IN const char FAR * nodename,
- IN const char FAR * servname,
- IN const struct addrinfo FAR * hints,
- OUT struct addrinfo FAR * FAR * res
- );
-
-typedef
-void
-(WSAAPI * LPFN_FREEADDRINFO)(
- IN struct addrinfo FAR * ai
- );
-
-typedef
-int
-(WSAAPI * LPFN_GETNAMEINFO)(
- IN const struct sockaddr FAR * sa,
- IN int salen,
- OUT char FAR * host,
- IN DWORD hostlen,
- OUT char FAR * serv,
- IN DWORD servlen,
- IN int flags
- );
-#endif
+#include <iphlpapi.h>
+#include <icmpapi.h>
/* used to disable connection reset messages on Windows XP */
#ifndef SIO_UDP_CONNRESET
@@ -229,13 +44,9 @@
#define IPV6_V6ONLY 27 /* Treat wildcard bind as AF_INET6-only. */
#endif
-#include "java_io_FileDescriptor.h"
-#include "java_net_SocketOptions.h"
-
#define MAX_BUFFER_LEN 2048
#define MAX_HEAP_BUFFER_LEN 65536
-
/* true if SO_RCVTIMEO is supported by underlying provider */
extern jboolean isRcvTimeoutSupported;
@@ -249,7 +60,7 @@
typedef union {
struct sockaddr sa;
struct sockaddr_in sa4;
- struct SOCKADDR_IN6 sa6;
+ struct sockaddr_in6 sa6;
} SOCKETADDRESS;
/*
@@ -264,7 +75,7 @@
#define SOCKETADDRESS_COPY(DST,SRC) { \
if ((SRC)->sa_family == AF_INET6) { \
- memcpy ((DST), (SRC), sizeof (struct SOCKADDR_IN6)); \
+ memcpy ((DST), (SRC), sizeof (struct sockaddr_in6)); \
} else { \
memcpy ((DST), (SRC), sizeof (struct sockaddr_in)); \
} \
--- a/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Thu Oct 27 09:42:08 2016 -0700
@@ -202,6 +202,7 @@
if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+ return IOS_THROWN;
}
return convertReturnVal(env, (jint)written, JNI_FALSE);
@@ -250,6 +251,7 @@
if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+ return IOS_THROWN;
}
return convertLongReturnVal(env, totalWritten, JNI_FALSE);
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletSecurity.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -40,36 +40,25 @@
import java.util.StringTokenizer;
import java.security.*;
import java.lang.reflect.*;
+import jdk.internal.misc.JavaNetURLClassLoaderAccess;
+import jdk.internal.misc.JavaSecurityAccess;
+import jdk.internal.misc.SharedSecrets;
import sun.awt.AWTSecurityManager;
import sun.awt.AppContext;
import sun.awt.AWTPermissions;
import sun.security.util.SecurityConstants;
+
/**
* This class defines an applet security policy
*
*/
public
class AppletSecurity extends AWTSecurityManager {
-
- //URLClassLoader.acc
- private static Field facc = null;
-
- //AccessControlContext.context;
- private static Field fcontext = null;
-
- static {
- try {
- facc = URLClassLoader.class.getDeclaredField("acc");
- facc.setAccessible(true);
- fcontext = AccessControlContext.class.getDeclaredField("context");
- fcontext.setAccessible(true);
- } catch (NoSuchFieldException e) {
- throw new UnsupportedOperationException(e);
- }
- }
-
+ private static final JavaNetURLClassLoaderAccess JNUCLA
+ = SharedSecrets.getJavaNetURLClassLoaderAccess();
+ private static final JavaSecurityAccess JSA = SharedSecrets.getJavaSecurityAccess();
/**
* Construct and initialize.
@@ -148,6 +137,7 @@
final ClassLoader currentLoader = context[i].getClassLoader();
if (currentLoader instanceof URLClassLoader) {
+ URLClassLoader ld = (URLClassLoader)currentLoader;
loader = AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
@@ -156,12 +146,12 @@
ProtectionDomain[] pds = null;
try {
- acc = (AccessControlContext) facc.get(currentLoader);
+ acc = JNUCLA.getAccessControlContext(ld);
if (acc == null) {
return null;
}
- pds = (ProtectionDomain[]) fcontext.get(acc);
+ pds = JSA.getProtectDomains(acc);
if (pds == null) {
return null;
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java Thu Oct 27 09:42:08 2016 -0700
@@ -30,10 +30,6 @@
import java.awt.Toolkit;
import java.io.*;
import java.io.FileNotFoundException;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.Callable;
@@ -244,11 +240,10 @@
* @exception FileNotFoundException if file does not exist
*/
public static ShellFolder getShellFolder(File file) throws FileNotFoundException {
- Path path = Paths.get(file.getPath());
if (file instanceof ShellFolder) {
return (ShellFolder)file;
}
- if (!Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
+ if (!file.exists()) {
throw new FileNotFoundException();
}
return shellFolderManager.createShellFolder(file);
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Thu Oct 27 09:42:08 2016 -0700
@@ -1970,6 +1970,11 @@
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() throws IOException {
+ boolean disable = Boolean.getBoolean(
+ "sun.rmi.server.activation.disableErrRedirect");
+ if (disable)
+ return null;
+
File file =
Files.createTempFile("rmid-err", null).toFile();
PrintStream errStream =
--- a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Thu Oct 27 09:42:08 2016 -0700
@@ -36,6 +36,7 @@
#include <BaseTsd.h>
#include <wincrypt.h>
#include <stdio.h>
+#include <memory>
#define OID_EKU_ANY "2.5.29.37.0"
@@ -48,6 +49,7 @@
#define KEYSTORE_EXCEPTION "java/security/KeyStoreException"
#define PROVIDER_EXCEPTION "java/security/ProviderException"
#define SIGNATURE_EXCEPTION "java/security/SignatureException"
+#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
extern "C" {
@@ -57,10 +59,22 @@
DEF_STATIC_JNI_OnLoad
/*
+ * Throws an arbitrary Java exception with the given message.
+ */
+void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,
+ const char *szMessage)
+{
+ jclass exceptionClazz = env->FindClass(exceptionName);
+ if (exceptionClazz != NULL) {
+ env->ThrowNew(exceptionClazz, szMessage);
+ }
+}
+
+/*
* Throws an arbitrary Java exception.
* The exception message is a Windows system error message.
*/
-void ThrowException(JNIEnv *env, char *exceptionName, DWORD dwError)
+void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)
{
char szMessage[1024];
szMessage[0] = '\0';
@@ -71,12 +85,22 @@
strcpy(szMessage, "Unknown error");
}
- jclass exceptionClazz = env->FindClass(exceptionName);
- if (exceptionClazz != NULL) {
- env->ThrowNew(exceptionClazz, szMessage);
- }
+ ThrowExceptionWithMessage(env, exceptionName, szMessage);
}
+/*
+ * Overloaded 'operator new[]' variant, which will raise Java's
+ * OutOfMemoryError in the case of a failure.
+ */
+static void* operator new[](std::size_t size, JNIEnv *env)
+{
+ void* buf = ::operator new[](size, std::nothrow);
+ if (buf == NULL) {
+ ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,
+ "Native memory allocation failed");
+ }
+ return buf;
+}
/*
* Maps the name of a hash algorithm to an algorithm identifier.
@@ -211,7 +235,10 @@
} else if (length > 0) {
- pbData = new BYTE[length];
+ pbData = new (env) BYTE[length];
+ if (pbData == NULL) {
+ __leave;
+ }
if (::CryptGenRandom(
hCryptProv,
@@ -441,7 +468,11 @@
NULL, 0)) > 1) {
// Found friendly name
- pszNameString = new char[cchNameString];
+ pszNameString = new (env) char[cchNameString];
+ if (pszNameString == NULL) {
+ __leave;
+ }
+
CertGetNameString(pc,
CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
pszNameString, cchNameString);
@@ -578,7 +609,10 @@
}
// Copy hash from Java to native buffer
- pHashBuffer = new jbyte[jHashSize];
+ pHashBuffer = new (env) jbyte[jHashSize];
+ if (pHashBuffer == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
// Set hash value in the hash object
@@ -616,7 +650,10 @@
__leave;
}
- pSignedHashBuffer = new jbyte[dwBufLen];
+ pSignedHashBuffer = new (env) jbyte[dwBufLen];
+ if (pSignedHashBuffer == NULL) {
+ __leave;
+ }
if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE)
{
ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
@@ -704,9 +741,16 @@
}
// Copy hash and signedHash from Java to native buffer
- pHashBuffer = new jbyte[jHashSize];
+ pHashBuffer = new (env) jbyte[jHashSize];
+ if (pHashBuffer == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
- pSignedHashBuffer = new jbyte[jSignedHashSize];
+
+ pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
+ if (pSignedHashBuffer == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
pSignedHashBuffer);
@@ -919,7 +963,10 @@
}
// Copy encoding from Java to native buffer
- pbCertEncoding = new jbyte[jCertEncodingSize];
+ pbCertEncoding = new (env) jbyte[jCertEncodingSize];
+ if (pbCertEncoding == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
// Create a certificate context from the encoded cert
@@ -932,7 +979,10 @@
// Set the certificate's friendly name
int size = env->GetStringLength(jCertAliasName);
- pszCertAliasName = new WCHAR[size + 1];
+ pszCertAliasName = new (env) WCHAR[size + 1];
+ if (pszCertAliasName == NULL) {
+ __leave;
+ }
jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
@@ -970,7 +1020,10 @@
__leave;
}
- pszContainerName = new char[dwDataLen];
+ pszContainerName = new (env) char[dwDataLen];
+ if (pszContainerName == NULL) {
+ __leave;
+ }
if (! ::CryptGetProvParam(
(HCRYPTPROV) hCryptProv,
@@ -984,7 +1037,10 @@
}
// Convert to a wide char string
- pwszContainerName = new WCHAR[dwDataLen];
+ pwszContainerName = new (env) WCHAR[dwDataLen];
+ if (pwszContainerName == NULL) {
+ __leave;
+ }
if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
@@ -1007,7 +1063,10 @@
__leave;
}
- pszProviderName = new char[dwDataLen];
+ pszProviderName = new (env) char[dwDataLen];
+ if (pszProviderName == NULL) {
+ __leave;
+ }
if (! ::CryptGetProvParam(
(HCRYPTPROV) hCryptProv,
@@ -1021,7 +1080,10 @@
}
// Convert to a wide char string
- pwszProviderName = new WCHAR[dwDataLen];
+ pwszProviderName = new (env) WCHAR[dwDataLen];
+ if (pwszProviderName == NULL) {
+ __leave;
+ }
if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
@@ -1161,7 +1223,10 @@
}
// Copy encoding from Java to native buffer
- pbCertEncoding = new jbyte[jCertEncodingSize];
+ pbCertEncoding = new (env) jbyte[jCertEncodingSize];
+ if (pbCertEncoding == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
// Create a certificate context from the encoded cert
@@ -1184,7 +1249,10 @@
if ((cchNameString = ::CertGetNameString(pTBDCertContext,
CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {
- pszNameString = new char[cchNameString];
+ pszNameString = new (env) char[cchNameString];
+ if (pszNameString == NULL) {
+ __leave;
+ }
::CertGetNameString(pTBDCertContext,
CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
@@ -1334,7 +1402,10 @@
continue; // not found
}
- pszNameString = new char[cchNameString];
+ pszNameString = new (env) char[cchNameString];
+ if (pszNameString == NULL) {
+ __leave;
+ }
if (::CertGetNameString(pCertContext,
CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
@@ -1510,7 +1581,10 @@
__try
{
// Copy data from Java buffer to native buffer
- pData = new jbyte[dwBufLen];
+ pData = new (env) jbyte[dwBufLen];
+ if (pData == NULL) {
+ __leave;
+ }
env->GetByteArrayRegion(jData, 0, dwBufLen, pData);
if (doEncrypt == JNI_TRUE) {
@@ -1584,7 +1658,10 @@
__leave;
}
- pbKeyBlob = new BYTE[dwBlobLen];
+ pbKeyBlob = new (env) BYTE[dwBlobLen];
+ if (pbKeyBlob == NULL) {
+ __leave;
+ }
// Generate key blob
if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0,
@@ -1638,8 +1715,12 @@
RSAPUBKEY* pRsaPubKey =
(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
+
int len = sizeof(pRsaPubKey->pubexp);
- exponentBytes = new jbyte[len];
+ exponentBytes = new (env) jbyte[len];
+ if (exponentBytes == NULL) {
+ __leave;
+ }
// convert from little-endian while copying from blob
for (int i = 0, j = len - 1; i < len; i++, j--) {
@@ -1690,9 +1771,12 @@
RSAPUBKEY* pRsaPubKey =
(RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
+
int len = pRsaPubKey->bitlen / 8;
-
- modulusBytes = new jbyte[len];
+ modulusBytes = new (env) jbyte[len];
+ if (modulusBytes == NULL) {
+ __leave;
+ }
BYTE * pbModulus =
(BYTE *) (keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
@@ -1813,12 +1897,16 @@
(jKeyBitLength / 8);
}
- jbyte* jBlobBytes = new jbyte[jBlobLength];
+ jbyte* jBlobBytes = NULL;
jbyte* jBlobElement;
jbyteArray jBlob = NULL;
jsize jElementLength;
__try {
+ jBlobBytes = new (env) jbyte[jBlobLength];
+ if (jBlobBytes == NULL) {
+ __leave;
+ }
BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;
if (bGeneratePrivateKeyBlob) {
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, 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
@@ -32,7 +32,6 @@
import java.security.*;
-import sun.security.action.GetPropertyAction;
import sun.security.util.PropertyExpander;
import sun.security.pkcs11.wrapper.*;
@@ -58,15 +57,30 @@
// will accept single threaded modules regardless of the setting in their
// config files.
private static final boolean staticAllowSingleThreadedModules;
+ private static final String osName;
+ private static final String osArch;
static {
- String p = "sun.security.pkcs11.allowSingleThreadedModules";
- String s = AccessController.doPrivileged(new GetPropertyAction(p));
- if ("false".equalsIgnoreCase(s)) {
+ List<String> props = AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ @Override
+ public List<String> run() {
+ return List.of(
+ System.getProperty(
+ "sun.security.pkcs11.allowSingleThreadedModules",
+ "true"),
+ System.getProperty("os.name"),
+ System.getProperty("os.arch"));
+ }
+ }
+ );
+ if ("false".equalsIgnoreCase(props.get(0))) {
staticAllowSingleThreadedModules = false;
} else {
staticAllowSingleThreadedModules = true;
}
+ osName = props.get(1);
+ osArch = props.get(2);
}
private final static boolean DEBUG = false;
@@ -650,8 +664,6 @@
// replace "/$ISA/" with "/sparcv9/" on 64-bit Solaris SPARC
// and with "/amd64/" on Solaris AMD64.
// On all other platforms, just turn it into a "/"
- String osName = System.getProperty("os.name", "");
- String osArch = System.getProperty("os.arch", "");
String prefix = lib.substring(0, i);
String suffix = lib.substring(i + 5);
if (osName.equals("SunOS") && osArch.equals("sparcv9")) {
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java Thu Oct 27 09:42:08 2016 -0700
@@ -58,7 +58,7 @@
*/
public class Constants {
- public static final String NEWLINE = System.getProperty("line.separator");
+ public static final String NEWLINE = System.lineSeparator();
public static final String INDENT = " ";
--- a/jdk/src/jdk.httpserver/share/classes/module-info.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/module-info.java Thu Oct 27 09:42:08 2016 -0700
@@ -24,7 +24,6 @@
*/
module jdk.httpserver {
- requires java.logging;
exports com.sun.net.httpserver;
exports com.sun.net.httpserver.spi;
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java Thu Oct 27 09:42:08 2016 -0700
@@ -29,7 +29,8 @@
import java.net.*;
import javax.net.ssl.*;
import java.util.*;
-import java.util.logging.Logger;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import java.text.*;
import com.sun.net.httpserver.*;
@@ -221,7 +222,7 @@
Logger logger = server.getLogger();
String msg = "sendResponseHeaders: rCode = "+ rCode
+ ": forcing contentLen = -1";
- logger.warning (msg);
+ logger.log (Level.WARNING, msg);
}
contentLen = -1;
}
@@ -234,7 +235,7 @@
final Logger logger = server.getLogger();
String msg =
"sendResponseHeaders: being invoked with a content length for a HEAD request";
- logger.warning (msg);
+ logger.log (Level.WARNING, msg);
}
noContentToSend = true;
contentLen = 0;
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java Thu Oct 27 09:42:08 2016 -0700
@@ -28,7 +28,8 @@
import java.io.*;
import javax.net.ssl.*;
import java.nio.channels.*;
-import java.util.logging.Logger;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.spi.*;
@@ -119,7 +120,7 @@
}
closed = true;
if (logger != null && chan != null) {
- logger.finest ("Closing connection: " + chan.toString());
+ logger.log (Level.TRACE, "Closing connection: " + chan.toString());
}
if (!chan.isOpen()) {
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java Thu Oct 27 09:42:08 2016 -0700
@@ -26,7 +26,7 @@
package sun.net.httpserver;
import java.io.*;
import java.util.*;
-import java.util.logging.Logger;
+import java.lang.System.Logger;
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.spi.*;
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,7 +25,8 @@
package sun.net.httpserver;
-import java.util.logging.Logger;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import java.security.PrivilegedAction;
/**
@@ -115,7 +116,8 @@
if (System.getProperty("sun.net.httpserver.readTimeout")
!=null)
{
- logger.warning ("sun.net.httpserver.readTimeout "+
+ logger.log (Level.WARNING,
+ "sun.net.httpserver.readTimeout "+
"property is no longer used. "+
"Use sun.net.httpserver.maxReqTime instead."
);
@@ -123,7 +125,8 @@
if (System.getProperty("sun.net.httpserver.writeTimeout")
!=null)
{
- logger.warning ("sun.net.httpserver.writeTimeout "+
+ logger.log (Level.WARNING,
+ "sun.net.httpserver.writeTimeout "+
"property is no longer used. Use "+
"sun.net.httpserver.maxRspTime instead."
);
@@ -131,7 +134,8 @@
if (System.getProperty("sun.net.httpserver.selCacheTimeout")
!=null)
{
- logger.warning ("sun.net.httpserver.selCacheTimeout "+
+ logger.log (Level.WARNING,
+ "sun.net.httpserver.selCacheTimeout "+
"property is no longer used."
);
}
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Thu Oct 27 09:42:08 2016 -0700
@@ -30,8 +30,8 @@
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
-import java.util.logging.Logger;
-import java.util.logging.Level;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import javax.net.ssl.*;
import com.sun.net.httpserver.*;
import java.security.AccessController;
@@ -81,7 +81,7 @@
final static boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1;
private Timer timer, timer1;
- private Logger logger;
+ private final Logger logger;
private Thread dispatcherThread;
ServerImpl (
@@ -90,7 +90,7 @@
this.protocol = protocol;
this.wrapper = wrapper;
- this.logger = Logger.getLogger ("com.sun.net.httpserver");
+ this.logger = System.getLogger ("com.sun.net.httpserver");
ServerConfig.checkLegacyProperties (logger);
https = protocol.equalsIgnoreCase ("https");
this.address = addr;
@@ -115,12 +115,12 @@
if (timer1Enabled) {
timer1 = new Timer ("server-timer1", true);
timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS);
- logger.config ("HttpServer timer1 enabled period in ms: "+TIMER_MILLIS);
- logger.config ("MAX_REQ_TIME: "+MAX_REQ_TIME);
- logger.config ("MAX_RSP_TIME: "+MAX_RSP_TIME);
+ logger.log (Level.DEBUG, "HttpServer timer1 enabled period in ms: ", TIMER_MILLIS);
+ logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME);
+ logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME);
}
events = new LinkedList<Event>();
- logger.config ("HttpServer created "+protocol+" "+ addr);
+ logger.log (Level.DEBUG, "HttpServer created "+protocol+" "+ addr);
}
public void bind (InetSocketAddress addr, int backlog) throws IOException {
@@ -211,7 +211,7 @@
dispatcherThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- logger.log(Level.FINER, "ServerImpl.stop: ", e);
+ logger.log (Level.TRACE, "ServerImpl.stop: ", e);
}
}
}
@@ -224,7 +224,7 @@
}
HttpContextImpl context = new HttpContextImpl (protocol, path, handler, this);
contexts.add (context);
- logger.config ("context created: " + path);
+ logger.log (Level.DEBUG, "context created: " + path);
return context;
}
@@ -234,7 +234,7 @@
}
HttpContextImpl context = new HttpContextImpl (protocol, path, null, this);
contexts.add (context);
- logger.config ("context created: " + path);
+ logger.log (Level.DEBUG, "context created: " + path);
return context;
}
@@ -243,7 +243,7 @@
throw new NullPointerException ("null path parameter");
}
contexts.remove (protocol, path);
- logger.config ("context removed: " + path);
+ logger.log (Level.DEBUG, "context removed: " + path);
}
public synchronized void removeContext (HttpContext context) throws IllegalArgumentException {
@@ -251,7 +251,7 @@
throw new IllegalArgumentException ("wrong HttpContext type");
}
contexts.remove ((HttpContextImpl)context);
- logger.config ("context removed: " + context.getPath());
+ logger.log (Level.DEBUG, "context removed: " + context.getPath());
}
public InetSocketAddress getAddress() {
@@ -310,7 +310,7 @@
}
} catch (IOException e) {
logger.log (
- Level.FINER, "Dispatcher (1)", e
+ Level.TRACE, "Dispatcher (1)", e
);
c.close();
}
@@ -331,7 +331,7 @@
idleConnections.add (c);
} catch (IOException e) {
dprint(e);
- logger.log(Level.FINER, "Dispatcher(8)", e);
+ logger.log (Level.TRACE, "Dispatcher(8)", e);
c.close();
}
}
@@ -416,9 +416,9 @@
// call the selector just to process the cancelled keys
selector.selectNow();
} catch (IOException e) {
- logger.log (Level.FINER, "Dispatcher (4)", e);
+ logger.log (Level.TRACE, "Dispatcher (4)", e);
} catch (Exception e) {
- logger.log (Level.FINER, "Dispatcher (7)", e);
+ logger.log (Level.TRACE, "Dispatcher (7)", e);
}
}
try {selector.close(); } catch (Exception e) {}
@@ -427,7 +427,7 @@
private void handleException (SelectionKey key, Exception e) {
HttpConnection conn = (HttpConnection)key.attachment();
if (e != null) {
- logger.log (Level.FINER, "Dispatcher (2)", e);
+ logger.log (Level.TRACE, "Dispatcher (2)", e);
}
closeConnection(conn);
}
@@ -439,10 +439,10 @@
Exchange t = new Exchange (chan, protocol, conn);
executor.execute (t);
} catch (HttpError e1) {
- logger.log (Level.FINER, "Dispatcher (4)", e1);
+ logger.log (Level.TRACE, "Dispatcher (4)", e1);
closeConnection(conn);
} catch (IOException e) {
- logger.log (Level.FINER, "Dispatcher (5)", e);
+ logger.log (Level.TRACE, "Dispatcher (5)", e);
closeConnection(conn);
}
}
@@ -522,7 +522,8 @@
newconnection = true;
if (https) {
if (sslContext == null) {
- logger.warning ("SSL connection received. No https contxt created");
+ logger.log (Level.WARNING,
+ "SSL connection received. No https contxt created");
throw new HttpError ("No SSL context established");
}
sslStreams = new SSLStreams (ServerImpl.this, sslContext, chan);
@@ -657,7 +658,7 @@
}
} catch (IOException e1) {
- logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1);
+ logger.log (Level.TRACE, "ServerImpl.Exchange (1)", e1);
closeConnection(connection);
} catch (NumberFormatException e3) {
reject (Code.HTTP_BAD_REQUEST,
@@ -666,7 +667,7 @@
reject (Code.HTTP_BAD_REQUEST,
requestLine, "URISyntaxException thrown");
} catch (Exception e4) {
- logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4);
+ logger.log (Level.TRACE, "ServerImpl.Exchange (2)", e4);
closeConnection(connection);
}
}
@@ -722,7 +723,7 @@
closeConnection(connection);
}
} catch (IOException e) {
- logger.log (Level.FINER, "ServerImpl.sendReply", e);
+ logger.log (Level.TRACE, "ServerImpl.sendReply", e);
closeConnection(connection);
}
}
@@ -730,7 +731,7 @@
}
void logReply (int code, String requestStr, String text) {
- if (!logger.isLoggable(Level.FINE)) {
+ if (!logger.isLoggable(Level.DEBUG)) {
return;
}
if (text == null) {
@@ -744,7 +745,7 @@
}
String message = r + " [" + code + " " +
Code.msg(code) + "] ("+text+")";
- logger.fine (message);
+ logger.log (Level.DEBUG, message);
}
long getTicks() {
@@ -843,7 +844,7 @@
}
}
for (HttpConnection c : toClose) {
- logger.log (Level.FINE, "closing: no request: " + c);
+ logger.log (Level.DEBUG, "closing: no request: " + c);
reqConnections.remove (c);
allConnections.remove (c);
c.close();
@@ -859,7 +860,7 @@
}
}
for (HttpConnection c : toClose) {
- logger.log (Level.FINE, "closing: no response: " + c);
+ logger.log (Level.DEBUG, "closing: no response: " + c);
rspConnections.remove (c);
allConnections.remove (c);
c.close();
@@ -870,13 +871,13 @@
}
void logStackTrace (String s) {
- logger.finest (s);
+ logger.log (Level.TRACE, s);
StringBuilder b = new StringBuilder ();
StackTraceElement[] e = Thread.currentThread().getStackTrace();
for (int i=0; i<e.length; i++) {
b.append (e[i].toString()).append("\n");
}
- logger.finest (b.toString());
+ logger.log (Level.TRACE, b.toString());
}
static long getTimeMillis(long secs) {
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Thu Oct 27 09:42:08 2016 -0700
@@ -50,6 +50,9 @@
import jdk.security.jarsigner.JarSigner;
import jdk.security.jarsigner.JarSignerException;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.timestamp.TimestampToken;
import sun.security.tools.KeyStoreUtil;
import sun.security.x509.*;
import sun.security.util.*;
@@ -87,6 +90,15 @@
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
+ private static final DisabledAlgorithmConstraints DISABLED_CHECK =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
+ private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+ private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
+ .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+
// Attention:
// This is the entry that get launched by the security tool jarsigner.
public static void main(String args[]) throws Exception {
@@ -163,6 +175,8 @@
private Throwable chainNotValidatedReason = null;
+ private boolean seeWeak = false;
+
CertificateFactory certificateFactory;
CertPathValidator validator;
PKIXParameters pkixParameters;
@@ -628,6 +642,10 @@
{
boolean anySigned = false; // if there exists entry inside jar signed
JarFile jf = null;
+ Map<String,String> digestMap = new HashMap<>();
+ Map<String,PKCS7> sigMap = new HashMap<>();
+ Map<String,String> sigNameMap = new HashMap<>();
+ Map<String,String> unparsableSignatures = new HashMap<>();
try {
jf = new JarFile(jarName, true);
@@ -638,16 +656,44 @@
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
entriesVec.addElement(je);
- InputStream is = null;
- try {
- is = jf.getInputStream(je);
- while (is.read(buffer, 0, buffer.length) != -1) {
- // we just read. this will throw a SecurityException
- // if a signature/digest check fails.
- }
- } finally {
- if (is != null) {
- is.close();
+ try (InputStream is = jf.getInputStream(je)) {
+ String name = je.getName();
+ if (signatureRelated(name)
+ && SignatureFileVerifier.isBlockOrSF(name)) {
+ String alias = name.substring(name.lastIndexOf('/') + 1,
+ name.lastIndexOf('.'));
+ try {
+ if (name.endsWith(".SF")) {
+ Manifest sf = new Manifest(is);
+ boolean found = false;
+ for (Object obj : sf.getMainAttributes().keySet()) {
+ String key = obj.toString();
+ if (key.endsWith("-Digest-Manifest")) {
+ digestMap.put(alias,
+ key.substring(0, key.length() - 16));
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ unparsableSignatures.putIfAbsent(alias,
+ String.format(
+ rb.getString("history.unparsable"),
+ name));
+ }
+ } else {
+ sigNameMap.put(alias, name);
+ sigMap.put(alias, new PKCS7(is));
+ }
+ } catch (IOException ioe) {
+ unparsableSignatures.putIfAbsent(alias, String.format(
+ rb.getString("history.unparsable"), name));
+ }
+ } else {
+ while (is.read(buffer, 0, buffer.length) != -1) {
+ // we just read. this will throw a SecurityException
+ // if a signature/digest check fails.
+ }
}
}
}
@@ -805,10 +851,11 @@
System.out.println(rb.getString(
".X.not.signed.by.specified.alias.es."));
}
- System.out.println();
}
- if (man == null)
+ if (man == null) {
+ System.out.println();
System.out.println(rb.getString("no.manifest."));
+ }
// If signer is a trusted cert or private entry in user's own
// keystore, it can be self-signed.
@@ -816,8 +863,99 @@
signerSelfSigned = false;
}
+ // Even if the verbose option is not specified, all out strings
+ // must be generated so seeWeak can be updated.
+ if (!digestMap.isEmpty()
+ || !sigMap.isEmpty()
+ || !unparsableSignatures.isEmpty()) {
+ if (verbose != null) {
+ System.out.println();
+ }
+ for (String s : sigMap.keySet()) {
+ if (!digestMap.containsKey(s)) {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nosf"), s));
+ }
+ }
+ for (String s : digestMap.keySet()) {
+ PKCS7 p7 = sigMap.get(s);
+ if (p7 != null) {
+ String history;
+ try {
+ SignerInfo si = p7.getSignerInfos()[0];
+ X509Certificate signer = si.getCertificate(p7);
+ String digestAlg = digestMap.get(s);
+ String sigAlg = AlgorithmId.makeSigAlg(
+ si.getDigestAlgorithmId().getName(),
+ si.getDigestEncryptionAlgorithmId().getName());
+ PublicKey key = signer.getPublicKey();
+ PKCS7 tsToken = si.getTsToken();
+ if (tsToken != null) {
+ SignerInfo tsSi = tsToken.getSignerInfos()[0];
+ X509Certificate tsSigner = tsSi.getCertificate(tsToken);
+ byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
+ TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
+ PublicKey tsKey = tsSigner.getPublicKey();
+ String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
+ String tsSigAlg = AlgorithmId.makeSigAlg(
+ tsSi.getDigestAlgorithmId().getName(),
+ tsSi.getDigestEncryptionAlgorithmId().getName());
+ Calendar c = Calendar.getInstance(
+ TimeZone.getTimeZone("UTC"),
+ Locale.getDefault(Locale.Category.FORMAT));
+ c.setTime(tsTokenInfo.getDate());
+ history = String.format(
+ rb.getString("history.with.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key),
+ c,
+ tsSigner.getSubjectX500Principal(),
+ withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(tsSigAlg, SIG_PRIMITIVE_SET),
+ withWeak(tsKey));
+ } else {
+ history = String.format(
+ rb.getString("history.without.ts"),
+ signer.getSubjectX500Principal(),
+ withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+ withWeak(sigAlg, SIG_PRIMITIVE_SET),
+ withWeak(key));
+ }
+ } catch (Exception e) {
+ // The only usage of sigNameMap, remember the name
+ // of the block file if it's invalid.
+ history = String.format(
+ rb.getString("history.unparsable"),
+ sigNameMap.get(s));
+ }
+ if (verbose != null) {
+ System.out.println(history);
+ }
+ } else {
+ unparsableSignatures.putIfAbsent(s, String.format(
+ rb.getString("history.nobk"), s));
+ }
+ }
+ if (verbose != null) {
+ for (String s : unparsableSignatures.keySet()) {
+ System.out.println(unparsableSignatures.get(s));
+ }
+ }
+ }
+ System.out.println();
if (!anySigned) {
- if (hasSignature) {
+ if (seeWeak) {
+ if (verbose != null) {
+ System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose"));
+ System.out.println("\n " +
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS +
+ "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS));
+ } else {
+ System.out.println(rb.getString("jar.treated.unsigned.see.weak"));
+ }
+ } else if (hasSignature) {
System.out.println(rb.getString("jar.treated.unsigned"));
} else {
System.out.println(rb.getString("jar.is.unsigned"));
@@ -845,7 +983,9 @@
if (weakAlg != 0) {
// In fact, jarsigner verification did not catch this
// since it has not read the JarFile content itself.
- // Everything is done with JarFile API.
+ // Everything is done with JarFile API. The signing
+ // history (digestMap etc) will show these info and
+ // print out proper warnings.
}
if (badKeyUsage) {
@@ -936,6 +1076,26 @@
System.exit(1);
}
+ private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
+ if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
+ return alg;
+ } else {
+ seeWeak = true;
+ return String.format(rb.getString("with.weak"), alg);
+ }
+ }
+
+ private String withWeak(PublicKey key) {
+ if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
+ return String.format(
+ rb.getString("key.bit"), KeyUtil.getKeySize(key));
+ } else {
+ seeWeak = true;
+ return String.format(
+ rb.getString("key.bit.weak"), KeyUtil.getKeySize(key));
+ }
+ }
+
private static MessageFormat validityTimeForm = null;
private static MessageFormat notYetTimeForm = null;
private static MessageFormat expiredTimeForm = null;
@@ -1125,22 +1285,22 @@
void signJar(String jarName, String alias)
throws Exception {
- DisabledAlgorithmConstraints dac =
- new DisabledAlgorithmConstraints(
- DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
-
- if (digestalg != null && !dac.permits(
- Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), digestalg, null)) {
+ if (digestalg != null && !DISABLED_CHECK.permits(
+ DIGEST_PRIMITIVE_SET, digestalg, null)) {
weakAlg |= 1;
}
- if (tSADigestAlg != null && !dac.permits(
- Collections.singleton(CryptoPrimitive.MESSAGE_DIGEST), tSADigestAlg, null)) {
+ if (tSADigestAlg != null && !DISABLED_CHECK.permits(
+ DIGEST_PRIMITIVE_SET, tSADigestAlg, null)) {
weakAlg |= 4;
}
- if (sigalg != null && !dac.permits(
- Collections.singleton(CryptoPrimitive.SIGNATURE), sigalg, null)) {
+ if (sigalg != null && !DISABLED_CHECK.permits(
+ SIG_PRIMITIVE_SET , sigalg, null)) {
weakAlg |= 2;
}
+ if (!DISABLED_CHECK.permits(
+ SIG_PRIMITIVE_SET, privateKey)) {
+ weakAlg |= 8;
+ }
boolean aliasUsed = false;
X509Certificate tsaCert = null;
@@ -1385,6 +1545,11 @@
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
tSADigestAlg, "-tsadigestalg"));
}
+ if ((weakAlg & 8) == 8) {
+ System.out.println(String.format(
+ rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
+ privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
+ }
} else {
System.out.println(rb.getString("jar.signed."));
}
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java Thu Oct 27 09:42:08 2016 -0700
@@ -145,11 +145,26 @@
{"jar.is.unsigned",
"jar is unsigned."},
{"jar.treated.unsigned",
- "Signature not parsable or verifiable. The jar will be treated as unsigned. The jar may have been signed with a weak algorithm that is now disabled. For more information, rerun jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+ "WARNING: Signature is either not parsable or not verifiable, and the jar will be treated as unsigned. For more information, re-run jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+ {"jar.treated.unsigned.see.weak",
+ "The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled.\n\nRe-run jarsigner with the -verbose option for more details."},
+ {"jar.treated.unsigned.see.weak.verbose",
+ "WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:"},
{"jar.signed.", "jar signed."},
{"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
{"jar.verified.", "jar verified."},
{"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
+
+ {"history.with.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s\n Timestamped by \"%6$s\" on %5$tc\n Timestamp digest algorithm: %7$s\n Timestamp signature algorithm: %8$s, %9$s"},
+ {"history.without.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s"},
+ {"history.unparsable", "- Unparsable signature-related file %s"},
+ {"history.nosf", "- Missing signature-related file META-INF/%s.SF"},
+ {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"},
+
+ {"with.weak", "%s (weak)"},
+ {"key.bit", "%d-bit key"},
+ {"key.bit.weak", "%d-bit key (weak)"},
+
{"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
@@ -248,6 +263,8 @@
"The signer's certificate is self-signed."},
{"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.",
"The %1$s algorithm specified for the %2$s option is considered a security risk."},
+ {"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.",
+ "The %s signing key has a keysize of %d which is considered a security risk."},
{"This.jar.contains.entries.whose.certificate.chain.is.not.validated.reason.1",
"This jar contains entries whose certificate chain is not validated. Reason: %s"},
{"no.timestamp.signing",
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Thu Oct 27 09:42:08 2016 -0700
@@ -80,6 +80,7 @@
String fname, mname, ename;
String zname = "";
String rootjar = null;
+ Set<String> concealedPackages = new HashSet<>();
private static final int BASE_VERSION = 0;
@@ -821,22 +822,21 @@
return true;
}
- private static Set<String> findPackages(ZipFile zf) {
- return zf.stream()
- .filter(e -> e.getName().endsWith(".class"))
- .map(e -> toPackageName(e))
- .filter(pkg -> pkg.length() > 0)
- .distinct()
- .collect(Collectors.toSet());
- }
-
private static String toPackageName(ZipEntry entry) {
return toPackageName(entry.getName());
}
private static String toPackageName(String path) {
assert path.endsWith(".class");
- int index = path.lastIndexOf('/');
+ int index;
+ if (path.startsWith(VERSIONS_DIR)) {
+ index = path.indexOf('/', VERSIONS_DIR.length());
+ if (index <= 0) {
+ return "";
+ }
+ path = path.substring(index + 1);
+ }
+ index = path.lastIndexOf('/');
if (index != -1) {
return path.substring(0, index).replace('/', '.');
} else {
@@ -875,7 +875,7 @@
entryMap.put(entryName, entry);
} else if (entries.add(entry)) {
jarEntries.add(entryName);
- if (entry.basename.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
+ if (entry.basename.endsWith(".class"))
packages.add(toPackageName(entry.basename));
if (isUpdate)
entryMap.put(entryName, entry);
@@ -1068,7 +1068,7 @@
}
jarEntries.add(name);
- if (name.endsWith(".class") && !(name.startsWith(VERSIONS_DIR)))
+ if (name.endsWith(".class"))
packages.add(toPackageName(name));
}
}
@@ -1762,6 +1762,13 @@
}
/**
+ * Print a warning message
+ */
+ void warn(String s) {
+ err.println(s);
+ }
+
+ /**
* Main routine to start program.
*/
public static void main(String args[]) {
@@ -1975,24 +1982,30 @@
ByteBuffer bb = ByteBuffer.wrap(moduleInfos.get(MODULE_INFO));
ModuleDescriptor rd = ModuleDescriptor.read(bb);
- Set<String> exports = rd.exports()
- .stream()
- .map(Exports::source)
- .collect(toSet());
-
- Set<String> conceals = packages.stream()
- .filter(p -> !exports.contains(p))
- .collect(toSet());
+ concealedPackages = findConcealedPackages(rd);
for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
if (!(isValidVersionedDescriptor(vd, rd)))
return false;
- e.setValue(extendedInfoBytes(rd, vd, e.getValue(), conceals));
+ e.setValue(extendedInfoBytes(rd, vd, e.getValue(), concealedPackages));
}
return true;
}
+ private Set<String> findConcealedPackages(ModuleDescriptor md){
+ Objects.requireNonNull(md);
+
+ Set<String> exports = md.exports()
+ .stream()
+ .map(Exports::source)
+ .collect(toSet());
+
+ return packages.stream()
+ .filter(p -> !exports.contains(p))
+ .collect(toSet());
+ }
+
private static boolean isPlatformModule(String name) {
return name.startsWith("java.") || name.startsWith("jdk.");
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java Thu Oct 27 09:42:08 2016 -0700
@@ -152,9 +152,13 @@
return;
}
if (fp.isPublicClass()) {
- main.error(Main.formatMsg("error.validator.new.public.class", entryName));
- isValid = false;
- return;
+ if (!isConcealed(internalName)) {
+ main.error(Main.formatMsg("error.validator.new.public.class", entryName));
+ isValid = false;
+ return;
+ }
+ main.warn(Main.formatMsg("warn.validator.concealed.public.class", entryName));
+ debug("%s is a public class entry in a concealed package", entryName);
}
debug("%s is a non-public class entry", entryName);
fps.put(internalName, fp);
@@ -169,7 +173,7 @@
// are the two classes/resources identical?
if (fp.isIdentical(matchFp)) {
- main.error(Main.formatMsg("error.validator.identical.entry", entryName));
+ main.warn(Main.formatMsg("warn.validator.identical.entry", entryName));
return; // it's okay, just takes up room
}
debug("sha1 not equal -- different bytes");
@@ -204,7 +208,7 @@
}
debug("%s is a resource", entryName);
- main.error(Main.formatMsg("error.validator.resources.with.same.name", entryName));
+ main.warn(Main.formatMsg("warn.validator.resources.with.same.name", entryName));
fps.put(internalName, fp);
return;
}
@@ -235,6 +239,15 @@
return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null;
}
+ private boolean isConcealed(String internalName) {
+ if (main.concealedPackages.isEmpty()) {
+ return false;
+ }
+ int idx = internalName.lastIndexOf('/');
+ String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
+ return main.concealedPackages.contains(pkgName);
+ }
+
private void debug(String fmt, Object... args) {
if (DEBUG) System.err.format(fmt, args);
}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Oct 27 09:42:08 2016 -0700
@@ -99,16 +99,19 @@
entry: {0}, is an isolated nested class
error.validator.new.public.class=\
entry: {0}, contains a new public class not found in base entries
-error.validator.identical.entry=\
- warning - entry: {0} contains a class that is identical to an entry already in the jar
error.validator.incompatible.class.version=\
entry: {0}, has a class version incompatible with an earlier version
error.validator.different.api=\
entry: {0}, contains a class with different api from earlier version
-error.validator.resources.with.same.name=\
- warning - entry: {0}, multiple resources with same name
error.validator.names.mismatch=\
entry: {0}, contains a class with internal name {1}, names do not match
+warn.validator.identical.entry=\
+ warning - entry: {0} contains a class that is identical to an entry already in the jar
+warn.validator.resources.with.same.name=\
+ warning - entry: {0}, multiple resources with same name
+warn.validator.concealed.public.class=\
+ warning - entry {0} is a public class in a concealed package, \n\
+ placing this jar on the class path will result in incompatible public interfaces
out.added.manifest=\
added manifest
out.added.module-info=\
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -246,9 +246,9 @@
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this object's class, if the size of the argument list
* does not match the number of declared arguments for the method,
- * if the method is a constructor or static intializer, or
+ * if the method is a constructor or static initializer, or
* if {@link #INVOKE_NONVIRTUAL} is specified and the method is
- * either abstract or a non-default interface member.
+ * abstract.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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,10 +347,12 @@
throws InvalidTypeException,
InvocationException {
/*
- * Only default methods allowed for nonvirtual invokes
+ * For nonvirtual invokes, method must have a body
*/
- if (isNonVirtual(options) && !method.isDefault()) {
- throw new IllegalArgumentException("Not a default method");
+ if (isNonVirtual(options)) {
+ if (method.isAbstract()) {
+ throw new IllegalArgumentException("Abstract method");
+ }
}
}
--- a/jdk/src/jdk.jdi/share/classes/module-info.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@
exports com.sun.jdi.connect.spi;
exports com.sun.jdi.event;
exports com.sun.jdi.request;
- exports com.sun.tools.jdi to jdk.hotspot.agent;
uses com.sun.jdi.connect.Connector;
uses com.sun.jdi.connect.spi.TransportService;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java Thu Oct 27 09:42:08 2016 -0700
@@ -186,7 +186,7 @@
new PrintWriter(System.err, true));
}
try {
- optionsHelper.handleOptions(this, args);
+ optionsHelper.handleOptionsNoUnhandled(this, args);
if (options.help) {
optionsHelper.showHelp(PROGNAME);
return EXIT_OK;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Oct 27 09:42:08 2016 -0700
@@ -466,7 +466,21 @@
return pp;
}
+ // used by jimage. Return unhandled arguments like "create", "describe".
public List<String> handleOptions(T task, String[] args) throws BadArgs {
+ return handleOptions(task, args, true);
+ }
+
+ // used by jlink. No unhandled arguments like "create", "describe".
+ void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs {
+ handleOptions(task, args, false);
+ }
+
+ // shared code that handles options for both jlink and jimage. jimage uses arguments like
+ // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned
+ // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag
+ // tells whether to allow for unhandled arguments or not.
+ private List<String> handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs {
// findbugs warning, copy instead of keeping a reference.
command = Arrays.copyOf(args, args.length);
@@ -499,10 +513,10 @@
String[] arr = new String[filteredArgs.size()];
args = filteredArgs.toArray(arr);
- List<String> rest = new ArrayList<>();
+ List<String> rest = collectUnhandled? new ArrayList<>() : null;
// process options
for (int i = 0; i < args.length; i++) {
- if (!args[i].isEmpty() && args[i].charAt(0) == '-') {
+ if (args[i].charAt(0) == '-') {
String name = args[i];
PlugOption pluginOption = null;
Option<T> option = getOption(name);
@@ -539,7 +553,12 @@
i = args.length;
}
} else {
- rest.add(args[i]);
+ if (collectUnhandled) {
+ rest.add(args[i]);
+ } else {
+ throw new BadArgs("err.orphan.argument", args[i]).
+ showUsage(true);
+ }
}
}
return rest;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Oct 27 09:42:08 2016 -0700
@@ -95,6 +95,7 @@
err.dir.exists={0} already exists
err.badpattern=bad pattern {0}
err.unknown.option=unknown option: {0}
+err.orphan.argument=orphan argument: {0}
err.missing.arg=no value given for {0}
err.internal.error=internal error: {0} {1} {2}
err.invalid.arg.for.option=invalid argument for option: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorResources_th.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.text.resources.ext;
+
+import java.util.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources_th extends BreakIteratorResourceBundle {
+ @Override
+ protected ResourceBundle getBreakIteratorInfo() {
+ return new BreakIteratorInfo_th();
+ }
+}
--- a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,24 +25,34 @@
package sun.reflect;
+import java.io.OptionalDataException;
+import java.lang.invoke.MethodHandle;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
+/**
+ * ReflectionFactory supports custom serialization.
+ * Its methods support the creation of uninitialized objects, invoking serialization
+ * private methods for readObject, writeObject, readResolve, and writeReplace.
+ * <p>
+ * ReflectionFactory access is restricted, if a security manager is active,
+ * unless the permission {@code RuntimePermission("reflectionFactoryAccess")}
+ * is granted.
+ */
public class ReflectionFactory {
private static final ReflectionFactory soleInstance = new ReflectionFactory();
- private final jdk.internal.reflect.ReflectionFactory delegate;
-
- private ReflectionFactory() {
- delegate = AccessController.doPrivileged(
+ private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged(
new PrivilegedAction<jdk.internal.reflect.ReflectionFactory>() {
public jdk.internal.reflect.ReflectionFactory run() {
return jdk.internal.reflect.ReflectionFactory.getReflectionFactory();
}
- });
- }
+ });
+
+ private ReflectionFactory() {}
private static final Permission REFLECTION_FACTORY_ACCESS_PERM
= new RuntimePermission("reflectionFactoryAccess");
@@ -53,7 +63,7 @@
*
* <p> First, if there is a security manager, its {@code checkPermission}
* method is called with a {@link java.lang.RuntimePermission} with target
- * {@code "reflectionFactoryAccess"}. This may result in a securit
+ * {@code "reflectionFactoryAccess"}. This may result in a security
* exception.
*
* <p> The returned {@code ReflectionFactory} object should be carefully
@@ -61,6 +71,7 @@
* data and invoke private methods, as well as to load unverified bytecodes.
* It must never be passed to untrusted code.
*
+ * @return the ReflectionFactory
* @throws SecurityException if a security manager exists and its
* {@code checkPermission} method doesn't allow access to
* the RuntimePermission "reflectionFactoryAccess".
@@ -73,11 +84,129 @@
return soleInstance;
}
- public Constructor<?> newConstructorForSerialization(Class<?> classToInstantiate,
- Constructor<?> constructorToCall)
+ /**
+ * Returns an accessible no-arg constructor for a class.
+ * The no-arg constructor is found searching the class and its supertypes.
+ *
+ * @param cl the class to instantiate
+ * @return a no-arg constructor for the class or {@code null} if
+ * the class or supertypes do not have a suitable no-arg constructor
+ */
+ public final Constructor<?> newConstructorForSerialization(Class<?> cl)
{
- return delegate.newConstructorForSerialization(classToInstantiate,
- constructorToCall);
+ return delegate.newConstructorForSerialization(cl);
+ }
+
+ /**
+ * Returns an accessible no-arg constructor for an externalizable class to be
+ * initialized using a public no-argument constructor.
+ *
+ * @param cl the class to instantiate
+ * @return A no-arg constructor for the class; returns {@code null} if
+ * the class does not implement {@link java.io.Externalizable}
+ */
+ public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+ return delegate.newConstructorForExternalization(cl);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObject} method of the class or
+ * {@code null} if the class does not have a {@code readObject} method
+ */
+ public final MethodHandle readObjectForSerialization(Class<?> cl) {
+ return delegate.readObjectForSerialization(cl);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readObjectNoData} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectInputStream} passed to
+ * {@code readObjectNoData}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code readObjectNoData} method
+ * of the class or {@code null} if the class does not have a
+ * {@code readObjectNoData} method
+ */
+ public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+ return delegate.readObjectNoDataForSerialization(cl);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeObject} method on
+ * a Serializable class.
+ * The first argument of {@link MethodHandle#invoke} is the serializable
+ * object and the second argument is the {@code ObjectOutputStream} passed to
+ * {@code writeObject}.
+ *
+ * @param cl a Serializable class
+ * @return a direct MethodHandle for the {@code writeObject} method of the class or
+ * {@code null} if the class does not have a {@code writeObject} method
+ */
+ public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+ return delegate.writeObjectForSerialization(cl);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code readResolve} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code readResolve} method of the class or
+ * {@code null} if the class does not have a {@code readResolve} method
+ */
+ public final MethodHandle readResolveForSerialization(Class<?> cl) {
+ return delegate.readResolveForSerialization(cl);
+ }
+
+ /**
+ * Returns a direct MethodHandle for the {@code writeReplace} method on
+ * a serializable class.
+ * The single argument of {@link MethodHandle#invoke} is the serializable
+ * object.
+ *
+ * @param cl the Serializable class
+ * @return a direct MethodHandle for the {@code writeReplace} method of the class or
+ * {@code null} if the class does not have a {@code writeReplace} method
+ */
+ public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+ return delegate.writeReplaceForSerialization(cl);
+ }
+
+ /**
+ * Returns true if the class has a static initializer.
+ * The presence of a static initializer is used to compute the serialVersionUID.
+ * @param cl a serializable class
+ * @return {@code true} if the class has a static initializer,
+ * otherwise {@code false}
+ */
+ public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+ return delegate.hasStaticInitializerForSerialization(cl);
+ }
+
+ /**
+ * Returns a new OptionalDataException with {@code eof} set to {@code true}
+ * or {@code false}.
+ * @param bool the value of {@code eof} in the created OptionalDataException
+ * @return a new OptionalDataException
+ */
+ public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+ Constructor<OptionalDataException> cons = delegate.newOptionalDataExceptionForSerialization();
+ try {
+ return cons.newInstance(bool);
+ } catch (InstantiationException|IllegalAccessException|InvocationTargetException ex) {
+ throw new InternalError("unable to create OptionalDataException", ex);
+ }
}
}
--- a/jdk/test/ProblemList.txt Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/ProblemList.txt Thu Oct 27 09:42:08 2016 -0700
@@ -134,8 +134,6 @@
java/lang/instrument/BootClassPath/BootClassPathTest.sh 8072130 macosx-all
-java/lang/instrument/DaemonThread/TestDaemonThread.java 8167001 generic-all
-
java/lang/management/MemoryMXBean/Pending.java 8158837 generic-all
java/lang/management/MemoryMXBean/PendingAllGC.sh 8158760 generic-all
--- a/jdk/test/TEST.groups Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/TEST.groups Thu Oct 27 09:42:08 2016 -0700
@@ -158,6 +158,7 @@
jdk_net = \
java/net \
+ -java/net/httpclient \
com/sun/net/httpserver \
sun/net \
jdk/net
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+import java.rmi.UnexpectedException;
+
+import javax.rmi.CORBA.Stub;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.CORBA.portable.ServantObject;
+
+
+/**
+ * ObjectStreamTest$Echo Stub class generated by rmic, do not edit.
+ */
+public class ObjectStreamTest$_Echo_Stub extends Stub implements ObjectStreamTest.Echo {
+
+ private static final String[] _type_ids = {
+ "RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
+ };
+
+ private static final long serialVersionUID = 5217577841494640354L;
+
+ public String[] _ids() {
+ return _type_ids.clone();
+ }
+
+ public Object echo(Object arg0) throws java.rmi.RemoteException {
+ if (!Util.isLocal(this)) {
+ try {
+ org.omg.CORBA.portable.InputStream in = null;
+ try {
+ OutputStream out = _request("echo", true);
+ Util.writeAny(out,arg0);
+ in = _invoke(out);
+ return Util.readAny(in);
+ } catch (ApplicationException ex) {
+ in = ex.getInputStream();
+ String $_id = in.read_string();
+ throw new UnexpectedException($_id);
+ } catch (RemarshalException ex) {
+ return echo(arg0);
+ } finally {
+ _releaseReply(in);
+ }
+ } catch (SystemException ex) {
+ throw Util.mapSystemException(ex);
+ }
+ } else {
+ ServantObject so = _servant_preinvoke("echo",ObjectStreamTest.Echo.class);
+ if (so == null) {
+ return echo(arg0);
+ }
+ try {
+ Object arg0Copy = Util.copyObject(arg0,_orb());
+ Object result = ((ObjectStreamTest.Echo)so.servant).echo(arg0Copy);
+ return Util.copyObject(result,_orb());
+ } catch (Throwable ex) {
+ Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+ throw Util.wrapException(exCopy);
+ } finally {
+ _servant_postinvoke(so);
+ }
+ }
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+import java.rmi.Remote;
+
+import javax.rmi.CORBA.Tie;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.CORBA_2_3.portable.ObjectImpl;
+
+
+/**
+ * ObjectStreamClass$Echo server tie class generated by rmic, do not edit.
+ */
+public class ObjectStreamTest$_Server_Tie extends ObjectImpl implements Tie {
+
+ volatile private ObjectStreamTest.Server target = null;
+
+ private static final String[] _type_ids = {
+ "RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
+ };
+
+ public void setTarget(Remote target) {
+ this.target = (ObjectStreamTest.Server) target;
+ }
+
+ public Remote getTarget() {
+ return target;
+ }
+
+ public org.omg.CORBA.Object thisObject() {
+ return this;
+ }
+
+ public void deactivate() {
+ _orb().disconnect(this);
+ _set_delegate(null);
+ target = null;
+ }
+
+ public ORB orb() {
+ return _orb();
+ }
+
+ public void orb(ORB orb) {
+ orb.connect(this);
+ }
+
+ public String[] _ids() {
+ return _type_ids.clone();
+ }
+
+ public OutputStream _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
+ try {
+ ObjectStreamTest.Server target = this.target;
+ if (target == null) {
+ throw new java.io.IOException();
+ }
+ org.omg.CORBA_2_3.portable.InputStream in =
+ (org.omg.CORBA_2_3.portable.InputStream) _in;
+ if (method.equals("echo")) {
+ Object arg0 = Util.readAny(in);
+ Object result = target.echo(arg0);
+ OutputStream out = reply.createReply();
+ Util.writeAny(out,result);
+ return out;
+ }
+ throw new BAD_OPERATION();
+ } catch (SystemException ex) {
+ throw ex;
+ } catch (Throwable ex) {
+ throw new UnknownException(ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Objects;
+import java.util.PropertyPermission;
+import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
+
+import javax.rmi.CORBA.Util;
+import javax.rmi.PortableRemoteObject;
+
+import org.omg.CORBA_2_3.ORB;
+import org.omg.CORBA_2_3.portable.OutputStream;
+import org.omg.CORBA_2_3.portable.InputStream;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.*
+ * @compile ObjectStreamTest.java ObjectStreamTest$_Echo_Stub.java
+ * ObjectStreamTest$_Server_Tie.java
+ * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io
+ * java.corba/com.sun.corba.se.impl.activation
+ * @summary Tests of ReflectionFactory use in IIOP Serialization
+ * @run testng/othervm ObjectStreamTest
+ * @run testng/othervm/policy=security.policy ObjectStreamTest
+ */
+
+@Test
+public class ObjectStreamTest {
+
+ enum Colors {RED, GREEN, YELLOW}
+
+ static Set<Colors> colorSet = new HashSet<>();
+
+ static {
+ colorSet.add(Colors.RED);
+ colorSet.add(Colors.GREEN);
+ }
+
+ @DataProvider(name = "Objects")
+ static Object[][] patterns() {
+ BigInteger bigInteger = new BigInteger("8943892002309239");
+ InetAddress inetAddr;
+ try {
+ inetAddr = java.net.InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
+ } catch (UnknownHostException ignored) {
+ inetAddr = null;
+ // ignored
+ }
+ HashMap<String, Object> hashMap = new HashMap<>();
+ hashMap.put("BigInteger", bigInteger);
+ hashMap.put("InetAddress", inetAddr);
+ hashMap.put("String", "bString");
+ Object[][] patterns = new Object[][]{
+ {"aString"},
+ {Integer.valueOf(5)},
+ {new SimpleObject(4, 4.0f)},
+ {Arrays.asList("a", "b", "c")},
+ {new String[]{"x", "y", "z"}},
+ {new ArrayList<Object>(1)}, // uses readObject/writeObject
+ {new StringBuffer("abc")}, // Has serialPersistentFields
+ {new StringBuilder("abc")},
+ {Colors.RED},
+ {inetAddr},
+ {LocalTime.MIDNIGHT}, // uses writeReplace/readResolve
+ {new LongAdder()}, // uses writeReplace/readResolve
+ {EnumSet.allOf(Colors.class)}, // used writeReplace/readResolve
+ {bigInteger},
+ {new BigDecimal(bigInteger)},
+ {hashMap},
+ {new PropertyPermission("abc", "read")}, // has serialPersistentFields
+ };
+ return patterns;
+ }
+
+
+ /**
+ * Check ObjectStreamClass facts match between core serialization and CORBA.
+ *
+ * @param value
+ */
+ @Test(dataProvider = "Objects")
+ void factCheck(Serializable value) {
+ Class<?> clazz = value.getClass();
+ java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz);
+ java.io.ObjectStreamField[] sFields = sOSC.getFields();
+ com.sun.corba.se.impl.io.ObjectStreamClass cOSC = corbaLookup(clazz);
+ com.sun.corba.se.impl.io.ObjectStreamField[] cFields = cOSC.getFields();
+
+ Assert.assertEquals(sFields.length, cFields.length, "Different number of fields");
+ for (int i = 0; i < sFields.length; i++) {
+ Assert.assertEquals(sFields[i].getName(), cFields[i].getName(),
+ "different field names " + cFields[i].getName());
+ Assert.assertEquals(sFields[i].getType(), cFields[i].getType(),
+ "different field types " + cFields[i].getName());
+ Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(),
+ "different field typestrings " + cFields[i].getName());
+ }
+
+ Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class<?>[]) null),
+ corbaMethod("hasReadObject", cOSC, (Class<?>[]) null),
+ "hasReadObject: " + value.getClass());
+
+ Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class<?>[]) null),
+ corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null),
+ "hasWriteObject: " + value.getClass());
+
+ Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class<?>[]) null),
+ corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null),
+ "hasWriteReplace: " + value.getClass());
+
+ Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class<?>[]) null),
+ corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null),
+ "hasReadResolve: " + value.getClass());
+
+ Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class<?>[]) null),
+ corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null),
+ "getSerialVersionUID: " + value.getClass());
+
+ }
+
+
+ /**
+ * Test that objects written using Util.writeAny can be serialized
+ * and deserialized using Util.readAny to equivalent objects.
+ */
+ @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+ void WriteValueObjectStreamTest01(Serializable value) throws Exception {
+ ORB orb = (ORB) ORB.init(new String[0], null);
+
+ OutputStream out = (OutputStream) orb.create_output_stream();
+ Util.writeAny(out, value);
+
+ InputStream in = (InputStream) out.create_input_stream();
+ Object actual = Util.readAny(in);
+
+ checkEquals(actual, value);
+ }
+
+ /**
+ * Test that objects can be echoed to a server and come back equivalent.
+ */
+ @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+ void echoObjects(Serializable value) throws Exception {
+ Echo echo = getEchoStub();
+ Object actual = echo.echo(value);
+ checkEquals(actual, value);
+ }
+
+
+ /**
+ * Initialize the ORB and the singleton Echo server stub.
+ * @return the stub for the Echo server.
+ * @throws RemoteException if an error occurs
+ */
+ synchronized Echo getEchoStub() throws RemoteException {
+ if (echoStub == null) {
+ ORB orb = (ORB) ORB.init(new String[0], null);
+ Echo server = new Server();
+ echoStub = (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(server);
+ echoStub.connect(orb);
+ }
+ return (Echo)echoStub;
+ }
+
+ /**
+ * The stub for the Echo Server class. Initialized on first use.
+ */
+ private javax.rmi.CORBA.Stub echoStub;
+
+ /**
+ * After all the tests run shutdown the orb.
+ */
+ @AfterClass
+ void shutdownOrb() {
+ ORB orb = (ORB) ORB.init(new String[0], null);
+ orb.shutdown(true);
+ }
+
+ /**
+ * Check if the value and result are equals, with some tests depending on the type.
+ * @param expected the expected value
+ * @param actual the actual value
+ */
+ static void checkEquals(Object actual, Object expected) {
+ Class<?> cl = expected.getClass();
+ Assert.assertEquals(actual.getClass(), cl,
+ "type of value not equal to class of result");
+ try {
+ if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) {
+ Assert.assertEquals(actual, expected, "echo'd object not equal");
+ } else {
+ Assert.assertEquals(toString(actual), toString(expected),
+ "toString values not equal");
+ }
+ } catch (NoSuchMethodException ex) {
+ Assert.assertEquals(toString(actual), toString(expected),
+ "toString values not equal");
+ }
+ }
+
+ /**
+ * Convert an object to a String, and correctly for arrays.
+ * @param obj an object
+ * @return the tostring for the object.
+ */
+ static String toString(Object obj) {
+ return obj.getClass().isArray()
+ ? Arrays.toString((Object[]) obj)
+ : Objects.toString(obj);
+ }
+
+ /**
+ * SimpleObject to test round trip.
+ */
+ static class SimpleObject implements Serializable {
+ private static final long serialVersionUID = 5217577841494640354L;
+
+ private int i = 0;
+ private float f = 0.0f;
+
+ SimpleObject(int i, float f) {
+ this.i = i;
+ this.f = f;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SimpleObject that = (SimpleObject) o;
+
+ if (i != that.i) return false;
+ return Float.compare(that.f, f) == 0;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = i;
+ result = 31 * result + (f != +0.0f ? Float.floatToIntBits(f) : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "SimpleObject{" +
+ "i=" + i +
+ ", f=" + f +
+ '}';
+ }
+ }
+
+
+ /**
+ * Lookup the CORBA ObjectStreamClass instance for a class.
+ * @param clazz the class
+ * @return the CORBA ObjectStreamClass instance for the class
+ */
+ static com.sun.corba.se.impl.io.ObjectStreamClass corbaLookup(Class<?> clazz) {
+ Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
+
+ try {
+ Method meth = oscClass.getDeclaredMethod("lookup", Class.class);
+ meth.setAccessible(true);
+ return (com.sun.corba.se.impl.io.ObjectStreamClass) meth.invoke(null, clazz);
+ } catch (NoSuchMethodException noMeth) {
+ throw new RuntimeException("missing method", noMeth);
+ } catch (IllegalAccessException | InvocationTargetException rex) {
+ throw new RuntimeException("invocation failed", rex);
+ }
+ }
+
+ /**
+ * Lookup aand invoke method on a serializable object via the CORBA ObjectStreamClass.
+ * @param methodName method name
+ * @param osc CORBA ObjectStreamClass
+ * @param argClasses method arguments
+ * @return the value returned from invoking the method
+ */
+ static Object corbaMethod(String methodName,
+ com.sun.corba.se.impl.io.ObjectStreamClass osc,
+ Class<?>... argClasses) {
+ Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
+
+ try {
+ Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
+ meth.setAccessible(true);
+ return meth.invoke(osc);
+
+ } catch (NoSuchMethodException noMeth) {
+ throw new RuntimeException("missing method" + osc.getName()
+ + "::" + methodName, noMeth);
+ } catch (IllegalAccessException | InvocationTargetException rex) {
+ throw new RuntimeException("invocation failed", rex);
+ }
+ }
+
+
+ /**
+ * Lookup aand invoke method on a serializable object via java.io.ObjectStreamClass.
+ * @param methodName method name
+ * @param osc java.io.ObjectStreamClass
+ * @param argClasses method arguments
+ * @return the value returned from invoking the method
+ */
+ static Object baseMethod(String methodName, java.io.ObjectStreamClass osc,
+ Class<?>... argClasses) {
+ Class<?> oscClass = java.io.ObjectStreamClass.class;
+
+ try {
+ Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
+ meth.setAccessible(true);
+ return meth.invoke(osc);
+
+ } catch (NoSuchMethodException noMeth) {
+ throw new RuntimeException("missing method: " + osc.getName()
+ + "::" + methodName, noMeth);
+ } catch (IllegalAccessException | InvocationTargetException rex) {
+ throw new RuntimeException("invocation failed", rex);
+ }
+ }
+
+ /**
+ * Simple echo interface to check IIOP serialization/deserialization.
+ */
+ interface Echo extends Remote {
+ Object echo(Object obj) throws RemoteException;
+ }
+
+ static class Server extends PortableRemoteObject implements Echo {
+
+ public Server() throws RemoteException {
+ super();
+ }
+
+ public Object echo(Object obj) {
+ return obj;
+ }
+ }
+
+ // Main can be used to run the tests from the command line with only testng.jar.
+ @SuppressWarnings("raw_types")
+ @Test(enabled = false)
+ public static void main(String[] args) {
+ Class<?>[] testclass = {ObjectStreamTest.class};
+ TestNG testng = new TestNG();
+ testng.setTestClasses(testclass);
+ testng.run();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,15 @@
+// Individual Permissions for ObjectStreamTest
+grant {
+ // Permissions needed to run the test
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+ permission java.net.SocketPermission "*", "resolve,connect,listen,accept";
+
+ // Permissions to allow ObjectTest to use IIOP ObjectStreamClass
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.corba.se.impl.io";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.io.SerializablePermission "enableSubclassImplementation";
+};
--- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,7 +25,8 @@
* @test
* @bug 8031195
* @bug 8071657
- * @summary JDI: Add support for static and default methods in interfaces
+ * @bug 8165827
+ * @summary JDI: Add support for static, private and default methods in interfaces
*
* @modules jdk.jdi
* @run build TestScaffold VMConnection TargetListener TargetAdapter
@@ -35,11 +36,13 @@
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
public class InterfaceMethodsTest extends TestScaffold {
private static final int RESULT_A = 1;
- private static final int RESULT_B = 1;
- private static final int RESULT_TARGET = 1;
+ private static final int RESULT_B = 2;
+ private static final int RESULT_TARGET = 3;
static interface InterfaceA {
static int staticMethodA() {
@@ -62,7 +65,10 @@
System.out.println("-InterfaceA: default interface method C-");
return RESULT_A;
}
-
+ private int privateMethodA() {
+ System.out.println("-InterfaceA: private interface method A-");
+ return RESULT_A;
+ }
int implementedMethod();
}
@@ -76,16 +82,18 @@
System.out.println("-InterfaceB: default interface method D-");
return RESULT_B;
}
-
static int staticMethodB() {
System.out.println("-InterfaceB: overridden static interface method B-");
return RESULT_B;
}
-
static int staticMethodC() {
System.out.println("-InterfaceB: static interface method C-");
return RESULT_B;
}
+ private int privateMethodB() {
+ System.out.println("-InterfaceB: private interface method B-");
+ return RESULT_B;
+ }
}
final static class TargetClass implements InterfaceB {
@@ -102,7 +110,7 @@
@Override
public int defaultMethodB() {
- System.out.println("-TargetClass: overridden default interface method D");
+ System.out.println("-TargetClass: overridden default interface method B");
return RESULT_TARGET;
}
@@ -169,9 +177,18 @@
}
private void testInterfaceA(ObjectReference ref) {
+
+ ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
+
+ /* Private method calls */
+
+ Method m = testLookup(ifaceClass, "privateMethodA", "()I", true, null); // should succeed
+
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_A), false);
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_A), true);
+
// Test non-virtual calls on InterfaceA
- ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
/* Default method calls */
// invoke the InterfaceA's "defaultMethodA"
@@ -185,39 +202,48 @@
// "defaultMethodD" from InterfaceB is not accessible from here
testInvokeNeg(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B),
- "Attempted to invoke non-existing method");
+ "Attempted to invoke non-existing method");
- // trying to invoke the asbtract method "implementedMethod"
+ // non-virtual invoke of the abstract method "implementedMethod" fails
testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(TARGET_CLASS_NAME),
- "Invocation of non-default methods is not supported");
-
+ "Invocation of abstract methods is not supported");
/* Static method calls */
- // invoke interface static method A
+ // invoke static interface method A
testInvokePos(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A));
// invoking static method A on the instance fails because static method A is
// not inherited by TargetClass.
testInvokeNeg(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A),
- "Invalid MethodID");
+ "Invalid MethodID");
- // invoke interface static method B
+ // invoke static interface method B
testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_A));
// invoking static method B on the instance fails because static method B is
// not inherited by TargetClass.
testInvokeNeg(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_A),
- "Invalid MethodID");
+ "Invalid MethodID");
// try to invoke a virtual method
- testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_A), true);
+ testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET), true);
}
private void testInterfaceB(ObjectReference ref) {
// Test non-virtual calls on InterfaceB
ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEB_NAME).get(0);
+ /* private method calls */
+
+ /* These should fail but won't because of JDK-8167416
+ testLookup(ifaceClass, "privateMethodA", "()I", true, NoSuchMethodError.class); // should fail
+ testLookup(ifaceClass, "privateMethodA", "()I", false, NoSuchMethodError.class); // should fail
+ */
+ Method m = testLookup(ifaceClass, "privateMethodB", "()I", true, null); // should succeed
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_B), false);
+ testInvokePos(m, ref, vm().mirrorOf(RESULT_B), true);
+
/* Default method calls */
// invoke the inherited "defaultMethodA"
@@ -267,19 +293,21 @@
private void testImplementationClass(ReferenceType targetClass, ObjectReference thisObject) {
// Test invocations on the implementation object
+ // Note: private interface calls have already been tested
+
/* Default method calls */
// "defaultMethodA" is accessible and not overridden
- testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A));
// "defaultMethodB" is accessible and overridden in TargetClass
testInvokePos(targetClass, thisObject, "defaultMethodB", "()I", vm().mirrorOf(RESULT_TARGET));
// "defaultMethodC" is accessible and overridden in InterfaceB
- testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_B));
// "defaultMethodD" is accessible
- testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_TARGET));
+ testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B));
/* Non-default instance method calls */
@@ -314,11 +342,16 @@
"Static interface methods are not inheritable");
}
+ // Non-virtual invocation
private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value) {
testInvokePos(targetClass, ref, methodName, methodSig, value, false);
}
+ // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should succeed.
private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, boolean virtual) {
logInvocation(ref, methodName, methodSig, targetClass);
@@ -331,11 +364,31 @@
}
}
+ // Invoke the given Method on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should succeed.
+ private void testInvokePos(Method method, ObjectReference ref, Value value, boolean virtual) {
+ logInvocation(ref, method.name(), method.signature(), method.declaringType());
+ try {
+ invoke(method.declaringType(), ref, method, value, virtual);
+ System.err.println("--- PASSED");
+ } catch (Exception e) {
+ System.err.println("--- FAILED");
+ failure("FAILED: Invocation failed with error message " + e.getLocalizedMessage());
+ }
+ }
+
+ // Non-virtual invocation - with lookup in targetClass
private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, String msg) {
testInvokeNeg(targetClass, ref, methodName, methodSig, value, msg, false);
}
+ // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+ // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+ // expected return value.
+ // Should fail - with msg decribing why failure was expected
private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
String methodSig, Value value, String msg, boolean virtual) {
logInvocation(ref, methodName, methodSig, targetClass);
@@ -350,12 +403,17 @@
}
private void invoke(ReferenceType targetClass, ObjectReference ref, String methodName,
- String methodSig, Value value, boolean virtual)
- throws Exception {
+ String methodSig, Value value, boolean virtual) throws Exception {
+
Method method = getMethod(targetClass, methodName, methodSig);
if (method == null) {
throw new Exception("Can't find method: " + methodName + " for class = " + targetClass);
}
+ invoke(targetClass, ref, method, value, virtual);
+ }
+
+ private void invoke(ReferenceType targetClass, ObjectReference ref, Method method,
+ Value value, boolean virtual) throws Exception {
println("Invoking " + (method.isAbstract() ? "abstract " : " ") + "method: " + method);
println(method.declaringType().toString());
@@ -365,7 +423,7 @@
if (virtual) {
returnValue = invokeVirtual(ref, method);
} else {
- returnValue = invokeInstance(ref, method);
+ returnValue = invokeNonVirtual(ref, method);
}
} else {
returnValue = invokeStatic(targetClass, method);
@@ -387,7 +445,7 @@
}
}
- private Value invokeInstance(ObjectReference ref, Method method) throws Exception {
+ private Value invokeNonVirtual(ObjectReference ref, Method method) throws Exception {
return ref.invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL);
}
@@ -449,4 +507,58 @@
methodName + methodSig);
}
}
+
+ private Method testLookup(ReferenceType targetClass, String methodName, String methodSig,
+ boolean declaredOnly, Class<?> expectedException) {
+
+ System.err.println("Looking up " + targetClass.name() + "." + methodName + methodSig);
+ try {
+ Method m = declaredOnly ?
+ lookupDeclaredMethod(targetClass, methodName, methodSig) :
+ lookupMethod(targetClass, methodName, methodSig);
+
+ if (expectedException == null) {
+ System.err.println("--- PASSED");
+ return m;
+ }
+ else {
+ System.err.println("--- FAILED");
+ failure("FAILED: lookup succeeded but expected exception "
+ + expectedException.getSimpleName());
+ return null;
+ }
+ }
+ catch (Throwable t) {
+ if (t.getClass() != expectedException) {
+ System.err.println("--- FAILED");
+ failure("FAILED: got exception " + t + " but expected exception "
+ + expectedException.getSimpleName());
+ return null;
+ }
+ else {
+ System.err.println("--- PASSED");
+ return null;
+ }
+ }
+ }
+
+ private Method lookupMethod(ReferenceType targetClass, String methodName, String methodSig) {
+ List methods = targetClass.allMethods();
+ Iterator iter = methods.iterator();
+ while (iter.hasNext()) {
+ Method method = (Method)iter.next();
+ if (method.name().equals(methodName) &&
+ method.signature().equals(methodSig)) {
+ return method;
+ }
+ }
+ throw new NoSuchMethodError();
+ }
+
+ private Method lookupDeclaredMethod(ReferenceType targetClass, String methodName, String methodSig) {
+ Method m = findMethod(targetClass, methodName, methodSig);
+ if (m == null)
+ throw new NoSuchMethodError();
+ return m;
+ }
}
--- a/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -28,6 +28,7 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import org.testng.Assert;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
@@ -65,20 +66,21 @@
*/
@Test
public void testGlobalFilter() throws Exception {
- if (ObjectInputFilter.Config.getSerialFilter() == null) {
- return;
- }
- try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bais)) {
+ ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter();
+
+ try {
ObjectInputFilter.Config.setSerialFilter(filter);
assertFalse(setSecurityManager,
"When SecurityManager exists, without "
- + "java.security.SerializablePermission(serialFilter) Exception should be thrown");
- Object o = ois.readObject();
+ + "java.io.SerializablePermission(serialFilter) "
+ + "IllegalStateException should be thrown");
} catch (AccessControlException ex) {
assertTrue(setSecurityManager);
assertTrue(ex.getMessage().contains("java.io.SerializablePermission"));
assertTrue(ex.getMessage().contains("serialFilter"));
+ } catch (IllegalStateException ise) {
+ // ISE should occur only if global filter already set
+ Assert.assertNotNull(global, "Global filter should be non-null");
}
}
--- a/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -126,9 +126,7 @@
ObjectInputFilter.Config.setSerialFilter(filter);
Assert.fail("set only once process-wide filter");
} catch (IllegalStateException ise) {
- if (sm != null) {
- Assert.fail("wrong exception when security manager is set", ise);
- }
+ // Normal, once set can never be re-set even if no security manager
} catch (SecurityException se) {
if (sm == null) {
Assert.fail("wrong exception when security manager is not set", se);
--- a/jdk/test/java/io/Serializable/serialFilter/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,7 +1,8 @@
-// Individual Permissions to for GlobalFilterTest
+// Individual Permissions to for GlobalFilterTest and FilterWithSecurityManager
grant {
// Specific permission under test
- permission java.security.SerializablePermission "serialFilter";
+ permission java.io.SerializablePermission "serialFilter";
+
// Permissions needed to run the test
permission java.util.PropertyPermission "*", "read";
permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/IsParallelCapable.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8165793
+ * @summary Test ClassLoader.isParallelCapable() method
+ * @run main IsParallelCapable
+ */
+
+import java.util.stream.Stream;
+
+public class IsParallelCapable {
+ public abstract static class TestCL extends ClassLoader {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ public abstract boolean expectCapable();
+ public Class findClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException("Why are you using this?");
+ }
+ }
+
+ public static class ParaCL extends TestCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() { return true; }
+ }
+
+ public static class NonParaCL extends TestCL {
+ @Override
+ public boolean expectCapable() {
+ // Doesn't call registerAsParallelCapable()
+ return false;
+ }
+ }
+
+ public static class NonParaSubCL1 extends ParaCL {
+ @Override
+ public boolean expectCapable() {
+ // Doesn't call registerAsParallelCapable()
+ return false;
+ }
+ }
+
+ public static class NonParaSubCL2 extends NonParaCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() {
+ // Superclass is not parallel capable
+ return false;
+ }
+ }
+
+ public static class ParaSubCL extends ParaCL {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+ @Override
+ public boolean expectCapable() { return true; }
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (!ClassLoader.getSystemClassLoader().isParallelCapable()) {
+ throw new RuntimeException("System classloader not parallel capable!?");
+ }
+
+ Stream.of(ParaCL.class,
+ NonParaCL.class,
+ NonParaSubCL1.class,
+ NonParaSubCL2.class,
+ ParaSubCL.class)
+ .forEach(IsParallelCapable::testClassLoaderClass);
+ }
+
+ private static void testClassLoaderClass(Class<? extends TestCL> klazz) {
+ try {
+ TestCL cl = (TestCL)klazz.newInstance();
+ if (cl.expectCapable() != cl.isParallelCapable()) {
+ throw new RuntimeException(klazz + " expectCapable: " +
+ cl.expectCapable() + ", isParallelCapable: " +
+ cl.isParallelCapable());
+ } else {
+ System.out.println(klazz + " passed");
+ }
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- a/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java Thu Oct 27 09:42:08 2016 -0700
@@ -29,7 +29,7 @@
public class TestDaemonThreadLauncher {
public static void main(String args[]) throws Exception {
for(int i=0; i<50; i++) {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
analyzer.shouldNotContain("ASSERTION FAILED");
analyzer.shouldHaveExitValue(0);
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, 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
@@ -34,6 +34,7 @@
* @modules java.management
* @build jdk.testlibrary.* LowMemoryTest MemoryUtil RunUtil
* @run main/timeout=600 LowMemoryTest
+ * @requires vm.gc == "null"
* @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
* @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
* @requires vm.opt.DisableExplicitGC != "true"
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Thu Oct 27 09:42:08 2016 -0700
@@ -40,7 +40,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe CheckActivateRef_Stub
* @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef
* @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef
* @key intermittent
@@ -118,7 +119,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -2,4 +2,6 @@
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.useDynamicProxies=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -38,4 +38,6 @@
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID MyRMI CheckAnnotations_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider MyRMI CheckAnnotations_Stub
* @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations
*/
@@ -77,7 +78,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID(rmidOut, rmidErr, false);
+ rmid = RMID.createRMIDOnEphemeralPort(rmidOut, rmidErr, false);
rmid.start();
/* Cause activation groups to have a security policy that will
@@ -228,6 +229,7 @@
return false;
}
+
// just make sure that last two strings are what we expect.
if (execOut.equals("ExecGroup-" + iteration)
&& (new String(destOut.substring(0,4)).equals("out" +
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
* MyRMI ActivatableImpl ActivatableImpl ActivatableImpl_Stub
* @run main/othervm/policy=security.policy/timeout=150 CheckImplClassLoader
*/
@@ -80,7 +81,7 @@
TestParams.defaultSecurityManager);
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("Create activation group in this VM");
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -39,4 +39,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe CheckRegisterInLog_Stub
* @run main/othervm/policy=security.policy/timeout=240 CheckRegisterInLog
*/
@@ -99,7 +100,7 @@
* Start up activation system daemon "rmid".
*/
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe
* @run main/othervm/policy=security.policy/timeout=240 CreatePrivateActivatable
*/
@@ -103,7 +104,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java Thu Oct 27 09:42:08 2016 -0700
@@ -35,7 +35,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* Foo FooReceiverImpl FooReceiverImpl_Stub Bar
* @run main/othervm/policy=security.policy/timeout=240 DownloadParameterClass
*/
@@ -90,7 +91,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -34,4 +34,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -35,4 +35,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe ElucidateNoSuchMethod_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe ElucidateNoSuchMethod_Stub
* @run main/othervm/policy=security.policy/timeout=240 ElucidateNoSuchMethod
*/
@@ -91,7 +92,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,7 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -37,4 +37,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -37,7 +37,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
Properties p = new Properties();
p.put("java.security.policy",
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh Thu Oct 27 09:42:08 2016 -0700
@@ -27,7 +27,7 @@
# loader, the context class loader should remain unchanged (i.e., not be
# set to the impl's class loader) when the impl is activated.
# @library ../../../testlibrary
-# @build TestLibrary RMID ActivationLibrary
+# @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
# @build ExtLoadedImplTest ExtLoadedImpl ExtLoadedImpl_Stub CheckLoader
# @run shell ext.sh
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe ForceLogSnapshot_Stub
* @run main/othervm/policy=security.policy/timeout=640 ForceLogSnapshot
*/
@@ -129,7 +130,7 @@
SNAPSHOT_INTERVAL;
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.addOptions(new String[] {option, "-Djava.compiler="});
rmid.start();
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java Thu Oct 27 09:42:08 2016 -0700
@@ -33,7 +33,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe InactiveGroup_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe InactiveGroup_Stub
* @run main/othervm/policy=security.policy/timeout=240 InactiveGroup
*/
@@ -101,7 +102,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -31,4 +31,7 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java Thu Oct 27 09:42:08 2016 -0700
@@ -33,7 +33,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* @run main/othervm/timeout=240 LookupActivationSystem
*/
@@ -55,7 +56,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("look up activation system");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,4 @@
+grant {
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
+};
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe NestedActivate_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe NestedActivate_Stub
* @run main/othervm/policy=security.policy/timeout=240 NestedActivate
*/
@@ -101,7 +102,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -31,4 +31,7 @@
// allow exporting of non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe NonExistentActivatable_Stub
* @run main/othervm/policy=security.policy/timeout=240 NonExistentActivatable
*/
@@ -91,7 +92,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -32,4 +32,6 @@
// allow exporting object with non-public remote interface
permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe RestartCrashedService_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe RestartCrashedService_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartCrashedService
*/
@@ -119,7 +120,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,7 +31,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* RestartLatecomer RestartLatecomer_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer
*/
@@ -166,7 +167,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -33,4 +33,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe RestartService_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe RestartService_Stub
* @run main/othervm/policy=security.policy/timeout=240 RestartService
*/
@@ -129,7 +130,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/restartService/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -33,4 +33,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
* TestSecurityManager RegisteringActivatable ShutdownGracefully_Stub
* @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
*/
@@ -76,7 +77,7 @@
// start an rmid.
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
// rmid needs to run with a security manager that
// simulates a log problem; rmid should also snapshot
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -2,4 +2,6 @@
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=java.lang.SecurityManager";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
permission com.sun.rmi.rmid.ExecOptionPermission "-Ddummyname=dummyvalue";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -25,4 +25,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java Thu Oct 27 09:42:08 2016 -0700
@@ -32,7 +32,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe UnregisterInactive_Stub
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe UnregisterInactive_Stub
* @run main/othervm/policy=security.policy/timeout=240 UnregisterInactive
*/
@@ -89,7 +90,7 @@
try {
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
System.err.println("Creating descriptor");
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -28,4 +28,7 @@
// allow exporting of remote objects on an arbitrary port.
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java Thu Oct 27 09:42:08 2016 -0700
@@ -35,7 +35,8 @@
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
* java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ * java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
* ActivateMe ActivateFails_Stub ShutdownThread
* @run main/othervm/java.security.policy=security.policy/timeout=240 ActivateFails
*/
@@ -93,7 +94,7 @@
* First run "rmid" and wait for it to start up.
*/
RMID.removeLog();
- rmid = RMID.createRMID();
+ rmid = RMID.createRMIDOnEphemeralPort();
rmid.start();
/* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -1,4 +1,6 @@
grant {
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -28,4 +28,7 @@
// test needs to export rmid and communicate with objects on arbitrary ports
permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+ permission java.lang.RuntimePermission "selectorProvider";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
};
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java Thu Oct 27 09:42:08 2016 -0700
@@ -51,6 +51,8 @@
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
public class RmidViaInheritedChannel implements Callback {
private static final Object lock = new Object();
@@ -185,6 +187,15 @@
*/
channel = ServerSocketChannel.open();
ServerSocket serverSocket = channel.socket();
+
+ // Enable SO_REUSEADDR before binding
+ serverSocket.setOption(SO_REUSEADDR, true);
+
+ // Enable SO_REUSEPORT, if supported, before binding
+ if (serverSocket.supportedOptions().contains(SO_REUSEPORT)) {
+ serverSocket.setOption(SO_REUSEPORT, true);
+ }
+
serverSocket.bind(
new InetSocketAddress(InetAddress.getLocalHost(),
TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT));
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java Thu Oct 27 09:42:08 2016 -0700
@@ -21,8 +21,11 @@
* questions.
*/
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.StringTokenizer;
@@ -39,8 +42,8 @@
protected Process vm = null;
private String classname = "";
- private String args = "";
- private String options = "";
+ protected String args = "";
+ protected String options = "";
private OutputStream outputStream = System.out;
private OutputStream errorStream = System.err;
private String policyFileName = null;
@@ -113,7 +116,7 @@
/**
* Exec the VM as specified in this object's constructor.
*/
- public void start() throws IOException {
+ private void start0() throws IOException {
if (vm != null)
throw new IllegalStateException("JavaVM already started");
@@ -152,12 +155,50 @@
mesg("command = " + Arrays.asList(javaCommand).toString());
vm = Runtime.getRuntime().exec(javaCommand);
+ }
- /* output from the execed process may optionally be captured. */
+ public void start() throws IOException {
+ start0();
+
+ /* output from the exec'ed process may optionally be captured. */
outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
}
+ public int startAndGetPort() throws IOException {
+ start0();
+
+ int port = -1;
+ if (options.contains("java.nio.channels.spi.SelectorProvider=RMIDSelectorProvider")) {
+ // Obtain the server socket channel's ephemeral port number of the
+ // child rmid process.
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(vm.getInputStream()));
+ String s;
+ while ((s = reader.readLine()) != null) {
+ System.out.println(s);
+ int i = s.indexOf(RMID.EPHEMERAL_MSG);
+ if (i != -1) {
+ String v = s.substring(RMID.EPHEMERAL_MSG.length());
+ port = Integer.valueOf(v);
+ break;
+ }
+ }
+ if (port == -1) {
+ // something failed
+ reader = new BufferedReader(new InputStreamReader(vm.getErrorStream()));
+ while ((s = reader.readLine()) != null)
+ System.err.println(s);
+ }
+ }
+
+ /* output from the exec'ed process may optionally be captured. */
+ outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
+ errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
+
+ return port;
+ }
+
public void destroy() {
if (vm != null) {
vm.destroy();
--- a/jdk/test/java/rmi/testlibrary/RMID.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/RMID.java Thu Oct 27 09:42:08 2016 -0700
@@ -49,20 +49,31 @@
public static String MANAGER_OPTION="-Djava.security.manager=";
- /** Test port for rmid */
- private final int port;
+ /**
+ * Test port for rmid.
+ *
+ * May initially be 0, which means that the child rmid process will choose
+ * an ephemeral port and report it back to the parent process. This field
+ * will then be set to the child rmid's ephemeral port value.
+ */
+ private volatile int port;
+ //private final boolean ephemeralPort
/** Initial log name */
protected static String log = "log";
/** rmid's logfile directory; currently must be "." */
protected static String LOGDIR = ".";
+ /** The output message from the child rmid process that directly precedes
+ * the ephemeral port number.*/
+ public static final String EPHEMERAL_MSG = "RmidSelectorProvider-listening-On:";
+
private static void mesg(Object mesg) {
System.err.println("RMID: " + mesg.toString());
}
/** make test options and arguments */
- private static String makeOptions(boolean debugExec) {
+ private static String makeOptions(int port, boolean debugExec) {
String options = " -Dsun.rmi.server.activation.debugExec=" +
debugExec;
@@ -87,6 +98,17 @@
// to avoid spurious timeouts on slow machines.
options += " -Dsun.rmi.activation.execTimeout=60000";
+ if (port == 0) {
+ // Ephemeral port, so have the rmid child process create the
+ // server socket channel and report its port number, over stdin.
+ options += " -classpath " + TestParams.testClassPath;
+ options += " --add-exports=java.base/sun.nio.ch=ALL-UNNAMED";
+ options += " -Djava.nio.channels.spi.SelectorProvider=RMIDSelectorProvider";
+
+ // Disable redirection of System.err to /tmp
+ options += " -Dsun.rmi.server.activation.disableErrRedirect=true";
+ }
+
return options;
}
@@ -107,7 +129,8 @@
String args =
" -log " + (new File(LOGDIR, log)).getAbsolutePath();
- if (includePortArg) {
+ // 0 = ephemeral port, do not include an explicit port number
+ if (includePortArg && port != 0) {
args += " -port " + port;
}
@@ -160,7 +183,7 @@
boolean debugExec, boolean includePortArg,
int port)
{
- String options = makeOptions(debugExec);
+ String options = makeOptions(port, debugExec);
String args = makeArgs(includePortArg, port);
RMID rmid = new RMID("sun.rmi.server.Activation", options, args,
out, err, port);
@@ -169,6 +192,17 @@
return rmid;
}
+ public static RMID createRMIDOnEphemeralPort() {
+ return createRMID(System.out, System.err, true, true, 0);
+ }
+
+ public static RMID createRMIDOnEphemeralPort(OutputStream out,
+ OutputStream err,
+ boolean debugExec)
+ {
+ return createRMID(out, err, debugExec, true, 0);
+ }
+
/**
* Private constructor. RMID instances should be created
@@ -247,7 +281,10 @@
// a well recognized exception (port already in use...).
mesg("Starting rmid on port " + port + ".");
- super.start();
+ int p = super.startAndGetPort();
+ if (p != -1)
+ port = p;
+ mesg("Started rmid on port " + port + ".");
// int slopFactor = 1;
// try {
@@ -271,8 +308,11 @@
try {
int status = vm.exitValue();
+ waitFor(TIMEOUT_SHUTDOWN_MS);
TestLibrary.bomb("Rmid process exited with status " + status + " after " +
(System.currentTimeMillis() - startTime) + "ms.");
+ } catch (InterruptedException | TimeoutException e) {
+ mesg(e);
} catch (IllegalThreadStateException ignore) { }
// The rmid process is alive; check to see whether
@@ -307,6 +347,8 @@
*/
public void restart() throws IOException {
destroy();
+ options = makeOptions(port, true);
+ args = makeArgs(true, port);
start();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,107 @@
+/*
+ * 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 java.io.*;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.nio.channels.Channel;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
+
+/**
+ * A SelectorProvider, that can be loaded by the child rmid process, whose
+ * inheritedChannel method will create a new server socket channel and report
+ * it back to the parent process, over stdout.
+ */
+public class RMIDSelectorProvider extends SelectorProvider {
+
+ private final SelectorProvider provider;
+ private ServerSocketChannel channel;
+
+ public RMIDSelectorProvider() {
+ provider = sun.nio.ch.DefaultSelectorProvider.create();
+ }
+
+ public DatagramChannel openDatagramChannel()
+ throws IOException
+ {
+ return provider.openDatagramChannel();
+ }
+
+ public DatagramChannel openDatagramChannel(ProtocolFamily family)
+ throws IOException
+ {
+ return provider.openDatagramChannel(family);
+ }
+
+ public Pipe openPipe()
+ throws IOException
+ {
+ return provider.openPipe();
+ }
+
+ public AbstractSelector openSelector()
+ throws IOException
+ {
+ return provider.openSelector();
+ }
+
+ public ServerSocketChannel openServerSocketChannel()
+ throws IOException
+ {
+ return provider.openServerSocketChannel();
+ }
+
+ public SocketChannel openSocketChannel()
+ throws IOException
+ {
+ return provider.openSocketChannel();
+ }
+
+ public synchronized Channel inheritedChannel() throws IOException {
+ System.out.println("RMIDSelectorProvider.inheritedChannel");
+ if (channel == null) {
+ // Create and bind a new server socket channel
+ channel = ServerSocketChannel.open();
+
+ // Enable SO_REUSEADDR before binding
+ channel.setOption(SO_REUSEADDR, true);
+
+ // Enable SO_REUSEPORT, if supported, before binding
+ if (channel.supportedOptions().contains(SO_REUSEPORT)) {
+ channel.setOption(SO_REUSEPORT, true);
+ }
+
+ channel.bind(new InetSocketAddress(0));
+
+ System.out.println(RMID.EPHEMERAL_MSG + channel.socket().getLocalPort());
+ }
+ return channel;
+ }
+}
--- a/jdk/test/java/rmi/testlibrary/TestParams.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/TestParams.java Thu Oct 27 09:42:08 2016 -0700
@@ -34,6 +34,7 @@
/** variables that hold value property values */
public static final String testSrc;
public static final String testClasses;
+ public static final String testClassPath;
/** name of default security policy for test JVM */
public static final String defaultPolicy;
@@ -57,6 +58,7 @@
static {
testSrc = TestLibrary.getProperty("test.src", ".");
testClasses = TestLibrary.getProperty("test.classes", ".");
+ testClassPath = TestLibrary.getProperty("test.class.path", ".");
String dp = TestLibrary.getProperty("java.security.policy", null);
if (dp == null) {
--- a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -624,7 +624,7 @@
@Test
public void test_chronoFields() {
ChronoLocalDate hdate = HijrahChronology.INSTANCE.date(1434, 6, 28);
- assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 3);
+ assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 7);
assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR), 7);
assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_MONTH), 4);
assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_YEAR), 25);
@@ -785,4 +785,32 @@
public void test_hijrahToJapanese(HijrahDate hijrah, String japanese) {
assertEquals(JapaneseChronology.INSTANCE.date(hijrah).toString(), japanese);
}
+
+ @DataProvider(name="alignedDayOfWeekInMonthTestDates")
+ Object[][] data_alignedDayOfWeekInMonth() {
+ return new Object[][] {
+ {1437, 9, 1, 1, 1},
+ {1437, 10, 1, 1, 1},
+ {1437, 10, 11, 2, 4},
+ {1437, 10, 29, 5, 1},
+ };
+ }
+
+ //-----------------------------------------------------------------------
+ // Test for aligned-week-of-month calculation based on the day-of-month
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="alignedDayOfWeekInMonthTestDates")
+ public void test_alignedWeekOfMonth(int year, int month, int dom, int wom, int dowm) {
+ HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom);
+ assertEquals(date.getLong(ChronoField.ALIGNED_WEEK_OF_MONTH), wom);
+ }
+
+ //-----------------------------------------------------------------------
+ // Test for aligned-day-of-week calculation based on the day-of-month
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="alignedDayOfWeekInMonthTestDates")
+ public void test_alignedDayOfWeekInMonth(int year, int month, int dom, int wom, int dowm) {
+ HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom);
+ assertEquals(date.getLong(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), dowm);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,127 @@
+/*
+ * 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 test.java.time.format;
+
+/*
+ * @test
+ * @bug 8146750
+ * @summary Test Narrow and NarrowStandalone month names are retrieved correctly.
+ */
+import static org.testng.Assert.assertEquals;
+
+import java.time.DayOfWeek;
+import java.time.Month;
+import java.time.format.TextStyle;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class TestNarrowMonthNamesAndDayNames {
+
+ static {
+ System.setProperty("java.locale.providers", "COMPAT");
+ }
+
+ private static final List<Month> MONTHVALUES = Arrays.asList(Month.values());
+ private static final List<DayOfWeek> DAYVALUES = Arrays.asList(DayOfWeek.values());
+ private static final List<TextStyle> TEXTSTYLELIST = Arrays.asList(TextStyle.NARROW,
+ TextStyle.NARROW_STANDALONE);
+ private static final List<Locale> LOCARR = Arrays.asList(Locale.US,
+ Locale.GERMANY,
+ Locale.FRANCE,
+ new Locale("no", "NO"));
+
+ /**
+ * Locale en_US, de_DE, fr_FR, no_NO will have same Narrow and
+ * Narrow_Standalone month Names for COMPAT Provider.
+ */
+ @DataProvider(name = "MonthNarrows")
+ public Object[][] monthNameData() {
+ return new Object[][]{{new String[]{
+ "J",
+ "F",
+ "M",
+ "A",
+ "M",
+ "J",
+ "J",
+ "A",
+ "S",
+ "O",
+ "N",
+ "D"
+ }},};
+ }
+
+ //-----------------------------------------------------------------------
+ // Check Narrow and Narrow_standalone month name values
+ //-----------------------------------------------------------------------
+ @Test(dataProvider = "MonthNarrows")
+ public void compareMonthNarrowValues(String[] monthNarrowExpected) {
+ LOCARR.forEach((loc) -> {
+ TEXTSTYLELIST.forEach((style) -> {
+ MONTHVALUES.forEach((value) -> {
+ String result = value.getDisplayName(style, loc);
+ int index = value.ordinal();
+ assertEquals(result, monthNarrowExpected[index], "Test failed"
+ + " for COMPAT Provider for locale "
+ + loc + " for style " + style.name()
+ + " with Month value " + value.name());
+ });
+ });
+ });
+ }
+
+ /**
+ * Locale en_US, de_DE, fr_FR, no_NO will have different Narrow and
+ * Narrow_Standalone Day Names for COMPAT Provider.
+ */
+ @DataProvider(name = "DayNarrows")
+ public Object[][] dayNameData() {
+ return new Object[][]{
+ {Locale.US, new String[]{"M", "T", "W", "T", "F", "S", "S"}},
+ {Locale.GERMANY, new String[]{"M", "D", "M", "D", "F", "S", "S"}},
+ {Locale.FRANCE, new String[]{"L", "M", "M", "J", "V", "S", "D"}},
+ {new Locale("no", "NO"), new String[]{"M", "T", "O", "T", "F", "L", "S"}},};
+ }
+
+ //-----------------------------------------------------------------------
+ // Check Narrow and Narrow_standalone Day name values
+ //-----------------------------------------------------------------------
+ @Test(dataProvider = "DayNarrows")
+ public void compareDayNarrowValues(Locale locale, String[] dayNarrowExpected) {
+ TEXTSTYLELIST.forEach((style) -> {
+ DAYVALUES.forEach((value) -> {
+ String result = value.getDisplayName(style, locale);
+ int index = value.ordinal();
+ assertEquals(result, dayNarrowExpected[index], "Test failed"
+ + " for COMPAT Provider for locale "
+ + locale + " for style " + style.name()
+ + " with Day value " + value.name());
+ });
+ });
+ }
+}
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java Thu Oct 27 09:42:08 2016 -0700
@@ -26,7 +26,6 @@
* @summary unit test for Arrays.ParallelPrefix().
* @author Tristan Yan
* @run testng ParallelPrefix
- * @key intermittent
*/
import java.util.Arrays;
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -89,7 +89,7 @@
String[] jresResult = new String[4];
if (jreSupportsLocale) {
for (int i = 0; i < 4; i++) {
- jresResult[i] = "sun.util.locale.provider."+classNames[i];
+ jresResult[i] = "sun.text." + classNames[i];
}
}
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh Thu Oct 27 09:42:08 2016 -0700
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 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
@@ -23,6 +23,6 @@
#
#
# @test
-# @bug 4052440 8062588
+# @bug 4052440 8062588 8165804
# @summary BreakIteratorProvider tests
# @run shell ExecTest.sh foo BreakIteratorProviderTest
--- a/jdk/test/javax/net/ssl/templates/SSLTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/javax/net/ssl/templates/SSLTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -94,12 +94,22 @@
/*
* Is the server ready to serve?
*/
- private final CountDownLatch serverCondition = new CountDownLatch(1);
+ private final CountDownLatch serverReadyCondition = new CountDownLatch(1);
/*
* Is the client ready to handshake?
*/
- private final CountDownLatch clientCondition = new CountDownLatch(1);
+ private final CountDownLatch clientReadyCondition = new CountDownLatch(1);
+
+ /*
+ * Is the server done?
+ */
+ private final CountDownLatch serverDoneCondition = new CountDownLatch(1);
+
+ /*
+ * Is the client done?
+ */
+ private final CountDownLatch clientDoneCondition = new CountDownLatch(1);
/*
* Public API.
@@ -162,6 +172,25 @@
return keystore;
}
+ // Try to accept a connection in 30 seconds.
+ public static SSLSocket accept(SSLServerSocket sslServerSocket)
+ throws IOException {
+
+ return accept(sslServerSocket, SERVER_TIMEOUT);
+ }
+
+ public static SSLSocket accept(SSLServerSocket sslServerSocket, int timeout)
+ throws IOException {
+
+ try {
+ sslServerSocket.setSoTimeout(timeout);
+ return (SSLSocket) sslServerSocket.accept();
+ } catch (SocketTimeoutException ste) {
+ sslServerSocket.close();
+ return null;
+ }
+ }
+
public SSLTest setSeparateServerThread(boolean separateServerThread) {
this.separateServerThread = separateServerThread;
return this;
@@ -202,33 +231,61 @@
}
public void signalServerReady() {
- serverCondition.countDown();
+ serverReadyCondition.countDown();
+ }
+
+ public void signalServerDone() {
+ serverDoneCondition.countDown();
}
public boolean waitForClientSignal(long timeout, TimeUnit unit)
throws InterruptedException {
- return clientCondition.await(timeout, unit);
+ return clientReadyCondition.await(timeout, unit);
}
public boolean waitForClientSignal() throws InterruptedException {
return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
}
+ public boolean waitForClientDone(long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ return clientDoneCondition.await(timeout, unit);
+ }
+
+ public boolean waitForClientDone() throws InterruptedException {
+ return waitForClientDone(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
+ }
+
public void signalClientReady() {
- clientCondition.countDown();
+ clientReadyCondition.countDown();
+ }
+
+ public void signalClientDone() {
+ clientDoneCondition.countDown();
}
public boolean waitForServerSignal(long timeout, TimeUnit unit)
throws InterruptedException {
- return serverCondition.await(timeout, unit);
+ return serverReadyCondition.await(timeout, unit);
}
public boolean waitForServerSignal() throws InterruptedException {
return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
}
+ public boolean waitForServerDone(long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ return serverDoneCondition.await(timeout, unit);
+ }
+
+ public boolean waitForServerDone() throws InterruptedException {
+ return waitForServerDone(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS);
+ }
+
public SSLTest setServerPeer(Peer serverPeer) {
this.serverPeer = serverPeer;
return this;
@@ -310,19 +367,14 @@
test.signalServerReady();
// Try to accept a connection in 30 seconds.
- SSLSocket sslSocket;
- try {
- sslServerSocket.setSoTimeout(SERVER_TIMEOUT);
- sslSocket = (SSLSocket) sslServerSocket.accept();
- print("Server accepted connection");
- } catch (SocketTimeoutException ste) {
- sslServerSocket.close();
-
+ SSLSocket sslSocket = accept(sslServerSocket);
+ if (sslSocket == null) {
// Ignore the test case if no connection within 30 seconds.
print("No incoming client connection in 30 seconds. "
- + "Ignore in server side.", ste);
+ + "Ignore in server side.");
return;
}
+ print("Server accepted connection");
// handle the connection
try {
@@ -353,6 +405,8 @@
sslSocket.close();
sslServerSocket.close();
}
+
+ test.signalServerDone();
}
/*
@@ -419,6 +473,8 @@
print("Run client application");
test.getClientApplication().run(sslSocket, test);
}
+
+ test.signalClientDone();
}
/*
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Thu Oct 27 09:42:08 2016 -0700
@@ -24,6 +24,7 @@
package jdk.testlibrary;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -40,7 +41,8 @@
public final class JarUtils {
/**
- * Create jar file with specified files.
+ * Create jar file with specified files. If a specified file does not exist,
+ * a new jar entry will be created with the file name itself as the content.
*/
public static void createJar(String dest, String... files)
throws IOException {
@@ -54,6 +56,8 @@
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(file)) {
fis.transferTo(jos);
+ } catch (FileNotFoundException e) {
+ jos.write(file.getBytes());
}
}
}
@@ -61,7 +65,17 @@
}
/**
- * Add specified files to existing jar file.
+ * Add or remove specified files to existing jar file. If a specified file
+ * to be updated or added does not exist, the jar entry will be created
+ * with the file name itself as the content.
+ *
+ * @param src the original jar file name
+ * @param dest the new jar file name
+ * @param files the files to update. The list is broken into 2 groups
+ * by a "-" string. The files before in the 1st group will
+ * be either updated or added. The files in the 2nd group
+ * will be removed. If no "-" exists, all files belong to
+ * the 1st group.
*/
public static void updateJar(String src, String dest, String... files)
throws IOException {
@@ -77,8 +91,11 @@
JarEntry entry = entries.nextElement();
String name = entry.getName();
boolean found = false;
+ boolean update = true;
for (String file : files) {
- if (name.equals(file)) {
+ if (file.equals("-")) {
+ update = false;
+ } else if (name.equals(file)) {
updatedFiles.add(file);
found = true;
break;
@@ -86,11 +103,18 @@
}
if (found) {
- System.out.println(String.format("Updating %s with %s",
- dest, name));
- jos.putNextEntry(new JarEntry(name));
- try (FileInputStream fis = new FileInputStream(name)) {
- fis.transferTo(jos);
+ if (update) {
+ System.out.println(String.format("Updating %s with %s",
+ dest, name));
+ jos.putNextEntry(new JarEntry(name));
+ try (FileInputStream fis = new FileInputStream(name)) {
+ fis.transferTo(jos);
+ } catch (FileNotFoundException e) {
+ jos.write(name.getBytes());
+ }
+ } else {
+ System.out.println(String.format("Removing %s from %s",
+ name, dest));
}
} else {
System.out.println(String.format("Copying %s to %s",
@@ -103,12 +127,17 @@
// append new files
for (String file : files) {
+ if (file.equals("-")) {
+ break;
+ }
if (!updatedFiles.contains(file)) {
System.out.println(String.format("Adding %s with %s",
dest, file));
jos.putNextEntry(new JarEntry(file));
try (FileInputStream fis = new FileInputStream(file)) {
fis.transferTo(jos);
+ } catch (FileNotFoundException e) {
+ jos.write(file.getBytes());
}
}
}
--- a/jdk/test/sun/net/www/protocol/https/HttpsClient/OriginServer.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- */
-
-/*
- *
- * This is a HTTP test server used by the regression test
- * for the bug fixes: 4323990, 4413069
- */
-
-import java.io.*;
-import java.net.*;
-import javax.net.*;
-
-/*
- * OriginServer.java -- a simple server that can serve
- * Http get request in both clear and secure channel
- */
-
-public abstract class OriginServer implements Runnable, Closeable {
-
- private ServerSocket server = null;
- Exception serverException = null;
- private volatile boolean closed;
-
- /**
- * Constructs a OriginServer based on ss and
- * obtains a response data's bytecodes using the method
- * getBytes.
- */
- protected OriginServer(ServerSocket ss) throws Exception
- {
- server = ss;
- newListener();
- if (serverException != null)
- throw serverException;
- }
-
- @Override
- public void close() throws IOException {
- if (closed)
- return;
- closed = true;
- server.close();
- }
-
- /**
- * Returns an array of bytes containing the bytes for
- * the data sent in the response.
- *
- * @return the bytes for the information that is being sent
- */
- public abstract byte[] getBytes();
-
- /**
- * The "listen" thread that accepts a connection to the
- * server, parses the header and sends back the response
- */
- public void run()
- {
- Socket socket;
-
- // accept a connection
- try {
- socket = server.accept();
- } catch (IOException e) {
- if (!closed) {
- System.out.println("Class Server died: " + e.getMessage());
- serverException = e;
- }
- return;
- }
- try {
- DataOutputStream out =
- new DataOutputStream(socket.getOutputStream());
- try {
- BufferedReader in =
- new BufferedReader(new InputStreamReader(
- socket.getInputStream()));
- // read the request
- readRequest(in);
- // retrieve bytecodes
- byte[] bytecodes = getBytes();
- // send bytecodes in response (assumes HTTP/1.0 or later)
- try {
- out.writeBytes("HTTP/1.0 200 OK\r\n");
- out.writeBytes("Content-Length: " + bytecodes.length +
- "\r\n");
- out.writeBytes("Content-Type: text/html\r\n\r\n");
- out.write(bytecodes);
- out.flush();
- } catch (IOException ie) {
- serverException = ie;
- return;
- }
-
- } catch (Exception e) {
- // write out error response
- out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
- out.writeBytes("Content-Type: text/html\r\n\r\n");
- out.flush();
- }
-
- } catch (IOException ex) {
- System.out.println("error writing response: " + ex.getMessage());
- serverException = ex;
-
- } finally {
- try {
- socket.close();
- } catch (IOException e) {
- serverException = e;
- }
- }
- }
-
- /**
- * Create a new thread to listen.
- */
- private void newListener()
- {
- (new Thread(this)).start();
- }
-
- /**
- * read the response, don't care for the syntax of the request-line
- * for this testing
- */
- private static void readRequest(BufferedReader in)
- throws IOException
- {
- String line = null;
- System.out.println("Server received: ");
- do {
- if (line != null)
- System.out.println(line);
- line = in.readLine();
- } while ((line.length() != 0) &&
- (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
- }
-}
--- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
* @summary HttpsURLConnection doesn't send Proxy-Authorization on CONNECT
* Incorrect checking of proxy server response
* @modules java.base/sun.net.www
+ * @library /javax/net/ssl/templates
* @run main/othervm ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic, ProxyAuthTest fail
@@ -41,12 +42,18 @@
// No way to reserve and restore java.lang.Authenticator, as well as read-once
// system properties, so this tests needs to run in othervm mode.
-import java.io.*;
-import java.net.*;
-import java.security.KeyStore;
-import javax.net.*;
-import javax.net.ssl.*;
-import java.security.cert.*;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Authenticator;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.Proxy;
+import java.net.URL;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
import static java.nio.charset.StandardCharsets.US_ASCII;
/*
@@ -65,27 +72,20 @@
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
- volatile private static int serverPort = 0;
-
- /*
- * The TestServer implements a OriginServer that
- * processes HTTP requests and responses.
+ /**
+ * read the response, don't care for the syntax of the request-line
+ * for this testing
*/
- static class TestServer extends OriginServer {
- public TestServer(ServerSocket ss) throws Exception {
- super(ss);
- }
-
- /*
- * Returns an array of bytes containing the bytes for
- * the data sent in the response.
- *
- * @return bytes for the data in the response
- */
- public byte[] getBytes() {
- return "Proxy authentication for tunneling succeeded ..".
- getBytes(US_ASCII);
- }
+ private static void readRequest(BufferedReader in) throws IOException {
+ String line = null;
+ System.out.println("Server received: ");
+ do {
+ if (line != null) {
+ System.out.println(line);
+ }
+ line = in.readLine();
+ } while ((line.length() != 0) &&
+ (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
}
/*
@@ -93,94 +93,96 @@
*/
public static void main(String args[]) throws Exception {
boolean expectSuccess;
- if (args[0].equals("succeed")) {
- expectSuccess = true;
- } else {
- expectSuccess = false;
- }
+ expectSuccess = args[0].equals("succeed");
String keyFilename =
- System.getProperty("test.src", "./") + "/" + pathToStores +
- "/" + keyStoreFile;
+ SSLTest.TEST_SRC + "/" + pathToStores + "/" + keyStoreFile;
String trustFilename =
- System.getProperty("test.src", "./") + "/" + pathToStores +
- "/" + trustStoreFile;
+ SSLTest.TEST_SRC + "/" + pathToStores + "/" + trustStoreFile;
+
+ SSLTest.setup(keyFilename, trustFilename, passwd);
+
+ new SSLTest()
+ .setServerApplication((socket, test) -> {
+ DataOutputStream out = new DataOutputStream(
+ socket.getOutputStream());
- System.setProperty("javax.net.ssl.keyStore", keyFilename);
- System.setProperty("javax.net.ssl.keyStorePassword", passwd);
- System.setProperty("javax.net.ssl.trustStore", trustFilename);
- System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+ try {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(socket.getInputStream()));
+
+ // read the request
+ readRequest(in);
+
+ // retrieve bytecodes
+ byte[] bytecodes =
+ "Proxy authentication for tunneling succeeded .."
+ .getBytes(US_ASCII);
- boolean useSSL = true;
- /*
- * setup the server
- */
- Closeable server;
- try {
- ServerSocketFactory ssf =
- ProxyAuthTest.getServerSocketFactory(useSSL);
- ServerSocket ss = ssf.createServerSocket(serverPort);
- serverPort = ss.getLocalPort();
- server = new TestServer(ss);
- } catch (Exception e) {
- System.out.println("Server side failed:" +
- e.getMessage());
- throw e;
- }
- // trigger the client
- try {
- doClientSide();
- if (!expectSuccess) {
- throw new RuntimeException(
- "Expected exception/failure to connect, but succeeded.");
- }
- } catch (IOException e) {
- if (expectSuccess) {
- System.out.println("Client side failed: " + e.getMessage());
- throw e;
- }
+ // send bytecodes in response (assumes HTTP/1.0 or later)
+ out.writeBytes("HTTP/1.0 200 OK\r\n");
+ out.writeBytes("Content-Length: " + bytecodes.length +
+ "\r\n");
+ out.writeBytes("Content-Type: text/html\r\n\r\n");
+ out.write(bytecodes);
+ out.flush();
+ } catch (IOException e) {
+ // write out error response
+ out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
+ out.writeBytes("Content-Type: text/html\r\n\r\n");
+ out.flush();
+ }
+ })
+ .setClientPeer(test -> {
+ try {
+ doClientSide(test);
+ if (!expectSuccess) {
+ throw new RuntimeException("Expected exception/failure "
+ + "to connect, but succeeded.");
+ }
+ } catch (IOException e) {
+ if (expectSuccess) {
+ System.out.println("Client side failed: "
+ + e.getMessage());
+ throw e;
+ }
- if (! (e.getMessage().contains("Unable to tunnel through proxy") &&
- e.getMessage().contains("407")) ) {
- throw new RuntimeException(
- "Expected exception about cannot tunnel, 407, etc, but got", e);
- } else {
- // Informative
- System.out.println("Caught expected exception: " + e.getMessage());
- }
- } finally {
- if (server != null)
- server.close();
- }
+ if (! (e.getMessage().contains(
+ "Unable to tunnel through proxy") &&
+ e.getMessage().contains("407")) ) {
+
+ throw new RuntimeException(
+ "Expected exception about cannot tunnel, "
+ + "407, etc, but got", e);
+ } else {
+ // Informative
+ System.out.println("Caught expected exception: "
+ + e.getMessage());
+ }
+ }
+ })
+ .runTest();
}
- private static ServerSocketFactory getServerSocketFactory
- (boolean useSSL) throws Exception {
- if (useSSL) {
- SSLServerSocketFactory ssf = null;
- // set up key manager to do server authentication
- SSLContext ctx;
- KeyManagerFactory kmf;
- KeyStore ks;
- char[] passphrase = passwd.toCharArray();
-
- ctx = SSLContext.getInstance("TLS");
- kmf = KeyManagerFactory.getInstance("SunX509");
- ks = KeyStore.getInstance("JKS");
+ static void doClientSide(SSLTest test) throws IOException {
- ks.load(new FileInputStream(System.getProperty(
- "javax.net.ssl.keyStore")), passphrase);
- kmf.init(ks, passphrase);
- ctx.init(kmf.getKeyManagers(), null, null);
+ // Wait for server to get started.
+ //
+ // The server side takes care of the issue if the server cannot
+ // get started in 90 seconds. The client side would just ignore
+ // the test case if the serer is not ready.
+ try {
+ if (!test.waitForServerSignal()) {
+ System.out.print("The server is not ready yet in 90 seconds. "
+ + "Ignore in client side.");
+ return;
+ }
+ } catch (InterruptedException e) {
+ System.out.print("InterruptedException occured. "
+ + "Ignore in client side.");
+ return;
+ }
- ssf = ctx.getServerSocketFactory();
- return ssf;
- } else {
- return ServerSocketFactory.getDefault();
- }
- }
-
- static void doClientSide() throws IOException {
/*
* setup up a proxy with authentication information
*/
@@ -190,23 +192,27 @@
* we want to avoid URLspoofCheck failures in cases where the cert
* DN name does not match the hostname in the URL.
*/
- HttpsURLConnection.setDefaultHostnameVerifier(
- new NameVerifier());
+ HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
- InetSocketAddress paddr = new InetSocketAddress("localhost", ps.getPort());
+ InetSocketAddress paddr = new InetSocketAddress(
+ "localhost", ps.getPort());
Proxy proxy = new Proxy(Proxy.Type.HTTP, paddr);
- URL url = new URL("https://" + "localhost:" + serverPort
- + "/index.html");
- BufferedReader in = null;
+ URL url = new URL("https://" + "localhost:" + test.getServerPort()
+ + "/index.html");
+
+ // Signal the server, the client is ready to communicate.
+ test.signalClientReady();
+
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection(proxy);
- try {
- in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
+ try (BufferedReader in = new BufferedReader(
+ new InputStreamReader(uc.getInputStream()))) {
+
String inputLine;
System.out.print("Client recieved from the server: ");
- while ((inputLine = in.readLine()) != null)
+ while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
- in.close();
+ }
} catch (IOException e) {
// Assert that the error stream is not accessible from the failed
// tunnel setup.
@@ -214,13 +220,13 @@
throw new RuntimeException("Unexpected error stream.");
}
- if (in != null)
- in.close();
throw e;
}
}
static class NameVerifier implements HostnameVerifier {
+
+ @Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
@@ -244,9 +250,9 @@
public static class TestAuthenticator extends Authenticator {
+ @Override
public PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication("Test",
- "test123".toCharArray());
+ return new PasswordAuthentication("Test", "test123".toCharArray());
}
}
}
--- a/jdk/test/sun/net/www/protocol/jar/B4957695.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/sun/net/www/protocol/jar/B4957695.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, 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
@@ -24,6 +24,7 @@
/**
* @test
* @bug 4957695
+ * @run main/othervm -Djava.io.tmpdir=. B4957695
* @summary URLJarFile.retrieve does not delete tmpFile on IOException
*/
--- a/jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +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 Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8137058
- * @summary Basic test for the unsupported newConstructorForSerialization
- * @modules jdk.unsupported
- */
-
-import java.lang.reflect.Constructor;
-import sun.reflect.ReflectionFactory;
-
-public class NewConstructorForSerialization {
-
- private static Constructor<?> getConstructor(Class<?> type)
- throws NoSuchMethodException
- {
- ReflectionFactory factory = ReflectionFactory.getReflectionFactory();
- Constructor<?> objectConstructor = type.getConstructor((Class[]) null);
-
- @SuppressWarnings("unchecked")
- Constructor<?> c = (Constructor<?>) factory
- .newConstructorForSerialization(type, objectConstructor);
- return c;
- }
-
- public static void main(String[] args) throws Exception {
- System.out.println(getConstructor(Object.class).newInstance());
- System.out.println(getConstructor(Foo.class).newInstance());
- System.out.println(getConstructor(Bar.class).newInstance());
- }
-
- static class Foo {
- public Foo() { }
- }
-
- static class Bar extends Foo {
- public Bar() { }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,289 @@
+/*
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.reflect.ReflectionFactory;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @bug 8137058 8164908
+ * @run testng ReflectionFactoryTest
+ * @run testng/othervm/policy=security.policy ReflectionFactoryTest
+ * @summary Basic test for the unsupported ReflectionFactory
+ * @modules jdk.unsupported
+ */
+
+public class ReflectionFactoryTest {
+
+ // Initialized by init()
+ static ReflectionFactory factory;
+
+ @DataProvider(name = "ClassConstructors")
+ static Object[][] classConstructors() {
+ return new Object[][] {
+ {Object.class},
+ {Foo.class},
+ {Bar.class},
+ };
+ }
+
+ @BeforeClass
+ static void init() {
+ factory = ReflectionFactory.getReflectionFactory();
+ }
+
+ /**
+ * Test that the correct Constructor is selected and run.
+ * @param type type of object to create
+ * @throws NoSuchMethodException - error
+ * @throws InstantiationException - error
+ * @throws IllegalAccessException - error
+ * @throws InvocationTargetException - error
+ */
+ @Test(dataProvider="ClassConstructors")
+ static void testConstructor(Class<?> type)
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException
+ {
+ @SuppressWarnings("unchecked")
+ Constructor<?> c = factory.newConstructorForSerialization(type);
+
+ Object o = c.newInstance();
+ Assert.assertEquals(o.getClass(), type, "Instance is wrong type");
+ if (o instanceof Foo) {
+ Foo foo = (Foo)o;
+ foo.check();
+ }
+ }
+
+ static class Foo {
+ private int foo;
+ public Foo() {
+ this.foo = 1;
+ }
+
+ public String toString() {
+ return "foo: " + foo;
+ }
+
+ public void check() {
+ int expectedFoo = 1;
+ Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
+ }
+ }
+
+ static class Bar extends Foo implements Serializable {
+ private int bar;
+ public Bar() {
+ this.bar = 1;
+ }
+
+ public String toString() {
+ return super.toString() + ", bar: " + bar;
+ }
+
+ public void check() {
+ super.check();
+ int expectedBar = 0;
+ Assert.assertEquals(bar, expectedBar, "bar() constructor not run");
+ }
+ }
+
+ /**
+ * Test newConstructorForExternalization returns the constructor and it can be called.
+ * @throws NoSuchMethodException - error
+ * @throws InstantiationException - error
+ * @throws IllegalAccessException - error
+ * @throws InvocationTargetException - error
+ */
+ @Test
+ static void newConstructorForExternalization()
+ throws NoSuchMethodException, InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ Constructor<?> cons = factory.newConstructorForExternalization(Ext.class);
+ Ext ext = (Ext)cons.newInstance();
+ Assert.assertEquals(ext.ext, 1, "Constructor not run");
+ }
+
+ static class Ext implements Externalizable {
+ private static final long serialVersionUID = 1L;
+
+ int ext;
+
+ public Ext() {
+ ext = 1;
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {}
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
+ }
+
+ @Test
+ static void testReadWriteObjectForSerialization() throws Throwable {
+ MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class);
+ Assert.assertNotNull(readObjectMethod, "readObjectMethod not found");
+
+ MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class);
+ Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found");
+
+ MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class);
+ Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found");
+
+ MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class);
+ Assert.assertNotNull(readResolveMethod, "readResolveMethod not found");
+
+ MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class);
+ Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found");
+
+ byte[] data = null;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ Ser ser = new Ser();
+
+ writeReplaceMethod.invoke(ser);
+ Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called");
+ Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called");
+
+ writeObjectMethod.invoke(ser, oos);
+ Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called");
+ Assert.assertTrue(ser.writeObjectCalled, "writeObject not called");
+ oos.flush();
+ data = baos.toByteArray();
+ }
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ Ser ser2 = new Ser();
+
+ readObjectMethod.invoke(ser2, ois);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject not called");
+ Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called");
+ Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+ readObjectNoDataMethod.invoke(ser2, ois);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+ Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+ Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+ readResolveMethod.invoke(ser2);
+ Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+ Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+ Assert.assertTrue(ser2.readResolveCalled, "readResolve not called");
+ }
+ }
+
+ @Test
+ static void hasStaticInitializer() {
+ boolean actual = factory.hasStaticInitializerForSerialization(Ser.class);
+ Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong");
+ }
+
+ static class Ser implements Serializable {
+ private static final long serialVersionUID = 2L;
+ static {
+ // Define a static class initialization method
+ }
+
+ boolean readObjectCalled = false;
+ boolean readObjectNoDataCalled = false;
+ boolean writeObjectCalled = false;
+ boolean readResolveCalled = false;
+ boolean writeReplaceCalled = false;
+
+ public Ser() {}
+
+ private void readObject(ObjectInputStream ois) throws IOException {
+ Assert.assertFalse(writeObjectCalled, "readObject called too many times");
+ readObjectCalled = ois.readBoolean();
+ }
+
+ private void readObjectNoData(ObjectInputStream ois) throws IOException {
+ Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times");
+ readObjectNoDataCalled = true;
+ }
+
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ Assert.assertFalse(writeObjectCalled, "writeObject called too many times");
+ writeObjectCalled = true;
+ oos.writeBoolean(writeObjectCalled);
+ }
+
+ private Object writeReplace() {
+ Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times");
+ writeReplaceCalled = true;
+ return this;
+ }
+
+ private Object readResolve() {
+ Assert.assertFalse(readResolveCalled, "readResolve called too many times");
+ readResolveCalled = true;
+ return this;
+ }
+ }
+
+ /**
+ * Test the constructor of OptionalDataExceptions.
+ */
+ @Test
+ static void newOptionalDataException() {
+ OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true);
+ Assert.assertTrue(ode.eof, "eof wrong");
+ ode = factory.newOptionalDataExceptionForSerialization(false);
+ Assert.assertFalse(ode.eof, "eof wrong");
+
+ }
+
+
+
+ // Main can be used to run the tests from the command line with only testng.jar.
+ @SuppressWarnings("raw_types")
+ @Test(enabled = false)
+ public static void main(String[] args) {
+ Class<?>[] testclass = {ReflectionFactoryTest.class};
+ TestNG testng = new TestNG();
+ testng.setTestClasses(testclass);
+ testng.run();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/ReflectionFactory/security.policy Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,11 @@
+// Individual Permissions for ReflectionFactoryTest
+grant {
+ // Permissions needed to run the test
+ permission java.util.PropertyPermission "*", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+ permission java.lang.RuntimePermission "reflectionFactoryAccess";
+};
--- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,31 +29,22 @@
/*
* @test
* @bug 4392475
+ * @library /javax/net/ssl/templates
* @summary Calling setWantClientAuth(true) disables anonymous suites
* @run main/othervm/timeout=180 AnonCipherWithWantClientAuth
*/
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.*;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.security.Security;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
public class AnonCipherWithWantClientAuth {
/*
- * =============================================================
- * 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 = "../../../../javax/net/ssl/etc";
@@ -61,106 +52,7 @@
static String trustStoreFile = "truststore";
static String passwd = "passphrase";
- /*
- * Is the server ready to serve?
- */
- volatile static boolean serverReady = false;
-
- /*
- * Turn on SSL debugging?
- */
- static boolean debug = false;
-
- /*
- * 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 =
- (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
- SSLServerSocket sslServerSocket =
- (SSLServerSocket) sslssf.createServerSocket(serverPort);
- serverPort = sslServerSocket.getLocalPort();
- String ciphers[]={"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
- "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"};
- sslServerSocket.setEnabledCipherSuites(ciphers);
- sslServerSocket.setWantClientAuth(true);
- /*
- * Signal Client, we're ready for his connect.
- */
- serverReady = true;
-
- SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
- 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 =
- (SSLSocketFactory) SSLSocketFactory.getDefault();
- SSLSocket sslSocket = (SSLSocket)
- sslsf.createSocket("localhost", serverPort);
- String ciphers[] = {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"};
- sslSocket.setEnabledCipherSuites(ciphers);
- sslSocket.setUseClientMode(true);
-
- 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 {
- // reset security properties to make sure that the algorithms
- // and keys used in this test are not disabled.
Security.setProperty("jdk.tls.disabledAlgorithms", "");
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
@@ -170,100 +62,84 @@
String trustFilename =
System.getProperty("test.src", "./") + "/" + pathToStores +
"/" + trustStoreFile;
-
- System.setProperty("javax.net.ssl.keyStore", keyFilename);
- System.setProperty("javax.net.ssl.keyStorePassword", passwd);
- System.setProperty("javax.net.ssl.trustStore", trustFilename);
- System.setProperty("javax.net.ssl.trustStorePassword", passwd);
-
- if (debug)
- System.setProperty("javax.net.debug", "all");
+ SSLTest.setup(keyFilename, trustFilename, passwd);
- /*
- * Start the tests.
- */
- new AnonCipherWithWantClientAuth();
- }
-
- Thread clientThread = null;
- Thread serverThread = null;
+ new SSLTest()
+ .setServerPeer(test -> {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(SSLTest.FREE_PORT);
+ test.setServerPort(sslServerSocket.getLocalPort());
+ SSLTest.print("Server is listening on port "
+ + test.getServerPort());
- /*
- * Primary constructor, used to drive remainder of the test.
- *
- * Fork off the other side, then do your work.
- */
- AnonCipherWithWantClientAuth () throws Exception {
- if (separateServerThread) {
- startServer(true);
- startClient(false);
- } else {
- startClient(true);
- startServer(false);
- }
+ String ciphers[] = {
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
+ sslServerSocket.setEnabledCipherSuites(ciphers);
+ sslServerSocket.setWantClientAuth(true);
+
+ // Signal the client, the server is ready to accept connection.
+ test.signalServerReady();
- /*
- * Wait for other side to close down.
- */
- if (separateServerThread) {
- serverThread.join();
- } else {
- clientThread.join();
- }
+ // Try to accept a connection in 30 seconds.
+ SSLSocket sslSocket = SSLTest.accept(sslServerSocket);
+ if (sslSocket == null) {
+ // Ignore the test case if no connection within 30 seconds.
+ SSLTest.print("No incoming client connection in 30 seconds."
+ + " Ignore in server side.");
+ return;
+ }
+ SSLTest.print("Server accepted connection");
- /*
- * When we get here, the test is pretty much over.
- *
- * If the main thread excepted, that propagates back
- * immediately. If the other thread threw an exception, we
- * should report back.
- */
- if (serverException != null)
- throw serverException;
- if (clientException != null)
- throw clientException;
- }
+ // handle the connection
+ try {
+ // Is it the expected client connection?
+ //
+ // Naughty test cases or third party routines may try to
+ // connection to this server port unintentionally. In
+ // order to mitigate the impact of unexpected client
+ // connections and avoid intermittent failure, it should
+ // be checked that the accepted connection is really linked
+ // to the expected client.
+ boolean clientIsReady = test.waitForClientSignal();
- void startServer(boolean newThread) throws Exception {
- if (newThread) {
- serverThread = new Thread() {
- public void run() {
- try {
- doServerSide();
- } catch (Exception e) {
- /*
- * Our server thread just died.
- */
- System.err.println("Server died...");
- serverReady = true;
- serverException = e;
+ if (clientIsReady) {
+ // Run the application in server side.
+ SSLTest.print("Run server application");
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ } else {
+ System.out.println(
+ "The client is not the expected one or timeout. "
+ + "Ignore in server side.");
}
+ } finally {
+ sslSocket.close();
+ sslServerSocket.close();
}
- };
- serverThread.start();
- } else {
- doServerSide();
- }
- }
+ })
+ .setClientApplication((socket, test) -> {
+ String ciphers[] = {
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" };
+ socket.setEnabledCipherSuites(ciphers);
+ socket.setUseClientMode(true);
- void startClient(boolean newThread) throws Exception {
- if (newThread) {
- clientThread = new Thread() {
- public void run() {
- try {
- doClientSide();
- } catch (Exception e) {
- /*
- * Our client thread just died.
- */
- System.err.println("Client died...");
- clientException = e;
- }
- }
- };
- clientThread.start();
- } else {
- doClientSide();
- }
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+ })
+ .runTest();
}
}
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Thu Oct 27 09:42:08 2016 -0700
@@ -22,25 +22,29 @@
*/
import com.sun.net.httpserver.*;
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-import java.util.Locale;
+import jdk.testlibrary.*;
+import jdk.testlibrary.JarUtils;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.PKCS9Attribute;
@@ -52,11 +56,22 @@
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
+/*
+ * @test
+ * @bug 6543842 6543440 6939248 8009636 8024302 8163304
+ * @summary checking response of timestamp
+ * @modules java.base/sun.security.pkcs
+ * java.base/sun.security.timestamp
+ * java.base/sun.security.x509
+ * java.base/sun.security.util
+ * java.base/sun.security.tools.keytool
+ * @library /lib/testlibrary
+ * @run main/timeout=600 TimestampCheck
+ */
public class TimestampCheck {
- static final String TSKS = "tsks";
- static final String JAR = "old.jar";
- static final String defaultPolicyId = "2.3.4.5";
+ static final String defaultPolicyId = "2.3.4";
+ static String host = null;
static class Handler implements HttpHandler, AutoCloseable {
@@ -75,11 +90,7 @@
t.getRequestBody().read(input);
try {
- int path = 0;
- if (t.getRequestURI().getPath().length() > 1) {
- path = Integer.parseInt(
- t.getRequestURI().getPath().substring(1));
- }
+ String path = t.getRequestURI().getPath().substring(1);
byte[] output = sign(input, path);
Headers out = t.getResponseHeaders();
out.set("Content-Type", "application/timestamp-reply");
@@ -97,24 +108,10 @@
/**
* @param input The data to sign
* @param path different cases to simulate, impl on URL path
- * 0: normal
- * 1: Missing nonce
- * 2: Different nonce
- * 3: Bad digets octets in messageImprint
- * 4: Different algorithmId in messageImprint
- * 5: whole chain in cert set
- * 6: extension is missing
- * 7: extension is non-critical
- * 8: extension does not have timestamping
- * 9: no cert in response
- * 10: normal
- * 11: always return default policy id
- * 12: normal
- * otherwise: normal
* @returns the signed
*/
- byte[] sign(byte[] input, int path) throws Exception {
- // Read TSRequest
+ byte[] sign(byte[] input, String path) throws Exception {
+
DerValue value = new DerValue(input);
System.err.println("\nIncoming Request\n===================");
System.err.println("Version: " + value.data.getInteger());
@@ -138,36 +135,33 @@
}
}
- // Write TSResponse
System.err.println("\nResponse\n===================");
- KeyStore ks = KeyStore.getInstance("JKS");
- try (FileInputStream fis = new FileInputStream(keystore)) {
- ks.load(fis, "changeit".toCharArray());
+ KeyStore ks = KeyStore.getInstance(
+ new File(keystore), "changeit".toCharArray());
+
+ String alias = "ts";
+ if (path.startsWith("bad") || path.equals("weak")) {
+ alias = "ts" + path;
}
- String alias = "ts";
- if (path == 6) alias = "tsbad1";
- if (path == 7) alias = "tsbad2";
- if (path == 8) alias = "tsbad3";
-
- if (path == 11) {
+ if (path.equals("diffpolicy")) {
policyId = new ObjectIdentifier(defaultPolicyId);
}
DerOutputStream statusInfo = new DerOutputStream();
statusInfo.putInteger(0);
- DerOutputStream token = new DerOutputStream();
AlgorithmId[] algorithms = {aid};
Certificate[] chain = ks.getCertificateChain(alias);
- X509Certificate[] signerCertificateChain = null;
+ X509Certificate[] signerCertificateChain;
X509Certificate signer = (X509Certificate)chain[0];
- if (path == 5) { // Only case 5 uses full chain
+
+ if (path.equals("fullchain")) { // Only case 5 uses full chain
signerCertificateChain = new X509Certificate[chain.length];
for (int i=0; i<chain.length; i++) {
signerCertificateChain[i] = (X509Certificate)chain[i];
}
- } else if (path == 9) {
+ } else if (path.equals("nocert")) {
signerCertificateChain = new X509Certificate[0];
} else {
signerCertificateChain = new X509Certificate[1];
@@ -179,11 +173,11 @@
tst.putInteger(1);
tst.putOID(policyId);
- if (path != 3 && path != 4) {
+ if (!path.equals("baddigest") && !path.equals("diffalg")) {
tst.putDerValue(messageImprint);
} else {
byte[] data = messageImprint.toByteArray();
- if (path == 4) {
+ if (path.equals("diffalg")) {
data[6] = (byte)0x01;
} else {
data[data.length-1] = (byte)0x01;
@@ -198,10 +192,10 @@
Calendar cal = Calendar.getInstance();
tst.putGeneralizedTime(cal.getTime());
- if (path == 2) {
+ if (path.equals("diffnonce")) {
tst.putInteger(1234);
- } else if (path == 1) {
- // do nothing
+ } else if (path.equals("nononce")) {
+ // no noce
} else {
tst.putInteger(nonce);
}
@@ -212,6 +206,8 @@
DerOutputStream tstInfo2 = new DerOutputStream();
tstInfo2.putOctetString(tstInfo.toByteArray());
+ // Always use the same algorithm at timestamp signing
+ // so it is different from the hash algorithm.
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initSign((PrivateKey)(ks.getKey(
alias, "changeit".toCharArray())));
@@ -229,12 +225,11 @@
SignerInfo signerInfo = new SignerInfo(
new X500Name(signer.getIssuerX500Principal().getName()),
signer.getSerialNumber(),
- aid, AlgorithmId.get("RSA"), sig.sign());
+ AlgorithmId.get("SHA-1"), AlgorithmId.get("RSA"), sig.sign());
SignerInfo[] signerInfos = {signerInfo};
- PKCS7 p7 =
- new PKCS7(algorithms, contentInfo, signerCertificateChain,
- signerInfos);
+ PKCS7 p7 = new PKCS7(algorithms, contentInfo,
+ signerCertificateChain, signerInfos);
ByteArrayOutputStream p7out = new ByteArrayOutputStream();
p7.encodeSignedData(p7out);
@@ -294,44 +289,68 @@
}
}
- public static void main(String[] args) throws Exception {
- try (Handler tsa = Handler.init(0, TSKS);) {
+ public static void main(String[] args) throws Throwable {
+
+ prepare();
+
+ try (Handler tsa = Handler.init(0, "tsks");) {
tsa.start();
int port = tsa.getPort();
-
- String cmd;
- // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
- // nonce generation in timestamping request. Not avaibale on
- // Windows and defaults to thread seed generator, not too bad.
- if (System.getProperty("java.home").endsWith("jre")) {
- cmd = System.getProperty("java.home") + "/../bin/jarsigner";
- } else {
- cmd = System.getProperty("java.home") + "/bin/jarsigner";
- }
-
- cmd += " " + System.getProperty("test.tool.vm.opts")
- + " -J-Djava.security.egd=file:/dev/./urandom"
- + " -J-Duser.language=en -J-Duser.country=US"
- + " -debug -keystore " + TSKS + " -storepass changeit"
- + " -tsa http://localhost:" + port + "/%d"
- + " -signedjar new_%d.jar " + JAR + " old";
+ host = "http://localhost:" + port + "/";
if (args.length == 0) { // Run this test
- jarsigner(cmd, 0, true); // Success, normal call
- jarsigner(cmd, 1, false); // These 4 should fail
- jarsigner(cmd, 2, false);
- jarsigner(cmd, 3, false);
- jarsigner(cmd, 4, false);
- jarsigner(cmd, 5, true); // Success, 6543440 solved.
- jarsigner(cmd, 6, false); // tsbad1
- jarsigner(cmd, 7, false); // tsbad2
- jarsigner(cmd, 8, false); // tsbad3
- jarsigner(cmd, 9, false); // no cert in timestamp
- jarsigner(cmd + " -tsapolicyid 1.2.3.4", 10, true);
- checkTimestamp("new_10.jar", "1.2.3.4", "SHA-256");
- jarsigner(cmd + " -tsapolicyid 1.2.3.5", 11, false);
- jarsigner(cmd + " -tsadigestalg SHA", 12, true);
- checkTimestamp("new_12.jar", defaultPolicyId, "SHA-1");
+ sign("none")
+ .shouldContain("is not timestamped")
+ .shouldHaveExitValue(0);
+
+ sign("badku")
+ .shouldHaveExitValue(0);
+ checkBadKU("badku.jar");
+
+ sign("normal")
+ .shouldNotContain("is not timestamped")
+ .shouldHaveExitValue(0);
+
+ sign("nononce")
+ .shouldHaveExitValue(1);
+ sign("diffnonce")
+ .shouldHaveExitValue(1);
+ sign("baddigest")
+ .shouldHaveExitValue(1);
+ sign("diffalg")
+ .shouldHaveExitValue(1);
+ sign("fullchain")
+ .shouldHaveExitValue(0); // Success, 6543440 solved.
+ sign("bad1")
+ .shouldHaveExitValue(1);
+ sign("bad2")
+ .shouldHaveExitValue(1);
+ sign("bad3")
+ .shouldHaveExitValue(1);
+ sign("nocert")
+ .shouldHaveExitValue(1);
+
+ sign("policy", "-tsapolicyid", "1.2.3")
+ .shouldHaveExitValue(0);
+ checkTimestamp("policy.jar", "1.2.3", "SHA-256");
+
+ sign("diffpolicy", "-tsapolicyid", "1.2.3")
+ .shouldHaveExitValue(1);
+
+ sign("tsaalg", "-tsadigestalg", "SHA")
+ .shouldHaveExitValue(0);
+ checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1");
+
+ sign("weak", "-digestalg", "MD5",
+ "-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
+ .shouldHaveExitValue(0)
+ .shouldMatch("MD5.*-digestalg.*risk")
+ .shouldMatch("MD5.*-tsadigestalg.*risk")
+ .shouldMatch("MD5withRSA.*-sigalg.*risk");
+ checkWeak("weak.jar");
+
+ // When .SF or .RSA is missing or invalid
+ checkMissingOrInvalidFiles("normal.jar");
} else { // Run as a standalone server
System.err.println("Press Enter to quit server");
System.in.read();
@@ -339,6 +358,95 @@
}
}
+ private static void checkMissingOrInvalidFiles(String s)
+ throws Throwable {
+ JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF");
+ verify("1.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Missing signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA");
+ verify("2.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Missing block file for signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF");
+ verify("3.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Unparsable signature-related file META-INF/OLD.SF");
+ JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA");
+ verify("4.jar", "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("Unparsable signature-related file META-INF/OLD.RSA");
+ }
+
+ static OutputAnalyzer jarsigner(List<String> extra)
+ throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
+ .addVMArg("-Duser.language=en")
+ .addVMArg("-Duser.country=US")
+ .addToolArg("-keystore")
+ .addToolArg("tsks")
+ .addToolArg("-storepass")
+ .addToolArg("changeit");
+ for (String s : extra) {
+ if (s.startsWith("-J")) {
+ launcher.addVMArg(s.substring(2));
+ } else {
+ launcher.addToolArg(s);
+ }
+ }
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ static OutputAnalyzer verify(String file, String... extra)
+ throws Throwable {
+ List<String> args = new ArrayList<>();
+ args.add("-verify");
+ args.add(file);
+ args.addAll(Arrays.asList(extra));
+ return jarsigner(args);
+ }
+
+ static void checkBadKU(String file) throws Throwable {
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ verify(file, "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("Signed by")
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ verify(file, "-J-Djava.security.debug=jar")
+ .shouldHaveExitValue(0)
+ .shouldContain("SignatureException: Key usage restricted")
+ .shouldContain("treated as unsigned")
+ .shouldContain("re-run jarsigner with debug enabled");
+ }
+
+ static void checkWeak(String file) throws Throwable {
+ verify(file)
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled.")
+ .shouldMatch("Re-run jarsigner with the -verbose option for more details");
+ verify(file, "-verbose")
+ .shouldHaveExitValue(0)
+ .shouldContain("treated as unsigned")
+ .shouldMatch("weak algorithm that is now disabled by")
+ .shouldMatch("Digest algorithm: .*weak")
+ .shouldMatch("Signature algorithm: .*weak")
+ .shouldMatch("Timestamp digest algorithm: .*weak")
+ .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
+ .shouldMatch("Timestamp signature algorithm: .*key.*weak");
+ verify(file, "-J-Djava.security.debug=jar")
+ .shouldHaveExitValue(0)
+ .shouldMatch("SignatureException:.*Disabled");
+ }
+
static void checkTimestamp(String file, String policyId, String digestAlg)
throws Exception {
try (JarFile jf = new JarFile(file)) {
@@ -365,41 +473,62 @@
}
}
+ static int which = 0;
+
/**
- * @param cmd the command line (with a hole to plug in)
- * @param path the path in the URL, i.e, http://localhost/path
- * @param expected if this command should succeed
+ * @param extra more args given to jarsigner
*/
- static void jarsigner(String cmd, int path, boolean expected)
- throws Exception {
- System.err.println("Test " + path);
- Process p = Runtime.getRuntime().exec(String.format(Locale.ROOT,cmd, path, path));
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(p.getErrorStream()));
- while (true) {
- String s = reader.readLine();
- if (s == null) break;
- System.err.println(s);
+ static OutputAnalyzer sign(String path, String... extra)
+ throws Throwable {
+ which++;
+ System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra));
+ List<String> args = List.of("-J-Djava.security.egd=file:/dev/./urandom",
+ "-debug", "-signedjar", path + ".jar", "old.jar",
+ path.equals("badku") ? "badku" : "old");
+ args = new ArrayList<>(args);
+ if (!path.equals("none") && !path.equals("badku")) {
+ args.add("-tsa");
+ args.add(host + path);
}
+ args.addAll(Arrays.asList(extra));
+ return jarsigner(args);
+ }
- // Will not see noTimestamp warning
- boolean seeWarning = false;
- reader = new BufferedReader(
- new InputStreamReader(p.getInputStream()));
- while (true) {
- String s = reader.readLine();
- if (s == null) break;
- System.err.println(s);
- if (s.indexOf("Warning:") >= 0) {
- seeWarning = true;
- }
+ static void prepare() throws Exception {
+ jdk.testlibrary.JarUtils.createJar("old.jar", "A");
+ Files.deleteIfExists(Paths.get("tsks"));
+ keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
+ keytool("-alias old -genkeypair -dname CN=old");
+ keytool("-alias badku -genkeypair -dname CN=badku");
+ keytool("-alias ts -genkeypair -dname CN=ts");
+ keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1");
+ keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
+ keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2");
+ keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
+
+ gencert("old");
+ gencert("badku", "-ext ku:critical=keyAgreement");
+ gencert("ts", "-ext eku:critical=ts");
+ gencert("tsweak", "-ext eku:critical=ts");
+ gencert("tsbad1");
+ gencert("tsbad2", "-ext eku=ts");
+ gencert("tsbad3", "-ext eku:critical=cs");
+ }
+
+ static void gencert(String alias, String... extra) throws Exception {
+ keytool("-alias " + alias + " -certreq -file " + alias + ".req");
+ String genCmd = "-gencert -alias ca -infile " +
+ alias + ".req -outfile " + alias + ".cert";
+ for (String s : extra) {
+ genCmd += " " + s;
}
- int result = p.waitFor();
- if (expected && result != 0 || !expected && result == 0) {
- throw new Exception("Failed");
- }
- if (seeWarning) {
- throw new Exception("See warning");
- }
+ keytool(genCmd);
+ keytool("-alias " + alias + " -importcert -file " + alias + ".cert");
+ }
+
+ static void keytool(String cmd) throws Exception {
+ cmd = "-keystore tsks -storepass changeit -keypass changeit " +
+ "-keyalg rsa -validity 200 " + cmd;
+ sun.security.tools.keytool.Main.main(cmd.split(" "));
}
}
--- a/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,6 +31,7 @@
* @library /lib/testlibrary warnings
* @modules java.base/sun.security.pkcs
* java.base/sun.security.timestamp
+ * java.base/sun.security.tools.keytool
* java.base/sun.security.util
* java.base/sun.security.x509
* java.management
--- a/jdk/test/sun/security/tools/jarsigner/ts.sh Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-#
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6543842 6543440 6939248 8009636 8024302
-# @summary checking response of timestamp
-# @modules java.base/sun.security.pkcs
-# java.base/sun.security.timestamp
-# java.base/sun.security.x509
-# java.base/sun.security.util
-#
-# @run shell/timeout=600 ts.sh
-
-# Run for a long time because jarsigner with timestamp needs to create a
-# 64-bit random number and it might be extremely slow on a machine with
-# not enough entropy pool
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
- Windows_* )
- FS="\\"
- ;;
- * )
- FS="/"
- ;;
-esac
-
-if [ "${TESTSRC}" = "" ] ; then
- TESTSRC="."
-fi
-if [ "${TESTJAVA}" = "" ] ; then
- JAVAC_CMD=`which javac`
- TESTJAVA=`dirname $JAVAC_CMD`/..
-fi
-
-JAR="${TESTJAVA}${FS}bin${FS}jar ${TESTTOOLVMOPTS}"
-JAVA="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS}"
-JAVAC="${TESTJAVA}${FS}bin${FS}javac ${TESTTOOLVMOPTS} ${TESTJAVACOPTS}"
-KT="${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200"
-
-rm tsks
-echo Nothing > A
-rm old.jar
-$JAR cvf old.jar A
-
-# ca is CA
-# old is signer for code
-# ts is signer for timestamp
-# tsbad1 has no extendedKeyUsage
-# tsbad2's extendedKeyUsage is non-critical
-# tsbad3's extendedKeyUsage has no timestamping
-
-$KT -alias ca -genkeypair -ext bc -dname CN=CA
-$KT -alias old -genkeypair -dname CN=old
-$KT -alias ts -genkeypair -dname CN=ts
-$KT -alias tsbad1 -genkeypair -dname CN=tsbad1
-$KT -alias tsbad2 -genkeypair -dname CN=tsbad2
-$KT -alias tsbad3 -genkeypair -dname CN=tsbad3
-
-$KT -alias old -certreq | \
- $KT -alias ca -gencert | \
- $KT -alias old -importcert
-$KT -alias ts -certreq | \
- $KT -alias ca -gencert -ext eku:critical=ts | \
- $KT -alias ts -importcert
-$KT -alias tsbad1 -certreq | \
- $KT -alias ca -gencert | \
- $KT -alias tsbad1 -importcert
-$KT -alias tsbad2 -certreq | \
- $KT -alias ca -gencert -ext eku=ts | \
- $KT -alias tsbad2 -importcert
-$KT -alias tsbad3 -certreq | \
- $KT -alias ca -gencert -ext eku:critical=cs | \
- $KT -alias tsbad3 -importcert
-
-EXTRAOPTS="--add-exports java.base/sun.security.pkcs=ALL-UNNAMED \
- --add-exports java.base/sun.security.timestamp=ALL-UNNAMED \
- --add-exports java.base/sun.security.x509=ALL-UNNAMED \
- --add-exports java.base/sun.security.util=ALL-UNNAMED"
-$JAVAC ${EXTRAOPTS} -d . ${TESTSRC}/TimestampCheck.java
-$JAVA ${TESTVMOPTS} ${EXTRAOPTS} "-Dtest.tool.vm.opts=${TESTTOOLVMOPTS}" TimestampCheck
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/ConcealedPackage.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8146486
+ * @summary Fail to create a MR modular JAR with a versioned entry in
+ * base-versioned empty package
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run testng ConcealedPackage
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.FileUtils;
+
+public class ConcealedPackage {
+ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+ .orElseThrow(() -> new RuntimeException("jar tool not found"));
+ private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+ .orElseThrow(() -> new RuntimeException("javac tool not found"));
+ private final String linesep = System.lineSeparator();
+ private final Path userdir;
+ private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
+ private final PrintStream out = new PrintStream(outbytes, true);
+ private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
+ private final PrintStream err = new PrintStream(errbytes, true);
+
+ public ConcealedPackage() throws IOException {
+ Path testsrc = Paths.get(System.getProperty("test.src"));
+ userdir = Paths.get(System.getProperty("user.dir", "."));
+
+ // compile the classes directory
+ Path source = testsrc.resolve("src").resolve("classes");
+ Path destination = Paths.get("classes");
+ javac(source, destination);
+
+ // compile the mr9 directory including module-info.java
+ source = testsrc.resolve("src").resolve("mr9");
+ destination = Paths.get("mr9");
+ javac(source, destination);
+
+ // move module-info.class for later use
+ Files.move(destination.resolve("module-info.class"),
+ Paths.get("module-info.class"));
+ }
+
+ private void javac(Path source, Path destination) throws IOException {
+ String[] args = Stream.concat(
+ Stream.of("-d", destination.toString()),
+ Files.walk(source)
+ .map(Path::toString)
+ .filter(s -> s.endsWith(".java"))
+ ).toArray(String[]::new);
+ JAVAC_TOOL.run(System.out, System.err, args);
+ }
+
+ private int jar(String cmd) {
+ outbytes.reset();
+ errbytes.reset();
+ return JAR_TOOL.run(out, err, cmd.split(" +"));
+ }
+
+ @AfterClass
+ public void cleanup() throws IOException {
+ Files.walk(userdir, 1)
+ .filter(p -> !p.equals(userdir))
+ .forEach(p -> {
+ try {
+ if (Files.isDirectory(p)) {
+ FileUtils.deleteFileTreeWithRetry(p);
+ } else {
+ FileUtils.deleteFileIfExistsWithRetry(p);
+ }
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ });
+ }
+
+ // updates a valid multi-release jar with a new public class in
+ // versioned section and fails
+ @Test
+ public void test1() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ jar("-tf mmr.jar");
+
+ String s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class"
+ );
+ Assert.assertEquals(actual, expected);
+
+ // failed build because of new public class
+ rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 1);
+
+ s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+ + "class not found in base entries")
+ );
+ }
+
+ // updates a valid multi-release jar with a module-info class and new
+ // concealed public class in versioned section and succeeds
+ @Test
+ public void test2() {
+ // successful build of multi-release jar
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+ Assert.assertEquals(rc, 0);
+
+ // successful build because of module-info and new public class
+ rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+ + "concealed package, \nplacing this jar on the class path "
+ + "will result in incompatible public interfaces")
+ );
+
+ jar("-tf mmr.jar");
+
+ s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/Bar.class",
+ "module-info.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+
+ // jar tool fails building mmr.jar because of new public class
+ @Test
+ public void test3() {
+ int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
+ Assert.assertEquals(rc, 1);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+ + "class not found in base entries")
+ );
+ }
+
+ // jar tool succeeds building mmr.jar because of concealed package
+ @Test
+ public void test4() {
+ int rc = jar("-cf mmr.jar module-info.class -C classes . " +
+ "--release 9 module-info.class -C mr9 .");
+ Assert.assertEquals(rc, 0);
+
+ String s = new String(errbytes.toByteArray());
+ Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+ + "concealed package, \nplacing this jar on the class path "
+ + "will result in incompatible public interfaces")
+ );
+
+ jar("-tf mmr.jar");
+
+ s = new String(outbytes.toByteArray());
+ Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "META-INF/",
+ "META-INF/MANIFEST.MF",
+ "module-info.class",
+ "META-INF/versions/9/module-info.class",
+ "p/",
+ "p/Hi.class",
+ "META-INF/versions/9/p/",
+ "META-INF/versions/9/p/Hi.class",
+ "META-INF/versions/9/p/internal/",
+ "META-INF/versions/9/p/internal/Bar.class"
+ );
+ Assert.assertEquals(actual, expected);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/classes/p/Hi.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * 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 p;
+
+public class Hi {
+ public void sayHi() {
+ System.out.println("Hi");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/module-info.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+module m1 {
+ exports p;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/Hi.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * 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 p;
+
+public class Hi {
+ public void sayHi() {
+ System.out.println("Hello");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/internal/Bar.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,31 @@
+/*
+ * 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 p.internal;
+
+public class Bar {
+ @Override
+ public String toString() {
+ return "p.internal.Bar";
+ }
+}
--- a/jdk/test/tools/jlink/JLinkTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/tools/jlink/JLinkTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -109,19 +109,16 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
- .option("")
.call().assertSuccess();
JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath())
.addMods("leaf1")
.option("--output")
- .option("")
.call().assertFailure("Error: no value given for --output");
JImageGenerator.getJLinkTask()
.modulePath("")
.output(helper.createNewImageDir(moduleName))
.addMods("leaf1")
- .option("")
.call().assertFailure("Error: no value given for --module-path");
}
@@ -132,7 +129,6 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("m")
- .option("")
.call().assertSuccess();
moduleName = "mod";
jmod = helper.generateDefaultJModule(moduleName).assertSuccess();
@@ -140,7 +136,6 @@
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods("m")
- .option("")
.call().assertSuccess();
}
@@ -282,18 +277,21 @@
helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid");
}
- // @file
+ // orphan argument - JDK-8166810
{
- Path path = Paths.get("embedded.properties");
- Files.write(path, Collections.singletonList("--strip-debug --add-modules " +
- "toto.unknown --compress UNKNOWN\n"));
- String[] userOptions = {"@", path.toAbsolutePath().toString()};
- String moduleName = "configembeddednocompresscomposite2";
+ String[] userOptions = {"--compress", "2", "foo" };
+ String moduleName = "orphanarg1";
helper.generateDefaultJModule(moduleName, "composite2");
- Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
- helper.checkImage(imageDir, moduleName, null, null);
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: foo");
}
+ // orphan argument - JDK-8166810
+ {
+ String[] userOptions = {"--output", "foo", "bar" };
+ String moduleName = "orphanarg2";
+ helper.generateDefaultJModule(moduleName, "composite2");
+ helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar");
+ }
}
private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException {
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -40,7 +40,7 @@
/*
* @test
- * @bug 8152143 8152704 8155649
+ * @bug 8152143 8152704 8155649 8165804
* @summary IncludeLocalesPlugin tests
* @author Naoto Sato
* @library ../../lib
@@ -236,6 +236,7 @@
"/jdk.localedata/sun/text/resources/ext/thai_dict",
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+ "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_ja.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class",
@@ -261,6 +262,7 @@
"/jdk.localedata/sun/text/resources/ext/thai_dict",
"/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
"/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+ "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
"/jdk.localedata/sun/text/resources/ext/FormatData_th.class"),
List.of(
"/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
@@ -431,13 +433,23 @@
for (Object[] data : testData) {
// create image for each test data
- System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
- Result result = JImageGenerator.getJLinkTask()
+ Result result;
+ if (data[INCLUDE_LOCALES_OPTION].toString().isEmpty()) {
+ System.out.println("Invoking jlink with no --include-locales option");
+ result = JImageGenerator.getJLinkTask()
+ .modulePath(helper.defaultModulePath())
+ .output(helper.createNewImageDir(moduleName))
+ .addMods((String) data[ADDMODS_OPTION])
+ .call();
+ } else {
+ System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
+ result = JImageGenerator.getJLinkTask()
.modulePath(helper.defaultModulePath())
.output(helper.createNewImageDir(moduleName))
.addMods((String) data[ADDMODS_OPTION])
.option((String) data[INCLUDE_LOCALES_OPTION])
.call();
+ }
String errorMsg = (String) data[ERROR_MESSAGE];
if (errorMsg.isEmpty()) {
--- a/jdk/test/tools/pack200/MultiRelease.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/tools/pack200/MultiRelease.java Thu Oct 27 09:42:08 2016 -0700
@@ -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
@@ -60,6 +60,7 @@
} else {
System.out.println("All tests(" + pass + ") passes");
}
+ Utils.cleanup();
}
/*
--- a/jdk/test/tools/pack200/Utils.java Thu Oct 27 09:38:46 2016 -0700
+++ b/jdk/test/tools/pack200/Utils.java Thu Oct 27 09:42:08 2016 -0700
@@ -94,7 +94,7 @@
}
File srcDir = new File(getVerifierDir(), "src");
List<File> javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT));
- File tmpFile = File.createTempFile("javac", ".tmp");
+ File tmpFile = File.createTempFile("javac", ".tmp", new File("."));
XCLASSES.mkdirs();
FileOutputStream fos = null;
PrintStream ps = null;
@@ -208,6 +208,10 @@
Utils.createFilter(".idx")));
toDelete.addAll(Utils.findFiles(new File("."),
Utils.createFilter(".gidx")));
+ toDelete.addAll(Utils.findFiles(new File("."),
+ Utils.createFilter(".tmp")));
+ toDelete.addAll(Utils.findFiles(new File("."),
+ Utils.createFilter(".class")));
for (File f : toDelete) {
f.delete();
}
--- a/langtools/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -383,3 +383,4 @@
90dd93e668a521642382561c47abe96ee2e065b7 jdk-9+138
17a82cb0e4b480e97021691d39917f15e3f7b653 jdk-9+139
6842e63d6c3971172214b411f29965852ca175d1 jdk-9+140
+296c875051187918f8f3f87e9432036d13013d39 jdk-9+141
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -113,7 +113,7 @@
* Internal compiler flags (no bits in the lower 16).
*****************************************/
- /** Flag is set if symbol is deprecated.
+ /** Flag is set if symbol is deprecated. See also DEPRECATED_REMOVAL.
*/
public static final int DEPRECATED = 1<<17;
@@ -293,6 +293,11 @@
*/
public static final long SYSTEM_MODULE = 1L<<53;
+ /**
+ * Flag to indicate the given symbol has been deprecated and marked for removal.
+ */
+ public static final long DEPRECATED_REMOVAL = 1L<<54;
+
/** Modifier masks.
*/
public static final int
@@ -402,7 +407,8 @@
THROWS(Flags.THROWS),
LAMBDA_METHOD(Flags.LAMBDA_METHOD),
TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
- MODULE(Flags.MODULE);
+ MODULE(Flags.MODULE),
+ DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL);
Flag(long flag) {
this.value = flag;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,11 +25,13 @@
package com.sun.tools.javac.code;
+import java.util.Arrays;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Options;
@@ -81,12 +83,13 @@
}
/**
- * Returns a new Lint that has the given LintCategory suppressed.
+ * Returns a new Lint that has the given LintCategorys suppressed.
+ * @param lc one or more categories to be suppressed
*/
- public Lint suppress(LintCategory lc) {
+ public Lint suppress(LintCategory... lc) {
Lint l = new Lint(this);
- l.values.remove(lc);
- l.suppressedValues.add(lc);
+ l.values.removeAll(Arrays.asList(lc));
+ l.suppressedValues.addAll(Arrays.asList(lc));
return l;
}
@@ -100,10 +103,31 @@
protected Lint(Context context) {
// initialize values according to the lint options
Options options = Options.instance(context);
- values = EnumSet.noneOf(LintCategory.class);
- for (Map.Entry<String, LintCategory> e: map.entrySet()) {
- if (options.lint(e.getKey()))
- values.add(e.getValue());
+
+ if (options.isSet(Option.XLINT) || options.isSet(Option.XLINT_CUSTOM, "all")) {
+ // If -Xlint or -Xlint:all is given, enable all categories by default
+ values = EnumSet.allOf(LintCategory.class);
+ } else if (options.isSet(Option.XLINT_CUSTOM, "none")) {
+ // if -Xlint:none is given, disable all categories by default
+ values = EnumSet.noneOf(LintCategory.class);
+ } else {
+ // otherwise, enable on-by-default categories
+ values = EnumSet.noneOf(LintCategory.class);
+
+ Source source = Source.instance(context);
+ if (source.compareTo(Source.JDK1_9) >= 0) {
+ values.add(LintCategory.DEP_ANN);
+ }
+ values.add(LintCategory.REMOVAL);
+ }
+
+ // Look for specific overrides
+ for (LintCategory lc : LintCategory.values()) {
+ if (options.isSet(Option.XLINT_CUSTOM, lc.option)) {
+ values.add(lc);
+ } else if (options.isSet(Option.XLINT_CUSTOM, "-" + lc.option)) {
+ values.remove(lc);
+ }
}
suppressedValues = EnumSet.noneOf(LintCategory.class);
@@ -213,6 +237,11 @@
RAW("rawtypes"),
/**
+ * Warn about use of deprecated-for-removal items.
+ */
+ REMOVAL("removal"),
+
+ /**
* Warn about Serializable classes that do not provide a serial version ID.
*/
SERIAL("serial"),
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Oct 27 09:42:08 2016 -0700
@@ -359,6 +359,10 @@
return (flags_field & DEPRECATED) != 0;
}
+ public boolean isDeprecatedForRemoval() {
+ return (flags_field & DEPRECATED_REMOVAL) != 0;
+ }
+
public boolean isDeprecatableViaAnnotation() {
switch (getKind()) {
case LOCAL_VARIABLE:
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, 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
@@ -340,6 +340,13 @@
&& toAnnotate.owner.kind != MTH
&& types.isSameType(c.type, syms.deprecatedType)) {
toAnnotate.flags_field |= Flags.DEPRECATED;
+ Attribute fr = c.member(names.forRemoval);
+ if (fr instanceof Attribute.Constant) {
+ Attribute.Constant v = (Attribute.Constant) fr;
+ if (v.type == syms.booleanType && ((Integer) v.value) != 0) {
+ toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
+ }
+ }
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Oct 27 09:42:08 2016 -0700
@@ -2398,6 +2398,7 @@
try {
if (needsRecovery && isSerializable(pt())) {
localEnv.info.isSerializable = true;
+ localEnv.info.isLambda = true;
}
List<Type> explicitParamTypes = null;
if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) {
@@ -2969,7 +2970,7 @@
}
if (isTargetSerializable) {
- chk.checkElemAccessFromSerializableLambda(that);
+ chk.checkAccessFromSerializableElement(that, true);
}
}
@@ -3364,7 +3365,7 @@
}
if (env.info.isSerializable) {
- chk.checkElemAccessFromSerializableLambda(tree);
+ chk.checkAccessFromSerializableElement(tree, env.info.isLambda);
}
result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo);
@@ -3507,7 +3508,7 @@
}
if (env.info.isSerializable) {
- chk.checkElemAccessFromSerializableLambda(tree);
+ chk.checkAccessFromSerializableElement(tree, env.info.isLambda);
}
env.info.selectSuper = selectSuperPrev;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,10 +56,15 @@
*/
boolean selectSuper = false;
- /** Is the current target of lambda expression or method reference serializable?
+ /** Is the current target of lambda expression or method reference serializable or is this a
+ * serializable class?
*/
boolean isSerializable = false;
+ /** Is this a lambda environment?
+ */
+ boolean isLambda = false;
+
/** Is this a speculative attribution environment?
*/
boolean isSpeculative = false;
@@ -117,6 +122,7 @@
info.returnResult = returnResult;
info.defaultSuperCallSite = defaultSuperCallSite;
info.isSerializable = isSerializable;
+ info.isLambda = isLambda;
info.isSpeculative = isSpeculative;
info.isAnonymousDiamond = isAnonymousDiamond;
info.isNewClass = isNewClass;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 27 09:42:08 2016 -0700
@@ -87,7 +87,7 @@
private final JavaFileManager fileManager;
private final Source source;
private final Profile profile;
- private final boolean warnOnAccessToSensitiveMembers;
+ private final boolean warnOnAnyAccessToMembers;
// The set of lint options currently in effect. It is initialized
// from the context, and then is set/reset as needed by Attr as it
@@ -131,7 +131,7 @@
allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
- warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers");
+ warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
Target target = Target.instance(context);
syntheticNameChar = target.syntheticNameChar();
@@ -139,11 +139,14 @@
profile = Profile.instance(context);
boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
+ boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
boolean enforceMandatoryWarnings = true;
deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION);
+ removalHandler = new MandatoryWarningHandler(log, verboseRemoval,
+ enforceMandatoryWarnings, "removal", LintCategory.REMOVAL);
uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked,
enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
sunApiHandler = new MandatoryWarningHandler(log, false,
@@ -185,6 +188,10 @@
*/
private MandatoryWarningHandler deprecationHandler;
+ /** A handler for messages about deprecated-for-removal usage.
+ */
+ private MandatoryWarningHandler removalHandler;
+
/** A handler for messages about unchecked or unsafe usage.
*/
private MandatoryWarningHandler uncheckedHandler;
@@ -218,8 +225,13 @@
* @param sym The deprecated symbol.
*/
void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
- if (!lint.isSuppressed(LintCategory.DEPRECATION))
+ if (sym.isDeprecatedForRemoval()) {
+ if (!lint.isSuppressed(LintCategory.REMOVAL)) {
+ removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
+ }
+ } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
+ }
}
/** Warn about unchecked operation.
@@ -257,6 +269,7 @@
*/
public void reportDeferredDiagnostics() {
deprecationHandler.reportDeferredDiagnostic();
+ removalHandler.reportDeferredDiagnostic();
uncheckedHandler.reportDeferredDiagnostic();
sunApiHandler.reportDeferredDiagnostic();
}
@@ -2605,8 +2618,11 @@
}
}
- void checkElemAccessFromSerializableLambda(final JCTree tree) {
- if (warnOnAccessToSensitiveMembers) {
+ void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) {
+ if (warnOnAnyAccessToMembers ||
+ (lint.isEnabled(LintCategory.SERIAL) &&
+ !lint.isSuppressed(LintCategory.SERIAL) &&
+ isLambda)) {
Symbol sym = TreeInfo.symbol(tree);
if (!sym.kind.matches(KindSelector.VAL_MTH)) {
return;
@@ -2622,9 +2638,16 @@
}
if (!types.isSubtype(sym.owner.type, syms.serializableType) &&
- isEffectivelyNonPublic(sym)) {
- log.warning(tree.pos(),
- "access.to.sensitive.member.from.serializable.element", sym);
+ isEffectivelyNonPublic(sym)) {
+ if (isLambda) {
+ if (belongsToRestrictedPackage(sym)) {
+ log.warning(LintCategory.SERIAL, tree.pos(),
+ "access.to.member.from.serializable.lambda", sym);
+ }
+ } else {
+ log.warning(tree.pos(),
+ "access.to.member.from.serializable.element", sym);
+ }
}
}
}
@@ -2643,6 +2666,14 @@
return false;
}
+ private boolean belongsToRestrictedPackage(Symbol sym) {
+ String fullName = sym.packge().fullname.toString();
+ return fullName.startsWith("java.") ||
+ fullName.startsWith("javax.") ||
+ fullName.startsWith("sun.") ||
+ fullName.contains(".internal.");
+ }
+
/** Report a conflict between a user symbol and a synthetic symbol.
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
@@ -3212,9 +3243,9 @@
}
void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
- if ((s.flags() & DEPRECATED) != 0 &&
- (other.flags() & DEPRECATED) == 0 &&
- s.outermostClass() != other.outermostClass()) {
+ if ( (s.isDeprecatedForRemoval()
+ || s.isDeprecated() && !other.isDeprecated())
+ && s.outermostClass() != other.outermostClass()) {
deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
@Override
public void report() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu Oct 27 09:42:08 2016 -0700
@@ -29,6 +29,7 @@
import java.util.HashMap;
+import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.tree.*;
@@ -224,7 +225,7 @@
diagHandler = new Log.DiscardDiagnosticHandler(log);
}
try {
- new AliveAnalyzer().analyzeTree(env, that, make);
+ new LambdaAliveAnalyzer().analyzeTree(env, that, make);
} finally {
if (!speculative) {
log.popDiagnosticHandler(diagHandler);
@@ -241,19 +242,7 @@
//related errors, which will allow for more errors to be detected
Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
try {
- new AssignAnalyzer() {
- WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym);
- @Override
- public void visitVarDef(JCVariableDecl tree) {
- enclosedSymbols.enter(tree.sym);
- super.visitVarDef(tree);
- }
- @Override
- protected boolean trackable(VarSymbol sym) {
- return enclosedSymbols.includes(sym) &&
- sym.owner.kind == MTH;
- }
- }.analyzeTree(env, that);
+ new LambdaAssignAnalyzer(env).analyzeTree(env, that);
LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
flowAnalyzer.analyzeTree(env, that, make);
return flowAnalyzer.inferredThrownTypes;
@@ -1341,6 +1330,79 @@
}
/**
+ * Specialized pass that performs reachability analysis on a lambda
+ */
+ class LambdaAliveAnalyzer extends AliveAnalyzer {
+
+ boolean inLambda;
+
+ @Override
+ public void visitReturn(JCReturn tree) {
+ //ignore lambda return expression (which might not even be attributed)
+ recordExit(new PendingExit(tree));
+ }
+
+ @Override
+ public void visitLambda(JCLambda tree) {
+ if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) {
+ return;
+ }
+ inLambda = true;
+ try {
+ super.visitLambda(tree);
+ } finally {
+ inLambda = false;
+ }
+ }
+
+ @Override
+ public void visitClassDef(JCClassDecl tree) {
+ //skip
+ }
+ }
+
+ /**
+ * Specialized pass that performs DA/DU on a lambda
+ */
+ class LambdaAssignAnalyzer extends AssignAnalyzer {
+ WriteableScope enclosedSymbols;
+ boolean inLambda;
+
+ LambdaAssignAnalyzer(Env<AttrContext> env) {
+ enclosedSymbols = WriteableScope.create(env.enclClass.sym);
+ }
+
+ @Override
+ public void visitLambda(JCLambda tree) {
+ if (inLambda) {
+ return;
+ }
+ inLambda = true;
+ try {
+ super.visitLambda(tree);
+ } finally {
+ inLambda = false;
+ }
+ }
+
+ @Override
+ public void visitVarDef(JCVariableDecl tree) {
+ enclosedSymbols.enter(tree.sym);
+ super.visitVarDef(tree);
+ }
+ @Override
+ protected boolean trackable(VarSymbol sym) {
+ return enclosedSymbols.includes(sym) &&
+ sym.owner.kind == MTH;
+ }
+
+ @Override
+ public void visitClassDef(JCClassDecl tree) {
+ //skip
+ }
+ }
+
+ /**
* Specialized pass that performs inference of thrown types for lambdas.
*/
class LambdaFlowAnalyzer extends FlowAnalyzer {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, 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
@@ -103,7 +103,6 @@
private final TypeAnnotations typeAnnotations;
private final Types types;
private final JCDiagnostic.Factory diags;
- private final Source source;
private final DeferredLintHandler deferredLintHandler;
private final Lint lint;
private final TypeEnvs typeEnvs;
@@ -131,7 +130,6 @@
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
- source = Source.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
lint = Lint.instance(context);
typeEnvs = TypeEnvs.instance(context);
@@ -178,6 +176,7 @@
/** Complete entering a class.
* @param sym The symbol of the class to be completed.
*/
+ @Override
public void complete(Symbol sym) throws CompletionFailure {
// Suppress some (recursive) MemberEnter invocations
if (!completionEnabled) {
@@ -414,7 +413,7 @@
Type attribImportType(JCTree tree, Env<AttrContext> env) {
Assert.check(completionEnabled);
Lint prevLint = chk.setLint(allowDeprecationOnImport ?
- lint : lint.suppress(LintCategory.DEPRECATION));
+ lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL));
try {
// To prevent deep recursion, suppress completion of some
// types.
@@ -751,12 +750,12 @@
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
- if (hasDeprecatedAnnotation(tree.mods.annotations))
- sym.flags_field |= DEPRECATED;
+ handleDeprecatedAnnotation(tree.mods.annotations, sym);
chk.checkNonCyclicDecl(tree);
}
//where:
+ @Override
protected JCExpression clearTypeParams(JCExpression superType) {
switch (superType.getTag()) {
case TYPEAPPLY:
@@ -767,16 +766,29 @@
}
/**
- * Check if a list of annotations contains a reference to
- * java.lang.Deprecated.
+ * If a list of annotations contains a reference to java.lang.Deprecated,
+ * set the DEPRECATED flag.
+ * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
**/
- private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) {
+ private void handleDeprecatedAnnotation(List<JCAnnotation> annotations, Symbol sym) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
- if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty())
- return true;
+ if (a.annotationType.type == syms.deprecatedType) {
+ sym.flags_field |= Flags.DEPRECATED;
+ a.args.stream()
+ .filter(e -> e.hasTag(ASSIGN))
+ .map(e -> (JCAssign) e)
+ .filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
+ .findFirst()
+ .ifPresent(assign -> {
+ JCExpression rhs = TreeInfo.skipParens(assign.rhs);
+ if (rhs.hasTag(LITERAL)
+ && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
+ sym.flags_field |= DEPRECATED_REMOVAL;
+ }
+ });
+ }
}
- return false;
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu Oct 27 09:42:08 2016 -0700
@@ -52,8 +52,6 @@
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
@@ -85,7 +83,10 @@
log = Log.instance(context);
options = Options.instance(context);
classLoaderClass = options.get("procloader");
- locations.update(log, Lint.instance(context), FSInfo.instance(context));
+
+ // Avoid initializing Lint
+ boolean warn = options.isLintSet("path");
+ locations.update(log, warn, FSInfo.instance(context));
// Setting this option is an indication that close() should defer actually closing
// the file manager until after a specified period of inactivity.
@@ -171,14 +172,6 @@
private long lastUsedTime = System.currentTimeMillis();
protected long deferredCloseTimeout = 0;
- protected Source getSource() {
- String sourceName = options.get(Option.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- return (source != null ? source : Source.DEFAULT);
- }
-
protected ClassLoader getClassLoader(URL[] urls) {
ClassLoader thisClassLoader = getClass().getClassLoader();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Oct 27 09:42:08 2016 -0700
@@ -42,7 +42,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;
-import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -63,7 +62,6 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import java.util.zip.ZipFile;
import javax.lang.model.SourceVersion;
import javax.tools.JavaFileManager;
@@ -159,10 +157,9 @@
}
}
- // could replace Lint by "boolean warn"
- void update(Log log, Lint lint, FSInfo fsInfo) {
+ void update(Log log, boolean warn, FSInfo fsInfo) {
this.log = log;
- warn = lint.isEnabled(Lint.LintCategory.PATH);
+ this.warn = warn;
this.fsInfo = fsInfo;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Oct 27 09:42:08 2016 -0700
@@ -1460,7 +1460,6 @@
ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
for (int i = 0; i<numAttributes; i++) {
CompoundAnnotationProxy proxy = readCompoundAnnotation();
-
if (proxy.type.tsym == syms.proprietaryType.tsym)
sym.flags_field |= PROPRIETARY;
else if (proxy.type.tsym == syms.profileType.tsym) {
@@ -1479,6 +1478,16 @@
target = proxy;
} else if (proxy.type.tsym == syms.repeatableType.tsym) {
repeatable = proxy;
+ } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
+ sym.flags_field |= DEPRECATED;
+ for (Pair<Name, Attribute> v : proxy.values) {
+ if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
+ Attribute.Constant c = (Attribute.Constant) v.snd;
+ if (c.type == syms.booleanType && ((Integer) c.value) != 0) {
+ sym.flags_field |= DEPRECATED_REMOVAL;
+ }
+ }
+ }
}
proxies.append(proxy);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Oct 27 09:42:08 2016 -0700
@@ -37,6 +37,7 @@
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
@@ -111,7 +112,6 @@
"all",
log.localize(PrefixKind.JAVAC, "opt.Xlint.all")));
for (LintCategory lc : LintCategory.values()) {
- if (lc.hidden) continue;
log.printRawLines(WriterKind.STDOUT,
String.format(LINT_KEY_FORMAT,
lc.option,
@@ -801,8 +801,8 @@
/** The kind of choices for this option, if any. */
private final ChoiceKind choiceKind;
- /** The choices for this option, if any, and whether or not the choices are hidden. */
- private final Map<String,Boolean> choices;
+ /** The choices for this option, if any. */
+ private final Set<String> choices;
/**
* Looks up the first option matching the given argument in the full set of options.
@@ -815,7 +815,8 @@
/**
* Looks up the first option matching the given argument within a set of options.
- * @param arg the argument to be matches
+ * @param arg the argument to be matched
+ * @param options the set of possible options
* @return the first option that matches, or null if none.
*/
public static Option lookup(String arg, Set<Option> options) {
@@ -867,7 +868,7 @@
}
Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group,
- ChoiceKind choiceKind, Map<String,Boolean> choices) {
+ ChoiceKind choiceKind, Set<String> choices) {
this(text, argsNameKey, descrKey, kind, group, choiceKind, choices, ArgKind.REQUIRED);
}
@@ -875,19 +876,12 @@
OptionKind kind, OptionGroup group,
ChoiceKind choiceKind, String... choices) {
this(text, null, descrKey, kind, group, choiceKind,
- createChoices(choices), ArgKind.REQUIRED);
+ new LinkedHashSet<>(Arrays.asList(choices)), ArgKind.REQUIRED);
}
- // where
- private static Map<String,Boolean> createChoices(String... choices) {
- Map<String,Boolean> map = new LinkedHashMap<>();
- for (String c: choices)
- map.put(c, false);
- return map;
- }
private Option(String text, String argsNameKey, String descrKey,
OptionKind kind, OptionGroup group,
- ChoiceKind choiceKind, Map<String,Boolean> choices,
+ ChoiceKind choiceKind, Set<String> choices,
ArgKind argKind) {
this.names = text.trim().split("\\s+");
Assert.check(names.length >= 1);
@@ -943,10 +937,10 @@
if (choices != null) {
String arg = option.substring(name.length());
if (choiceKind == ChoiceKind.ONEOF)
- return choices.keySet().contains(arg);
+ return choices.contains(arg);
else {
for (String a: arg.split(",+")) {
- if (!choices.keySet().contains(a))
+ if (!choices.contains(a))
return false;
}
}
@@ -1016,7 +1010,7 @@
if (choices != null) {
if (choiceKind == ChoiceKind.ONEOF) {
// some clients like to see just one of option+choice set
- for (String s: choices.keySet())
+ for (String s : choices)
helper.remove(primaryName + s);
String opt = primaryName + arg;
helper.put(opt, opt);
@@ -1113,12 +1107,10 @@
if (argsNameKey == null) {
if (choices != null) {
String sep = "{";
- for (Map.Entry<String,Boolean> e: choices.entrySet()) {
- if (!e.getValue()) {
- sb.append(sep);
- sb.append(e.getKey());
- sep = ",";
- }
+ for (String choice : choices) {
+ sb.append(sep);
+ sb.append(choices);
+ sep = ",";
}
sb.append("}");
}
@@ -1163,14 +1155,14 @@
}
}
- private static Map<String,Boolean> getXLintChoices() {
- Map<String,Boolean> choices = new LinkedHashMap<>();
- choices.put("all", false);
- for (Lint.LintCategory c : Lint.LintCategory.values())
- choices.put(c.option, c.hidden);
- for (Lint.LintCategory c : Lint.LintCategory.values())
- choices.put("-" + c.option, c.hidden);
- choices.put("none", false);
+ private static Set<String> getXLintChoices() {
+ Set<String> choices = new LinkedHashSet<>();
+ choices.add("all");
+ for (Lint.LintCategory c : Lint.LintCategory.values()) {
+ choices.add(c.option);
+ choices.add("-" + c.option);
+ }
+ choices.add("none");
return choices;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Oct 27 09:42:08 2016 -0700
@@ -1321,14 +1321,31 @@
Some input files additionally use or override a deprecated API.
# 0: file name
+compiler.note.removal.filename=\
+ {0} uses or overrides a deprecated API that is marked for removal.
+
+compiler.note.removal.plural=\
+ Some input files use or override a deprecated API that is marked for removal.
+
+# The following string may appear after one of the above removal messages.
+compiler.note.removal.recompile=\
+ Recompile with -Xlint:removal for details.
+
+# 0: file name
+compiler.note.removal.filename.additional=\
+ {0} has additional uses or overrides of a deprecated API that is marked for removal.
+
+compiler.note.removal.plural.additional=\
+ Some input files additionally use or override a deprecated API that is marked for removal.
+
+# 0: file name
compiler.note.unchecked.filename=\
{0} uses unchecked or unsafe operations.
compiler.note.unchecked.plural=\
Some input files use unchecked or unsafe operations.
-# The following string may appear after one of the above deprecation
-# messages.
+# The following string may appear after one of the above unchecked messages.
compiler.note.unchecked.recompile=\
Recompile with -Xlint:unchecked for details.
@@ -1441,6 +1458,10 @@
compiler.warn.has.been.deprecated=\
{0} in {1} has been deprecated
+# 0: symbol, 1: symbol
+compiler.warn.has.been.deprecated.for.removal=\
+ {0} in {1} has been deprecated and marked for removal
+
# 0: symbol
compiler.warn.sun.proprietary=\
{0} is internal proprietary API and may be removed in a future release
@@ -1712,8 +1733,12 @@
Redundant {0} annotation. {1}
# 0: symbol
-compiler.warn.access.to.sensitive.member.from.serializable.element=\
- access to sensitive member {0} from serializable element can be publicly accessible to untrusted code
+compiler.warn.access.to.member.from.serializable.element=\
+ access to member {0} from serializable element can be publicly accessible to untrusted code
+
+# 0: symbol
+compiler.warn.access.to.member.from.serializable.lambda=\
+ access to member {0} from serializable lambda can be publicly accessible to untrusted code
#####
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Oct 27 09:42:08 2016 -0700
@@ -219,8 +219,12 @@
javac.opt.Xlint.desc.rawtypes=\
Warn about use of raw types.
+javac.opt.Xlint.desc.removal=\
+ Warn about use of API that has been marked for removal.
+
javac.opt.Xlint.desc.serial=\
- Warn about Serializable classes that do not provide a serial version ID.
+ Warn about Serializable classes that do not provide a serial version ID. \n\
+\ Also warn about access to non-public members from a serializable element.
javac.opt.Xlint.desc.static=\
Warn about accessing a static member using an instance.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,7 @@
public final Name family;
public final Name finalize;
public final Name forName;
+ public final Name forRemoval;
public final Name getClass;
public final Name getClassLoader;
public final Name getComponentType;
@@ -242,6 +243,7 @@
family = fromString("family");
finalize = fromString("finalize");
forName = fromString("forName");
+ forRemoval = fromString("forRemoval");
getClass = fromString("getClass");
getClassLoader = fromString("getClassLoader");
getComponentType = fromString("getComponentType");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java Thu Oct 27 09:42:08 2016 -0700
@@ -27,7 +27,6 @@
import java.util.*;
-import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
import static com.sun.tools.javac.main.Option.*;
@@ -113,6 +112,18 @@
return (values.get(option.primaryName + value) != null);
}
+ /** Check if the value for a lint option has been explicitly set, either with -Xlint:opt
+ * or if all lint options have enabled and this one not disabled with -Xlint:-opt.
+ */
+ public boolean isLintSet(String s) {
+ // return true if either the specific option is enabled, or
+ // they are all enabled without the specific one being
+ // disabled
+ return
+ isSet(XLINT_CUSTOM, s) ||
+ (isSet(XLINT) || isSet(XLINT_CUSTOM, "all")) && isUnset(XLINT_CUSTOM, "-" + s);
+ }
+
/**
* Check if the value for an undocumented option has not been set.
*/
@@ -170,25 +181,4 @@
for (Runnable r: listeners)
r.run();
}
-
- /** Check for a lint suboption. */
- public boolean lint(String s) {
- // return true if either the specific option is enabled, or
- // they are all enabled without the specific one being
- // disabled
- return
- isSet(XLINT_CUSTOM, s) ||
- (isSet(XLINT) || isSet(XLINT_CUSTOM, "all") || (s.equals("dep-ann") && depAnnOnByDefault())) &&
- isUnset(XLINT_CUSTOM, "-" + s);
- }
- // where
- private boolean depAnnOnByDefault() {
- String sourceName = get(Option.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- if (source == null)
- source = Source.DEFAULT;
- return source.compareTo(Source.JDK1_9) >= 0;
- }
}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Thu Oct 27 09:42:08 2016 -0700
@@ -353,11 +353,12 @@
protected Content getFramesJavaScript() {
HtmlTree script = HtmlTree.SCRIPT();
String scriptCode = DocletConstants.NL +
- " targetPage = \"\" + window.location.search;" + DocletConstants.NL +
- " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL +
- " targetPage = targetPage.substring(1);" + DocletConstants.NL +
- " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))" + DocletConstants.NL +
- " targetPage = \"undefined\";" + DocletConstants.NL +
+ " tmpTargetPage = \"\" + window.location.search;" + DocletConstants.NL +
+ " if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")" + DocletConstants.NL +
+ " tmpTargetPage = tmpTargetPage.substring(1);" + DocletConstants.NL +
+ " if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))" + DocletConstants.NL +
+ " tmpTargetPage = \"undefined\";" + DocletConstants.NL +
+ " targetPage = tmpTargetPage;" + DocletConstants.NL +
" function validURL(url) {" + DocletConstants.NL +
" try {" + DocletConstants.NL +
" url = decodeURIComponent(url);" + DocletConstants.NL +
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Thu Oct 27 09:42:08 2016 -0700
@@ -234,11 +234,12 @@
protected Content getFramesJavaScript() {
HtmlTree scriptTree = HtmlTree.SCRIPT();
String scriptCode = "\n" +
- " targetPage = \"\" + window.location.search;\n" +
- " if (targetPage != \"\" && targetPage != \"undefined\")\n" +
- " targetPage = targetPage.substring(1);\n" +
- " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))\n" +
- " targetPage = \"undefined\";\n" +
+ " tmpTargetPage = \"\" + window.location.search;\n" +
+ " if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n" +
+ " tmpTargetPage = tmpTargetPage.substring(1);\n" +
+ " if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n" +
+ " tmpTargetPage = \"undefined\";\n" +
+ " targetPage = tmpTargetPage;\n" +
" function validURL(url) {\n" +
" try {\n" +
" url = decodeURIComponent(url);\n" +
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java Thu Oct 27 09:42:08 2016 -0700
@@ -308,9 +308,7 @@
public CommentUtils cmtUtils;
/**
- * A sorted set of packages specified on the command-line merged with a
- * collection of packages that contain the classes specified on the
- * command-line.
+ * A sorted set of included packages.
*/
public SortedSet<PackageElement> packages = null;
@@ -399,10 +397,8 @@
private void initPackages() {
packages = new TreeSet<>(utils.makePackageComparator());
- packages.addAll(getSpecifiedPackages());
- for (TypeElement aClass : getSpecifiedClasses()) {
- packages.add(utils.containingPackage(aClass));
- }
+ // add all the included packages
+ packages.addAll(docEnv.getIncludedPackageElements());
}
public Set<Doclet.Option> getSupportedOptions() {
@@ -647,7 +643,7 @@
if (docencoding == null) {
docencoding = encoding;
}
- typeElementCatalog = new TypeElementCatalog(getSpecifiedClasses(), this);
+ typeElementCatalog = new TypeElementCatalog(docEnv.getIncludedTypeElements(), this);
initTagletManager(customTagStrs);
groups.stream().forEach((grp) -> {
group.checkPackageGroups(grp.value1, grp.value2);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Thu Oct 27 09:42:08 2016 -0700
@@ -587,18 +587,28 @@
}
private Set<PackageElement> computeModulePackages() throws ToolException {
- final AccessKind accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE);
+ AccessKind accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE);
final boolean documentAllModulePackages = (accessValue == AccessKind.PACKAGE ||
accessValue == AccessKind.PRIVATE);
+ accessValue = accessFilter.getAccessValue(ElementKind.MODULE);
+ final boolean moduleDetailedMode = (accessValue == AccessKind.PACKAGE ||
+ accessValue == AccessKind.PRIVATE);
Set<PackageElement> expandedModulePackages = new LinkedHashSet<>();
for (ModuleElement mdle : specifiedModuleElements) {
- // add all exported packages belonging to a specified module
- if (specifiedModuleElements.contains(mdle)) {
+ if (documentAllModulePackages) { // include all packages
+ List<PackageElement> packages = ElementFilter.packagesIn(mdle.getEnclosedElements());
+ expandedModulePackages.addAll(packages);
+ expandedModulePackages.addAll(getAllModulePackages(mdle));
+ } else { // selectively include required packages
List<ExportsDirective> exports = ElementFilter.exportsIn(mdle.getDirectives());
for (ExportsDirective export : exports) {
- expandedModulePackages.add(export.getPackage());
+ // add if fully exported or add qualified exports only if desired
+ if (export.getTargetModules() == null
+ || documentAllModulePackages || moduleDetailedMode) {
+ expandedModulePackages.add(export.getPackage());
+ }
}
}
@@ -613,27 +623,6 @@
}
}
}
-
- if (!documentAllModulePackages) {
- List<ExportsDirective> exports = ElementFilter.exportsIn(mdle.getDirectives());
- // check exported packages
- for (ExportsDirective export : exports) {
- List<? extends ModuleElement> targetModules = export.getTargetModules();
- if (targetModules == null) { // no qualified exports, add 'em all
- expandedModulePackages.add(export.getPackage());
- } else { // qualified export, add only if target module is being considered
- for (ModuleElement target : targetModules) {
- if (specifiedModuleElements.contains(target)) {
- expandedModulePackages.add(export.getPackage());
- }
- }
- }
- }
- } else { // add all exported and module private packages
- List<PackageElement> packages = ElementFilter.packagesIn(mdle.getEnclosedElements());
- expandedModulePackages.addAll(packages);
- expandedModulePackages.addAll(getAllModulePackages(mdle));
- }
}
return expandedModulePackages;
}
@@ -668,8 +657,7 @@
if (!mdle.isUnnamed())
imodules.add(mdle);
PackageElement pkg = toolEnv.elements.getPackageOf(klass);
- if (!pkg.isUnnamed())
- ipackages.add(pkg);
+ ipackages.add(pkg);
addAllClasses(iclasses, klass, true);
});
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Thu Oct 27 09:42:08 2016 -0700
@@ -30,7 +30,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
/**
@@ -78,7 +77,12 @@
while (true) {
nextToken();
if (sval != null && !isQuoted() && sval.startsWith("-")) {
- foundOption(sval);
+ // allow POSIX getopt() option format,
+ // to be consistent with command-line
+ String opt = sval.startsWith("--")
+ ? sval.substring(1)
+ : sval;
+ foundOption(opt);
} else {
break;
}
@@ -104,28 +108,13 @@
}
}
- String[] next(String... strings) {
- return next(Arrays.stream(strings));
- }
-
- String[] next(Stream<String> stream) {
- next();
- if (sval == null) {
- return null;
- }
- String[] matches = stream
- .filter(s -> s.startsWith(sval))
- .toArray(size -> new String[size]);
- return matches;
- }
-
/**
* Set the allowed options. Must be called before any options would be read
* and before calling any of the option functionality below.
*/
void allowedOptions(String... opts) {
for (String opt : opts) {
- options.put(opt, false);
+ options.putIfAbsent(opt, false);
}
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,6 +31,7 @@
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
@@ -61,6 +62,8 @@
import jdk.internal.jline.console.history.MemoryHistory;
import jdk.internal.jline.extra.EditingHistory;
import jdk.internal.jshell.tool.StopDetectingInputStream.State;
+import jdk.internal.misc.Signal;
+import jdk.internal.misc.Signal.Handler;
class ConsoleIOContext extends IOContext {
@@ -170,6 +173,21 @@
bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer));
}
}
+ try {
+ Signal.handle(new Signal("CONT"), new Handler() {
+ @Override public void handle(Signal sig) {
+ try {
+ in.getTerminal().reset();
+ in.redrawLine();
+ in.flush();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ });
+ } catch (IllegalArgumentException ignored) {
+ //the CONT signal does not exist on this platform
+ }
}
@Override
@@ -390,7 +408,7 @@
private int inputBytesPointer;
@Override
- public synchronized int readUserInput() {
+ public synchronized int readUserInput() throws IOException {
while (inputBytes == null || inputBytes.length <= inputBytesPointer) {
boolean prevHandleUserInterrupt = in.getHandleUserInterrupt();
History prevHistory = in.getHistory();
@@ -401,12 +419,8 @@
in.setHistory(userInputHistory);
inputBytes = (in.readLine("") + System.getProperty("line.separator")).getBytes();
inputBytesPointer = 0;
- } catch (IOException ex) {
- ex.printStackTrace();
- return -1;
} catch (UserInterruptException ex) {
- repl.state.stop();
- return -1;
+ throw new InterruptedIOException();
} finally {
in.setHistory(prevHistory);
in.setHandleUserInterrupt(prevHandleUserInterrupt);
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ExternalEditor.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ExternalEditor.java Thu Oct 27 09:42:08 2016 -0700
@@ -80,7 +80,7 @@
private void setupWatch(String initialText) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.dir = Files.createTempDirectory("jshelltemp");
- this.tmpfile = Files.createTempFile(dir, null, ".edit");
+ this.tmpfile = Files.createTempFile(dir, null, ".java");
Files.write(tmpfile, initialText.getBytes(Charset.forName("UTF-8")));
dir.register(watcher,
ENTRY_CREATE,
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Thu Oct 27 09:42:08 2016 -0700
@@ -28,16 +28,26 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collector;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;
import static jdk.internal.jshell.tool.ContinuousCompletionProvider.PERFECT_MATCHER;
@@ -114,8 +124,8 @@
return mode.getContinuationPrompt(nextId);
}
- public boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at) {
- return new Setter(messageHandler, at).setFeedback();
+ public boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at, Consumer<String> retainer) {
+ return new Setter(messageHandler, at).setFeedback(retainer);
}
public boolean setFormat(MessageHandler messageHandler, ArgTokenizer at) {
@@ -126,22 +136,14 @@
return new Setter(messageHandler, at).setTruncation();
}
- public boolean setMode(MessageHandler messageHandler, ArgTokenizer at) {
- return new Setter(messageHandler, at).setMode();
+ public boolean setMode(MessageHandler messageHandler, ArgTokenizer at, Consumer<String> retainer) {
+ return new Setter(messageHandler, at).setMode(retainer);
}
public boolean setPrompt(MessageHandler messageHandler, ArgTokenizer at) {
return new Setter(messageHandler, at).setPrompt();
}
- public String retainFeedback(MessageHandler messageHandler, ArgTokenizer at) {
- return new Setter(messageHandler, at).retainFeedback();
- }
-
- public String retainMode(MessageHandler messageHandler, ArgTokenizer at) {
- return new Setter(messageHandler, at).retainMode();
- }
-
public boolean restoreEncodedModes(MessageHandler messageHandler, String encoded) {
return new Setter(messageHandler, new ArgTokenizer("<init>", "")).restoreEncodedModes(encoded);
}
@@ -177,6 +179,15 @@
selectorMap.put(e.name().toLowerCase(Locale.US), e);
}
+ private static class SelectorSets {
+ Set<FormatCase> cc;
+ Set<FormatAction> ca;
+ Set<FormatWhen> cw;
+ Set<FormatResolve> cr;
+ Set<FormatUnresolved> cu;
+ Set<FormatErrors> ce;
+ }
+
/**
* Holds all the context of a mode mode
*/
@@ -197,12 +208,32 @@
String continuationPrompt = ">> ";
static class Setting {
+
final long enumBits;
final String format;
+
Setting(long enumBits, String format) {
this.enumBits = enumBits;
this.format = format;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Setting) {
+ Setting ing = (Setting) o;
+ return enumBits == ing.enumBits && format.equals(ing.format);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 67 * hash + (int) (this.enumBits ^ (this.enumBits >>> 32));
+ hash = 67 * hash + Objects.hashCode(this.format);
+ return hash;
+ }
}
/**
@@ -274,6 +305,25 @@
}
}
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Mode) {
+ Mode m = (Mode) o;
+ return name.equals((m.name))
+ && commandFluff == m.commandFluff
+ && prompt.equals((m.prompt))
+ && continuationPrompt.equals((m.continuationPrompt))
+ && cases.equals((m.cases));
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
+
/**
* Set if this mode displays informative/confirmational messages on
* commands.
@@ -308,13 +358,17 @@
return String.join(RECORD_SEPARATOR, el);
}
- private boolean add(String field, Setting ing) {
- List<Setting> settings = cases.computeIfAbsent(field, k -> new ArrayList<>());
+ private void add(String field, Setting ing) {
+ List<Setting> settings = cases.get(field);
if (settings == null) {
- return false;
+ settings = new ArrayList<>();
+ cases.put(field, settings);
+ } else {
+ // remove obscured settings
+ long mask = ~ing.enumBits;
+ settings.removeIf(t -> (t.enumBits & mask) == 0);
}
settings.add(ing);
- return true;
}
void set(String field,
@@ -465,6 +519,37 @@
return res;
}
+ private static SelectorSets unpackEnumbits(long enumBits) {
+ class Unpacker {
+
+ SelectorSets u = new SelectorSets();
+ long b = enumBits;
+
+ <E extends Enum<E>> Set<E> unpackEnumbits(E[] values) {
+ Set<E> c = new HashSet<>();
+ for (int i = 0; i < values.length; ++i) {
+ if ((b & (1 << i)) != 0) {
+ c.add(values[i]);
+ }
+ }
+ b >>>= values.length;
+ return c;
+ }
+
+ SelectorSets unpack() {
+ // inverseof the order they were packed
+ u.ce = unpackEnumbits(FormatErrors.values());
+ u.cu = unpackEnumbits(FormatUnresolved.values());
+ u.cr = unpackEnumbits(FormatResolve.values());
+ u.cw = unpackEnumbits(FormatWhen.values());
+ u.ca = unpackEnumbits(FormatAction.values());
+ u.cc = unpackEnumbits(FormatCase.values());
+ return u;
+ }
+ }
+ return new Unpacker().unpack();
+ }
+
interface Selector<E extends Enum<E> & Selector<E>> {
SelectorCollector<E> collector(Setter.SelectorList sl);
String doc();
@@ -675,31 +760,197 @@
Setter(MessageHandler messageHandler, ArgTokenizer at) {
this.messageHandler = messageHandler;
this.at = at;
+ at.allowedOptions("-retain");
}
void fluff(String format, Object... args) {
messageHandler.fluff(format, args);
}
+ void hard(String format, Object... args) {
+ messageHandler.hard(format, args);
+ }
+
void fluffmsg(String messageKey, Object... args) {
messageHandler.fluffmsg(messageKey, args);
}
+ void hardmsg(String messageKey, Object... args) {
+ messageHandler.hardmsg(messageKey, args);
+ }
+
+ boolean showFluff() {
+ return messageHandler.showFluff();
+ }
+
void errorat(String messageKey, Object... args) {
+ if (!valid) {
+ // no spew of errors
+ return;
+ }
+ valid = false;
Object[] a2 = Arrays.copyOf(args, args.length + 2);
a2[args.length] = at.whole();
messageHandler.errormsg(messageKey, a2);
}
+ String selectorsToString(SelectorSets u) {
+ StringBuilder sb = new StringBuilder();
+ selectorToString(sb, u.cc, FormatCase.values());
+ selectorToString(sb, u.ca, FormatAction.values());
+ selectorToString(sb, u.cw, FormatWhen.values());
+ selectorToString(sb, u.cr, FormatResolve.values());
+ selectorToString(sb, u.cu, FormatUnresolved.values());
+ selectorToString(sb, u.ce, FormatErrors.values());
+ return sb.toString();
+ }
+
+ private <E extends Enum<E>> void selectorToString(StringBuilder sb, Set<E> c, E[] values) {
+ if (!c.containsAll(Arrays.asList(values))) {
+ sb.append(c.stream()
+ .sorted((x, y) -> x.ordinal() - y.ordinal())
+ .map(v -> v.name().toLowerCase(Locale.US))
+ .collect(new Collector<CharSequence, StringJoiner, String>() {
+ @Override
+ public BiConsumer<StringJoiner, CharSequence> accumulator() {
+ return StringJoiner::add;
+ }
+
+ @Override
+ public Supplier<StringJoiner> supplier() {
+ return () -> new StringJoiner(",", (sb.length() == 0)? "" : "-", "")
+ .setEmptyValue("");
+ }
+
+ @Override
+ public BinaryOperator<StringJoiner> combiner() {
+ return StringJoiner::merge;
+ }
+
+ @Override
+ public Function<StringJoiner, String> finisher() {
+ return StringJoiner::toString;
+ }
+
+ @Override
+ public Set<Characteristics> characteristics() {
+ return Collections.emptySet();
+ }
+ }));
+ }
+ }
+
+ // Show format settings -- in a predictable order, for testing...
+ void showFormatSettings(Mode sm, String f) {
+ if (sm == null) {
+ modeMap.entrySet().stream()
+ .sorted((es1, es2) -> es1.getKey().compareTo(es2.getKey()))
+ .forEach(m -> showFormatSettings(m.getValue(), f));
+ } else {
+ sm.cases.entrySet().stream()
+ .filter(ec -> (f == null)
+ ? !ec.getKey().equals(TRUNCATION_FIELD)
+ : ec.getKey().equals(f))
+ .sorted((ec1, ec2) -> ec1.getKey().compareTo(ec2.getKey()))
+ .forEach(ec -> {
+ ec.getValue().forEach(s -> {
+ hard("/set format %s %s %s %s",
+ sm.name, ec.getKey(), toStringLiteral(s.format),
+ selectorsToString(unpackEnumbits(s.enumBits)));
+
+ });
+ });
+ }
+ }
+
+ void showTruncationSettings(Mode sm) {
+ if (sm == null) {
+ modeMap.values().forEach(m -> showTruncationSettings(m));
+ } else {
+ List<Mode.Setting> trunc = sm.cases.get(TRUNCATION_FIELD);
+ if (trunc != null) {
+ trunc.forEach(s -> {
+ hard("/set truncation %s %s %s",
+ sm.name, s.format,
+ selectorsToString(unpackEnumbits(s.enumBits)));
+ });
+ }
+ }
+ }
+
+ void showPromptSettings(Mode sm) {
+ if (sm == null) {
+ modeMap.values().forEach(m -> showPromptSettings(m));
+ } else {
+ hard("/set prompt %s %s %s",
+ sm.name,
+ toStringLiteral(sm.prompt),
+ toStringLiteral(sm.continuationPrompt));
+ }
+ }
+
+ void showModeSettings(String umode, String msg) {
+ if (umode == null) {
+ modeMap.values().forEach(n -> showModeSettings(n));
+ } else {
+ Mode m;
+ String retained = retainedMap.get(umode);
+ if (retained == null) {
+ m = searchForMode(umode, msg);
+ if (m == null) {
+ return;
+ }
+ umode = m.name;
+ retained = retainedMap.get(umode);
+ } else {
+ m = modeMap.get(umode);
+ }
+ if (retained != null) {
+ Mode rm = new Mode(encodedModeIterator(retained));
+ showModeSettings(rm);
+ hard("/set mode -retain %s", umode);
+ if (m != null && !m.equals(rm)) {
+ hard("");
+ showModeSettings(m);
+ }
+ } else {
+ showModeSettings(m);
+ }
+ }
+ }
+
+ void showModeSettings(Mode sm) {
+ hard("/set mode %s %s",
+ sm.name, sm.commandFluff ? "-command" : "-quiet");
+ showPromptSettings(sm);
+ showFormatSettings(sm, null);
+ showTruncationSettings(sm);
+ }
+
+ void showFeedbackSetting() {
+ if (retainedCurrentMode != null) {
+ hard("/set feedback -retain %s", retainedCurrentMode.name);
+ }
+ if (mode != retainedCurrentMode) {
+ hard("/set feedback %s", mode.name);
+ }
+ }
+
// For /set prompt <mode> "<prompt>" "<continuation-prompt>"
boolean setPrompt() {
Mode m = nextMode();
+ String prompt = nextFormat();
+ String continuationPrompt = nextFormat();
+ checkOptionsAndRemainingInput();
+ if (valid && prompt == null) {
+ showPromptSettings(m);
+ return valid;
+ }
if (valid && m.readOnly) {
errorat("jshell.err.not.valid.with.predefined.mode", m.name);
- valid = false;
+ } else if (continuationPrompt == null) {
+ errorat("jshell.err.continuation.prompt.required");
}
- String prompt = valid ? nextFormat() : null;
- String continuationPrompt = valid ? nextFormat() : null;
if (valid) {
m.setPrompts(prompt, continuationPrompt);
} else {
@@ -714,210 +965,210 @@
*
* @return true if successful
*/
- boolean setMode() {
- at.allowedOptions("-command", "-quiet", "-delete");
- String umode = nextModeIdentifier();
- Mode om = null;
- String omode = at.next();
- if (valid && omode != null) {
- om = toMode(omode);
- }
- checkOptionsAndRemainingInput();
- boolean commandOption = at.hasOption("-command");
- boolean quietOption = at.hasOption("-quiet");
- boolean deleteOption = at.hasOption("-delete");
- // Only one (or zero) of the options can be used
- if (valid && at.optionCount() > 1) {
- errorat("jshell.err.conflicting.options");
- valid = false;
- }
- if (valid) {
- Mode m = modeMap.get(umode);
- if (m != null && m.readOnly) {
- // Cannot make changes to a the built-in modes
- errorat("jshell.err.not.valid.with.predefined.mode", m.name);
- valid = false;
- } else if (deleteOption) {
- if (m == null) {
+ boolean setMode(Consumer<String> retainer) {
+ class SetMode {
+
+ final String umode;
+ final String omode;
+ final boolean commandOption;
+ final boolean quietOption;
+ final boolean deleteOption;
+ final boolean retainOption;
+
+ SetMode() {
+ at.allowedOptions("-command", "-quiet", "-delete", "-retain");
+ umode = nextModeIdentifier();
+ omode = nextModeIdentifier();
+ checkOptionsAndRemainingInput();
+ commandOption = at.hasOption("-command");
+ quietOption = at.hasOption("-quiet");
+ deleteOption = at.hasOption("-delete");
+ retainOption = at.hasOption("-retain");
+ }
+
+ void delete() {
+ // Note: delete, for safety reasons, does NOT do name matching
+ if (commandOption || quietOption) {
+ errorat("jshell.err.conflicting.options");
+ } else if (!(retainOption ? retainedMap : modeMap).containsKey(umode)) {
// Cannot delete a mode that does not exist
errorat("jshell.err.mode.unknown", umode);
- valid = false;
- } else if (mode.name.equals(m.name)) {
+ } else if (omode != null) {
+ // old mode is for creation
+ errorat("jshell.err.unexpected.at.end", omode);
+ } else if (mode.name.equals(umode)) {
// Cannot delete the current mode out from under us
errorat("jshell.err.cannot.delete.current.mode", umode);
- valid = false;
+ } else if (retainOption && retainedCurrentMode != null &&
+ retainedCurrentMode.name.equals(umode)) {
+ // Cannot delete the retained mode or re-start will have an error
+ errorat("jshell.err.cannot.delete.retained.mode", umode);
} else {
- // Remove the mode
- modeMap.remove(umode);
+ Mode m = modeMap.get(umode);
+ if (m != null && m.readOnly) {
+ errorat("jshell.err.not.valid.with.predefined.mode", umode);
+ } else {
+ // Remove the mode
+ modeMap.remove(umode);
+ if (retainOption) {
+ // Remove the retained mode
+ retainedMap.remove(umode);
+ updateRetainedModes();
+ }
+ }
}
- } else {
- if (om != null || m == null) {
- // We are copying and existing mode and/or creating a
- // brand-new mode -- in either case create from scratch
- m = (om != null)
- ? new Mode(umode, om)
- : new Mode(umode);
- modeMap.put(umode, m);
- fluffmsg("jshell.msg.feedback.new.mode", m.name);
- // Set the current mode by name, in case we just smashed
- // the current mode
- if (umode.equals(mode.name)) {
- mode = modeMap.get(mode.name);
+ }
+
+ void retain() {
+ if (commandOption || quietOption) {
+ errorat("jshell.err.conflicting.options");
+ } else if (omode != null) {
+ // old mode is for creation
+ errorat("jshell.err.unexpected.at.end", omode);
+ } else {
+ Mode m = modeMap.get(umode);
+ if (m == null) {
+ // can only retain existing modes
+ errorat("jshell.err.mode.unknown", umode);
+ } else if (m.readOnly) {
+ errorat("jshell.err.not.valid.with.predefined.mode", umode);
+ } else {
+ // Add to local cache of retained current encodings
+ retainedMap.put(m.name, m.encode());
+ updateRetainedModes();
}
}
- if (commandOption || quietOption || om == null) {
- // set command fluff, if explicit, or wholly new
- m.setCommandFluff(!quietOption);
+ }
+
+ void updateRetainedModes() {
+ // Join all the retained encodings
+ String encoded = String.join(RECORD_SEPARATOR, retainedMap.values());
+ // Retain it
+ retainer.accept(encoded);
+ }
+
+ void create() {
+ if (commandOption && quietOption) {
+ errorat("jshell.err.conflicting.options");
+ } else if (!commandOption && !quietOption) {
+ errorat("jshell.err.mode.creation");
+ } else if (modeMap.containsKey(umode)) {
+ // Mode already exists
+ errorat("jshell.err.mode.exists", umode);
+ } else {
+ Mode om = searchForMode(omode);
+ if (valid) {
+ // We are copying an existing mode and/or creating a
+ // brand-new mode -- in either case create from scratch
+ Mode m = (om != null)
+ ? new Mode(umode, om)
+ : new Mode(umode);
+ modeMap.put(umode, m);
+ fluffmsg("jshell.msg.feedback.new.mode", m.name);
+ m.setCommandFluff(commandOption);
+ }
}
}
+
+ boolean set() {
+ if (valid && !commandOption && !quietOption && !deleteOption &&
+ omode == null && !retainOption) {
+ // Not a creation, deletion, or retain -- show mode(s)
+ showModeSettings(umode, "jshell.err.mode.creation");
+ } else if (valid && umode == null) {
+ errorat("jshell.err.missing.mode");
+ } else if (valid && deleteOption) {
+ delete();
+ } else if (valid && retainOption) {
+ retain();
+ } else if (valid) {
+ create();
+ }
+ if (!valid) {
+ fluffmsg("jshell.msg.see", "/help /set mode");
+ }
+ return valid;
+ }
}
- if (!valid) {
- fluffmsg("jshell.msg.see", "/help /set mode");
- }
- return valid;
+ return new SetMode().set();
}
- // For /set feedback <mode>
- boolean setFeedback() {
+ // For /set format <mode> <field> "<format>" <selector>...
+ boolean setFormat() {
Mode m = nextMode();
- if (valid) {
- mode = m;
- fluffmsg("jshell.msg.feedback.mode", mode.name);
+ String field = toIdentifier(next(), "jshell.err.field.name");
+ String format = nextFormat();
+ if (valid && format == null) {
+ if (field != null && m != null && !m.cases.containsKey(field)) {
+ errorat("jshell.err.field.name", field);
+ } else {
+ showFormatSettings(m, field);
+ }
} else {
- fluffmsg("jshell.msg.see", "/help /set feedback");
- printFeedbackModes();
+ installFormat(m, field, format, "/help /set format");
}
return valid;
}
- // For /set format <mode> "<format>" <selector>...
- boolean setFormat() {
- Mode m = nextMode();
- if (valid && m.readOnly) {
- errorat("jshell.err.not.valid.with.predefined.mode", m.name);
- valid = false;
- }
- String field = valid
- ? toIdentifier(at.next(), "jshell.err.missing.field", "jshell.err.field.name")
- : null;
- String format = valid ? nextFormat() : null;
- return installFormat(m, field, format, "/help /set format");
- }
-
// For /set truncation <mode> <length> <selector>...
boolean setTruncation() {
Mode m = nextMode();
- if (valid && m.readOnly) {
- errorat("jshell.err.not.valid.with.predefined.mode", m.name);
- valid = false;
- }
- String length = at.next();
+ String length = next();
if (length == null) {
- errorat("jshell.err.truncation.expected.length");
- valid = false;
+ showTruncationSettings(m);
} else {
try {
// Assure that integer format is correct
Integer.parseUnsignedInt(length);
} catch (NumberFormatException ex) {
errorat("jshell.err.truncation.length.not.integer", length);
- valid = false;
}
+ // install length into an internal format field
+ installFormat(m, TRUNCATION_FIELD, length, "/help /set truncation");
}
- // install length into an internal format field
- return installFormat(m, TRUNCATION_FIELD, length, "/help /set truncation");
- }
-
- String retainFeedback() {
- String umode = at.next();
- if (umode != null) {
- toModeIdentifier(umode);
- Mode m = valid ? toMode(umode) : null;
- if (valid && !m.readOnly && !retainedMap.containsKey(m.name)) {
- errorat("jshell.err.retained.feedback.mode.must.be.retained.or.predefined");
- valid = false;
- }
- if (valid) {
- mode = m;
- retainedCurrentMode = m;
- fluffmsg("jshell.msg.feedback.mode", mode.name);
- } else {
- fluffmsg("jshell.msg.see", "/help /retain feedback");
- return null;
- }
- }
- return mode.name;
+ return valid;
}
- /**
- * Retain (or delete from retention) a previously set mode.
- *
- * @return all retained modes encoded into a String
- */
- String retainMode() {
- at.allowedOptions("-delete");
- String umode = nextModeIdentifier();
- // -delete is the only valid option, fail for anything else
+ // For /set feedback <mode>
+ boolean setFeedback(Consumer<String> retainer) {
+ String umode = next();
checkOptionsAndRemainingInput();
- boolean deleteOption = at.hasOption("-delete");
- // Lookup the mode
- Mode m;
- if (!valid) {
- m = null;
- // Skip this stuff, we have failed already
- } else if (deleteOption) {
- // If delete, allow for deleting, from retention, a mode that
- // has been locally deleted but is retained.
- // Also require the full name.
- m = modeMap.get(umode);
- if (m == null && !retainedMap.containsKey(umode)) {
- errorat("jshell.err.mode.unknown", umode);
- valid = false;
- }
- } else {
- // For retain do normal lookup and checking
- m = toMode(umode);
- }
-
- // Built-in modes cannot be retained or deleted
- if (valid && m != null && m.readOnly) {
- errorat("jshell.err.not.valid.with.predefined.mode", umode);
- valid = false;
+ boolean retainOption = at.hasOption("-retain");
+ if (valid && umode == null && !retainOption) {
+ showFeedbackSetting();
+ hard("");
+ showFeedbackModes();
+ return true;
}
if (valid) {
- if (deleteOption) {
- if (mode.name.equals(umode)) {
- // Cannot delete the current mode out from under us
- errorat("jshell.err.cannot.delete.current.mode", umode);
- valid = false;
- } else if (retainedCurrentMode != null && retainedCurrentMode.name.equals(umode)) {
- // Cannot delete the retained mode or re-start has error
- errorat("jshell.err.cannot.delete.retained.mode", umode);
- valid = false;
- } else {
- // Delete the mode
- modeMap.remove(umode);
- retainedMap.remove(umode);
+ Mode m = umode == null
+ ? mode
+ : searchForMode(toModeIdentifier(umode));
+ if (valid && retainOption && !m.readOnly && !retainedMap.containsKey(m.name)) {
+ errorat("jshell.err.retained.feedback.mode.must.be.retained.or.predefined");
+ }
+ if (valid) {
+ if (umode != null) {
+ mode = m;
+ fluffmsg("jshell.msg.feedback.mode", mode.name);
}
- } else {
- // Retain the current encoding
- retainedMap.put(m.name, m.encode());
+ if (retainOption) {
+ retainedCurrentMode = m;
+ retainer.accept(m.name);
+ }
}
}
- if (valid) {
- // Join all the retained encodings
- return String.join(RECORD_SEPARATOR, retainedMap.values());
- } else {
- fluffmsg("jshell.msg.see", "/help /retain mode");
- return null;
+ if (!valid) {
+ fluffmsg("jshell.msg.see", "/help /set feedback");
+ return false;
}
+ return true;
}
boolean restoreEncodedModes(String allEncoded) {
try {
// Iterate over each record in each encoded mode
- String[] ms = allEncoded.split(RECORD_SEPARATOR);
- Iterator<String> itr = Arrays.asList(ms).iterator();
+ Iterator<String> itr = encodedModeIterator(allEncoded);
while (itr.hasNext()) {
// Reconstruct the encoded mode
Mode m = new Mode(itr);
@@ -934,50 +1185,60 @@
}
}
+ Iterator<String> encodedModeIterator(String encoded) {
+ String[] ms = encoded.split(RECORD_SEPARATOR);
+ return Arrays.asList(ms).iterator();
+ }
+
// install the format of a field under parsed selectors
- boolean installFormat(Mode m, String field, String format, String help) {
+ void installFormat(Mode m, String field, String format, String help) {
String slRaw;
List<SelectorList> slList = new ArrayList<>();
- while (valid && (slRaw = at.next()) != null) {
+ while (valid && (slRaw = next()) != null) {
SelectorList sl = new SelectorList();
sl.parseSelectorList(slRaw);
slList.add(sl);
}
+ checkOptionsAndRemainingInput();
if (valid) {
- if (slList.isEmpty()) {
+ if (m.readOnly) {
+ errorat("jshell.err.not.valid.with.predefined.mode", m.name);
+ } else if (slList.isEmpty()) {
// No selectors specified, then always the format
m.set(field, ALWAYS, format);
} else {
// Set the format of the field for specified selector
slList.stream()
.forEach(sl -> m.set(field,
- sl.cases.getSet(), sl.actions.getSet(), sl.whens.getSet(),
- sl.resolves.getSet(), sl.unresolvedCounts.getSet(), sl.errorCounts.getSet(),
- format));
+ sl.cases.getSet(), sl.actions.getSet(), sl.whens.getSet(),
+ sl.resolves.getSet(), sl.unresolvedCounts.getSet(), sl.errorCounts.getSet(),
+ format));
}
} else {
fluffmsg("jshell.msg.see", help);
}
- return valid;
}
void checkOptionsAndRemainingInput() {
- if (!valid) {
- return;
- }
String junk = at.remainder();
if (!junk.isEmpty()) {
errorat("jshell.err.unexpected.at.end", junk);
- valid = false;
} else {
String bad = at.badOptions();
if (!bad.isEmpty()) {
errorat("jshell.err.unknown.option", bad);
- valid = false;
}
}
}
+ String next() {
+ String s = at.next();
+ if (s == null) {
+ checkOptionsAndRemainingInput();
+ }
+ return s;
+ }
+
/**
* Check that the specified string is an identifier (Java identifier).
* If null display the missing error. If it is not an identifier,
@@ -985,45 +1246,41 @@
*
* @param id the string to check, MUST be the most recently retrieved
* token from 'at'.
- * @param missing the resource error to display if null
+ * @param missing null for no null error, otherwise the resource error to display if id is null
* @param err the resource error to display if not an identifier
* @return the identifier string, or null if null or not an identifier
*/
- String toIdentifier(String id, String missing, String err) {
- if (id == null) {
- errorat(missing);
- valid = false;
+ private String toIdentifier(String id, String err) {
+ if (!valid || id == null) {
return null;
}
if (at.isQuoted() ||
!id.codePoints().allMatch(cp -> Character.isJavaIdentifierPart(cp))) {
errorat(err, id);
- valid = false;
return null;
}
return id;
}
- String toModeIdentifier(String id) {
- return toIdentifier(id, "jshell.err.missing.mode", "jshell.err.mode.name");
+ private String toModeIdentifier(String id) {
+ return toIdentifier(id, "jshell.err.mode.name");
}
- String nextModeIdentifier() {
- return toModeIdentifier(at.next());
+ private String nextModeIdentifier() {
+ return toModeIdentifier(next());
}
- Mode nextMode() {
+ private Mode nextMode() {
String umode = nextModeIdentifier();
- return toMode(umode);
+ return searchForMode(umode);
}
- Mode toMode(String umode) {
- if (!valid) {
- return null;
- }
- if (umode == null) {
- errorat("jshell.err.missing.mode");
- valid = false;
+ private Mode searchForMode(String umode) {
+ return searchForMode(umode, null);
+ }
+
+ private Mode searchForMode(String umode, String msg) {
+ if (!valid || umode == null) {
return null;
}
Mode m = modeMap.get(umode);
@@ -1038,39 +1295,101 @@
if (matches.length == 1) {
return matches[0];
} else {
- valid = false;
+ if (msg != null) {
+ hardmsg(msg, "");
+ }
if (matches.length == 0) {
errorat("jshell.err.feedback.does.not.match.mode", umode);
} else {
errorat("jshell.err.feedback.ambiguous.mode", umode);
}
- printFeedbackModes();
+ if (showFluff()) {
+ showFeedbackModes();
+ }
return null;
}
}
- void printFeedbackModes() {
- fluffmsg("jshell.msg.feedback.mode.following");
+ void showFeedbackModes() {
+ if (!retainedMap.isEmpty()) {
+ hardmsg("jshell.msg.feedback.retained.mode.following");
+ retainedMap.keySet().stream()
+ .sorted()
+ .forEach(mk -> hard(" %s", mk));
+ }
+ hardmsg("jshell.msg.feedback.mode.following");
modeMap.keySet().stream()
- .forEach(mk -> fluff(" %s", mk));
+ .sorted()
+ .forEach(mk -> hard(" %s", mk));
+ }
+
+ // Read and test if the format string is correctly
+ private String nextFormat() {
+ return toFormat(next());
}
// Test if the format string is correctly
- final String nextFormat() {
- String format = at.next();
- if (format == null) {
- errorat("jshell.err.feedback.expected.format");
- valid = false;
+ private String toFormat(String format) {
+ if (!valid || format == null) {
return null;
}
if (!at.isQuoted()) {
errorat("jshell.err.feedback.must.be.quoted", format);
- valid = false;
- return null;
+ return null;
}
return format;
}
+ // Convert to a quoted string
+ private String toStringLiteral(String s) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('"');
+ final int length = s.length();
+ for (int offset = 0; offset < length;) {
+ final int codepoint = s.codePointAt(offset);
+
+ switch (codepoint) {
+ case '\b':
+ sb.append("\\b");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\f':
+ sb.append("\\f");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ case '\"':
+ sb.append("\\\"");
+ break;
+ case '\'':
+ sb.append("\\'");
+ break;
+ case '\\':
+ sb.append("\\\\");
+ break;
+ default:
+ if (codepoint < 040) {
+ sb.append(String.format("\\%o", codepoint));
+ } else {
+ sb.appendCodePoint(codepoint);
+ }
+ break;
+ }
+
+ // do something with the codepoint
+ offset += Character.charCount(codepoint);
+
+ }
+ sb.append('"');
+ return sb.toString();
+ }
+
class SelectorList {
SelectorCollector<FormatCase> cases = new SelectorCollector<>(FormatCase.all);
@@ -1088,19 +1407,16 @@
Selector<?> sel = selectorMap.get(as);
if (sel == null) {
errorat("jshell.err.feedback.not.a.valid.selector", as, s);
- valid = false;
return;
}
SelectorCollector<?> collector = sel.collector(this);
if (lastCollector == null) {
if (!collector.isEmpty()) {
errorat("jshell.err.feedback.multiple.sections", as, s);
- valid = false;
return;
}
} else if (collector != lastCollector) {
errorat("jshell.err.feedback.different.selector.kinds", as, s);
- valid = false;
return;
}
collector.add(sel);
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java Thu Oct 27 09:42:08 2016 -0700
@@ -54,7 +54,7 @@
public abstract void replaceLastHistoryEntry(String source);
- public abstract int readUserInput();
+ public abstract int readUserInput() throws IOException;
class InputInterruptedException extends Exception {
private static final long serialVersionUID = 1L;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Oct 27 09:42:08 2016 -0700
@@ -133,32 +133,26 @@
final PrintStream userout;
final PrintStream usererr;
final Preferences prefs;
+ final Map<String, String> envvars;
final Locale locale;
final Feedback feedback = new Feedback();
/**
- * The constructor for the tool (used by tool launch via main and by test
- * harnesses to capture ins and outs.
- * @param in command line input -- snippets, commands and user input
- * @param cmdout command line output, feedback including errors
- * @param cmderr start-up errors and debugging info
- * @param console console control interaction
- * @param userout code execution output -- System.out.printf("hi")
- * @param usererr code execution error stream -- System.err.printf("Oops")
- * @param prefs preferences to use
- * @param locale locale to use
+ * Simple constructor for the tool used by main.
+ * @param in command line input
+ * @param out command line output, feedback including errors, user System.out
+ * @param err start-up errors and debugging info, user System.err
*/
- public JShellTool(InputStream in, PrintStream cmdout, PrintStream cmderr,
- PrintStream console,
- PrintStream userout, PrintStream usererr,
- Preferences prefs, Locale locale) {
- this(in, cmdout, cmderr, console, null, userout, usererr, prefs, locale);
+ public JShellTool(InputStream in, PrintStream out, PrintStream err) {
+ this(in, out, err, out, null, out, err,
+ Preferences.userRoot().node("tool/JShell"),
+ System.getenv(),
+ Locale.getDefault());
}
/**
- * The constructor for the tool (used by tool launch via main and by test
- * harnesses to capture ins and outs.
+ * The complete constructor for the tool (used by test harnesses).
* @param cmdin command line input -- snippets and commands
* @param cmdout command line output, feedback including errors
* @param cmderr start-up errors and debugging info
@@ -167,12 +161,13 @@
* @param userout code execution output -- System.out.printf("hi")
* @param usererr code execution error stream -- System.err.printf("Oops")
* @param prefs preferences to use
+ * @param envvars environment variable mapping to use
* @param locale locale to use
*/
public JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
PrintStream console,
InputStream userin, PrintStream userout, PrintStream usererr,
- Preferences prefs, Locale locale) {
+ Preferences prefs, Map<String, String> envvars, Locale locale) {
this.cmdin = cmdin;
this.cmdout = cmdout;
this.cmderr = cmderr;
@@ -186,6 +181,7 @@
this.userout = userout;
this.usererr = usererr;
this.prefs = prefs;
+ this.envvars = envvars;
this.locale = locale;
}
@@ -204,12 +200,16 @@
JShell state = null;
Subscription shutdownSubscription = null;
+ static final EditorSetting BUILT_IN_EDITOR = new EditorSetting(null, false);
+
private boolean debug = false;
public boolean testPrompt = false;
private String cmdlineClasspath = null;
private String startup = null;
- private String[] editor = null;
- private boolean editorWait = false;
+ private EditorSetting editor = BUILT_IN_EDITOR;
+
+ private static final String[] EDITOR_ENV_VARS = new String[] {
+ "JSHELLEDITOR", "VISUAL", "EDITOR"};
// Commands and snippets which should be replayed
private List<String> replayableHistory;
@@ -273,7 +273,8 @@
* @param format printf format
* @param args printf args
*/
- void hard(String format, Object... args) {
+ @Override
+ public void hard(String format, Object... args) {
rawout(feedback.getPre() + format + feedback.getPost(), args);
}
@@ -288,6 +289,15 @@
}
/**
+ * Should optional informative be displayed?
+ * @return true if they should be displayed
+ */
+ @Override
+ public boolean showFluff() {
+ return feedback.shouldDisplayCommandFluff() && interactive();
+ }
+
+ /**
* Optional output
*
* @param format printf format
@@ -295,7 +305,7 @@
*/
@Override
public void fluff(String format, Object... args) {
- if (feedback.shouldDisplayCommandFluff() && interactive()) {
+ if (showFluff()) {
hard(format, args);
}
}
@@ -307,7 +317,7 @@
* @param args printf args
*/
void fluffRaw(String format, Object... args) {
- if (feedback.shouldDisplayCommandFluff() && interactive()) {
+ if (showFluff()) {
rawout(format, args);
}
}
@@ -389,7 +399,8 @@
* @param key the resource key
* @param args
*/
- void hardmsg(String key, Object... args) {
+ @Override
+ public void hardmsg(String key, Object... args) {
cmdout.println(prefix(messageFormat(key, args)));
}
@@ -428,7 +439,7 @@
*/
@Override
public void fluffmsg(String key, Object... args) {
- if (feedback.shouldDisplayCommandFluff() && interactive()) {
+ if (showFluff()) {
hardmsg(key, args);
}
}
@@ -474,10 +485,7 @@
* @throws Exception
*/
public static void main(String[] args) throws Exception {
- new JShellTool(System.in, System.out, System.err, System.out,
- System.out, System.err,
- Preferences.userRoot().node("tool/JShell"),
- Locale.getDefault())
+ new JShellTool(System.in, System.out, System.err)
.start(args);
}
@@ -501,18 +509,7 @@
}
}
- // Read retained editor setting (if any)
- String editorString = prefs.get(EDITOR_KEY, "");
- if (editorString == null || editorString.isEmpty()) {
- editor = null;
- } else {
- char waitMarker = editorString.charAt(0);
- if (waitMarker == '-' || waitMarker == '*') {
- editorWait = waitMarker == '-';
- editorString = editorString.substring(1);
- }
- editor = editorString.split(RECORD_SEPARATOR);
- }
+ configEditor();
resetState(); // Initialize
@@ -542,6 +539,23 @@
}
}
+ private EditorSetting configEditor() {
+ // Read retained editor setting (if any)
+ editor = EditorSetting.fromPrefs(prefs);
+ if (editor != null) {
+ return editor;
+ }
+ // Try getting editor setting from OS environment variables
+ for (String envvar : EDITOR_ENV_VARS) {
+ String v = envvars.get(envvar);
+ if (v != null) {
+ return editor = new EditorSetting(v.split("\\s+"), false);
+ }
+ }
+ // Default to the built-in editor
+ return editor = BUILT_IN_EDITOR;
+ }
+
/**
* Process the command line arguments.
* Set options.
@@ -681,9 +695,24 @@
}
@Override
+ public void hard(String format, Object... args) {
+ //ignore
+ }
+
+ @Override
+ public void hardmsg(String messageKey, Object... args) {
+ //ignore
+ }
+
+ @Override
public void errormsg(String messageKey, Object... args) {
startmsg(messageKey, args);
}
+
+ @Override
+ public boolean showFluff() {
+ return false;
+ }
}
private void resetState() {
@@ -745,7 +774,7 @@
startUpRun(getResourceString("startup.feedback"));
// These predefined modes are read-only
feedback.markModesReadOnly();
- // Restore user defined modes retained on previous run with /retain mode
+ // Restore user defined modes retained on previous run with /set mode -retain
String encoded = prefs.get(MODE_KEY, null);
if (encoded != null && !encoded.isEmpty()) {
if (!feedback.restoreEncodedModes(initmh, encoded)) {
@@ -755,7 +784,7 @@
}
if (commandLineFeedbackMode != null) {
// The feedback mode to use was specified on the command line, use it
- if (!feedback.setFeedback(initmh, new ArgTokenizer("--feedback", commandLineFeedbackMode))) {
+ if (!setFeedback(initmh, new ArgTokenizer("--feedback", commandLineFeedbackMode))) {
regenerateOnDeath = false;
}
commandLineFeedbackMode = null;
@@ -763,8 +792,8 @@
String fb = prefs.get(FEEDBACK_KEY, null);
if (fb != null) {
// Restore the feedback mode to use that was retained
- // on a previous run with /retain feedback
- feedback.retainFeedback(initmh, new ArgTokenizer("/retain feedback", fb));
+ // on a previous run with /set feedback -retain
+ setFeedback(initmh, new ArgTokenizer("previous retain feedback", "-retain " + fb));
}
}
}
@@ -1227,14 +1256,6 @@
"editor", fileCompletions(Files::isExecutable),
"start", FILE_COMPLETION_PROVIDER),
STARTSWITH_MATCHER)));
- registerCommand(new Command("/retain",
- arg -> cmdRetain(arg),
- new ContinuousCompletionProvider(Map.of(
- "feedback", feedback.modeCompletions(),
- "mode", feedback.modeCompletions(),
- "editor", fileCompletions(Files::isExecutable),
- "start", FILE_COMPLETION_PROVIDER),
- STARTSWITH_MATCHER)));
registerCommand(new Command("/?",
"help.quest",
arg -> cmdHelp(arg),
@@ -1293,9 +1314,6 @@
private static final String[] SET_SUBCOMMANDS = new String[]{
"format", "truncation", "feedback", "mode", "prompt", "editor", "start"};
- private static final String[] RETAIN_SUBCOMMANDS = new String[]{
- "feedback", "mode", "editor", "start"};
-
final boolean cmdSet(String arg) {
String cmd = "/set";
ArgTokenizer at = new ArgTokenizer(cmd, arg.trim());
@@ -1304,95 +1322,61 @@
return false;
}
switch (which) {
+ case "_retain": {
+ errormsg("jshell.err.setting.to.retain.must.be.specified", at.whole());
+ return false;
+ }
+ case "_blank": {
+ // show top-level settings
+ new SetEditor().set();
+ showSetStart();
+ setFeedback(this, at); // no args so shows feedback setting
+ hardmsg("jshell.msg.set.show.mode.settings");
+ return true;
+ }
case "format":
return feedback.setFormat(this, at);
case "truncation":
return feedback.setTruncation(this, at);
case "feedback":
- return feedback.setFeedback(this, at);
+ return setFeedback(this, at);
case "mode":
- return feedback.setMode(this, at);
+ return feedback.setMode(this, at,
+ retained -> prefs.put(MODE_KEY, retained));
case "prompt":
return feedback.setPrompt(this, at);
case "editor":
- return setEditor(at, true);
+ return new SetEditor(at).set();
case "start":
- return setStart(cmd, at, true);
+ return setStart(at);
default:
errormsg("jshell.err.arg", cmd, at.val());
return false;
}
}
- final boolean cmdRetain(String arg) {
- String cmd = "/retain";
- ArgTokenizer at = new ArgTokenizer(cmd, arg.trim());
- String which = subCommand(cmd, at, RETAIN_SUBCOMMANDS);
- if (which == null) {
- return false;
- }
- switch (which) {
- case "feedback": {
- String fb = feedback.retainFeedback(this, at);
- if (fb != null) {
- // If a feedback mode has been set now, or in the past, retain it
- prefs.put(FEEDBACK_KEY, fb);
- return true;
- }
- return false;
- }
- case "mode":
- String retained = feedback.retainMode(this, at);
- if (retained != null) {
- // Retain this mode and all previously retained modes
- prefs.put(MODE_KEY, retained);
- return true;
- }
- return false;
- case "editor":
- if (!setEditor(at, false)) {
- return false;
- }
- // retain editor setting
- prefs.put(EDITOR_KEY, (editor == null)
- ? ""
- : (editorWait? "-" : "*") + String.join(RECORD_SEPARATOR, editor));
- return true;
- case "start": {
- if (!setStart(cmd, at, false)) {
- return false;
- }
- // retain startup setting
- prefs.put(STARTUP_KEY, startup);
- return true;
- }
- default:
- errormsg("jshell.err.arg", cmd, at.val());
- return false;
- }
+ boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at) {
+ return feedback.setFeedback(messageHandler, at,
+ fb -> prefs.put(FEEDBACK_KEY, fb));
}
- // Print the help doc for the specified sub-command
- boolean printSubCommandHelp(String cmd, ArgTokenizer at, String helpPrefix, String[] subs) {
- String which = subCommand(cmd, at, subs);
- if (which == null) {
- return false;
+ // Find which, if any, sub-command matches.
+ // Return null on error
+ String subCommand(String cmd, ArgTokenizer at, String[] subs) {
+ at.allowedOptions("-retain");
+ String sub = at.next();
+ if (sub == null) {
+ // No sub-command was given
+ return at.hasOption("-retain")
+ ? "_retain"
+ : "_blank";
}
- hardrb(helpPrefix + which);
- return true;
- }
-
- // Find which, if any, sub-command matches
- String subCommand(String cmd, ArgTokenizer at, String[] subs) {
- String[] matches = at.next(subs);
- if (matches == null) {
- // No sub-command was given
- errormsg("jshell.err.sub.arg", cmd);
- return null;
- }
+ String[] matches = Arrays.stream(subs)
+ .filter(s -> s.startsWith(sub))
+ .toArray(size -> new String[size]);
if (matches.length == 0) {
// There are no matching sub-commands
- errormsg("jshell.err.arg", cmd, at.val());
+ errormsg("jshell.err.arg", cmd, sub);
fluffmsg("jshell.msg.use.one.of", Arrays.stream(subs)
.collect(Collectors.joining(", "))
);
@@ -1400,7 +1384,7 @@
}
if (matches.length > 1) {
// More than one sub-command matches the initial characters provided
- errormsg("jshell.err.sub.ambiguous", cmd, at.val());
+ errormsg("jshell.err.sub.ambiguous", cmd, sub);
fluffmsg("jshell.msg.use.one.of", Arrays.stream(matches)
.collect(Collectors.joining(", "))
);
@@ -1409,67 +1393,232 @@
return matches[0];
}
- // The sub-command: /set editor <editor-command-line>>
- boolean setEditor(ArgTokenizer at, boolean argsRequired) {
- at.allowedOptions("-default", "-wait");
- String prog = at.next();
- List<String> ed = new ArrayList<>();
- while (at.val() != null) {
- ed.add(at.val());
- at.nextToken();
+ static class EditorSetting {
+
+ static String BUILT_IN_REP = "-default";
+ static char WAIT_PREFIX = '-';
+ static char NORMAL_PREFIX = '*';
+
+ final String[] cmd;
+ final boolean wait;
+
+ EditorSetting(String[] cmd, boolean wait) {
+ this.wait = wait;
+ this.cmd = cmd;
+ }
+
+ // returns null if not stored in preferences
+ static EditorSetting fromPrefs(Preferences prefs) {
+ // Read retained editor setting (if any)
+ String editorString = prefs.get(EDITOR_KEY, "");
+ if (editorString == null || editorString.isEmpty()) {
+ return null;
+ } else if (editorString.equals(BUILT_IN_REP)) {
+ return BUILT_IN_EDITOR;
+ } else {
+ boolean wait = false;
+ char waitMarker = editorString.charAt(0);
+ if (waitMarker == WAIT_PREFIX || waitMarker == NORMAL_PREFIX) {
+ wait = waitMarker == WAIT_PREFIX;
+ editorString = editorString.substring(1);
+ }
+ String[] cmd = editorString.split(RECORD_SEPARATOR);
+ return new EditorSetting(cmd, wait);
+ }
+ }
+
+ static void removePrefs(Preferences prefs) {
+ prefs.remove(EDITOR_KEY);
+ }
+
+ void toPrefs(Preferences prefs) {
+ prefs.put(EDITOR_KEY, (this == BUILT_IN_EDITOR)
+ ? BUILT_IN_REP
+ : (wait ? WAIT_PREFIX : NORMAL_PREFIX) + String.join(RECORD_SEPARATOR, cmd));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof EditorSetting) {
+ EditorSetting ed = (EditorSetting) o;
+ return Arrays.equals(cmd, ed.cmd) && wait == ed.wait;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 71 * hash + Arrays.deepHashCode(this.cmd);
+ hash = 71 * hash + (this.wait ? 1 : 0);
+ return hash;
}
+ }
+
+ class SetEditor {
+
+ private final ArgTokenizer at;
+ private final String[] command;
+ private final boolean hasCommand;
+ private final boolean defaultOption;
+ private final boolean deleteOption;
+ private final boolean waitOption;
+ private final boolean retainOption;
+ private final int primaryOptionCount;
+
+ SetEditor(ArgTokenizer at) {
+ at.allowedOptions("-default", "-wait", "-retain", "-delete");
+ String prog = at.next();
+ List<String> ed = new ArrayList<>();
+ while (at.val() != null) {
+ ed.add(at.val());
+ at.nextToken(); // so that options are not interpreted as jshell options
+ }
+ this.at = at;
+ this.command = ed.toArray(new String[ed.size()]);
+ this.hasCommand = command.length > 0;
+ this.defaultOption = at.hasOption("-default");
+ this.deleteOption = at.hasOption("-delete");
+ this.waitOption = at.hasOption("-wait");
+ this.retainOption = at.hasOption("-retain");
+ this.primaryOptionCount = (hasCommand? 1 : 0) + (defaultOption? 1 : 0) + (deleteOption? 1 : 0);
+ }
+
+ SetEditor() {
+ this(new ArgTokenizer("", ""));
+ }
+
+ boolean set() {
+ if (!check()) {
+ return false;
+ }
+ if (primaryOptionCount == 0 && !retainOption) {
+ // No settings or -retain, so this is a query
+ EditorSetting retained = EditorSetting.fromPrefs(prefs);
+ if (retained != null) {
+ // retained editor is set
+ hard("/set editor -retain %s", format(retained));
+ }
+ if (retained == null || !retained.equals(editor)) {
+ // editor is not retained or retained is different from set
+ hard("/set editor %s", format(editor));
+ }
+ return true;
+ }
+ if (retainOption && deleteOption) {
+ EditorSetting.removePrefs(prefs);
+ }
+ install();
+ if (retainOption && !deleteOption) {
+ editor.toPrefs(prefs);
+ fluffmsg("jshell.msg.set.editor.retain", format(editor));
+ }
+ return true;
+ }
+
+ private boolean check() {
+ if (!checkOptionsAndRemainingInput(at)) {
+ return false;
+ }
+ if (primaryOptionCount > 1) {
+ errormsg("jshell.err.default.option.or.program", at.whole());
+ return false;
+ }
+ if (waitOption && !hasCommand) {
+ errormsg("jshell.err.wait.applies.to.external.editor", at.whole());
+ return false;
+ }
+ return true;
+ }
+
+ private void install() {
+ if (hasCommand) {
+ editor = new EditorSetting(command, waitOption);
+ } else if (defaultOption) {
+ editor = BUILT_IN_EDITOR;
+ } else if (deleteOption) {
+ configEditor();
+ } else {
+ return;
+ }
+ fluffmsg("jshell.msg.set.editor.set", format(editor));
+ }
+
+ private String format(EditorSetting ed) {
+ if (ed == BUILT_IN_EDITOR) {
+ return "-default";
+ } else {
+ Stream<String> elems = Arrays.stream(ed.cmd);
+ if (ed.wait) {
+ elems = Stream.concat(Stream.of("-wait"), elems);
+ }
+ return elems.collect(joining(" "));
+ }
+ }
+ }
+
+ // The sub-command: /set start <start-file>
+ boolean setStart(ArgTokenizer at) {
+ at.allowedOptions("-default", "-none", "-retain");
+ String fn = at.next();
if (!checkOptionsAndRemainingInput(at)) {
return false;
}
boolean defaultOption = at.hasOption("-default");
- boolean waitOption = at.hasOption("-wait");
- if (prog != null) {
- if (defaultOption) {
- errormsg("jshell.err.default.option.or.program", at.whole());
+ boolean noneOption = at.hasOption("-none");
+ boolean retainOption = at.hasOption("-retain");
+ boolean hasFile = fn != null;
+
+ int argCount = (defaultOption ? 1 : 0) + (noneOption ? 1 : 0) + (hasFile ? 1 : 0);
+ if (argCount > 1) {
+ errormsg("jshell.err.option.or.filename", at.whole());
+ return false;
+ }
+ if (argCount == 0 && !retainOption) {
+ // no options or filename, show current setting
+ showSetStart();
+ return true;
+ }
+ if (hasFile) {
+ String init = readFile(fn, "/set start");
+ if (init == null) {
return false;
}
- editor = ed.toArray(new String[ed.size()]);
- editorWait = waitOption;
- fluffmsg("jshell.msg.set.editor.set", prog);
+ startup = init;
} else if (defaultOption) {
- if (waitOption) {
- errormsg("jshell.err.wait.applies.to.external.editor", at.whole());
- return false;
- }
- editor = null;
- } else if (argsRequired) {
- errormsg("jshell.err.set.editor.arg");
- return false;
+ startup = DEFAULT_STARTUP;
+ } else if (noneOption) {
+ startup = "";
+ }
+ if (retainOption) {
+ // retain startup setting
+ prefs.put(STARTUP_KEY, startup);
}
return true;
}
- // The sub-command: /set start <start-file>
- boolean setStart(String cmd, ArgTokenizer at, boolean argsRequired) {
- at.allowedOptions("-default", "-none");
- String fn = at.next();
- if (!checkOptionsAndRemainingInput(at)) {
- return false;
+ void showSetStart() {
+ String retained = prefs.get(STARTUP_KEY, null);
+ if (retained != null) {
+ showSetStart(true, retained);
}
- int argCount = at.optionCount() + ((fn != null) ? 1 : 0);
- if (argCount > 1 || argsRequired && argCount == 0) {
- errormsg("jshell.err.option.or.filename", at.whole());
- return false;
+ if (retained == null || !startup.equals(retained)) {
+ showSetStart(false, startup);
}
- if (fn != null) {
- String init = readFile(fn, cmd + " start");
- if (init == null) {
- return false;
- } else {
- startup = init;
- return true;
- }
- } else if (at.hasOption("-default")) {
- startup = DEFAULT_STARTUP;
- } else if (at.hasOption("-none")) {
- startup = "";
+ }
+
+ void showSetStart(boolean isRetained, String start) {
+ String cmd = "/set start" + (isRetained ? " -retain " : " ");
+ String stset;
+ if (start.equals(DEFAULT_STARTUP)) {
+ stset = cmd + "-default";
+ } else if (start.isEmpty()) {
+ stset = cmd + "-none";
+ } else {
+ stset = prefix("startup.jsh:\n" + start + "\n" + cmd + "startup.jsh", "");
}
- return true;
+ hard(stset);
}
boolean cmdClasspath(String arg) {
@@ -1559,17 +1708,18 @@
Command[] matches = commands.values().stream()
.filter(c -> c.command.startsWith(subject))
.toArray(size -> new Command[size]);
- at.mark();
- String sub = at.next();
- if (sub != null && matches.length == 1) {
+ if (matches.length == 1) {
String cmd = matches[0].command;
- switch (cmd) {
- case "/set":
- at.rewind();
- return printSubCommandHelp(cmd, at, "help.set.", SET_SUBCOMMANDS);
- case "/retain":
- at.rewind();
- return printSubCommandHelp(cmd, at, "help.retain.", RETAIN_SUBCOMMANDS);
+ if (cmd.equals("/set")) {
+ // Print the help doc for the specified sub-command
+ String which = subCommand(cmd, at, SET_SUBCOMMANDS);
+ if (which == null) {
+ return false;
+ }
+ if (!which.equals("_blank")) {
+ hardrb("help.set." + which);
+ return true;
+ }
}
}
if (matches.length > 0) {
@@ -1813,7 +1963,7 @@
String src = sb.toString();
Consumer<String> saveHandler = new SaveHandler(src, srcSet);
Consumer<String> errorHandler = s -> hard("Edit Error: %s", s);
- if (editor == null) {
+ if (editor == BUILT_IN_EDITOR) {
try {
EditPad.edit(errorHandler, src, saveHandler);
} catch (RuntimeException ex) {
@@ -1822,8 +1972,8 @@
return false;
}
} else {
- ExternalEditor.edit(editor, errorHandler, src, saveHandler, input,
- editorWait, this::hardrb);
+ ExternalEditor.edit(editor.cmd, errorHandler, src, saveHandler, input,
+ editor.wait, this::hardrb);
}
return true;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java Thu Oct 27 09:42:08 2016 -0700
@@ -37,5 +37,11 @@
void fluffmsg(String messageKey, Object... args);
+ void hard(String format, Object... args);
+
+ void hardmsg(String messageKey, Object... args);
+
void errormsg(String messageKey, Object... args);
+
+ boolean showFluff();
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Oct 27 09:42:08 2016 -0700
@@ -52,12 +52,17 @@
jshell.err.no.such.command.or.snippet.id = No such command or snippet id: {0}
jshell.err.command.ambiguous = Command: ''{0}'' is ambiguous: {1}
-jshell.err.set.editor.arg = The ''/set editor'' command requires a path argument
jshell.msg.set.editor.set = Editor set to: {0}
+jshell.msg.set.editor.retain = Editor setting retained: {0}
jshell.err.cant.launch.editor = Cannot launch editor -- unexpected exception: {0}
jshell.msg.try.set.editor = Try /set editor to use external editor.
jshell.msg.press.return.to.leave.edit.mode = Press return to leave edit mode.
-jshell.err.wait.applies.to.external.editor = -wait applies to external editors, cannot be used with -default
+jshell.err.wait.applies.to.external.editor = -wait applies to external editors
+
+jshell.err.setting.to.retain.must.be.specified = The setting to retain must be specified -- {0}
+jshell.msg.set.show.mode.settings = \nTo show mode settings use ''/set prompt'', ''/set truncation'', ...\n\
+or use ''/set mode'' followed by the feedback mode name.
+jshell.err.continuation.prompt.required = Continuation prompt required -- {0}
jshell.msg.try.command.without.args = Try ''{0}'' without arguments.
jshell.msg.no.active = There are no active definitions.
@@ -104,12 +109,10 @@
jshell.err.mode.name = Expected a feedback mode name: {0}
jshell.err.missing.mode = Missing the feedback mode -- {0}
jshell.err.field.name = Expected a field name: {0} -- {1}
-jshell.err.missing.field = Missing the field name -- {0}
jshell.err.mode.unknown = No feedback mode named: {0} -- {1}
jshell.err.feedback.does.not.match.mode = Does not match any current feedback mode: {0} -- {1}
jshell.err.feedback.ambiguous.mode = Matches more then one current feedback mode: {0} -- {1}
-jshell.err.feedback.expected.format = Expected format missing -- {0}
jshell.err.feedback.must.be.quoted = Format ''{0}'' must be quoted -- {1}
jshell.err.feedback.not.a.valid.selector = Not a valid selector ''{0}'' in ''{1}'' -- {2}
jshell.err.feedback.multiple.sections = Selector kind in multiple sections of selector list ''{0}'' in ''{1}'' -- {2}
@@ -117,22 +120,25 @@
jshell.msg.feedback.new.mode = Created new feedback mode: {0}
jshell.msg.feedback.mode = Feedback mode: {0}
-jshell.msg.feedback.mode.following = The feedback mode should be one of the following:
+jshell.msg.feedback.mode.following = Available feedback modes:
+jshell.msg.feedback.retained.mode.following = Retained feedback modes:
+jshell.err.mode.creation = To create a new mode either the -command or the -quiet option must be used -- {0}
+jshell.err.mode.exists = Mode to be created already exists: {0} -- {1}
jshell.err.truncation.expected.length = Expected truncation length -- {0}
jshell.err.truncation.length.not.integer = Truncation length must be an integer: {0} -- {1}
jshell.err.not.valid.with.predefined.mode = Not valid with a predefined mode: {0} -- {1}
jshell.err.retained.feedback.mode.must.be.retained.or.predefined = \
-''/retain feedback <mode>'' requires that <mode> is predefined or has been retained with ''/retain mode'' -- {0}
+''/set feedback -retain <mode>'' requires that <mode> is predefined or has been retained with ''/set mode -retain'' -- {0}
jshell.err.unknown.option = Unknown option: {0} -- {1}
-jshell.err.default.option.or.program = Specify -default option or program, not both -- {0}
-jshell.err.option.or.filename = Specify either one option or a startup file name -- {0}
+jshell.err.default.option.or.program = Specify -default option, -delete option, or program -- {0}
+jshell.err.option.or.filename = Specify no more than one of -default, -none, or a startup file name -- {0}
jshell.err.unexpected.at.end = Unexpected arguments at end of command: {0} -- {1}
jshell.err.conflicting.options = Conflicting options -- {0}
jshell.err.cannot.delete.current.mode = The current feedback mode ''{0}'' cannot be deleted, use ''/set feedback'' first -- {1}
-jshell.err.cannot.delete.retained.mode = The retained feedback mode ''{0}'' cannot be deleted, use ''/retain feedback'' first -- {1}
+jshell.err.cannot.delete.retained.mode = The retained feedback mode ''{0}'' cannot be deleted, use ''/set feedback -retain'' first -- {1}
jshell.err.may.not.specify.options.and.snippets = Options and snippets must not both be used: {0}
jshell.err.no.such.snippets = No such snippet: {0}
jshell.err.the.snippet.cannot.be.used.with.this.command = This command does not accept the snippet ''{0}'' : {1}
@@ -374,36 +380,20 @@
The contents of the specified <file> become the default start-up snippets and commands.\n\n\
/set feedback <mode>\n\t\
Set the feedback mode describing displayed feedback for entered snippets and commands.\n\n\
-/set mode <mode> [<old-mode>] [-command|-quiet|-delete]\n\t\
+/set mode <mode> [<old-mode>] -command|-quiet|-delete\n\t\
Create or update a user-defined feedback mode, optionally copying from an existing mode.\n\n\
/set prompt <mode> "<prompt>" "<continuation-prompt>"\n\t\
Set the displayed prompts for a given feedback mode.\n\n\
/set truncation <mode> <length> <selector>...\n\t\
- Set the maximum length of a displayed value\n\
+ Set the maximum length of a displayed value.\n\n\
/set format <mode> <field> "<format>" <selector>...\n\t\
- Configure a feedback mode by setting the format of a field when the selector matchs.\n\n\
+ Configure a feedback mode by setting the format of a field when the selector matches.\n\n\
+/set\n\t\
+ Show editor, start, and feedback settings as /set commands.\n\t\
+ To show the settings of any of the above, omit the set value.\n\n\
To get more information about one of these forms, use /help with the form specified.\n\
For example: /help /set format
-help.retain.summary = retain jshell configuration information for subsequent sessions
-help.retain.args = editor|start|feedback|mode
-help.retain =\
-Retain jshell configuration information for future invocations of the jshell tool,\n\
-including: the external editor to use, the start-up definitions to use, the\n\
-configuration of a feedback mode, or the feedback mode to use.\n\
-\n\
-/retain editor [<command> <optional-arg>...]\n\t\
- Specify the command to launch for the /edit command.\n\t\
- The <command> is an operating system dependent string.\n\n\
-/retain start [<file>]\n\t\
- The contents of the specified <file> become the default start-up snippets and commands.\n\n\
-/retain feedback [<mode>]\n\t\
- Set the feedback mode describing displayed feedback for entered snippets and commands.\n\n\
-/retain mode <mode>\n\t\
- Create a user-defined feedback mode, optionally copying from an existing mode.\n\n\
-To get more information about one of these forms, use /help with the form specified.\n\
-For example: /help /retain feedback
-
help.quest.summary = get information about jshell
help.quest.args = [<command>|<subject>]
help.quest =\
@@ -467,11 +457,24 @@
possible fully qualified names based on the content of the specified classpath.\n\t\t\
The "<fix-shortcut>" is either Alt-F1 or Alt-Enter, depending on the platform.
+help.set._retain = \
+The '-retain' option saves a setting so that it is used in future sessions.\n\
+The -retain option can be used on the following forms of /set:\n\n\t\
+/set editor -retain\n\t\
+/set start -retain\n\t\
+/set feedback -retain\n\t\
+/set mode -retain\n\n\
+See these commands for more detail -- for example /help /set editor
+
help.set.format = \
-Set the format for reporting a snippet event.\n\
+Set the format for reporting a snippet event:\n\
\n\t\
/set format <mode> <field> "<format>" <selector>...\n\
\n\
+Show the format settings:\n\
+\n\t\
+/set format [<mode> [<field>]]\n\
+\n\
Where <mode> is the name of a previously defined feedback mode -- see '/help /set mode'.\n\
Where <field> is the name of context-specific format to define.\n\
Where <format> is a quoted string which will be the value of the field if one of\n\
@@ -541,13 +544,24 @@
/set format myformat action 'Update replaced' replaced-update\n\t\
/set format myformat display '{pre}{action} class {name}{post}' class-ok\n\t\
/set format myformat display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update\n\n\
-Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n
+Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n\
+\n\
+The form without <format> shows the current format settings.\n\
+When the <mode> is specified only the format settings for that mode are shown.\n\
+When both the <mode> and <field> are specified only the format settings for that\n\
+mode and field are shown. Example:\n\t\
+/set format myformat\n\
+shows the format settings for the mode myformat\n
help.set.truncation = \
-Set the max length a displayed value.\n\
+Set the max length of a displayed value:\n\
\n\t\
/set truncation <mode> <length> <selector>...\n\
\n\
+Show the current truncation settings:\n\
+\n\t\
+/set truncation [<mode>]\n\
+\n\
Where <mode> is the name of a previously defined feedback mode -- see '/help /set mode'.\n\
Where <length> is an unsigned integer representing a maximum length.\n\
Where <selector> is only needed if you wish to fine-tune value truncation length\n\
@@ -571,63 +585,151 @@
/set trunc mymode 80\n\t\
/set truncation mymode 45 expression\n\t\
/set truncation mymode 0 vardecl-modified,replaced\n\n\
-Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n
+Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n\
+\n\
+The form without <length> shows the truncation settings.\n\
+When the <mode> is specified only the truncation settings for that mode are shown.\n\
+Example:\n\t\
+/set truncation myformat\n\
+shows the truncation settings for the mode myformat\n
help.set.feedback = \
-Set the feedback mode describing displayed feedback for entered snippets and commands.\n\
+Set the feedback mode describing displayed feedback for entered snippets and commands:\n\
+\n\t\
+/set feedback [-retain] <mode>\n\
+\n\
+Retain the current feedback mode for future sessions:\n\
\n\t\
-/set feedback <mode>\n\
+/set feedback -retain\n\
+\n\
+Show the feedback mode and list available modes:\n\
+\n\t\
+/set feedback\n\
\n\
Where <mode> is the name of a previously defined feedback mode.\n\
You may use just enough letters to make it unique.\n\
User-defined modes can be added, see '/help /set mode'\n\
-Currently defined feedback modes:\n
+\n\
+When the -retain option is used, the setting will be used in this and future\n\
+runs of the jshell tool.\n\
+\n\
+The form without <mode> or -retain displays the current feedback mode and available modes.\n
help.set.mode = \
-Create a user-defined feedback mode, optionally copying from an existing mode.\n\
+Create a user-defined feedback mode, optionally copying from an existing mode:\n\
\n\t\
/set mode <mode> [<old-mode>] [-command|-quiet|-delete]\n\
+Retain a user-defined feedback mode for future sessions:\n\
+\n\t\
+/set mode -retain <mode>\n\
+\n\
+Delete a user-defined feedback mode:\n\
+\n\t\
+/set mode -delete [-retain] <mode>\n\
+\n\
+Show feedback mode settings:\n\
+\n\t\
+/set mode [<mode>]\n\
\n\
Where <new-mode> is the name of a mode you wish to create.\n\
Where <old-mode> is the name of a previously defined feedback mode.\n\
If <old-mode> is present, its settings are copied to the new mode.\n\
'-command' vs '-quiet' determines if informative/verifying command feedback is displayed.\n\
\n\
-Once the new mode is created, use '/set format' and '/set prompt' to configure it.\n\
-Use '/set feedback' to use the new mode.\n\
+Once the new mode is created, use '/set format', '/set prompt' and '/set truncation'\n\
+to configure it. Use '/set feedback' to use the new mode.\n\
+\n\
+When the -retain option is used, the mode (including its component prompt, format,\n\
+and truncation settings) will be used in this and future runs of the jshell tool.\n\
+When both -retain and -delete are used, the mode is deleted from the current\n\
+and future sessions.\n\
+\n\
+The form without options shows the mode settings.\n\
+When the <mode> is specified only the mode settings for that mode are shown.\n\
+Note: the settings for the mode include the settings for prompt, format, and\n\
+truncation -- so these are displayed as well.\n\
+Example:\n\t\
+/set mode myformat\n\
+shows the mode, prompt, format, and truncation settings for the mode myformat\n
help.set.prompt = \
-Set the prompts. Both the normal prompt and the continuation-prompt must be set.\n\
+Set the prompts. Both the normal prompt and the continuation-prompt must be set:\n\
\n\t\
/set prompt <mode> \"<prompt>\" \"<continuation-prompt>\"\n\
\n\
+Show the normal prompt and the continuation-prompts:\n\
+\n\t\
+/set prompt [<mode>]\n\
+\n\
Where <mode> is the name of a previously defined feedback mode.\n\
Where <prompt> and <continuation-prompt> are quoted strings printed as input prompts;\n\
Both may optionally contain '%s' which will be substituted with the next snippet id --\n\
note that what is entered may not be assigned that id, for example it may be an error or command.\n\
-The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n
+The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n\
+\n\
+The form without <prompt> shows the currently set prompts.\n\
+When the <mode> is specified only the prompts for that mode are shown.\n\
+Example:\n\t\
+/set prompt myformat\n\
+shows the prompts set for the mode myformat\n
help.set.editor =\
-Specify the command to launch for the /edit command.\n\
+Specify the command to launch for the /edit command:\n\
+\n\t\
+/set editor [-retain] [-wait] <command>\n\
+\n\t\
+/set editor [-retain] -default\n\
\n\t\
-/set editor [-wait] <command>|-default\n\
+/set editor [-retain] -delete\n\
+\n\
+Retain the current editor setting for future sessions:\n\
+\n\t\
+/set editor -retain\n\
+\n\
+Show the command to launch for the /edit command:\n\
+\n\t\
+/set editor\n\
\n\
The <command> is an operating system dependent string.\n\
The <command> may include space-separated arguments (such as flags)\n\n\
If the -default option is specified, the built-in default editor will be used.\n\n\
-Otherwise an external editor should be specified in <command>. When <command>\n\
+If the -delete option is specified, previous settings are ignored -- the editor\n\
+settings are initialized as when starting the jshell tool. Specifically, if there\n\
+is a retained setting it is used (unless both -retain and -delete are specified --\n\
+which deletes the retained setting), if one of these environment variables is set\n\
+it will be used: JSHELLEDITOR, VISUAL, or EDITOR (in that order). Otherwise the\n\
+built-in default editor will be used.\n\n\
+If <command> is specified, it will be used as the external editor. The <command>\n\
+consists of the program and zero or more program arguments. When <command>\n\
is used, the temporary file to edit will be appended as the last argument.\n\
Normally, edit mode will last until the external editor exits. Some external editors\n\
will exit immediately (for example, if the edit window exists) either external editor\n\
flags should be used to prevent immediate exit, or the -wait option should be used to\n\
prompt the user to indicate when edit mode should end.\n\n\
Note: while in edit mode no command inputs are seen. After leaving edit mode changes\n\
-to the edited snippets are not seen.
+to the edited snippets are not seen.\n\
+\n\
+When the -retain option is used, the setting will be used in this and future\n\
+runs of the jshell tool.\n\
+\n\
+The form without <command> or options shows the editor setting.\n
help.set.start =\
-Set the start-up configuration -- a sequence of snippets and commands read at start-up.\n\
+Set the start-up configuration -- a sequence of snippets and commands read at start-up:\n\
+\n\t\
+/set start [-retain] <file>\n\
+\n\t\
+/set start [-retain] -default\n\
\n\t\
-/set start <file>|-default|-none\n\
+/set start [-retain] -none\n\
+\n\
+Retain the start-up configuration for future sessions:\n\
+\n\t\
+/set start -retain\n\
+\n\
+Show the start-up setting:\n\
+\n\t\
+/set start\n\
\n\
The contents of the specified <file> become the start-up snippets and commands used\n\
when the /reset or /reload commands are used in this session.\n\
@@ -637,59 +739,14 @@
or commands will be used.\n\
This command is good for testing the start-up settings. To retain them for future\n\
runs of the jshell tool use the command:\n\t\
-/retain start\n
-
-help.retain.feedback = \
-Retain which feedback mode to use for displayed feedback for entered snippets and commands.\n\
-This feedback mode will be used in this and future sessions of the jshell tool.\n\
-\n\t\
-/retain feedback [<mode>]\n\
-\n\
-Where <mode> is the name of a previously defined feedback mode.\n\
-You may use just enough letters to make it unique.\n\
-If the <mode> is not specified, this command retains the current mode (as set\n\
-with the most recent /set feedback or /retain feedback command.)\n\
-
-help.retain.mode = \
-Retain the existence and configuration of a user-defined feedback mode.\n\
-This mode will be available in this and future sessions of the jshell tool.
-\n\t\
-/retain mode <mode>\n\
+/set start -retain\n\
\n\
-Where <mode> is the name of a mode you wish to retain.\n\
-The <mode> must previously have been created with /set mode and\n\
-configured as desired with /set prompt, /set format, and /set truncation.\n
-
-help.retain.editor =\
-Retain the command to launch for the /edit command. This command will be invoked when\n\
-the /edit command is used in this and future sessions of the jshell tool.\n\
-\n\t\
-/retain editor [<command>|-default]\n\
+When the -retain option is used, the setting will be used in this and future\n\
+runs of the jshell tool.\n\
\n\
-If <command> is specified, it is an operating system dependent string which\n\
-may include space-separated arguments (such as flags). When /edit is used, the\n\
-temporary file to edit will be appended as the last argument.\n\
-If instead the -default option is specified, the built-in default editor will be used.\n\
-If neither is specified, the editor set in the last /set editor or /retain editor\n\
-command will be used.\n\
-The editor will be retained and used in this and future runs of the jshell tool.
-
-help.retain.start =\
-Retain the start-up configuration -- a sequence of snippets and commands read\n\
-at start-up.\n\
-\n\t\
-/retain start [<file>|-default|-none]\n\
-\n\
-If <file> is specified, the contents of the specified <file> become the\n\
-start-up snippets\n\
-and commands.\n\
-If instead the -default option is specified, the predefined start-up snippets\n\
-will be the start-up.\n\
-If the -none option is used, the start-up will be empty -- no start-up snippets\n\
-or commands will be used.\n\
-If none of these is specified, the start-up is the last specified in a\n\
-''/set start'' or ''/retain start'' command.\n\
-The start-up will be retained and used when the jshell tool is started or reset
+The form without <file> or options shows the start-up setting.\n\
+Note: if the start-up was last set from a file, this is shown with the\n\
+contents of the file followed by a 'set start' command.
startup.feedback = \
/set mode verbose -command \n\
@@ -773,6 +830,8 @@
\n\
/set mode silent -quiet \n\
/set prompt silent '-> ' '>> ' \n\
+/set truncation silent 80\n\
+/set truncation silent 1000 varvalue,expression\n\
/set format silent pre '| ' \n\
/set format silent post '%n' \n\
/set format silent errorpre '| ' \n\
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Thu Oct 27 09:42:08 2016 -0700
@@ -28,6 +28,7 @@
import jdk.jshell.spi.ExecutionControl;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.io.InterruptedIOException;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -167,6 +168,10 @@
* user input cannot use {@code System.in} as the input stream for
* the remote process.
* <p>
+ * The {@code read} method of the {@code InputStream} may throw the {@link InterruptedIOException}
+ * to signal the user canceled the input. The currently running snippet will be automatically
+ * {@link JShell#stop() stopped}.
+ * <p>
* The default, if this is not set, is to provide an empty input stream
* -- {@code new ByteArrayInputStream(new byte[0])}.
*
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java Thu Oct 27 09:42:08 2016 -0700
@@ -42,7 +42,7 @@
@Override
public synchronized int read() throws IOException {
- if (start == end) {
+ if (start == end && !closed) {
inputNeeded();
}
while (start == end) {
@@ -62,6 +62,32 @@
}
}
+ @Override
+ public synchronized int read(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ int c = read();
+ if (c == -1) {
+ return -1;
+ }
+ b[off] = (byte)c;
+
+ int totalRead = 1;
+ while (totalRead < len && start != end) {
+ int r = read();
+ if (r == (-1))
+ break;
+ b[off + totalRead++] = (byte) r;
+ }
+ return totalRead;
+ }
+
protected void inputNeeded() throws IOException {}
private synchronized void write(int b) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java Thu Oct 27 09:42:08 2016 -0700
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
@@ -42,6 +43,7 @@
import com.sun.jdi.VirtualMachine;
import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
/**
@@ -54,6 +56,10 @@
*/
public class Util {
+ private static final int TAG_DATA = 0;
+ private static final int TAG_CLOSED = 1;
+ private static final int TAG_EXCEPTION = 2;
+
// never instanciated
private Util() {}
@@ -131,6 +137,25 @@
inputSignal.write('1');
inputSignal.flush();
}
+ @Override
+ public synchronized int read() throws IOException {
+ int tag = super.read();
+ switch (tag) {
+ case TAG_DATA: return super.read();
+ case TAG_CLOSED: close(); return -1;
+ case TAG_EXCEPTION:
+ int len = (super.read() << 0) + (super.read() << 8) + (super.read() << 16) + (super.read() << 24);
+ byte[] message = new byte[len];
+ for (int i = 0; i < len; i++) {
+ message[i] = (byte) super.read();
+ }
+ throw new IOException(new String(message, "UTF-8"));
+ case -1:
+ return -1;
+ default:
+ throw new IOException("Internal error: unrecognized message tag: " + tag);
+ }
+ }
};
inputs.put(e.getKey(), inputPipe.createOutput());
e.getValue().accept(inputPipe);
@@ -163,6 +188,7 @@
public static ExecutionControl remoteInputOutput(InputStream input, OutputStream output,
Map<String, OutputStream> outputStreamMap, Map<String, InputStream> inputStreamMap,
BiFunction<ObjectInput, ObjectOutput, ExecutionControl> factory) throws IOException {
+ ExecutionControl[] result = new ExecutionControl[1];
Map<String, OutputStream> augmentedStreamMap = new HashMap<>(outputStreamMap);
ObjectOutput commandOut = new ObjectOutputStream(Util.multiplexingOutputStream("$command", output));
for (Entry<String, InputStream> e : inputStreamMap.entrySet()) {
@@ -172,7 +198,28 @@
@Override
public void write(int b) throws IOException {
//value ignored, just a trigger to read from the input
- inTarget.write(in.read());
+ try {
+ int r = in.read();
+ if (r == (-1)) {
+ inTarget.write(TAG_CLOSED);
+ } else {
+ inTarget.write(new byte[] {TAG_DATA, (byte) r});
+ }
+ } catch (InterruptedIOException exc) {
+ try {
+ result[0].stop();
+ } catch (ExecutionControlException ex) {
+ debug(ex, "$" + e.getKey() + "-input-requested.write");
+ }
+ } catch (IOException exc) {
+ byte[] message = exc.getMessage().getBytes("UTF-8");
+ inTarget.write(TAG_EXCEPTION);
+ inTarget.write((message.length >> 0) & 0xFF);
+ inTarget.write((message.length >> 8) & 0xFF);
+ inTarget.write((message.length >> 16) & 0xFF);
+ inTarget.write((message.length >> 24) & 0xFF);
+ inTarget.write(message);
+ }
}
});
}
@@ -180,7 +227,7 @@
OutputStream commandInTarget = commandIn.createOutput();
augmentedStreamMap.put("$command", commandInTarget);
new DemultiplexInput(input, augmentedStreamMap, Arrays.asList(commandInTarget)).start();
- return factory.apply(new ObjectInputStream(commandIn), commandOut);
+ return result[0] = factory.apply(new ObjectInputStream(commandIn), commandOut);
}
/**
@@ -198,4 +245,13 @@
}
}
+ /**
+ * Log a serious unexpected internal exception.
+ *
+ * @param ex the exception
+ * @param where a description of the context of the exception
+ */
+ private static void debug(Throwable ex, String where) {
+ // Reserved for future logging
+ }
}
--- a/langtools/test/Makefile Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/Makefile Thu Oct 27 09:42:08 2016 -0700
@@ -157,11 +157,6 @@
-refvmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH)
endif
-ifeq ($(ARCH_DATA_MODEL),32)
- # Set the GC options for test vms
- JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC
- JTREG_OPTIONS += $(JTREG_GC_OPTION)
-endif
# Set the max memory for jtreg target test JVMs
JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m
JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
@@ -256,6 +251,17 @@
JCK_COMPILER_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-compiler
JCK_RUNTIME_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-runtime-Xcompile
+# Is the test JVM 32-bit?
+DATA_MODEL := \
+ $(shell $(JT_JAVA)/bin/java -XshowSettings:properties -version 2>&1 | \
+ grep 'sun\.arch\.data\.model' | \
+ awk '{print $$3}')
+ifeq ($(DATA_MODEL), 32)
+ # Set the GC options for test vms having a smaller address space
+ JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC
+ JTREG_OPTIONS += $(JTREG_GC_OPTION)
+endif
+
# Default make rule -- warning, may take a while
all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary
@echo "Testing completed successfully"
--- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756
+ * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8151921
* @summary Verify that the output has the right javascript.
* @author jamieh
* @library ../lib
@@ -54,11 +54,12 @@
checkOutput("index.html", true,
"<script type=\"text/javascript\">\n"
- + " targetPage = \"\" + window.location.search;\n"
- + " if (targetPage != \"\" && targetPage != \"undefined\")\n"
- + " targetPage = targetPage.substring(1);\n"
- + " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))\n"
- + " targetPage = \"undefined\";\n"
+ + " tmpTargetPage = \"\" + window.location.search;\n"
+ + " if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n"
+ + " tmpTargetPage = tmpTargetPage.substring(1);\n"
+ + " if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n"
+ + " tmpTargetPage = \"undefined\";\n"
+ + " targetPage = tmpTargetPage;\n"
+ " function validURL(url) {\n"
+ " try {\n"
+ " url = decodeURIComponent(url);\n"
--- a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985
+ * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985 8151921
* @summary Verify that the output has the right javascript.
* @author jamieh
* @library ../lib
@@ -54,11 +54,12 @@
checkOutput("index.html", true,
"<script type=\"text/javascript\">\n"
- + " targetPage = \"\" + window.location.search;\n"
- + " if (targetPage != \"\" && targetPage != \"undefined\")\n"
- + " targetPage = targetPage.substring(1);\n"
- + " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))\n"
- + " targetPage = \"undefined\";\n"
+ + " tmpTargetPage = \"\" + window.location.search;\n"
+ + " if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n"
+ + " tmpTargetPage = tmpTargetPage.substring(1);\n"
+ + " if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n"
+ + " tmpTargetPage = \"undefined\";\n"
+ + " targetPage = tmpTargetPage;\n"
+ " function validURL(url) {\n"
+ " try {\n"
+ " url = decodeURIComponent(url);\n"
--- a/langtools/test/jdk/javadoc/tool/modules/FilterOptions.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/javadoc/tool/modules/FilterOptions.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8159305
+ * @bug 8159305 8167383
* @summary Tests elements filtering options
* @modules
* jdk.javadoc/jdk.javadoc.internal.api
@@ -73,6 +73,10 @@
"--module", "m1", "--show-module-contents", "api");
checkModuleMode("API");
+ checkModulesSpecified("m1");
+ checkModulesIncluded("m1");
+ checkPackagesIncluded("pub");
+ checkPackagesNotIncluded("pro", "pqe");
}
@Test
@@ -81,6 +85,10 @@
"--module", "m1", "--show-module-contents", "all");
checkModuleMode("ALL");
+ checkModulesSpecified("m1");
+ checkModulesIncluded("m1");
+ checkPackagesIncluded("pub", "pqe");
+ checkPackagesNotIncluded("pro");
}
@Test
@@ -92,6 +100,7 @@
checkModulesSpecified("m1");
checkModulesIncluded("m1");
checkPackagesIncluded("pub");
+ checkPackagesNotIncluded("pqe", "pro");
checkTypesIncluded("pub.A", "pub.A.ProtectedNested", "pub.A.PublicNested");
}
@@ -102,9 +111,10 @@
"--show-packages", "all");
checkModulesSpecified("m1");
checkModulesIncluded("m1");
- checkPackagesIncluded("pub", "pro");
+ checkPackagesIncluded("pub", "pqe", "pro");
checkTypesIncluded("pub.A", "pub.A.ProtectedNested", "pub.A.PublicNested",
+ "pqe.A", "pqe.A.ProtectedNested", "pqe.A.PublicNested",
"pro.A", "pro.A.ProtectedNested", "pro.A.PublicNested");
}
@@ -221,6 +231,7 @@
checkModulesSpecified("m1");
checkModulesIncluded("m1");
checkPackagesIncluded("pub");
+ checkPackagesNotIncluded("pqe", "pro");
checkTypesIncluded("pub.A", "pub.A.PublicNested");
checkMembers(Visibility.PUBLIC);
@@ -235,6 +246,7 @@
checkModulesSpecified("m1");
checkModulesIncluded("m1");
checkPackagesIncluded("pub");
+ checkPackagesNotIncluded("pqe", "pro");
checkTypesIncluded("pub.A", "pub.A.ProtectedNested", "pub.A.PublicNested");
checkMembers(Visibility.PROTECTED);
@@ -250,6 +262,7 @@
checkModulesSpecified("m1");
checkModulesIncluded("m1");
checkPackagesIncluded("pub");
+ checkPackagesNotIncluded("pqe", "pro");
checkTypesIncluded("pub.A", "pub.A.ProtectedNested", "pub.A.PublicNested");
checkMembers(Visibility.PROTECTED);
@@ -264,10 +277,10 @@
checkModuleMode("ALL");
checkModulesSpecified("m1");
checkModulesIncluded("m1");
- checkPackagesIncluded("pub");
- checkPackagesIncluded("pro");
+ checkPackagesIncluded("pub", "pqe", "pro");
checkTypesIncluded("pub.B", "pub.B.Nested", "pub.B.ProtectedNested", "pub.B.PublicNested",
"pub.A", "pub.A.Nested", "pub.A.ProtectedNested", "pub.A.PublicNested",
+ "pqe.A", "pqe.A.Nested", "pqe.A.ProtectedNested", "pqe.A.PublicNested",
"pro.B", "pro.B.Nested", "pro.B.ProtectedNested", "pro.B.PublicNested",
"pro.A", "pro.A.Nested", "pro.A.ProtectedNested", "pro.A.PublicNested");
@@ -283,12 +296,13 @@
checkModuleMode("ALL");
checkModulesSpecified("m1");
checkModulesIncluded("m1");
- checkPackagesIncluded("pub");
- checkPackagesIncluded("pro");
+ checkPackagesIncluded("pub", "pqe", "pro");
checkTypesIncluded("pub.B", "pub.B.PrivateNested", "pub.B.Nested", "pub.B.ProtectedNested",
"pub.B.PublicNested",
"pub.A", "pub.A.PrivateNested", "pub.A.Nested", "pub.A.ProtectedNested",
"pub.A.PublicNested",
+ "pqe.A", "pqe.A.PrivateNested", "pqe.A.Nested", "pqe.A.ProtectedNested",
+ "pqe.A.PublicNested",
"pro.B", "pro.B.PrivateNested", "pro.B.Nested", "pro.B.ProtectedNested",
"pro.B.PublicNested",
"pro.A", "pro.A.PrivateNested", "pro.A.Nested", "pro.A.ProtectedNested",
@@ -365,8 +379,17 @@
.classes(createClass("pub", "B", false))
.classes(createClass("pro", "A", true))
.classes(createClass("pro", "B", false))
+ .classes(createClass("pqe", "A", true))
.exports("pub")
+ .exportsTo("pqe", "m2")
.write(src);
+
+ ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
+ mb2.comment("The second module")
+ .classes(createClass("m2pub", "A", true))
+ .requires("m1")
+ .write(src);
+
return src.toString();
}
--- a/langtools/test/jdk/javadoc/tool/modules/Modules.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java Thu Oct 27 09:42:08 2016 -0700
@@ -222,7 +222,10 @@
.classes("package pkg2; /** @see pkg1.A */ public class B { }")
.write(src);
+ Path out = base.resolve("out-1");
+ Files.createDirectories(out);
String log = new JavadocTask(tb)
+ .outdir(out)
.options("--module-source-path", src.toString(),
"--module-path", modulePath.toString(),
"--module", "m2")
@@ -233,7 +236,10 @@
throw new Exception("Error not found");
}
+ out = base.resolve("out-2");
+ Files.createDirectories(out);
new JavadocTask(tb)
+ .outdir(out)
.options("--module-source-path", src.toString(),
"--module-path", modulePath.toString(),
"--add-modules", "m1",
--- a/langtools/test/jdk/jshell/CommandCompletionTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -54,7 +54,7 @@
public void testCommand() {
assertCompletion("/deb|", false);
- assertCompletion("/re|", false, "/reload ", "/reset ", "/retain ");
+ assertCompletion("/re|", false, "/reload ", "/reset ");
assertCompletion("/h|", false, "/help ", "/history ");
}
@@ -195,34 +195,6 @@
);
}
- public void testRetain() throws IOException {
- List<String> p1 = listFiles(Paths.get(""));
- FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
- Collections.sort(p1);
-
- String[] modes = {"concise ", "normal ", "silent ", "verbose "};
- test(false, new String[] {"--no-startup"},
- a -> assertCompletion(a, "/ret|", false, "/retain "),
- a -> assertCompletion(a, "/retain |", false, "editor ", "feedback ", "mode ", "start "),
-
- // /retain editor
- a -> assertCompletion(a, "/retain e|", false, "editor "),
- a -> assertCompletion(a, "/retain editor |", false, p1.toArray(new String[p1.size()])),
-
- // /retain feedback
- a -> assertCompletion(a, "/retain fe|", false, "feedback "),
- a -> assertCompletion(a, "/retain fe |", false, modes),
-
- // /retain mode
- a -> assertCompletion(a, "/retain mo|", false, "mode "),
- a -> assertCompletion(a, "/retain mo |", false, modes),
-
- // /retain start
- a -> assertCompletion(a, "/retain st|", false, "start "),
- a -> assertCompletion(a, "/retain st |", false, p1.toArray(new String[p1.size()]))
- );
- }
-
private void createIfNeeded(Path file) throws IOException {
if (!Files.exists(file))
Files.createFile(file);
--- a/langtools/test/jdk/jshell/ExternalEditorTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ExternalEditorTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -193,7 +193,6 @@
@Test
public void setUnknownEditor() {
test(
- a -> assertCommand(a, "/set editor", "| The '/set editor' command requires a path argument"),
a -> assertCommand(a, "/set editor UNKNOWN", "| Editor set to: UNKNOWN"),
a -> assertCommand(a, "int a;", null),
a -> assertCommandOutputStartsWith(a, "/ed 1",
--- a/langtools/test/jdk/jshell/KullaTesting.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/KullaTesting.java Thu Oct 27 09:42:08 2016 -0700
@@ -21,7 +21,10 @@
* questions.
*/
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintStream;
import java.io.StringWriter;
import java.lang.reflect.Method;
@@ -83,7 +86,7 @@
private SourceCodeAnalysis analysis = null;
private JShell state = null;
- private TestingInputStream inStream = null;
+ private InputStream inStream = null;
private ByteArrayOutputStream outStream = null;
private ByteArrayOutputStream errStream = null;
@@ -106,7 +109,11 @@
}
public void setInput(String s) {
- inStream.setInput(s);
+ setInput(new ByteArrayInputStream(s.getBytes()));
+ }
+
+ public void setInput(InputStream in) {
+ inStream = in;
}
public String getOutput() {
@@ -159,11 +166,27 @@
}
public void setUp(Consumer<JShell.Builder> bc) {
- inStream = new TestingInputStream();
+ InputStream in = new InputStream() {
+ @Override
+ public int read() throws IOException {
+ assertNotNull(inStream);
+ return inStream.read();
+ }
+ @Override
+ public int read(byte[] b) throws IOException {
+ assertNotNull(inStream);
+ return inStream.read(b);
+ }
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ assertNotNull(inStream);
+ return inStream.read(b, off, len);
+ }
+ };
outStream = new ByteArrayOutputStream();
errStream = new ByteArrayOutputStream();
JShell.Builder builder = JShell.builder()
- .in(inStream)
+ .in(in)
.out(new PrintStream(outStream))
.err(new PrintStream(errStream));
bc.accept(builder);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/PipeInputStreamTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test 8167461
+ * @summary Verify PipeInputStream works.
+ * @modules jdk.compiler/com.sun.tools.javac.util
+ * jdk.jshell
+ * @run testng PipeInputStreamTest
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.testng.annotations.Test;
+
+import com.sun.tools.javac.util.Pair;
+
+import static org.testng.Assert.*;
+
+@Test
+public class PipeInputStreamTest {
+
+ public void testReadArrayNotBlocking() throws Exception {
+ Pair<InputStream, OutputStream> streams = createPipeStream();
+ InputStream in = streams.fst;
+ OutputStream out = streams.snd;
+ out.write('a');
+ byte[] data = new byte[12];
+ assertEquals(in.read(data), 1);
+ assertEquals(data[0], 'a');
+ out.write('a'); out.write('b'); out.write('c');
+ assertEquals(in.read(data), 3);
+ assertEquals(data[0], 'a');
+ assertEquals(data[1], 'b');
+ assertEquals(data[2], 'c');
+ }
+
+ private Pair<InputStream, OutputStream> createPipeStream() throws Exception {
+ Class<?> pipeStreamClass = Class.forName("jdk.jshell.execution.PipeInputStream");
+ Constructor<?> c = pipeStreamClass.getDeclaredConstructor();
+ c.setAccessible(true);
+ Object pipeStream = c.newInstance();
+ Method createOutputStream = pipeStreamClass.getDeclaredMethod("createOutput");
+ createOutputStream.setAccessible(true);
+ return Pair.of((InputStream) pipeStream, (OutputStream) createOutputStream.invoke(pipeStream));
+ }
+
+}
--- a/langtools/test/jdk/jshell/ReplToolTesting.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ReplToolTesting.java Thu Oct 27 09:42:08 2016 -0700
@@ -93,6 +93,7 @@
private Map<String, ImportInfo> imports;
private boolean isDefaultStartUp = true;
private Preferences prefs;
+ private Map<String, String> envvars;
public JShellTool repl = null;
@@ -232,6 +233,11 @@
@BeforeMethod
public void setUp() {
prefs = new MemoryPreferences();
+ envvars = new HashMap<>();
+ }
+
+ protected void setEnvVar(String name, String value) {
+ envvars.put(name, value);
}
public void testRaw(Locale locale, String[] args, ReplTest... tests) {
@@ -247,9 +253,11 @@
new PrintStream(cmdout),
new PrintStream(cmderr),
new PrintStream(console),
+ userin,
new PrintStream(userout),
new PrintStream(usererr),
prefs,
+ envvars,
locale);
repl.testPrompt = true;
try {
@@ -462,7 +470,8 @@
private List<String> computeCompletions(String code, boolean isSmart) {
JShellTool js = this.repl != null ? this.repl
- : new JShellTool(null, null, null, null, null, null, prefs, Locale.ROOT);
+ : new JShellTool(null, null, null, null, null, null, null,
+ prefs, envvars, Locale.ROOT);
int cursor = code.indexOf('|');
code = code.replace("|", "");
assertTrue(cursor > -1, "'|' not found: " + code);
--- a/langtools/test/jdk/jshell/StartOptionTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/StartOptionTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -37,6 +37,7 @@
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
+import java.util.HashMap;
import java.util.Locale;
import java.util.function.Consumer;
@@ -63,9 +64,11 @@
new PrintStream(cmdout),
new PrintStream(cmderr),
new PrintStream(console),
+ null,
new PrintStream(userout),
new PrintStream(usererr),
new ReplToolTesting.MemoryPreferences(),
+ new HashMap<>(),
Locale.ROOT);
}
--- a/langtools/test/jdk/jshell/ToolBasicTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -431,12 +431,12 @@
(a) -> assertMethod(a, "void f() {}", "()V", "f"),
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
(a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
- (a) -> assertCommand(a, "/retain start " + startUpFile.toString(), null)
+ (a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
);
Path unknown = compiler.getPath("UNKNOWN");
test(
- (a) -> assertCommandOutputStartsWith(a, "/retain start " + unknown.toString(),
- "| File '" + unknown + "' for '/retain start' is not found.")
+ (a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
+ "| File '" + unknown + "' for '/set start' is not found.")
);
test(false, new String[0],
(a) -> {
--- a/langtools/test/jdk/jshell/ToolCommandOptionTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8157395 8157393 8157517 8158738 8167128
+ * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637
* @summary Tests of jshell comand options, and undoing operations
* @modules jdk.jshell/jdk.internal.jshell.tool
* @build ToolCommandOptionTest ReplToolTesting
@@ -124,50 +124,118 @@
(a) -> assertCommand(a, "/set editor -furball -mattress",
"| Unknown option: -furball -mattress -- /set editor -furball -mattress"),
(a) -> assertCommand(a, "/set editor -default prog",
- "| Specify -default option or program, not both -- /set editor -default prog"),
+ "| Specify -default option, -delete option, or program -- /set editor -default prog"),
(a) -> assertCommand(a, "/set editor prog",
"| Editor set to: prog"),
(a) -> assertCommand(a, "/set editor prog -default",
- "| Editor set to: prog"),
+ "| Editor set to: prog -default"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor prog -default"),
(a) -> assertCommand(a, "/se ed prog -furball",
- "| Editor set to: prog"),
+ "| Editor set to: prog -furball"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor prog -furball"),
+ (a) -> assertCommand(a, "/se ed -delete",
+ "| Editor set to: -default"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -default"),
(a) -> assertCommand(a, "/set editor prog arg1 -furball arg3 -default arg4",
- "| Editor set to: prog"),
+ "| Editor set to: prog arg1 -furball arg3 -default arg4"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor prog arg1 -furball arg3 -default arg4"),
(a) -> assertCommand(a, "/set editor -default",
- ""),
+ "| Editor set to: -default"),
(a) -> assertCommand(a, "/se edi -def",
- ""),
+ "| Editor set to: -default"),
(a) -> assertCommand(a, "/set editor",
- "| The '/set editor' command requires a path argument")
+ "| /set editor -default")
);
}
public void retainEditorTest() {
test(
- (a) -> assertCommand(a, "/retain editor -furball",
- "| Unknown option: -furball -- /retain editor -furball"),
- (a) -> assertCommand(a, "/retain editor -furball prog",
- "| Unknown option: -furball -- /retain editor -furball prog"),
- (a) -> assertCommand(a, "/retain editor -furball -mattress",
- "| Unknown option: -furball -mattress -- /retain editor -furball -mattress"),
- (a) -> assertCommand(a, "/retain editor -default prog",
- "| Specify -default option or program, not both -- /retain editor -default prog"),
- (a) -> assertCommand(a, "/retain editor -default -wait",
- "| -wait applies to external editors, cannot be used with -default"),
- (a) -> assertCommand(a, "/retain editor prog",
+ (a) -> assertCommand(a, "/set editor -retain -furball",
+ "| Unknown option: -furball -- /set editor -retain -furball"),
+ (a) -> assertCommand(a, "/set editor -retain -furball prog",
+ "| Unknown option: -furball -- /set editor -retain -furball prog"),
+ (a) -> assertCommand(a, "/set editor -retain -furball -mattress",
+ "| Unknown option: -furball -mattress -- /set editor -retain -furball -mattress"),
+ (a) -> assertCommand(a, "/set editor -retain -default prog",
+ "| Specify -default option, -delete option, or program -- /set editor -retain -default prog"),
+ (a) -> assertCommand(a, "/set editor -retain -wait",
+ "| -wait applies to external editors"),
+ (a) -> assertCommand(a, "/set editor -retain -default -wait",
+ "| -wait applies to external editors"),
+ (a) -> assertCommand(a, "/set editor -retain prog",
+ "| Editor set to: prog\n" +
+ "| Editor setting retained: prog"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain prog"),
+ (a) -> assertCommand(a, "/se ed other",
+ "| Editor set to: other"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain prog\n" +
+ "| /set editor other"),
+ (a) -> assertCommand(a, "/se ed -delete",
"| Editor set to: prog"),
- (a) -> assertCommand(a, "/retain editor prog -default",
- "| Editor set to: prog"),
- (a) -> assertCommand(a, "/ret ed prog -furball",
- "| Editor set to: prog"),
- (a) -> assertCommand(a, "/retain editor prog arg1 -furball arg3 -default arg4",
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain prog"),
+ (a) -> assertCommand(a, "/set editor -retain prog -default",
+ "| Editor set to: prog -default\n" +
+ "| Editor setting retained: prog -default"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain prog -default"),
+ (a) -> assertCommand(a, "/se ed -retain prog -furball",
+ "| Editor set to: prog -furball\n" +
+ "| Editor setting retained: prog -furball"),
+ (a) -> assertCommand(a, "/set editor -retain prog arg1 -furball arg3 -default arg4",
+ "| Editor set to: prog arg1 -furball arg3 -default arg4\n" +
+ "| Editor setting retained: prog arg1 -furball arg3 -default arg4"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain prog arg1 -furball arg3 -default arg4"),
+ (a) -> assertCommand(a, "/set editor -retain -default",
+ "| Editor set to: -default\n" +
+ "| Editor setting retained: -default"),
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain -default"),
+ (a) -> assertCommand(a, "/se e -ret -def",
+ "| Editor set to: -default\n" +
+ "| Editor setting retained: -default"),
+ (a) -> assertCommand(a, "/set editor -retain",
+ "| Editor setting retained: -default")
+ );
+ }
+
+ public void setEditorEnvTest() {
+ setEnvVar("EDITOR", "best one");
+ setEditorEnvSubtest();
+ setEnvVar("EDITOR", "not this");
+ setEnvVar("VISUAL", "best one");
+ setEditorEnvSubtest();
+ setEnvVar("VISUAL", "not this");
+ setEnvVar("JSHELLEDITOR", "best one");
+ setEditorEnvSubtest();
+ }
+
+ private void setEditorEnvSubtest() {
+ test(
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor best one"),
+ (a) -> assertCommand(a, "/set editor prog",
"| Editor set to: prog"),
- (a) -> assertCommand(a, "/retain editor -default",
- ""),
- (a) -> assertCommand(a, "/reta edi -def",
- ""),
- (a) -> assertCommand(a, "/retain editor",
- "")
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor prog"),
+ (a) -> assertCommand(a, "/set editor -delete",
+ "| Editor set to: best one"),
+ (a) -> assertCommand(a, "/set editor -retain stored editor",
+ "| Editor set to: stored editor\n" +
+ "| Editor setting retained: stored editor")
+ );
+ test(
+ (a) -> assertCommand(a, "/set editor",
+ "| /set editor -retain stored editor"),
+ (a) -> assertCommand(a, "/set editor -delete -retain",
+ "| Editor set to: best one")
);
}
@@ -182,45 +250,56 @@
(a) -> assertCommand(a, "/set start -furball -mattress",
"| Unknown option: -furball -mattress -- /set start -furball -mattress"),
(a) -> assertCommand(a, "/set start foo -default",
- "| Specify either one option or a startup file name -- /set start foo -default"),
+ "| Specify no more than one of -default, -none, or a startup file name -- /set start foo -default"),
(a) -> assertCommand(a, "/set start frfg",
"| File 'frfg' for '/set start' is not found."),
(a) -> assertCommand(a, "/set start -default",
""),
+ (a) -> assertCommand(a, "/set start",
+ "| /set start -default"),
(a) -> assertCommand(a, "/se sta -no",
""),
(a) -> assertCommand(a, "/set start",
- "| Specify either one option or a startup file name -- /set start")
+ "| /set start -none")
);
}
public void retainStartTest() {
test(
- (a) -> assertCommand(a, "/retain start -furball",
- "| Unknown option: -furball -- /retain start -furball"),
- (a) -> assertCommand(a, "/retain start -furball pyle",
- "| Unknown option: -furball -- /retain start -furball pyle"),
- (a) -> assertCommand(a, "/ret st pyle -furball",
- "| Unknown option: -furball -- /retain st pyle -furball"),
- (a) -> assertCommand(a, "/retain start -furball -mattress",
- "| Unknown option: -furball -mattress -- /retain start -furball -mattress"),
- (a) -> assertCommand(a, "/retain start foo -default",
- "| Specify either one option or a startup file name -- /retain start foo -default"),
- (a) -> assertCommand(a, "/retain start frfg",
- "| File 'frfg' for '/retain start' is not found."),
- (a) -> assertCommand(a, "/retain start -default",
+ (a) -> assertCommand(a, "/set start -retain -furball",
+ "| Unknown option: -furball -- /set start -retain -furball"),
+ (a) -> assertCommand(a, "/set start -retain -furball pyle",
+ "| Unknown option: -furball -- /set start -retain -furball pyle"),
+ (a) -> assertCommand(a, "/se st -re pyle -furball",
+ "| Unknown option: -furball -- /set st -re pyle -furball"),
+ (a) -> assertCommand(a, "/set start -retain -furball -mattress",
+ "| Unknown option: -furball -mattress -- /set start -retain -furball -mattress"),
+ (a) -> assertCommand(a, "/set start -retain foo -default",
+ "| Specify no more than one of -default, -none, or a startup file name -- /set start -retain foo -default"),
+ (a) -> assertCommand(a, "/set start -retain -default foo",
+ "| Specify no more than one of -default, -none, or a startup file name -- /set start -retain -default foo"),
+ (a) -> assertCommand(a, "/set start -retain frfg",
+ "| File 'frfg' for '/set start' is not found."),
+ (a) -> assertCommand(a, "/set start -retain -default",
""),
- (a) -> assertCommand(a, "/ret sta -no",
+ (a) -> assertCommand(a, "/set start",
+ "| /set start -retain -default"),
+ (a) -> assertCommand(a, "/set sta -no",
""),
- (a) -> assertCommand(a, "/retain start",
- "")
+ (a) -> assertCommand(a, "/set start",
+ "| /set start -retain -default\n" +
+ "| /set start -none"),
+ (a) -> assertCommand(a, "/se st -ret",
+ ""),
+ (a) -> assertCommand(a, "/se sta",
+ "| /set start -retain -none")
);
}
public void setModeTest() {
test(
- (a) -> assertCommandOutputStartsWith(a, "/set mode",
- "| Missing the feedback mode"),
+ (a) -> assertCommandOutputContains(a, "/set mode",
+ "| /set format verbose unresolved"),
(a) -> assertCommandOutputStartsWith(a, "/set mode *",
"| Expected a feedback mode name: *"),
(a) -> assertCommandOutputStartsWith(a, "/set mode -quiet",
@@ -229,11 +308,13 @@
"| Expected a feedback mode name: *"),
(a) -> assertCommandOutputStartsWith(a, "/set mode amode normal thing",
"| Unexpected arguments at end of command: thing"),
- (a) -> assertCommand(a, "/set mode mymode",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode",
+ "| To create a new mode either the -command or the -quiet option must be used"),
+ (a) -> assertCommand(a, "/set mode mymode -command",
"| Created new feedback mode: mymode"),
(a) -> assertCommand(a, "/set mode mymode -delete",
""),
- (a) -> assertCommand(a, "/set mode mymode normal",
+ (a) -> assertCommand(a, "/set mode mymode normal -command",
"| Created new feedback mode: mymode"),
(a) -> assertCommand(a, "/set mode -del mymode",
""),
@@ -245,18 +326,33 @@
"| Conflicting options"),
(a) -> assertCommandOutputStartsWith(a, "/set mode mymode -d",
"| No feedback mode named: mymode"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode normal",
- "| Not valid with a predefined mode: normal"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode normal -c",
+ "| Mode to be created already exists: normal"),
(a) -> assertCommand(a, "/se mo -c mymode",
"| Created new feedback mode: mymode"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode",
+ "| /set mode mymode -command"),
(a) -> assertCommand(a, "/set feedback mymode",
"| Feedback mode: mymode"),
+ (a) -> assertCommand(a, "/se fe",
+ "| /set feedback mymode\n" +
+ "| \n" +
+ "| Available feedback modes:\n" +
+ "| concise\n" +
+ "| mymode\n" +
+ "| normal\n" +
+ "| silent\n" +
+ "| verbose"),
(a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete",
"| The current feedback mode 'mymode' cannot be deleted"),
(a) -> assertCommand(a, "/set feedback no",
"| Feedback mode: normal"),
(a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete",
""),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode",
+ "| To create a new mode either the -command or the -quiet option must be used -- \n" +
+ "| Does not match any current feedback mode: mymode -- /set mode mymode\n" +
+ "| Available feedback modes:"),
(a) -> assertCommandCheckOutput(a, "/set feedback",
(s) -> assertFalse(s.contains("mymode"), "Didn't delete: " + s))
);
@@ -272,8 +368,20 @@
""),
(a) -> assertCommand(a, "45",
"blurb"),
- (a) -> assertCommand(a, "/set mode mymode normal",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode normal",
+ "| To create a new mode either the -command or the -quiet option must be used"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -command normal",
+ "| Mode to be created already exists: mymode"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode mymode -delete",
+ "| The current feedback mode 'mymode' cannot be deleted, use '/set feedback' first"),
+ (a) -> assertCommand(a, "/set feedback normal",
+ "| Feedback mode: normal"),
+ (a) -> assertCommand(a, "/set mode mymode -delete",
+ ""),
+ (a) -> assertCommand(a, "/set mode mymode -command normal",
"| Created new feedback mode: mymode"),
+ (a) -> assertCommand(a, "/set feedback mymode",
+ "| Feedback mode: mymode"),
(a) -> assertCommandOutputContains(a, "45",
" ==> 45")
);
@@ -281,67 +389,89 @@
public void retainModeTest() {
test(
- (a) -> assertCommandOutputStartsWith(a, "/retain mode",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain",
"| Missing the feedback mode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode *",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain *",
"| Expected a feedback mode name: *"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode amode normal",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain amode normal",
"| Unexpected arguments at end of command: normal"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode mymode",
- "| Does not match any current feedback mode: mymode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode mymode -delete",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain mymode",
"| No feedback mode named: mymode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode -d mymode",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain mymode -delete",
+ "| No feedback mode named: mymode"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain -d mymode",
"| No feedback mode named: mymode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode normal",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain normal",
"| Not valid with a predefined mode: normal"),
- (a) -> assertCommand(a, "/set mode mymode verbose",
+ (a) -> assertCommand(a, "/set mode mymode verbose -command",
"| Created new feedback mode: mymode"),
- (a) -> assertCommand(a, "/retain mode mymode",
+ (a) -> assertCommand(a, "/set mode -retain mymode",
""),
(a) -> assertCommand(a, "/set mode mymode -delete",
""),
- (a) -> assertCommand(a, "/retain mode mymode -delete",
+ (a) -> assertCommand(a, "/set mode -retain mymode -delete",
""),
- (a) -> assertCommand(a, "/set mode kmode normal",
+ (a) -> assertCommand(a, "/set mode kmode normal -command",
"| Created new feedback mode: kmode"),
- (a) -> assertCommand(a, "/retain mode kmode",
+ (a) -> assertCommand(a, "/set mode -retain kmode",
""),
(a) -> assertCommand(a, "/set mode kmode -delete",
""),
- (a) -> assertCommand(a, "/set mode tmode normal",
+ (a) -> assertCommand(a, "/set mode tmode normal -command",
"| Created new feedback mode: tmode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain feedback tmode",
- "| '/retain feedback <mode>' requires that <mode> is predefined or has been retained with '/retain mode'"),
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback -retain tmode",
+ "| '/set feedback -retain <mode>' requires that <mode> is predefined or has been retained with '/set mode -retain'"),
(a) -> assertCommand(a, "/set format tmode display 'YES'",
""),
(a) -> assertCommand(a, "/set feedback tmode",
"| Feedback mode: tmode"),
(a) -> assertCommand(a, "45",
"YES"),
- (a) -> assertCommand(a, "/retain mode tmode",
+ (a) -> assertCommand(a, "/set mode -retain tmode",
""),
- (a) -> assertCommand(a, "/retain feedback tmode",
+ (a) -> assertCommand(a, "/set feedback -retain tmode",
"| Feedback mode: tmode"),
(a) -> assertCommand(a, "/set format tmode display 'blurb'",
""),
+ (a) -> assertCommand(a, "/set format tmode display",
+ "| /set format tmode display \"blurb\""),
+ (a) -> assertCommandOutputContains(a, "/set mode tmode",
+ "| /set format tmode display \"YES\""),
(a) -> assertCommand(a, "45",
"blurb")
);
test(
+ (a) -> assertCommand(a, "/set format tmode display",
+ "| /set format tmode display \"YES\""),
+ (a) -> assertCommandOutputContains(a, "/set mode tmode",
+ "| /set format tmode display \"YES\""),
(a) -> assertCommand(a, "45",
"YES"),
(a) -> assertCommand(a, "/set feedback kmode",
"| Feedback mode: kmode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode kmode -delete",
+ (a) -> assertCommand(a, "/set feedback",
+ "| /set feedback -retain tmode\n" +
+ "| /set feedback kmode\n" +
+ "| \n" +
+ "| Retained feedback modes:\n" +
+ "| kmode\n" +
+ "| tmode\n" +
+ "| Available feedback modes:\n" +
+ "| concise\n" +
+ "| kmode\n" +
+ "| normal\n" +
+ "| silent\n" +
+ "| tmode\n" +
+ "| verbose"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain kmode -delete",
"| The current feedback mode 'kmode' cannot be deleted"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode tmode -delete",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain tmode -delete",
"| The retained feedback mode 'tmode' cannot be deleted"),
- (a) -> assertCommand(a, "/retain feedback normal",
+ (a) -> assertCommand(a, "/set feedback -retain normal",
"| Feedback mode: normal"),
- (a) -> assertCommand(a, "/retain mode tmode -delete",
+ (a) -> assertCommand(a, "/set mode -retain tmode -delete",
""),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode kmode -delete",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain kmode -delete",
"")
);
test(
--- a/langtools/test/jdk/jshell/ToolFormatTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolFormatTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261
+ * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840
* @summary Tests for output customization
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -33,10 +33,17 @@
* @build KullaTesting TestingInputStream toolbox.ToolBox Compiler
* @run testng ToolFormatTest
*/
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
@Test
public class ToolFormatTest extends ReplToolTesting {
@@ -81,6 +88,58 @@
}
}
+ public void testSetFormatOverride() {
+ test(
+ (a) -> assertCommand(a, "/set mode tm -c", "| Created new feedback mode: tm"),
+ (a) -> assertCommand(a, "/se fo tm x \"aaa\"", ""),
+ (a) -> assertCommand(a, "/se fo tm x \"bbb\" class,method-added", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"bbb\" class,method-added"),
+ (a) -> assertCommand(a, "/se fo tm x \"ccc\" class,method-added,modified", ""),
+ (a) -> assertCommand(a, "/se fo tm x \"ddd\" class,method-added", ""),
+ (a) -> assertCommand(a, "/se fo tm x \"eee\" method-added", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"ccc\" class,method-added,modified\n" +
+ "| /set format tm x \"ddd\" class,method-added\n" +
+ "| /set format tm x \"eee\" method-added"),
+ (a) -> assertCommand(a, "/se fo tm x \"EEE\" method-added,replaced", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"ccc\" class,method-added,modified\n" +
+ "| /set format tm x \"ddd\" class,method-added\n" +
+ "| /set format tm x \"EEE\" method-added,replaced"),
+ (a) -> assertCommand(a, "/se fo tm x \"fff\" method-added,replaced-ok", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"ccc\" class,method-added,modified\n" +
+ "| /set format tm x \"ddd\" class,method-added\n" +
+ "| /set format tm x \"EEE\" method-added,replaced\n" +
+ "| /set format tm x \"fff\" method-added,replaced-ok"),
+ (a) -> assertCommand(a, "/se fo tm x \"ggg\" method-ok", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"ccc\" class,method-added,modified\n" +
+ "| /set format tm x \"ddd\" class,method-added\n" +
+ "| /set format tm x \"EEE\" method-added,replaced\n" +
+ "| /set format tm x \"ggg\" method-ok"),
+ (a) -> assertCommand(a, "/se fo tm x \"hhh\" method", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"ccc\" class,method-added,modified\n" +
+ "| /set format tm x \"ddd\" class,method-added\n" +
+ "| /set format tm x \"hhh\" method"),
+ (a) -> assertCommand(a, "/se fo tm x \"iii\" method,class", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"aaa\" \n" +
+ "| /set format tm x \"iii\" class,method"),
+ (a) -> assertCommand(a, "/se fo tm x \"jjj\"", ""),
+ (a) -> assertCommand(a, "/se fo tm x",
+ "| /set format tm x \"jjj\"")
+ );
+ }
+
public void testSetFormatSelector() {
List<ReplTest> tests = new ArrayList<>();
tests.add((a) -> assertCommandOutputStartsWith(a, "/set mode ate -quiet",
@@ -167,8 +226,14 @@
(a) -> assertCommandOutputStartsWith(a, "/set feedback test", ""),
(a) -> assertCommand(a, "/set format test display '{type}:{value}' primary", ""),
(a) -> assertCommand(a, "/set truncation test 20", ""),
+ (a) -> assertCommand(a, "/set truncation test", "| /set truncation test 20"),
+ (a) -> assertCommandOutputContains(a, "/set truncation", "/set truncation test 20"),
(a) -> assertCommand(a, "/set trunc test 10 varvalue", ""),
(a) -> assertCommand(a, "/set trunc test 3 assignment", ""),
+ (a) -> assertCommandOutputContains(a, "/set truncation",
+ "/set truncation test 10 varvalue"),
+ (a) -> assertCommandOutputContains(a, "/set truncation test",
+ "/set truncation test 10 varvalue"),
(a) -> assertCommand(a, "String r = s", "String:\"ABACABADABACABA ..."),
(a) -> assertCommand(a, "r", "String:\"ABACA ..."),
(a) -> assertCommand(a, "r=s", "String:\"AB")
@@ -201,6 +266,45 @@
);
}
+ public void testPrompt() {
+ test(
+ (a) -> assertCommand(a, "/set mode tp -quiet", "| Created new feedback mode: tp"),
+ (a) -> assertCommand(a, "/set prompt tp 'aaa' 'bbb'", ""),
+ (a) -> assertCommand(a, "/set prompt tp",
+ "| /set prompt tp \"aaa\" \"bbb\""),
+ (a) -> assertCommandOutputContains(a, "/set prompt",
+ "| /set prompt tp \"aaa\" \"bbb\""),
+ (a) -> assertCommand(a, "/set mode -retain tp", ""),
+ (a) -> assertCommand(a, "/set prompt tp 'ccc' 'ddd'", ""),
+ (a) -> assertCommand(a, "/set prompt tp",
+ "| /set prompt tp \"ccc\" \"ddd\""),
+ (a) -> assertCommandCheckOutput(a, "/set mode tp",
+ (s) -> {
+ try {
+ BufferedReader rdr = new BufferedReader(new StringReader(s));
+ assertEquals(rdr.readLine(), "| /set mode tp -quiet",
+ "| /set mode tp -quiet");
+ assertEquals(rdr.readLine(), "| /set prompt tp \"aaa\" \"bbb\"",
+ "| /set prompt tp \"aaa\" \"bbb\"");
+ String l = rdr.readLine();
+ while (l.startsWith("| /set format tp ")) {
+ l = rdr.readLine();
+ }
+ assertEquals(l, "| /set mode -retain tp",
+ "| /set mode -retain tp");
+ assertEquals(rdr.readLine(), "| ",
+ "| ");
+ assertEquals(rdr.readLine(), "| /set mode tp -quiet",
+ "| /set mode tp -quiet");
+ assertEquals(rdr.readLine(), "| /set prompt tp \"ccc\" \"ddd\"",
+ "| /set prompt tp \"ccc\" \"ddd\"");
+ } catch (IOException ex) {
+ fail("threw " + ex);
+ }
+ })
+ );
+ }
+
public void testShowFeedbackModes() {
test(
(a) -> assertCommandOutputContains(a, "/set feedback", "normal")
@@ -216,7 +320,8 @@
(a) -> assertCommand(a, "/se fee nmq2", ""),
(a) -> assertCommand(a, "/set mode nmc -command normal", ""),
(a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode nm", "| Created new feedback mode: nm"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode nm -command",
+ "| Created new feedback mode: nm"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal")
);
@@ -231,37 +336,35 @@
test(
(a) -> assertCommandOutputStartsWith(a, "/set mode tee -command foo",
"| Does not match any current feedback mode: foo"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode tee flurb",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode tee -quiet flurb",
"| Does not match any current feedback mode: flurb"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode tee",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -command tee",
"| Created new feedback mode: tee"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode verbose",
- "| Not valid with a predefined mode: verbose"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode verbose -command",
+ "| Mode to be created already exists: verbose"),
(a) -> assertCommandOutputStartsWith(a, "/set mode te -command normal",
"| Created new feedback mode: te"),
(a) -> assertCommand(a, "/set format te errorpre 'ERROR: '", ""),
(a) -> assertCommandOutputStartsWith(a, "/set feedback te",
""),
- (a) -> assertCommandOutputStartsWith(a, "/set ",
- "ERROR: The '/set' command requires a sub-command"),
(a) -> assertCommandOutputStartsWith(a, "/set xyz",
"ERROR: Invalid '/set' argument: xyz"),
(a) -> assertCommandOutputStartsWith(a, "/set f",
"ERROR: Ambiguous sub-command argument to '/set': f"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback",
- "ERROR: Missing the feedback mode"),
+ "| /set feedback te"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback xyz",
"ERROR: Does not match any current feedback mode"),
- (a) -> assertCommandOutputStartsWith(a, "/set format",
- "ERROR: Missing the feedback mode"),
+ (a) -> assertCommandOutputStartsWith(a, "/set feed",
+ "| /set feedback te"),
(a) -> assertCommandOutputStartsWith(a, "/set format xyz",
"ERROR: Does not match any current feedback mode"),
(a) -> assertCommandOutputStartsWith(a, "/set format t",
"ERROR: Matches more then one current feedback mode: t"),
- (a) -> assertCommandOutputStartsWith(a, "/set format te",
- "ERROR: Missing the field name"),
+ (a) -> assertCommandOutputStartsWith(a, "/set format qqq",
+ "ERROR: Does not match any current feedback mode: qqq"),
(a) -> assertCommandOutputStartsWith(a, "/set format te fld",
- "ERROR: Expected format missing"),
+ "ERROR: Expected a field name:"),
(a) -> assertCommandOutputStartsWith(a, "/set format te fld aaa",
"ERROR: Format 'aaa' must be quoted"),
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' frog",
@@ -274,30 +377,28 @@
"ERROR: Different selector kinds in same sections of"),
(a) -> assertCommandOutputStartsWith(a, "/set trunc te 20x",
"ERROR: Truncation length must be an integer: 20x"),
- (a) -> assertCommandOutputStartsWith(a, "/set trunc te",
- "ERROR: Expected truncation length"),
+ (a) -> assertCommandOutputStartsWith(a, "/set trunc qaz",
+ "ERROR: Does not match any current feedback mode: qaz -- /set trunc qaz"),
(a) -> assertCommandOutputStartsWith(a, "/set truncation te 111 import,added",
"ERROR: Different selector kinds in same sections of"),
- (a) -> assertCommandOutputStartsWith(a, "/set mode",
+ (a) -> assertCommandOutputContains(a, "/set mode",
+ "| /set truncation verbose"),
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -command",
"ERROR: Missing the feedback mode"),
(a) -> assertCommandOutputStartsWith(a, "/set mode x -quiet y",
"ERROR: Does not match any current feedback mode"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt",
- "ERROR: Missing the feedback mode"),
+ "| /set prompt"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt te",
- "ERROR: Expected format missing"),
+ "| /set prompt te "),
(a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa xyz",
"ERROR: Format 'aaa' must be quoted"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt te 'aaa' xyz",
"ERROR: Format 'xyz' must be quoted"),
- (a) -> assertCommandOutputStartsWith(a, "/set prompt",
- "ERROR: Missing the feedback mode"),
- (a) -> assertCommandOutputStartsWith(a, "/set prompt te",
- "ERROR: Expected format missing"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa",
"ERROR: Format 'aaa' must be quoted"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt te 'aaa'",
- "ERROR: Expected format missing"),
+ "ERROR: Continuation prompt required"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal",
"| Feedback mode: normal")
);
--- a/langtools/test/jdk/jshell/ToolLocaleMessageTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolLocaleMessageTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -106,10 +106,11 @@
(a) -> assertCommandOK(a, "/set feedback test", "test"),
(a) -> assertCommandFail(a, "/list zebra"),
- (a) -> assertCommandFail(a, "/set editor", "/set editor"),
+ (a) -> assertCommandFail(a, "/set editor -rot", "/set editor -rot"),
(a) -> assertCommandFail(a, "/set snowball", "/set", "snowball"),
- (a) -> assertCommandFail(a, "/set", "/set", "/help"),
- (a) -> assertCommandFail(a, "/set f", "feedback"),
+ (a) -> assertCommandOK(a, "/set", "| /set feedback test", "verbose"),
+ (a) -> assertCommandFail(a, "/set f", "/set"),
+ (a) -> assertCommandOK(a, "/set fe", "| /set feedback test"),
(a) -> assertCommandFail(a, "/classpath", "/classpath"),
(a) -> assertCommandFail(a, "/help rabbits", "rabbits"),
(a) -> assertCommandFail(a, "/drop"),
@@ -164,27 +165,20 @@
(a) -> assertCommandOK(a, "/set format te errorpre 'ERROR: '"),
(a) -> assertCommandOK(a, "/set feedback te"),
- (a) -> assertCommandFail(a, "/set "),
(a) -> assertCommandFail(a, "/set xyz", "xyz"),
(a) -> assertCommandFail(a, "/set f", "/set", "f"),
- (a) -> assertCommandFail(a, "/set feedback"),
(a) -> assertCommandFail(a, "/set feedback xyz"),
- (a) -> assertCommandFail(a, "/set format"),
(a) -> assertCommandFail(a, "/set format xyz"),
(a) -> assertCommandFail(a, "/set format t"),
- (a) -> assertCommandFail(a, "/set format te"),
(a) -> assertCommandFail(a, "/set format te fld"),
(a) -> assertCommandFail(a, "/set format te fld aaa", "aaa"),
(a) -> assertCommandFail(a, "/set format te fld 'aaa' frog"),
(a) -> assertCommandFail(a, "/set format te fld 'aaa' import-frog"),
(a) -> assertCommandFail(a, "/set format te fld 'aaa' import-import"),
(a) -> assertCommandFail(a, "/set format te fld 'aaa' import,added"),
- (a) -> assertCommandFail(a, "/set mode"),
(a) -> assertCommandFail(a, "/set mode x xyz"),
(a) -> assertCommandFail(a, "/set mode x -quiet y"),
(a) -> assertCommandFail(a, "/set mode tee -command foo", "foo"),
- (a) -> assertCommandFail(a, "/set prompt"),
- (a) -> assertCommandFail(a, "/set prompt te"),
(a) -> assertCommandFail(a, "/set prompt te aaa xyz", "aaa"),
(a) -> assertCommandFail(a, "/set prompt te 'aaa' xyz", "xyz"),
(a) -> assertCommandFail(a, "/set prompt te aaa"),
--- a/langtools/test/jdk/jshell/ToolRetainTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolRetainTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8157200
+ * @bug 8157200 8163840
* @summary Tests of what information is retained across jshell tool runs
* @modules jdk.jshell/jdk.internal.jshell.tool
* @build ToolRetainTest ReplToolTesting
@@ -41,10 +41,12 @@
(a) -> assertCommand(a, "/set feedback trm", ""),
(a) -> assertCommand(a, "/set format trm display '{name}:{value}'", ""),
(a) -> assertCommand(a, "int x = 45", "x:45"),
- (a) -> assertCommand(a, "/retain mode trm", ""),
+ (a) -> assertCommand(a, "/set mode -retain trm", ""),
(a) -> assertCommand(a, "/exit", "")
);
test(
+ (a) -> assertCommandOutputContains(a, "/set mode trm",
+ "/set format trm display \"{name}:{value}\""),
(a) -> assertCommand(a, "/set feedback trm", ""),
(a) -> assertCommand(a, "int x = 45", "x:45")
);
@@ -53,21 +55,25 @@
public void testRetain2Mode() {
test(
(a) -> assertCommand(a, "/set mode trm1 -quiet", "| Created new feedback mode: trm1"),
- (a) -> assertCommand(a, "/retain mode trm1", ""),
- (a) -> assertCommand(a, "/retain feedback trm1", ""),
+ (a) -> assertCommand(a, "/set mode -retain trm1", ""),
+ (a) -> assertCommand(a, "/set feedback -retain trm1", ""),
(a) -> assertCommand(a, "/set format trm1 display '{name}:{value}'", ""),
(a) -> assertCommand(a, "int x = 66", "x:66"),
- (a) -> assertCommand(a, "/retain mode trm1", ""),
+ (a) -> assertCommand(a, "/set mode -retain trm1", ""),
(a) -> assertCommand(a, "/exit", "")
);
test(
(a) -> assertCommand(a, "/set mode trm2 -quiet", ""),
(a) -> assertCommand(a, "/set format trm2 display '{name}={value}'", ""),
(a) -> assertCommand(a, "int x = 45", "x:45"),
- (a) -> assertCommand(a, "/retain mode trm2", ""),
+ (a) -> assertCommand(a, "/set mode -retain trm2", ""),
(a) -> assertCommand(a, "/exit", "")
);
test(
+ (a) -> assertCommandOutputContains(a, "/set mode trm1",
+ "/set format trm1 display \"{name}:{value}\""),
+ (a) -> assertCommand(a, "/set format trm2 display",
+ "| /set format trm2 display \"{name}={value}\""),
(a) -> assertCommand(a, "int x = 99", "x:99"),
(a) -> assertCommand(a, "/set feedback trm2", ""),
(a) -> assertCommand(a, "int z = 77", "z=77")
@@ -76,31 +82,48 @@
public void testRetainFeedback() {
test(
- (a) -> assertCommand(a, "/retain feedback verbose", "| Feedback mode: verbose"),
+ (a) -> assertCommand(a, "/set feedback -retain verbose", "| Feedback mode: verbose"),
(a) -> assertCommand(a, "/exit", "")
);
test(
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback",
+ "| /set feedback -retain verbose\n" +
+ "| \n" +
+ "| "),
(a) -> assertCommandOutputContains(a, "int h =8", "| created variable h : int")
);
}
public void testRetainFeedbackBlank() {
+ String feedbackOut =
+ "| /set feedback -retain verbose\n" +
+ "| \n" +
+ "| Available feedback modes:\n" +
+ "| concise\n" +
+ "| normal\n" +
+ "| silent\n" +
+ "| verbose";
test(
(a) -> assertCommand(a, "/set feedback verbose", "| Feedback mode: verbose"),
- (a) -> assertCommand(a, "/retain feedback", ""),
+ (a) -> assertCommand(a, "/set feedback -retain", ""),
+ (a) -> assertCommand(a, "/set feedback", feedbackOut),
(a) -> assertCommand(a, "/exit", "")
);
test(
+ (a) -> assertCommand(a, "/set feedback", feedbackOut),
(a) -> assertCommandOutputContains(a, "int qw = 5", "| created variable qw : int")
);
}
public void testRetainEditor() {
test(
- (a) -> assertCommand(a, "/retain editor nonexistent", "| Editor set to: nonexistent"),
+ (a) -> assertCommand(a, "/set editor -retain nonexistent",
+ "| Editor set to: nonexistent\n" +
+ "| Editor setting retained: nonexistent"),
(a) -> assertCommand(a, "/exit", "")
);
test(
+ (a) -> assertCommand(a, "/set editor", "| /set editor -retain nonexistent"),
(a) -> assertCommandOutputContains(a, "int h =8", ""),
(a) -> assertCommandOutputContains(a, "/edit h", "Edit Error:")
);
@@ -109,7 +132,7 @@
public void testRetainEditorBlank() {
test(
(a) -> assertCommand(a, "/set editor nonexistent", "| Editor set to: nonexistent"),
- (a) -> assertCommand(a, "/retain editor", ""),
+ (a) -> assertCommand(a, "/set editor -retain", "| Editor setting retained: nonexistent"),
(a) -> assertCommand(a, "/exit", "")
);
test(
@@ -120,22 +143,25 @@
public void testRetainModeNeg() {
test(
- (a) -> assertCommandOutputStartsWith(a, "/retain mode verbose",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain verbose",
"| Not valid with a predefined mode"),
- (a) -> assertCommandOutputStartsWith(a, "/retain mode ????",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode -retain ????",
"| Expected a feedback mode name: ????")
);
}
public void testRetainFeedbackNeg() {
test(
- (a) -> assertCommandOutputStartsWith(a, "/retain feedback babble1",
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback -retain babble1",
"| Does not match any current feedback mode"),
- (a) -> assertCommand(a, "/set mode trfn",
+ (a) -> assertCommandOutputStartsWith(a, "/set mode trfn",
+ "| To create a new mode either the -command or the -quiet option must be used -- \n" +
+ "| Does not match any current feedback mode: trfn -- /set mode trfn"),
+ (a) -> assertCommand(a, "/set mode trfn -command",
"| Created new feedback mode: trfn"),
- (a) -> assertCommandOutputContains(a, "/retain feedback trfn",
+ (a) -> assertCommandOutputContains(a, "/set feedback -retain trfn",
"is predefined or has been retained"),
- (a) -> assertCommandOutputStartsWith(a, "/retain feedback !!!!",
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback -retain !!!!",
"| Expected a feedback mode name: !!!!")
);
}
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -193,8 +193,8 @@
"| '/save' requires a filename argument."),
(a) -> assertCommand(a, "/open",
"| '/open' requires a filename argument."),
- (a) -> assertCommand(a, "/set start",
- "| Specify either one option or a startup file name -- /set start")
+ (a) -> assertCommandOutputStartsWith(a, "/drop",
+ "| In the /drop argument, please specify an import, variable, method, or class to drop.")
);
}
--- a/langtools/test/jdk/jshell/UserInputTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/jdk/jshell/UserInputTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -23,12 +23,15 @@
/*
* @test
- * @bug 8131023
+ * @bug 8131023 8167461
* @summary Verify that the user's code can read System.in
* @build KullaTesting TestingInputStream
* @run testng UserInputTest
*/
+import java.io.IOException;
+import java.io.InputStream;
+
import org.testng.annotations.Test;
@Test
@@ -37,8 +40,61 @@
public void testReadInput() {
setInput("AB\n");
assertEval("System.in.read()", "65");
- setInput("BC\n");
- assertEval("System.in.read()", "66");
+ setInput("CD\n");
+ assertEval("System.in.read()", "67");
+ }
+
+ public void testScanner() {
+ assertEval("import java.util.Scanner;");
+ assertEval("Scanner s = new Scanner(System.in);");
+ setInput("12\n");
+ assertEval("s.nextInt();", "12");
}
+ public void testClose() {
+ setInput(new InputStream() {
+ private final byte[] data = new byte[] {0, 1, 2};
+ private int cursor;
+ @Override public int read() throws IOException {
+ if (cursor < data.length) {
+ return data[cursor++];
+ } else {
+ return -1;
+ }
+ }
+ });
+ assertEval("int read;", "0");
+ assertEval("System.in.read();", "0");
+ assertEval("System.in.read();", "1");
+ assertEval("System.in.read();", "2");
+ assertEval("System.in.read();", "-1");
+ assertEval("System.in.read();", "-1");
+ assertEval("System.in.read();", "-1");
+ }
+
+ public void testException() {
+ setInput(new InputStream() {
+ private final int[] data = new int[] {0, 1, -2, 2};
+ private int cursor;
+ @Override public int read() throws IOException {
+ if (cursor < data.length) {
+ int d = data[cursor++];
+ if (d == (-2)) {
+ throw new IOException("Crashed");
+ }
+ return d;
+ } else {
+ return -1;
+ }
+ }
+ });
+ assertEval("int read;", "0");
+ assertEval("System.in.read();", "0");
+ assertEval("System.in.read();", "1");
+ assertEval("java.io.IOException e;");
+ assertEval("try { System.in.read(); } catch (java.io.IOException exc) { e = exc; }");
+ assertEval("e", "java.io.IOException: Crashed");
+ assertEval("System.in.read();", "2");
+ assertEval("System.in.read();", "-1");
+ }
}
--- a/langtools/test/tools/javac/Paths/MineField.sh Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/Paths/MineField.sh Thu Oct 27 09:42:08 2016 -0700
@@ -109,9 +109,15 @@
echo 'public class Main {public static void main(String[] a) {Lib.f();}}' > Main.java
# Create a jar file that is good enough to put on the javac boot class path (i.e. contains java.lang.**)
-Sys "$jimage" extract --dir modules ${TESTJAVA}/lib/modules
-Sys "$jar" cf java-lang.jar -C modules/java.base java/lang
-Sys rm -rf modules
+if [ -r ${TESTJAVA}/lib/modules ]; then
+ Sys "$jimage" extract --dir modules ${TESTJAVA}/lib/modules
+ Sys "$jar" cf java-lang.jar -C modules/java.base java/lang
+ Sys rm -rf modules
+elif [ -d ${TESTJAVA}/modules ]; then
+ Sys "$jar" cf java-lang.jar -C ${TESTJAVA}/modules/java.base java/lang
+else
+ echo 'cannot create java-lang.jar' ; exit 1
+fi
#----------------------------------------------------------------
# Verify that javac class search order is the same as java's
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableElementTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,241 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8029102
+ * @summary Enhance compiler warnings for Lambda
+ * Checks that the warning for accessing non public members of a class is
+ * fired correctly.
+ * @compile/fail/ref=WarnSerializableElementTest.out -XDrawDiagnostics -Werror -XDwarnOnAccessToMembers WarnSerializableElementTest.java
+ */
+
+import java.io.Serializable;
+
+public class WarnSerializableElementTest {
+
+ void warnLambda() throws Exception {
+ SAM t3 = (SAM & Serializable)WarnSerializableElementTest::packageClassMethod;
+ SAM t4 = (SAM & Serializable)WarnSerializableElementTest::protectedClassMethod;
+ SAM t5 = (SAM & Serializable)WarnSerializableElementTest::privateClassMethod;
+
+ WarnSerializableElementTest test = new WarnSerializableElementTest();
+ SAM t6 = (SAM & Serializable)test::packageInstanceMethod;
+ SAM t7 = (SAM & Serializable)test::protectedInstanceMethod;
+ SAM t8 = (SAM & Serializable)test::privateInstanceMethod;
+
+ SAM t9 = (SAM & Serializable) c -> {
+
+ WarnSerializableElementTest.staticPackageField = "";
+ WarnSerializableElementTest.staticProtectedField = "";
+ WarnSerializableElementTest.staticPrivateField = "";
+
+ packageField = "";
+ protectedField = "";
+ privateField = "";
+
+ WarnSerializableElementTest.packageClassMethod(null);
+ WarnSerializableElementTest.protectedClassMethod(null);
+ WarnSerializableElementTest.privateClassMethod(null);
+
+ packageInstanceMethod(null);
+ protectedInstanceMethod(null);
+ privateInstanceMethod(null);
+
+ PrivateClass.effectivelyNonPublicStaticField = "";
+ PrivateClass.effectivelyNonPublicClassMethod();
+
+ PrivateClass p = new PrivateClass();
+ p.effectivelyNonPublicInstanceField = "";
+ p.effectivelyNonPublicInstanceMethod();
+
+ return null;
+ };
+ }
+
+ private void warnAnoInnerClass() throws Exception {
+ new SerializableDesc() {
+ public void m(Object param) throws Exception {
+ WarnSerializableElementTest.staticPackageField = "";
+ WarnSerializableElementTest.staticProtectedField = "";
+ WarnSerializableElementTest.staticPrivateField = "";
+
+ packageField = "";
+ protectedField = "";
+ privateField = "";
+
+ WarnSerializableElementTest.packageClassMethod(null);
+ WarnSerializableElementTest.protectedClassMethod(null);
+ WarnSerializableElementTest.privateClassMethod(null);
+
+ packageInstanceMethod(null);
+ protectedInstanceMethod(null);
+ privateInstanceMethod(null);
+
+ PrivateClass.effectivelyNonPublicStaticField = "";
+ PrivateClass.effectivelyNonPublicClassMethod();
+
+ PrivateClass p = new PrivateClass();
+ p.effectivelyNonPublicInstanceField = "";
+ p.effectivelyNonPublicInstanceMethod();
+ }
+ };
+ }
+
+ void dontWarnLambda() throws Exception {
+ SAM t1 = (SAM & Serializable)WarnSerializableElementTest::publicClassMethod;
+
+ WarnSerializableElementTest test = new WarnSerializableElementTest();
+ SAM t2 = (SAM & Serializable)test::publicInstanceMethod;
+
+ int[] buffer = {0};
+
+ SAM t3 = (SAM & Serializable) param -> {
+ Object localVar;
+ localVar = null;
+ param = null;
+
+ WarnSerializableElementTest.staticPublicField = "";
+ publicField = "";
+ WarnSerializableElementTest.publicClassMethod(null);
+ publicInstanceMethod(null);
+
+ PublicClass.effectivelyPublicStaticField = "";
+ PublicClass.effectivelyPublicClassMethod();
+
+ PublicClass p = new PublicClass();
+ p.effectivelyPublicInstanceField = "";
+ p.effectivelyPublicInstanceMethod();
+
+ int l = buffer.length;
+
+ return null;
+ };
+ }
+
+ private void dontWarnAnoInnerClass() throws Exception {
+ final int[] buffer = {0};
+ new SerializableDesc() {
+ public void m(Object param) throws Exception {
+ Object localVar;
+ localVar = null;
+ param = null;
+
+ WarnSerializableElementTest.staticPublicField = "";
+ publicField = "";
+ WarnSerializableElementTest.publicClassMethod(null);
+ publicInstanceMethod(null);
+
+ PublicClass.effectivelyPublicStaticField = "";
+ PublicClass.effectivelyPublicClassMethod();
+
+ PublicClass p = new PublicClass();
+ p.effectivelyPublicInstanceField = "";
+ p.effectivelyPublicInstanceMethod();
+
+ int l = buffer.length;
+ }
+ };
+ }
+
+ enum WarnEnum {
+ A {
+ public void m() throws Exception {
+ WarnSerializableElementTest.staticPackageField = "";
+ WarnSerializableElementTest.staticProtectedField = "";
+ WarnSerializableElementTest.staticPrivateField = "";
+
+ WarnSerializableElementTest test =
+ new WarnSerializableElementTest();
+
+ test.packageField = "";
+ test.protectedField = "";
+ test.privateField = "";
+
+ WarnSerializableElementTest.packageClassMethod(null);
+ WarnSerializableElementTest.protectedClassMethod(null);
+ WarnSerializableElementTest.privateClassMethod(null);
+
+ test.packageInstanceMethod(null);
+ test.protectedInstanceMethod(null);
+ test.privateInstanceMethod(null);
+
+ PrivateClass.effectivelyNonPublicStaticField = "";
+ PrivateClass.effectivelyNonPublicClassMethod();
+
+ PrivateClass p = new PrivateClass();
+ p.effectivelyNonPublicInstanceField = "";
+ p.effectivelyNonPublicInstanceMethod();
+ }
+ };
+
+ public void m() throws Exception {}
+ }
+
+ static String staticPackageField;
+ static private String staticPrivateField;
+ static protected String staticProtectedField;
+ static public String staticPublicField;
+
+ String packageField;
+ private String privateField;
+ protected String protectedField;
+ public String publicField;
+
+ static Object packageClassMethod(String s) {
+ return null;
+ }
+
+ static private Object privateClassMethod(String s) {
+ return null;
+ }
+
+ static protected Object protectedClassMethod(String s) {
+ return null;
+ }
+
+ static public Object publicClassMethod(String s) {
+ return null;
+ }
+
+ Object packageInstanceMethod(String s) {
+ return null;
+ }
+
+ protected Object protectedInstanceMethod(String s) {
+ return null;
+ }
+
+ private Object privateInstanceMethod(String s) {
+ return null;
+ }
+
+ public Object publicInstanceMethod(String s) {
+ return null;
+ }
+
+ interface SAM {
+ Object apply(String s) throws Exception;
+ }
+
+ interface SAM2 {
+ Object apply(String arg1, String arg2);
+ }
+
+ class SerializableDesc implements Serializable {
+ public void m(Object param) throws Exception {}
+ }
+
+ static private class PrivateClass {
+ static public String effectivelyNonPublicStaticField;
+ public String effectivelyNonPublicInstanceField;
+
+ static public void effectivelyNonPublicClassMethod() {}
+ public void effectivelyNonPublicInstanceMethod() {}
+ }
+
+ static public class PublicClass {
+ static public String effectivelyPublicStaticField;
+ public String effectivelyPublicInstanceField;
+
+ static public void effectivelyPublicClassMethod() {}
+ public void effectivelyPublicInstanceMethod() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableElementTest.out Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,35 @@
+WarnSerializableElementTest.java:56:44: compiler.warn.access.to.member.from.serializable.element: staticPackageField
+WarnSerializableElementTest.java:57:44: compiler.warn.access.to.member.from.serializable.element: staticProtectedField
+WarnSerializableElementTest.java:58:44: compiler.warn.access.to.member.from.serializable.element: staticPrivateField
+WarnSerializableElementTest.java:60:17: compiler.warn.access.to.member.from.serializable.element: packageField
+WarnSerializableElementTest.java:61:17: compiler.warn.access.to.member.from.serializable.element: protectedField
+WarnSerializableElementTest.java:62:17: compiler.warn.access.to.member.from.serializable.element: privateField
+WarnSerializableElementTest.java:64:44: compiler.warn.access.to.member.from.serializable.element: packageClassMethod(java.lang.String)
+WarnSerializableElementTest.java:65:44: compiler.warn.access.to.member.from.serializable.element: protectedClassMethod(java.lang.String)
+WarnSerializableElementTest.java:66:44: compiler.warn.access.to.member.from.serializable.element: privateClassMethod(java.lang.String)
+WarnSerializableElementTest.java:68:17: compiler.warn.access.to.member.from.serializable.element: packageInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:69:17: compiler.warn.access.to.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:70:17: compiler.warn.access.to.member.from.serializable.element: privateInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:72:29: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicStaticField
+WarnSerializableElementTest.java:73:29: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicClassMethod()
+WarnSerializableElementTest.java:76:18: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicInstanceField
+WarnSerializableElementTest.java:77:18: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicInstanceMethod()
+WarnSerializableElementTest.java:141:44: compiler.warn.access.to.member.from.serializable.element: staticPackageField
+WarnSerializableElementTest.java:142:44: compiler.warn.access.to.member.from.serializable.element: staticProtectedField
+WarnSerializableElementTest.java:143:44: compiler.warn.access.to.member.from.serializable.element: staticPrivateField
+WarnSerializableElementTest.java:148:21: compiler.warn.access.to.member.from.serializable.element: packageField
+WarnSerializableElementTest.java:149:21: compiler.warn.access.to.member.from.serializable.element: protectedField
+WarnSerializableElementTest.java:150:21: compiler.warn.access.to.member.from.serializable.element: privateField
+WarnSerializableElementTest.java:152:44: compiler.warn.access.to.member.from.serializable.element: packageClassMethod(java.lang.String)
+WarnSerializableElementTest.java:153:44: compiler.warn.access.to.member.from.serializable.element: protectedClassMethod(java.lang.String)
+WarnSerializableElementTest.java:154:44: compiler.warn.access.to.member.from.serializable.element: privateClassMethod(java.lang.String)
+WarnSerializableElementTest.java:156:21: compiler.warn.access.to.member.from.serializable.element: packageInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:157:21: compiler.warn.access.to.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:158:21: compiler.warn.access.to.member.from.serializable.element: privateInstanceMethod(java.lang.String)
+WarnSerializableElementTest.java:160:29: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicStaticField
+WarnSerializableElementTest.java:161:29: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicClassMethod()
+WarnSerializableElementTest.java:164:18: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicInstanceField
+WarnSerializableElementTest.java:165:18: compiler.warn.access.to.member.from.serializable.element: effectivelyNonPublicInstanceMethod()
+- compiler.err.warnings.and.werror
+1 error
+32 warnings
--- a/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.java Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 8029102
- * @summary Enhance compiler warnings for Lambda
- * Checks that the warning for accessing non public members of a class is
- * fired correctly.
- * @compile/fail/ref=WarnSerializableLambdaTest.out -XDrawDiagnostics -Werror -XDwarnOnAccessToSensitiveMembers WarnSerializableLambdaTest.java
- */
-
-import java.io.Serializable;
-
-public class WarnSerializableLambdaTest {
-
- void warnLambda() throws Exception {
- SAM t3 = (SAM & Serializable)WarnSerializableLambdaTest::packageClassMethod;
- SAM t4 = (SAM & Serializable)WarnSerializableLambdaTest::protectedClassMethod;
- SAM t5 = (SAM & Serializable)WarnSerializableLambdaTest::privateClassMethod;
-
- WarnSerializableLambdaTest test = new WarnSerializableLambdaTest();
- SAM t6 = (SAM & Serializable)test::packageInstanceMethod;
- SAM t7 = (SAM & Serializable)test::protectedInstanceMethod;
- SAM t8 = (SAM & Serializable)test::privateInstanceMethod;
-
- SAM t9 = (SAM & Serializable) c -> {
-
- WarnSerializableLambdaTest.staticPackageField = "";
- WarnSerializableLambdaTest.staticProtectedField = "";
- WarnSerializableLambdaTest.staticPrivateField = "";
-
- packageField = "";
- protectedField = "";
- privateField = "";
-
- WarnSerializableLambdaTest.packageClassMethod(null);
- WarnSerializableLambdaTest.protectedClassMethod(null);
- WarnSerializableLambdaTest.privateClassMethod(null);
-
- packageInstanceMethod(null);
- protectedInstanceMethod(null);
- privateInstanceMethod(null);
-
- PrivateClass.effectivelyNonPublicStaticField = "";
- PrivateClass.effectivelyNonPublicClassMethod();
-
- PrivateClass p = new PrivateClass();
- p.effectivelyNonPublicInstanceField = "";
- p.effectivelyNonPublicInstanceMethod();
-
- return null;
- };
- }
-
- private void warnAnoInnerClass() throws Exception {
- new SerializableDesc() {
- public void m(Object param) throws Exception {
- WarnSerializableLambdaTest.staticPackageField = "";
- WarnSerializableLambdaTest.staticProtectedField = "";
- WarnSerializableLambdaTest.staticPrivateField = "";
-
- packageField = "";
- protectedField = "";
- privateField = "";
-
- WarnSerializableLambdaTest.packageClassMethod(null);
- WarnSerializableLambdaTest.protectedClassMethod(null);
- WarnSerializableLambdaTest.privateClassMethod(null);
-
- packageInstanceMethod(null);
- protectedInstanceMethod(null);
- privateInstanceMethod(null);
-
- PrivateClass.effectivelyNonPublicStaticField = "";
- PrivateClass.effectivelyNonPublicClassMethod();
-
- PrivateClass p = new PrivateClass();
- p.effectivelyNonPublicInstanceField = "";
- p.effectivelyNonPublicInstanceMethod();
- }
- };
- }
-
- void dontWarnLambda() throws Exception {
- SAM t1 = (SAM & Serializable)WarnSerializableLambdaTest::publicClassMethod;
-
- WarnSerializableLambdaTest test = new WarnSerializableLambdaTest();
- SAM t2 = (SAM & Serializable)test::publicInstanceMethod;
-
- int[] buffer = {0};
-
- SAM t3 = (SAM & Serializable) param -> {
- Object localVar;
- localVar = null;
- param = null;
-
- WarnSerializableLambdaTest.staticPublicField = "";
- publicField = "";
- WarnSerializableLambdaTest.publicClassMethod(null);
- publicInstanceMethod(null);
-
- PublicClass.effectivelyPublicStaticField = "";
- PublicClass.effectivelyPublicClassMethod();
-
- PublicClass p = new PublicClass();
- p.effectivelyPublicInstanceField = "";
- p.effectivelyPublicInstanceMethod();
-
- int l = buffer.length;
-
- return null;
- };
- }
-
- private void dontWarnAnoInnerClass() throws Exception {
- final int[] buffer = {0};
- new SerializableDesc() {
- public void m(Object param) throws Exception {
- Object localVar;
- localVar = null;
- param = null;
-
- WarnSerializableLambdaTest.staticPublicField = "";
- publicField = "";
- WarnSerializableLambdaTest.publicClassMethod(null);
- publicInstanceMethod(null);
-
- PublicClass.effectivelyPublicStaticField = "";
- PublicClass.effectivelyPublicClassMethod();
-
- PublicClass p = new PublicClass();
- p.effectivelyPublicInstanceField = "";
- p.effectivelyPublicInstanceMethod();
-
- int l = buffer.length;
- }
- };
- }
-
- enum WarnEnum {
- A {
- public void m() throws Exception {
- WarnSerializableLambdaTest.staticPackageField = "";
- WarnSerializableLambdaTest.staticProtectedField = "";
- WarnSerializableLambdaTest.staticPrivateField = "";
-
- WarnSerializableLambdaTest test =
- new WarnSerializableLambdaTest();
-
- test.packageField = "";
- test.protectedField = "";
- test.privateField = "";
-
- WarnSerializableLambdaTest.packageClassMethod(null);
- WarnSerializableLambdaTest.protectedClassMethod(null);
- WarnSerializableLambdaTest.privateClassMethod(null);
-
- test.packageInstanceMethod(null);
- test.protectedInstanceMethod(null);
- test.privateInstanceMethod(null);
-
- PrivateClass.effectivelyNonPublicStaticField = "";
- PrivateClass.effectivelyNonPublicClassMethod();
-
- PrivateClass p = new PrivateClass();
- p.effectivelyNonPublicInstanceField = "";
- p.effectivelyNonPublicInstanceMethod();
- }
- };
-
- public void m() throws Exception {}
- }
-
- static String staticPackageField;
- static private String staticPrivateField;
- static protected String staticProtectedField;
- static public String staticPublicField;
-
- String packageField;
- private String privateField;
- protected String protectedField;
- public String publicField;
-
- static Object packageClassMethod(String s) {
- return null;
- }
-
- static private Object privateClassMethod(String s) {
- return null;
- }
-
- static protected Object protectedClassMethod(String s) {
- return null;
- }
-
- static public Object publicClassMethod(String s) {
- return null;
- }
-
- Object packageInstanceMethod(String s) {
- return null;
- }
-
- protected Object protectedInstanceMethod(String s) {
- return null;
- }
-
- private Object privateInstanceMethod(String s) {
- return null;
- }
-
- public Object publicInstanceMethod(String s) {
- return null;
- }
-
- interface SAM {
- Object apply(String s) throws Exception;
- }
-
- interface SAM2 {
- Object apply(String arg1, String arg2);
- }
-
- class SerializableDesc implements Serializable {
- public void m(Object param) throws Exception {}
- }
-
- static private class PrivateClass {
- static public String effectivelyNonPublicStaticField;
- public String effectivelyNonPublicInstanceField;
-
- static public void effectivelyNonPublicClassMethod() {}
- public void effectivelyNonPublicInstanceMethod() {}
- }
-
- static public class PublicClass {
- static public String effectivelyPublicStaticField;
- public String effectivelyPublicInstanceField;
-
- static public void effectivelyPublicClassMethod() {}
- public void effectivelyPublicInstanceMethod() {}
- }
-}
--- a/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTest.out Thu Oct 27 09:38:46 2016 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-WarnSerializableLambdaTest.java:15:38: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:16:38: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:17:38: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:20:38: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:21:38: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:22:38: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:26:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField
-WarnSerializableLambdaTest.java:27:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField
-WarnSerializableLambdaTest.java:28:39: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField
-WarnSerializableLambdaTest.java:30:13: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField
-WarnSerializableLambdaTest.java:31:13: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField
-WarnSerializableLambdaTest.java:32:13: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField
-WarnSerializableLambdaTest.java:34:39: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:35:39: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:36:39: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:38:13: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:39:13: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:40:13: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:42:25: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField
-WarnSerializableLambdaTest.java:43:25: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod()
-WarnSerializableLambdaTest.java:46:14: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField
-WarnSerializableLambdaTest.java:47:14: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod()
-WarnSerializableLambdaTest.java:56:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField
-WarnSerializableLambdaTest.java:57:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField
-WarnSerializableLambdaTest.java:58:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField
-WarnSerializableLambdaTest.java:60:17: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField
-WarnSerializableLambdaTest.java:61:17: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField
-WarnSerializableLambdaTest.java:62:17: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField
-WarnSerializableLambdaTest.java:64:43: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:65:43: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:66:43: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:68:17: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:69:17: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:70:17: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:72:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField
-WarnSerializableLambdaTest.java:73:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod()
-WarnSerializableLambdaTest.java:76:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField
-WarnSerializableLambdaTest.java:77:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod()
-WarnSerializableLambdaTest.java:141:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPackageField
-WarnSerializableLambdaTest.java:142:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticProtectedField
-WarnSerializableLambdaTest.java:143:43: compiler.warn.access.to.sensitive.member.from.serializable.element: staticPrivateField
-WarnSerializableLambdaTest.java:148:21: compiler.warn.access.to.sensitive.member.from.serializable.element: packageField
-WarnSerializableLambdaTest.java:149:21: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedField
-WarnSerializableLambdaTest.java:150:21: compiler.warn.access.to.sensitive.member.from.serializable.element: privateField
-WarnSerializableLambdaTest.java:152:43: compiler.warn.access.to.sensitive.member.from.serializable.element: packageClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:153:43: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:154:43: compiler.warn.access.to.sensitive.member.from.serializable.element: privateClassMethod(java.lang.String)
-WarnSerializableLambdaTest.java:156:21: compiler.warn.access.to.sensitive.member.from.serializable.element: packageInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:157:21: compiler.warn.access.to.sensitive.member.from.serializable.element: protectedInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:158:21: compiler.warn.access.to.sensitive.member.from.serializable.element: privateInstanceMethod(java.lang.String)
-WarnSerializableLambdaTest.java:160:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicStaticField
-WarnSerializableLambdaTest.java:161:29: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicClassMethod()
-WarnSerializableLambdaTest.java:164:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceField
-WarnSerializableLambdaTest.java:165:18: compiler.warn.access.to.sensitive.member.from.serializable.element: effectivelyNonPublicInstanceMethod()
-- compiler.err.warnings.and.werror
-1 error
-54 warnings
--- a/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.java Thu Oct 27 09:42:08 2016 -0700
@@ -4,7 +4,7 @@
* @summary Enhance compiler warnings for Lambda
* Checks that the warning for accessing non public members of a class is
* fired correctly.
- * @compile/fail/ref=WarnSerializableLambdaTestb.out -XDrawDiagnostics -Werror -XDwarnOnAccessToSensitiveMembers WarnSerializableLambdaTestb.java
+ * @compile/fail/ref=WarnSerializableLambdaTestb.out -XDrawDiagnostics -Werror -XDwarnOnAccessToMembers WarnSerializableLambdaTestb.java
*/
import java.io.Serializable;
--- a/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.out Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.out Thu Oct 27 09:42:08 2016 -0700
@@ -1,7 +1,5 @@
-WarnSerializableLambdaTestb.java:14:69: compiler.warn.access.to.sensitive.member.from.serializable.element: test()
-WarnSerializableLambdaTestb.java:18:69: compiler.warn.access.to.sensitive.member.from.serializable.element: test()
-WarnSerializableLambdaTestb.java:36:40: compiler.warn.access.to.sensitive.member.from.serializable.element: j
-WarnSerializableLambdaTestb.java:50:25: compiler.warn.access.to.sensitive.member.from.serializable.element: r
+WarnSerializableLambdaTestb.java:36:40: compiler.warn.access.to.member.from.serializable.element: j
+WarnSerializableLambdaTestb.java:50:25: compiler.warn.access.to.member.from.serializable.element: r
- compiler.err.warnings.and.werror
1 error
-4 warnings
+2 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestc.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,20 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8026721
+ * @summary Enhance Lambda serialization
+ * Checks that the warning for accessing non public members of a class is fired correctly.
+ * @compile -Xlint:serial -Werror WarnSerializableLambdaTestc.java
+ */
+
+import javax.tools.SimpleJavaFileObject;
+import java.io.Serializable;
+
+public class WarnSerializableLambdaTestc {
+ public interface SerializableIntf<T> extends Serializable {
+ String get(T o);
+ }
+
+ private void dontWarn() {
+ SerializableIntf<SimpleJavaFileObject> s = SimpleJavaFileObject::getName;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestc.out Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,4 @@
+WarnSerializableLambdaTestc.java:18:52: compiler.warn.access.to.member.from.serializable.lambda
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -21,8 +21,11 @@
* questions.
*/
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
import javax.tools.ToolProvider;
-import java.util.Objects;
/**
* @test
@@ -36,6 +39,18 @@
// run in other vm to ensure the initialization code path is exercised.
public class ToolProviderTest {
public static void main(String... args) {
+ // The following code allows the test to be skipped when run on
+ // an exploded image.
+ // See https://bugs.openjdk.java.net/browse/JDK-8155858
+ Path javaHome = Paths.get(System.getProperty("java.home"));
+ Path image = javaHome.resolve("lib").resolve("modules");
+ Path modules = javaHome.resolve("modules");
+ if (!Files.exists(image) && Files.exists(modules)) {
+ System.err.println("Test running on exploded image");
+ System.err.println("Test skipped!");
+ return;
+ }
+
System.setSecurityManager(new SecurityManager());
Objects.requireNonNull(ToolProvider.getSystemDocumentationTool());
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Thu Oct 27 09:42:08 2016 -0700
@@ -257,6 +257,8 @@
// ignore package and class names
if (cs.matches("(com|java|javax|jdk|sun)\\.[A-Za-z.]+"))
continue;
+ if (cs.matches("(java|javax|sun)\\."))
+ continue;
// ignore debug flag names
if (cs.startsWith("debug."))
continue;
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Thu Oct 27 09:42:08 2016 -0700
@@ -111,6 +111,7 @@
compiler.err.cant.inherit.from.anon # error for subclass of anonymous class
compiler.misc.bad.class.file # class file is malformed
compiler.misc.bad.const.pool.entry # constant pool entry has wrong type
+compiler.warn.access.to.member.from.serializable.lambda # in order to generate it we need to modify a restricted package
# The following module-related messages will have to stay on the not-yet list for various reasons:
compiler.warn.locn.unknown.file.on.module.path # Never issued ATM (short circuited with an if (false))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalFilename.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.note.removal.filename
+// key: compiler.note.removal.recompile
+// options: -Xlint:-removal
+
+class RemovalFilename {
+ RemovalClass d;
+}
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalFilenameAdditional.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.note.removal.filename.additional
+// key: compiler.warn.has.been.deprecated.for.removal
+// options: -Xmaxwarns 1
+
+class RemovalFilename {
+ RemovalClass d;
+}
+
+class RemovalFilenameAdditional {
+ RemovalClass d;
+}
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalClass.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalFilename.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+class RemovalFileName {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalPlural.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.note.removal.plural
+// key: compiler.note.removal.recompile
+// options: -Xlint:-removal
+
+class RemovalPlural {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalClass.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalFilename.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+class RemovalFileName {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalPlural.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+class RemovalPlural {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalPluralAdditional.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+// key: compiler.note.removal.plural.additional
+// key: compiler.warn.has.been.deprecated.for.removal
+// options: -Xlint:deprecation -Xmaxwarns 1
+
+class RemovalPluralAdditional {
+ RemovalClass d;
+}
--- a/langtools/test/tools/javac/diags/examples/WarnSerializableLambda.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/diags/examples/WarnSerializableLambda.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,21 +21,24 @@
* questions.
*/
-// key: compiler.warn.access.to.sensitive.member.from.serializable.element
-// options: -XDwarnOnAccessToSensitiveMembers
+// key: compiler.warn.access.to.member.from.serializable.element
+// options: -XDwarnOnAccessToMembers
import java.io.Serializable;
public class WarnSerializableLambda {
- interface SAM {
- void apply(String s);
- }
-
private void m1() {
- SAM s = (SAM & Serializable) c -> {
- packageField = "";
+ new SerializableClass() {
+ @Override
+ public void m() {
+ packageField = "";
+ }
};
}
String packageField;
+
+ class SerializableClass implements Serializable {
+ public void m() {}
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8168480/T8168480.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,125 @@
+/*
+ * @test
+ * @bug 8168480
+ * @summary Speculative attribution of lambda causes NPE in Flow
+ * @compile T8168480.java
+ */
+
+import java.util.function.Supplier;
+
+class T8168480 {
+ void f(Runnable r) { }
+ void s(Supplier<Runnable> r) { }
+
+ private void testVoid(boolean cond) {
+ f(() ->
+ new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ }.run());
+
+ f(() ->
+ f(() -> {
+ switch (42) {
+ default:
+ break;
+ }
+ }));
+
+ f(() -> {
+ if (cond) {
+ new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ }.run();
+ } else {
+ f(() -> {
+ switch (42) {
+ default:
+ break;
+ }
+ });
+ }
+ });
+ }
+
+ private void testReturn(boolean cond) {
+ s(() ->
+ new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ });
+
+ s(() ->
+ () -> {
+ switch (42) {
+ default:
+ break;
+ }
+ });
+
+ s(() -> {
+ if (cond) {
+ return new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ };
+ } else {
+ return () -> {
+ switch (42) {
+ default:
+ break;
+ }
+ };
+ }
+ });
+
+ s(() -> {
+ return cond ?
+ new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ } : () -> {
+ switch (42) {
+ default:
+ break;
+ }
+ };
+ });
+
+ s(() -> cond ?
+ new Runnable() {
+ public void run() {
+ switch (42) {
+ default:
+ break;
+ }
+ }
+ } : () -> {
+ switch (42) {
+ default:
+ break;
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8168480/T8168480b.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8168480
+ * @summary Speculative attribution of lambda causes NPE in Flow
+ * @compile/fail/ref=T8168480b.out -XDrawDiagnostics T8168480b.java
+ */
+
+import java.util.function.Supplier;
+
+class T8168480b {
+ Supplier<Runnable> ssr = () -> () -> { while (true); System.err.println("Hello"); };
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8168480/T8168480b.out Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,2 @@
+T8168480b.java:11:57: compiler.err.unreachable.stmt
+1 error
--- a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -26,6 +26,7 @@
* @bug 8002099 8010822
* @summary Add support for intersection types in cast expression
* @modules jdk.compiler/com.sun.tools.javac.util
+ * @run main/othervm IntersectionTargetTypeTest
*/
import com.sun.source.util.JavacTask;
--- a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java Thu Oct 27 09:42:08 2016 -0700
@@ -31,6 +31,7 @@
*/
import java.io.File;
+import java.nio.file.Path;
import java.util.*;
import java.util.Map.Entry;
@@ -84,7 +85,9 @@
continue;
if (type.endsWith("module-info"))
continue;
- String moduleName = fm.asPath(file).getName(1).toString();
+ Path path = fm.asPath(file);
+ int moduleIndex = path.getNameCount() - type.split("\\Q.\\E").length - 1;
+ String moduleName = path.getName(moduleIndex).toString();
try {
ModuleElement me = elements.getModuleElement(moduleName);
me.getClass();
--- a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Oct 27 09:42:08 2016 -0700
@@ -25,7 +25,7 @@
* @test
* @bug 8038455
* @summary Verify that annotation processor can overwrite source and class files it generated
- * during previous compilations, and that the Symbols are updated appropriatelly.
+ * during previous compilations, and that the Symbols are updated appropriately.
* @library /tools/lib /tools/javac/lib/
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
--- a/langtools/test/tools/javac/profiles/ProfileOptionTest.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/javac/profiles/ProfileOptionTest.java Thu Oct 27 09:42:08 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -176,9 +176,14 @@
Arrays.asList(fo));
task.analyze();
- List<String> expectDiagCodes = (p.value >= e.getKey().value)
- ? Collections.<String>emptyList()
- : Arrays.asList("compiler.err.not.in.profile");
+ List<String> expectDiagCodes = new ArrayList<>();
+ if (fo.getName().equals("TPolicyFile.java")) {
+ expectDiagCodes.add("compiler.warn.has.been.deprecated.for.removal");
+ }
+
+ if (p.value < e.getKey().value) {
+ expectDiagCodes.add("compiler.err.not.in.profile");
+ }
checkDiags(opts + " " + fo.getName(), dl.getDiagnostics(), expectDiagCodes);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/Removal.java Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,544 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8145471
+ * @summary javac changes for enhanced deprecation
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * @modules jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
+ * @run main Removal
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import toolbox.JavacTask;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+/*
+ * From JEP 277, JDK-8085614
+ *
+ * use site | API declaration site
+ * context | not dep. ord. dep. term. dep.
+ * +----------------------------------
+ * not dep. | N W W
+ * |
+ * ord. dep. | N N (2) W (4)
+ * |
+ * term. dep. | N N (3) W (5)
+ */
+
+public class Removal extends TestRunner {
+ public static void main(String... args) throws Exception {
+ Removal r = new Removal();
+ r.runTests(m -> new Object[] { Paths.get(m.getName()) });
+ r.report();
+ }
+
+ private final ToolBox tb = new ToolBox();
+ private final Path libSrc = Paths.get("lib").resolve("src");
+ private final Path libClasses = Paths.get("lib").resolve("classes");
+ int testCount = 0;
+
+ /**
+ * Options that may be used during compilation.
+ */
+ enum Options {
+ DEFAULT(),
+ XLINT_DEPRECATED("-Xlint:deprecation"),
+ XLINT_NO_REMOVAL("-Xlint:-removal");
+
+ Options(String... opts) {
+ this.opts = Arrays.asList(opts);
+ }
+
+ final List<String> opts;
+ }
+
+ /**
+ * The kind of deprecation.
+ */
+ enum DeprKind {
+ NONE("", null),
+ DEPRECATED("@Deprecated ", "compiler.warn.has.been.deprecated"),
+ REMOVAL("@Deprecated(forRemoval=true) ", "compiler.warn.has.been.deprecated.for.removal");
+ DeprKind(String anno, String warn) {
+ this.anno = anno;
+ this.warn = warn;
+ }
+ final String anno;
+ final String warn;
+ }
+
+ final String[] lib = {
+ "package lib; public class Class {\n"
+ + " public static void method() { }\n"
+ + " @Deprecated public static void depMethod() { }\n"
+ + " @Deprecated(forRemoval=true) public static void remMethod() { }\n"
+ + " public static int field;\n"
+ + " @Deprecated public static int depField;\n"
+ + " @Deprecated(forRemoval=true) public static int remField;\n"
+ + "}",
+ "package lib; @Deprecated public class DepClass { }",
+ "package lib; @Deprecated(forRemoval=true) public class RemClass { }"
+ };
+
+ /**
+ * The kind of declaration to be referenced at the use site.
+ */
+ enum RefKind {
+ CLASS("lib.%s c;", "Class", "DepClass", "RemClass"),
+ METHOD("{ lib.Class.%s(); }", "method", "depMethod", "remMethod"),
+ FIELD("int i = lib.Class.%s;", "field", "depField", "remField");
+
+ RefKind(String template, String def, String dep, String rem) {
+ fragments.put(DeprKind.NONE, String.format(template, def));
+ fragments.put(DeprKind.DEPRECATED, String.format(template, dep));
+ fragments.put(DeprKind.REMOVAL, String.format(template, rem));
+ }
+
+ String getFragment(DeprKind k) {
+ return fragments.get(k);
+ }
+
+ private final Map<DeprKind, String> fragments = new EnumMap<>(DeprKind.class);
+ }
+
+ /**
+ * Get source code for a reference to a possibly-deprecated item declared in a library.
+ * @param refKind the kind of element (class, method, field) being referenced
+ * @param declDeprKind the kind of deprecation on the declaration of the item being referenced
+ * @param useDeprKind the kind of deprecation enclosing the use site
+ * @return
+ */
+ static String getSource(RefKind refKind, DeprKind declDeprKind, DeprKind useDeprKind) {
+ return "package p; "
+ + useDeprKind.anno
+ + "class Class { "
+ + refKind.getFragment(declDeprKind)
+ + " }";
+ }
+
+ private static final String NO_OUTPUT = null;
+
+ public Removal() throws IOException {
+ super(System.err);
+ initLib();
+ }
+
+ void initLib() throws IOException {
+ tb.writeJavaFiles(libSrc, lib);
+
+ new JavacTask(tb)
+ .outdir(Files.createDirectories(libClasses))
+ .files(tb.findJavaFiles(libSrc))
+ .run()
+ .writeAll();
+ }
+
+ void report() {
+ out.println(testCount + " test cases");
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: not deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseNone(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.NONE),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseDeprecated(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: deprecated for removal
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: not deprecated
+ * Options: default
+ * Expect: deprecated note
+ */
+ @Test
+ public void test_DeclDeprecated_UseNone_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.NONE),
+ Options.DEFAULT,
+ "compiler.note.deprecated.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: not deprecated
+ * Options: -Xlint:deprecation
+ * Expect: deprecated warning
+ */
+ @Test
+ public void test_DeclDeprecated_UseNone_XlintDep(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:29: compiler.warn.has.been.deprecated: lib.DepClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:37: compiler.warn.has.been.deprecated: depMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:43: compiler.warn.has.been.deprecated: depField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.NONE),
+ Options.XLINT_DEPRECATED,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclDeprecated_UseDeprecated(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: deprecated for removal
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclDeprecated_UseRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:29: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:37: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:43: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: default, @SuppressWarnings("removal")
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_SuppressRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String source =
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE)
+ .replace("class Class", "@SuppressWarnings(\"removal\") class Class");
+
+ test(base,
+ source,
+ Options.DEFAULT,
+ null);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseDeprecated_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:41: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:49: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:55: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseDeprecated_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.DEPRECATED),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated for removal
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseRemoval_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:58: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:66: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:72: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated for removal
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseRemoval_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.REMOVAL),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Additional special case:
+ * there should not be any warnings for any reference in a type-import statement.
+ */
+ @Test
+ public void test_UseImports(Path base) throws IOException {
+ String source =
+ "import lib.Class;\n"
+ + "import lib.DepClass;\n"
+ + "import lib.RemClass;\n"
+ + "class C { }";
+ for (Options o : Options.values()) {
+ test(base, source, o, NO_OUTPUT);
+ }
+ }
+
+ /**
+ * Compile source code with given options, and check for expected output.
+ * The compilation is done twice, first against the library in source form,
+ * and then again, against the compiled library.
+ * @param base base working directory
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, String source, Options options, String expectText) throws IOException {
+ test(base.resolve("lib-source"), libSrc, source, options, expectText);
+ test(base.resolve("lib-classes"), libClasses, source, options, expectText);
+ }
+
+ /**
+ * Compile source code with given options against a given version of the library,
+ * and check for expected output.
+ * @param base base working directory
+ * @param lib the directory containing the library, in either source or compiled form
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, Path lib, String source, Options options, String expectText)
+ throws IOException {
+ Expect expect = (expectText != null && expectText.contains("compiler.warn.")) ? Expect.FAIL : Expect.SUCCESS;
+ test(base, lib, source, options.opts, expect, expectText);
+ }
+
+ /**
+ * Compile source code with given options against a given version of the library,
+ * and check for expected exit code and expected output.
+ * @param base base working directory
+ * @param lib the directory containing the library, in either source or compiled form
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expect the expected outcome of the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, Path lib, String source, List<String> options,
+ Expect expect, String expectText) throws IOException {
+ testCount++;
+
+ Path src = base.resolve("src");
+ Path classes = Files.createDirectories(base.resolve("classes"));
+ tb.writeJavaFiles(src, source);
+
+ List<String> allOptions = new ArrayList<>();
+ allOptions.add("-XDrawDiagnostics");
+ allOptions.add("-Werror");
+ allOptions.addAll(options);
+
+ out.println("Source: " + source);
+ out.println("Classpath: " + lib);
+ out.println("Options: " + options.stream().collect(Collectors.joining(" ")));
+
+ String log = new JavacTask(tb)
+ .outdir(classes)
+ .classpath(lib) // use classpath for libSrc or libClasses
+ .files(tb.findJavaFiles(src))
+ .options(allOptions.toArray(new String[0]))
+ .run(expect)
+ .writeAll()
+ .getOutput(OutputKind.DIRECT);
+
+ if (expectText == null) {
+ if (!log.trim().isEmpty())
+ error("Unexpected text found: >>>" + log + "<<<");
+ } else {
+ if (!log.contains(expectText))
+ error("expected text not found: >>>" + expectText + "<<<");
+ }
+ }
+}
+
--- a/langtools/test/tools/lib/toolbox/JavadocTask.java Thu Oct 27 09:38:46 2016 -0700
+++ b/langtools/test/tools/lib/toolbox/JavadocTask.java Thu Oct 27 09:42:08 2016 -0700
@@ -38,7 +38,9 @@
import java.util.stream.Stream;
import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.DocumentationTool;
import javax.tools.JavaFileManager;
+import javax.tools.JavaFileManager.Location;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
@@ -303,7 +305,8 @@
if (fileManager == null)
fileManager = internalFileManager = jdtool.getStandardFileManager(null, null, null);
if (outdir != null)
- setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outdir));
+ setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT,
+ Collections.singletonList(outdir));
if (classpath != null)
setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
if (sourcepath != null)
@@ -326,7 +329,7 @@
}
}
- private void setLocationFromPaths(StandardLocation location, List<Path> files) throws IOException {
+ private void setLocationFromPaths(Location location, List<Path> files) throws IOException {
if (!(fileManager instanceof StandardJavaFileManager))
throw new IllegalStateException("not a StandardJavaFileManager");
((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
--- a/make/CreateJmods.gmk Thu Oct 27 09:38:46 2016 -0700
+++ b/make/CreateJmods.gmk Thu Oct 27 09:42:08 2016 -0700
@@ -44,6 +44,10 @@
CONF_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
$(SUPPORT_OUTPUTDIR)/modules_conf $(IMPORT_MODULES_CONF))))
CLASSES_DIR := $(wildcard $(JDK_OUTPUTDIR)/modules/$(MODULE))
+INCLUDE_HEADERS_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
+ $(SUPPORT_OUTPUTDIR)/modules_include $(IMPORT_MODULES_INCLUDE_HEADERS))))
+MAN_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
+ $(SUPPORT_OUTPUTDIR)/modules_man $(IMPORT_MODULES_MAN))))
$(eval $(call FillCacheFind, \
$(LIBS_DIR) $(CMDS_DIR) $(CONF_DIR) $(CLASSES_DIR) \
@@ -65,6 +69,14 @@
JMOD_FLAGS += --class-path $(CLASSES_DIR)
DEPS += $(call CacheFind, $(CLASSES_DIR))
endif
+ifneq ($(INCLUDE_HEADERS_DIR), )
+ JMOD_FLAGS += --header-files $(INCLUDE_HEADERS_DIR)
+ DEPS += $(call CacheFind, $(INCLUDE_HEADERS_DIR))
+endif
+ifneq ($(MAN_DIR), )
+ JMOD_FLAGS += --man-pages $(MAN_DIR)
+ DEPS += $(call CacheFind, $(MAN_DIR))
+endif
# Add dependencies on other jmod files. Only java.base needs access to other
# jmods.
@@ -103,7 +115,7 @@
--os-arch $(OPENJDK_TARGET_CPU_LEGACY) \
--os-version $(REQUIRED_OS_VERSION) \
--module-path $(JMODS_DIR) \
- --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' \
+ --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' \
$(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
$(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@
--- a/make/Images.gmk Thu Oct 27 09:38:46 2016 -0700
+++ b/make/Images.gmk Thu Oct 27 09:42:08 2016 -0700
@@ -131,35 +131,41 @@
$(JLINK_JLI_CLASSES) \
#
+JLINK_JRE_EXTRA_OPTS := --no-man-pages --no-header-files
+
ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true)
- JLINK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods
+ JLINK_JDK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods
endif
$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JDK_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jdk jimage
$(RM) -r $(JDK_IMAGE_DIR)
- $(JLINK_TOOL) --output $(JDK_IMAGE_DIR) \
- --add-modules $(JDK_MODULES_LIST) $(JLINK_EXTRA_OPTS)
+ $(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \
+ $(JLINK_JDK_EXTRA_OPTS) \
+ --output $(JDK_IMAGE_DIR)
$(TOUCH) $@
$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre jimage
$(RM) -r $(JRE_IMAGE_DIR)
- $(JLINK_TOOL) --output $(JRE_IMAGE_DIR) \
- --add-modules $(JRE_MODULES_LIST)
+ $(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \
+ $(JLINK_JRE_EXTRA_OPTS) \
+ --output $(JRE_IMAGE_DIR)
$(TOUCH) $@
JRE_COMPACT1_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact1
JRE_COMPACT2_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact2
JRE_COMPACT3_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact3
+
$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact1 jimage
$(RM) -r $(JRE_COMPACT1_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT1_MODULES_LIST) \
+ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT1_IMAGE_DIR)
$(TOUCH) $@
@@ -168,6 +174,7 @@
$(ECHO) Creating jre compact2 jimage
$(RM) -r $(JRE_COMPACT2_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT2_MODULES_LIST) \
+ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT2_IMAGE_DIR)
$(TOUCH) $@
@@ -176,6 +183,7 @@
$(ECHO) Creating jre compact3 jimage
$(RM) -r $(JRE_COMPACT3_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT3_MODULES_LIST) \
+ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT3_IMAGE_DIR)
$(TOUCH) $@
@@ -313,16 +321,6 @@
endif # Windows
################################################################################
-# /include dir
-
-$(eval $(call SetupCopyFiles,COPY_INCLUDES, \
- SRC := $(JDK_OUTPUTDIR)/include, \
- DEST := $(JDK_IMAGE_DIR)/include, \
- FILES := $(call CacheFind,$(JDK_OUTPUTDIR)/include)))
-
-JDK_TARGETS += $(COPY_INCLUDES)
-
-################################################################################
# doc files
JRE_DOC_FILES ?= LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README
--- a/make/common/SetupJavaCompilers.gmk Thu Oct 27 09:38:46 2016 -0700
+++ b/make/common/SetupJavaCompilers.gmk Thu Oct 27 09:42:08 2016 -0700
@@ -28,11 +28,11 @@
include JavaCompilation.gmk
-DISABLE_WARNINGS := -Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough,-try,-varargs,-empty,-finally
+DISABLE_WARNINGS := -Xlint:all,-deprecation,-removal,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough,-try,-varargs,-empty,-finally
# If warnings needs to be non-fatal for testing purposes use a command like:
# make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000"
-JAVAC_WARNINGS := -Xlint:all -Werror
+JAVAC_WARNINGS := -Xlint:all,-removal -Werror
# The BOOT_JAVAC setup uses the boot jdk compiler to compile the tools
# and the interim javac, to be run by the boot jdk.
--- a/nashorn/.hgtags Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/.hgtags Thu Oct 27 09:42:08 2016 -0700
@@ -374,3 +374,4 @@
4a6ee1185fc821df063e4d1537fa7ad2ebe9eb02 jdk-9+138
e3b11296395b39bfeb3364f26c2ef77fa652e300 jdk-9+139
785843878cf78d50cc2959ea2c5a4202bbe885b4 jdk-9+140
+a46b7d3867957a868a6cc8ee66c05079b883733a jdk-9+141
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Thu Oct 27 09:42:08 2016 -0700
@@ -42,6 +42,8 @@
import jdk.internal.jline.console.ConsoleReader;
import jdk.internal.jline.console.KeyMap;
import jdk.internal.jline.extra.EditingHistory;
+import jdk.internal.misc.Signal;
+import jdk.internal.misc.Signal.Handler;
class Console implements AutoCloseable {
private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
@@ -68,6 +70,21 @@
in.addCompleter(completer);
Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
bind(DOCUMENTATION_SHORTCUT, (ActionListener)evt -> showDocumentation(docHelper));
+ try {
+ Signal.handle(new Signal("CONT"), new Handler() {
+ @Override public void handle(Signal sig) {
+ try {
+ in.getTerminal().reset();
+ in.redrawLine();
+ in.flush();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ });
+ } catch (IllegalArgumentException ignored) {
+ //the CONT signal does not exist on this platform
+ }
}
String readLine(final String prompt) throws IOException {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Thu Oct 27 09:42:08 2016 -0700
@@ -129,10 +129,11 @@
@Override
public String getProgram(final String... statements) {
+ Objects.requireNonNull(statements);
final StringBuilder sb = new StringBuilder();
for (final String statement : statements) {
- sb.append(statement).append(';');
+ sb.append(Objects.requireNonNull(statement)).append(';');
}
return sb.toString();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java Thu Oct 27 09:42:08 2016 -0700
@@ -47,13 +47,25 @@
private final Global global;
- ArrayIterator(final Object iteratedObject, final IterationKind iterationKind, final Global global) {
+ private ArrayIterator(final Object iteratedObject, final IterationKind iterationKind, final Global global) {
super(global.getArrayIteratorPrototype(), $nasgenmap$);
this.iteratedObject = iteratedObject instanceof ScriptObject ? (ScriptObject) iteratedObject : null;
this.iterationKind = iterationKind;
this.global = global;
}
+ static ArrayIterator newArrayValueIterator(final Object iteratedObject) {
+ return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.VALUE, Global.instance());
+ }
+
+ static ArrayIterator newArrayKeyIterator(final Object iteratedObject) {
+ return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.KEY, Global.instance());
+ }
+
+ static ArrayIterator newArrayKeyValueIterator(final Object iteratedObject) {
+ return new ArrayIterator(Global.toObject(iteratedObject), IterationKind.KEY_VALUE, Global.instance());
+ }
+
/**
* 22.1.5.2.1 %ArrayIteratorPrototype%.next()
*
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Thu Oct 27 09:42:08 2016 -0700
@@ -1726,7 +1726,7 @@
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object entries(final Object self) {
- return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY_VALUE, Global.instance());
+ return ArrayIterator.newArrayKeyValueIterator(self);
}
/**
@@ -1737,7 +1737,7 @@
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object keys(final Object self) {
- return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.KEY, Global.instance());
+ return ArrayIterator.newArrayKeyIterator(self);
}
/**
@@ -1748,7 +1748,7 @@
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object values(final Object self) {
- return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance());
+ return ArrayIterator.newArrayValueIterator(self);
}
/**
@@ -1759,7 +1759,7 @@
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
public static Object getIterator(final Object self) {
- return new ArrayIterator(Global.toObject(self), AbstractIterator.IterationKind.VALUE, Global.instance());
+ return ArrayIterator.newArrayValueIterator(self);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -232,6 +232,17 @@
return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getFloat32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -232,6 +232,17 @@
return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getFloat64ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -225,6 +225,17 @@
return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getInt16ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -224,6 +224,17 @@
return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getInt32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -224,6 +224,17 @@
return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getInt8ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Thu Oct 27 09:42:08 2016 -0700
@@ -701,13 +701,9 @@
}
thisIndex = matcher.end();
- if (thisIndex == string.length() && matcher.start() == matcher.end()) {
- // Avoid getting empty match at end of string twice
- break;
- }
- // ECMA 15.5.4.10 String.prototype.match(regexp)
- if (thisIndex == previousLastIndex) {
+ // ECMA6 21.2.5.6 step 8.g.iv.5: If matchStr is empty advance index by one
+ if (matcher.start() == matcher.end()) {
setLastIndex(thisIndex + 1);
previousLastIndex = thisIndex + 1;
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -229,6 +229,17 @@
return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getUint16ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -244,6 +244,17 @@
return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getUint32ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java Thu Oct 27 09:42:08 2016 -0700
@@ -230,6 +230,17 @@
return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getUint8ArrayPrototype();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Thu Oct 27 09:38:46 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Thu Oct 27 09:42:08 2016 -0700
@@ -82,7 +82,6 @@
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
private static final MethodHandle RINT_D = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle();
private static final MethodHandle RINT_O = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", Object.class, Object.class).methodHandle();
- private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle();
private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) {
super((nb.position(start).limit(end)).slice(), end - start);
@@ -124,8 +123,6 @@
return MH.filterArguments(setter, 2, RINT_O);
} else if (elementType == double.class) {
return MH.filterArguments(setter, 2, RINT_D);
- } else if (elementType == long.class) {
- return MH.filterArguments(setter, 2, CLAMP_LONG);
}
}
return setter;
@@ -195,7 +192,7 @@
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
- return set(index, rint(value), strict);
+ return set(index, (int) rint(value), strict);
}
private static double rint(final double rint) {
@@ -207,15 +204,6 @@
return rint(JSType.toNumber(rint));
}
- @SuppressWarnings("unused")
- private static long clampLong(final long l) {
- if(l < 0L) {
- return 0L;
- } else if(l > 0xffL) {
- return 0xffL;
- }
- return l;
- }
}
/**
@@ -278,6 +266,17 @@
return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end);
}
+ /**
+ * ECMA 6 22.2.3.30 %TypedArray%.prototype [ @@iterator ] ( )
+ *
+ * @param self the self reference
+ * @return an iterator over the array's values
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, name = "@@iterator")
+ public static Object getIterator(final Object self) {
+ return ArrayIterator.newArrayValueIterator(self);
+ }
+
@Override
protected ScriptObject getPrototype(final Global global) {
return global.getUint8ClampedArrayPrototype();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8164708.js Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8164708: String.prototype.replace replaces empty match twice
+ *
+ * @test
+ * @run
+ */
+
+Assert.assertEquals("4005".replace(/\B(?=(\d{3})+(?!\d))/g, ","), "4,005");
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8168146.js Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8168146: Infinite recursion in Uint8ClampedArray.set
+ *
+ * @test
+ * @run
+ */
+
+
+var a = new Uint8ClampedArray(10);
+
+for (var i = 0; i < 10; i++) {
+ a[i] = i;
+ Assert.assertTrue(a[i] === i);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/JDK-8168140.js Thu Oct 27 09:42:08 2016 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8168140: TypedArrays should implement ES6 iterator protocol
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+let TypedArrayTypes = [
+ Int8Array,
+ Uint8Array,
+ Uint8ClampedArray,
+ Int16Array,
+ Uint16Array,
+ Int32Array,
+ Uint32Array,
+ Float32Array,
+ Float64Array
+];
+
+let arrays = [];
+let sum = 0;
+
+TypedArrayTypes.forEach(function(ArrayType) {
+ var a = new ArrayType(10);
+ for (let i = 0; i < a.length; i++) {
+ a[i] = i;
+ }
+ arrays.push(a);
+});
+
+Assert.assertTrue(arrays.length === 9);
+
+for (let array of arrays) {
+
+ Assert.assertTrue(array.length === 10);
+ let count = 0;
+
+ for (let value of array) {
+ Assert.assertTrue(value === count++);
+ sum += value;
+ }
+}
+
+Assert.assertTrue(sum === 405);
--- a/test/failure_handler/src/share/conf/common.properties Thu Oct 27 09:38:46 2016 -0700
+++ b/test/failure_handler/src/share/conf/common.properties Thu Oct 27 09:42:08 2016 -0700
@@ -34,9 +34,8 @@
jcmd.vm.classloader_stats jcmd.vm.stringtable \
jcmd.vm.symboltable jcmd.vm.uptime jcmd.vm.dynlibs \
jcmd.vm.system_properties \
- jcmd.gc.class_stats jcmd.gc.class_histogram \
- jstack \
- jmap.heap jmap.histo jmap.clstats jmap.finalizerinfo
+ jcmd.gc.heap_info jcmd.gc.class_stats jcmd.gc.class_histogram jcmd.gc.finalizer_info \
+ jstack
jinfo.app=jinfo
@@ -55,16 +54,12 @@
jcmd.gc.class_stats.args=%p GC.class_stats
jcmd.gc.class_histogram.args=%p GC.class_histogram
+jcmd.gc.finalizer_info.args=%p GC.finalizer_info
+jcmd.gc.heap_info.args=%p GC.heap_info
jstack.app=jstack
jstack.params.repeat=6
-jmap.app=jmap
-jmap.heap.args=-heap %p
-jmap.histo.args=-histo %p
-jmap.clstats.args=-clstats %p
-jmap.finalizerinfo.args=-finalizerinfo %p
-
################################################################################
# environment info to gather
################################################################################
--- a/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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 jdk.test.lib.cli.predicate;
--- a/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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 jdk.test.lib.cli.predicate;
--- a/test/lib/sun/hotspot/WhiteBox.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/WhiteBox.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot;
--- a/test/lib/sun/hotspot/code/BlobType.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/code/BlobType.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot.code;
--- a/test/lib/sun/hotspot/code/CodeBlob.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/code/CodeBlob.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot.code;
--- a/test/lib/sun/hotspot/code/NMethod.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/code/NMethod.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot.code;
--- a/test/lib/sun/hotspot/cpuinfo/CPUInfo.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/cpuinfo/CPUInfo.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot.cpuinfo;
--- a/test/lib/sun/hotspot/gc/GC.java Thu Oct 27 09:38:46 2016 -0700
+++ b/test/lib/sun/hotspot/gc/GC.java Thu Oct 27 09:42:08 2016 -0700
@@ -19,7 +19,6 @@
* 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.hotspot.gc;