--- a/.hgtags Thu Oct 20 16:54:00 2016 -0700
+++ b/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/.hgtags-top-repo Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/common/autoconf/flags.m4 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/common/autoconf/generated-configure.sh Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/module-info.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/sun/corba/Bridge.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/corba/src/java.corba/share/classes/sun/corba/SharedSecrets.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/hotspot/src/share/vm/runtime/signature.cpp Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jaxp/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jaxws/.hgtags Tue Oct 25 12:25:44 2016 -0700
@@ -386,3 +386,4 @@
7d3a8f52b124db26ba8425c2931b748dd9d2791b jdk-9+138
7a7aadf3c4500cc273c889aa1172d4fe3844bb6b jdk-9+139
9004617323fe99cbe4fad48f373cb2ed4fc50aa6 jdk-9+140
+b2c18f755228d1d19a86cd7d5fa1abb6b1495dfb jdk-9+141
--- a/jdk/make/gendata/GendataBreakIterator.gmk Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/make/gendata/GendataBreakIterator.gmk Tue Oct 25 12:25:44 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/ObjectStreamClass.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java Tue Oct 25 12:25:44 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/time/chrono/HijrahDate.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahDate.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java Tue Oct 25 12:25:44 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/PropertyResourceBundle.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Tue Oct 25 12:25:44 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/reflect/ReflectionFactory.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/module-info.java Tue Oct 25 12:25:44 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/BreakDictionary.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 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 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java Tue Oct 25 12:25:44 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 20 16:54:00 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 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Tue Oct 25 12:25:44 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 20 16:54:00 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Tue Oct 25 12:25:44 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/lib/security/default.policy Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/share/lib/security/default.policy Tue Oct 25 12:25:44 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/windows/native/libnet/NetworkInterface_winXP.c Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Tue Oct 25 12:25:44 2016 -0700
@@ -627,11 +627,12 @@
(*env)->SetObjectArrayElement(env, bindsArr, bind_index++, ibObj);
} else /* AF_INET6 */ {
int scope;
+ jboolean ret;
iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
if (iaObj == NULL) {
return NULL;
}
- jboolean ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));
+ ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.sa6.sin6_addr.s6_addr));
if (ret == JNI_FALSE) {
return NULL;
}
--- a/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Tue Oct 25 12:25:44 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.rmi/share/classes/sun/rmi/server/Activation.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/Config.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/Constants.java Tue Oct 25 12:25:44 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 = " ";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorResources_th.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java Tue Oct 25 12:25:44 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);
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 2016 -0700
@@ -0,0 +1,433 @@
+/*
+ * 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.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+
+import javax.naming.CommunicationException;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NamingException;
+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 jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.JDKToolLauncher;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterSuite;
+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
+ * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
+ * -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
+ * @run testng/othervm/policy=security.policy
+ * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
+ * -Djava.naming.provider.url=iiop://localhost:1050 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);
+ }
+
+ /**
+ * The process spawned to run orbd.
+ */
+ static Process orbdProcess;
+ static Thread orbThread;
+
+ @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")
+ static 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"})
+ static 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 = false, dependsOnMethods = {"factCheck"})
+ static void echoObjects(Serializable value) throws Exception {
+ Context initialNamingContext = Server.init();
+ Echo echo = (Echo) PortableRemoteObject.narrow(
+ initialNamingContext.lookup(Server.serverID), Echo.class);
+ Object actual = echo.echo(value);
+ checkEquals(actual, value);
+ }
+
+ /**
+ * 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 serialization/deserialization.
+ */
+ interface Echo extends Remote {
+ Object echo(Object obj) throws RemoteException;
+ }
+
+ static class Server extends PortableRemoteObject implements Echo {
+
+ public static final String serverID = "ObjectStreamTestServer";
+
+ private static Context initialNamingContext;
+
+ private static Server server;
+
+ public Server() throws RemoteException {
+ super();
+ }
+
+ public Object echo(Object obj) {
+ return obj;
+ }
+
+
+ public static Context init() {
+ if (initialNamingContext == null) {
+ try {
+ startOrbd();
+ Thread.sleep(5000L); // Give it 5 seconds
+ } catch (Exception eex) {
+ throw new RuntimeException("Orbd", eex);
+ }
+ for (int i = 0; i < 1; i++) {
+ try {
+ Thread.sleep(1L);
+ initialNamingContext = new InitialContext();
+ server = new Server();
+ initialNamingContext.rebind(serverID, server);
+ } catch (CommunicationException | InterruptedException cex) {
+ System.out.printf("retry #%d sec: ex: %s%n", i, cex);
+ } catch (NamingException ex) {
+ throw new RuntimeException("can't initialize naming context", ex);
+ } catch (RemoteException rex) {
+ throw new RuntimeException("can't initialize server", rex);
+ }
+ }
+ }
+ if (initialNamingContext == null) {
+ Assert.fail("Can't initialize the Orb, no naming context");
+ }
+ return initialNamingContext;
+ }
+ }
+
+ static void startOrbd() throws Exception {
+ System.out.println("\nStarting orbd with NS port 1050 ");
+ JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd")
+ .addToolArg("-ORBInitialHost").addToolArg("localhost")
+ .addToolArg("-ORBInitialPort").addToolArg("1050");
+
+ System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand()));
+ ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand());
+
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+ orbdProcess = pb.start();
+ }
+
+ @AfterSuite
+ static void killOrbd() throws Exception {
+ if (orbdProcess != null) {
+ orbdProcess.destroyForcibly();
+ orbdProcess.waitFor();
+ System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n",
+ orbdProcess.getPid(), orbdProcess.exitValue());
+ }
+ }
+
+
+
+ // 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 Tue Oct 25 12:25:44 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/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/io/Serializable/serialFilter/security.policy Tue Oct 25 12:25:44 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";
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/RMID.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/rmi/testlibrary/TestParams.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh Tue Oct 25 12:25:44 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/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java Thu Oct 20 16:54:00 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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/tools/jlink/plugins/IncludeLocalesPluginTest.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java Tue Oct 25 12:25:44 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",
--- a/jdk/test/tools/pack200/MultiRelease.java Thu Oct 20 16:54:00 2016 -0700
+++ b/jdk/test/tools/pack200/MultiRelease.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/jdk/test/tools/pack200/Utils.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ExternalEditor.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/IOContext.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/PipeInputStream.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/Makefile Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/javadoc/tool/modules/FilterOptions.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ExternalEditorTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/KullaTesting.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ReplToolTesting.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/StartOptionTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolFormatTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolLocaleMessageTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolRetainTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/jdk/jshell/UserInputTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/Paths/MineField.sh Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 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 20 16:54:00 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/T8029102/WarnSerializableLambdaTestb.out Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/diags/examples/WarnSerializableLambda.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/javac/profiles/ProfileOptionTest.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/langtools/test/tools/lib/toolbox/JavadocTask.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/make/CreateJmods.gmk Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/make/Images.gmk Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/make/common/SetupJavaCompilers.gmk Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/.hgtags Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayIterator.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/failure_handler/src/share/conf/common.properties Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/WhiteBox.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/code/BlobType.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/code/CodeBlob.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/code/NMethod.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/cpuinfo/CPUInfo.java Tue Oct 25 12:25:44 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 20 16:54:00 2016 -0700
+++ b/test/lib/sun/hotspot/gc/GC.java Tue Oct 25 12:25:44 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;