Merge
authorduke
Wed, 05 Jul 2017 21:46:22 +0200
changeset 38598 6a1b521db882
parent 38597 3e6c168b4edb (current diff)
parent 38592 858bcf5481e6 (diff)
child 38600 aad06058a621
Merge
jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html
jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java
--- a/.hgtags-top-repo	Thu May 26 17:19:03 2016 +0000
+++ b/.hgtags-top-repo	Wed Jul 05 21:46:22 2017 +0200
@@ -362,3 +362,4 @@
 e882bcdbdac436523f3d5681611d3118a3804ea7 jdk-9+117
 047f95de8f918d8ff5e8cd2636a2abb5c3c8adb8 jdk-9+118
 3463a3f14f0f0e8a68f29ac6405454f2fa2f598a jdk-9+119
+647e0142a5a52749db572b5e6638d561def6479e jdk-9+120
--- a/common/autoconf/configure.ac	Thu May 26 17:19:03 2016 +0000
+++ b/common/autoconf/configure.ac	Wed Jul 05 21:46:22 2017 +0200
@@ -229,6 +229,7 @@
 
 JDKOPT_DETECT_INTREE_EC
 JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER
+JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
 
 ###############################################################################
 #
--- a/common/autoconf/generated-configure.sh	Thu May 26 17:19:03 2016 +0000
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 21:46:22 2017 +0200
@@ -650,6 +650,7 @@
 JOBS
 MEMORY_SIZE
 NUM_CORES
+ENABLE_GENERATE_CLASSLIST
 BUILD_FAILURE_HANDLER
 ENABLE_INTREE_EC
 STLPORT_LIB
@@ -1226,6 +1227,7 @@
 with_dxsdk_lib
 with_dxsdk_include
 enable_jtreg_failure_handler
+enable_generate_classlist
 with_num_cores
 with_memory_size
 with_jobs
@@ -2005,6 +2007,10 @@
                           Default is auto, where the failure handler is built
                           if all dependencies are present and otherwise just
                           disabled.
+  --disable-generate-classlist
+                          forces enabling or disabling of the generation of a
+                          CDS classlist at build time. Default is to generate
+                          it when either the server or client JVMs are built.
   --enable-sjavac         use sjavac to do fast incremental compiles
                           [disabled]
   --disable-javac-server  disable javac server [enabled]
@@ -4391,6 +4397,12 @@
 #
 
 
+################################################################################
+#
+# Enable or disable generation of the classlist at build time
+#
+
+
 #
 # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -5080,7 +5092,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1463732692
+DATE_WHEN_GENERATED=1464173584
 
 ###############################################################################
 #
@@ -64812,6 +64824,51 @@
 
 
 
+  # Check whether --enable-generate-classlist was given.
+if test "${enable_generate_classlist+set}" = set; then :
+  enableval=$enable_generate_classlist;
+fi
+
+
+  # Check if it's likely that it's possible to generate the classlist. Depending
+  # on exact jvm configuration it could be possible anyway.
+  if   [[ " $JVM_VARIANTS " =~ " server " ]]   ||   [[ " $JVM_VARIANTS " =~ " client " ]]  ; then
+    ENABLE_GENERATE_CLASSLIST_POSSIBLE="true"
+  else
+    ENABLE_GENERATE_CLASSLIST_POSSIBLE="false"
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the CDS classlist generation should be enabled" >&5
+$as_echo_n "checking if the CDS classlist generation should be enabled... " >&6; }
+  if test "x$enable_generate_classlist" = "xyes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5
+$as_echo "yes, forced" >&6; }
+    ENABLE_GENERATE_CLASSLIST="true"
+    if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&5
+$as_echo "$as_me: WARNING: Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS" >&2;}
+    fi
+  elif test "x$enable_generate_classlist" = "xno"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5
+$as_echo "no, forced" >&6; }
+    ENABLE_GENERATE_CLASSLIST="false"
+  elif test "x$enable_generate_classlist" = "x"; then
+    if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+      ENABLE_GENERATE_CLASSLIST="true"
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+      ENABLE_GENERATE_CLASSLIST="false"
+    fi
+  else
+    as_fn_error $? "Invalid value for --enable-generate-classlist: $enable_generate_classlist" "$LINENO" 5
+  fi
+
+
+
+
 ###############################################################################
 #
 # Configure parts of the build that only affect the build performance,
--- a/common/autoconf/jdk-options.m4	Thu May 26 17:19:03 2016 +0000
+++ b/common/autoconf/jdk-options.m4	Wed Jul 05 21:46:22 2017 +0200
@@ -491,3 +491,46 @@
 
   AC_SUBST(BUILD_FAILURE_HANDLER)
 ])
+
+################################################################################
+#
+# Enable or disable generation of the classlist at build time
+#
+AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST],
+[
+  AC_ARG_ENABLE([generate-classlist], [AS_HELP_STRING([--disable-generate-classlist],
+      [forces enabling or disabling of the generation of a CDS classlist at build time.
+      Default is to generate it when either the server or client JVMs are built.])])
+
+  # Check if it's likely that it's possible to generate the classlist. Depending
+  # on exact jvm configuration it could be possible anyway.
+  if HOTSPOT_CHECK_JVM_VARIANT(server) || HOTSPOT_CHECK_JVM_VARIANT(client); then
+    ENABLE_GENERATE_CLASSLIST_POSSIBLE="true"
+  else
+    ENABLE_GENERATE_CLASSLIST_POSSIBLE="false"
+  fi
+
+  AC_MSG_CHECKING([if the CDS classlist generation should be enabled])
+  if test "x$enable_generate_classlist" = "xyes"; then
+    AC_MSG_RESULT([yes, forced])
+    ENABLE_GENERATE_CLASSLIST="true"
+    if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xfalse"; then
+      AC_MSG_WARN([Generation of classlist might not be possible with JVM Variants $JVM_VARIANTS])
+    fi
+  elif test "x$enable_generate_classlist" = "xno"; then
+    AC_MSG_RESULT([no, forced])
+    ENABLE_GENERATE_CLASSLIST="false"
+  elif test "x$enable_generate_classlist" = "x"; then
+    if test "x$ENABLE_GENERATE_CLASSLIST_POSSIBLE" = "xtrue"; then
+      AC_MSG_RESULT([yes])
+      ENABLE_GENERATE_CLASSLIST="true"
+    else
+      AC_MSG_RESULT([no])
+      ENABLE_GENERATE_CLASSLIST="false"
+    fi
+  else
+    AC_MSG_ERROR([Invalid value for --enable-generate-classlist: $enable_generate_classlist])
+  fi
+
+  AC_SUBST([ENABLE_GENERATE_CLASSLIST])
+])
--- a/common/autoconf/spec.gmk.in	Thu May 26 17:19:03 2016 +0000
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 21:46:22 2017 +0200
@@ -285,6 +285,8 @@
 
 BUILD_FAILURE_HANDLER := @BUILD_FAILURE_HANDLER@
 
+ENABLE_GENERATE_CLASSLIST := @ENABLE_GENERATE_CLASSLIST@
+
 # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep
 # it in sync.
 BOOT_JDK:=@BOOT_JDK@
--- a/corba/.hgtags	Thu May 26 17:19:03 2016 +0000
+++ b/corba/.hgtags	Wed Jul 05 21:46:22 2017 +0200
@@ -362,3 +362,4 @@
 7a1b36bf2fe55a9a7732489ccdd326c910329a7e jdk-9+117
 8c2c2d17f7ce92a31c9ccb44a122ec62f5a85ace jdk-9+118
 daf533920b1266603b5cbdab31908d2a931c5361 jdk-9+119
+5943b791e131e79b969d4cea053aecda34801723 jdk-9+120
--- a/hotspot/.hgtags	Thu May 26 17:19:03 2016 +0000
+++ b/hotspot/.hgtags	Wed Jul 05 21:46:22 2017 +0200
@@ -522,3 +522,4 @@
 88170d3642905b9e6cac03e8efcc976885a7e6da jdk-9+117
 9b1075cac08dc836ec32e7b368415cbe3aceaf8c jdk-9+118
 15f3fe264872766bcb205696198f0c1502420e17 jdk-9+119
+0be6f4f5d18671184e62583668cb1d783dffa128 jdk-9+120
--- a/jdk/.hgtags	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/.hgtags	Wed Jul 05 21:46:22 2017 +0200
@@ -362,3 +362,4 @@
 4da0f73ce03aaf245b92cc040cc0ab0e3fa54dc2 jdk-9+117
 e1eba5cfa5cc8c66d524396a05323dc93568730a jdk-9+118
 bad3f8a33db271a6143ba6eac0c8bd5bbd942417 jdk-9+119
+b9a518bf72516954e57ac2f6e3ef21e13008f1cd jdk-9+120
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 21:46:22 2017 +0200
@@ -267,6 +267,7 @@
                 Java_jdk_internal_misc_VM_geteuid;
                 Java_jdk_internal_misc_VM_getgid;
                 Java_jdk_internal_misc_VM_getegid;
+                Java_jdk_internal_misc_VM_getRuntimeArguments;
                 Java_jdk_internal_misc_VM_initialize;
 
                 Java_java_lang_reflect_Module_defineModule0;
--- a/jdk/src/java.base/share/classes/java/lang/Boolean.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java	Wed Jul 05 21:46:22 2017 +0200
@@ -117,7 +117,9 @@
      * Parses the string argument as a boolean.  The {@code boolean}
      * returned represents the value {@code true} if the string argument
      * is not {@code null} and is equal, ignoring case, to the string
-     * {@code "true"}. <p>
+     * {@code "true"}.
+     * Otherwise, a false value is returned, including for a null
+     * argument.<p>
      * Example: {@code Boolean.parseBoolean("True")} returns {@code true}.<br>
      * Example: {@code Boolean.parseBoolean("yes")} returns {@code false}.
      *
@@ -165,6 +167,8 @@
      * specified string.  The {@code Boolean} returned represents a
      * true value if the string argument is not {@code null}
      * and is equal, ignoring case, to the string {@code "true"}.
+     * Otherwise, a false value is returned, including for a null
+     * argument.
      *
      * @param   s   a string.
      * @return  the {@code Boolean} value represented by the string.
@@ -241,14 +245,12 @@
 
     /**
      * Returns {@code true} if and only if the system property named
-     * by the argument exists and is equal to the string {@code
-     * "true"}. (Beginning with version 1.0.2 of the Java&trade;
-     * platform, the test of this string is case insensitive.) A
-     * system property is accessible through {@code getProperty}, a
-     * method defined by the {@code System} class.
-     * <p>
-     * If there is no property with the specified name, or if the specified
-     * name is empty or null, then {@code false} is returned.
+     * by the argument exists and is equal to, ignoring case, the
+     * string {@code "true"}.
+     * A system property is accessible through {@code getProperty}, a
+     * method defined by the {@code System} class.  <p> If there is no
+     * property with the specified name, or if the specified name is
+     * empty or null, then {@code false} is returned.
      *
      * @param   name   the system property name.
      * @return  the {@code boolean} value of the system property.
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java	Wed Jul 05 21:46:22 2017 +0200
@@ -306,8 +306,9 @@
             return DEFAULT_WALKER;
         }
 
-        checkPermission(options);
-        return new StackWalker(toEnumSet(options));
+        EnumSet<Option> optionSet = toEnumSet(options);
+        checkPermission(optionSet);
+        return new StackWalker(optionSet);
     }
 
     /**
@@ -341,8 +342,9 @@
         if (estimateDepth <= 0) {
             throw new IllegalArgumentException("estimateDepth must be > 0");
         }
-        checkPermission(options);
-        return new StackWalker(toEnumSet(options), estimateDepth);
+        EnumSet<Option> optionSet = toEnumSet(options);
+        checkPermission(optionSet);
+        return new StackWalker(optionSet, estimateDepth);
     }
 
     // ----- private constructors ------
@@ -540,13 +542,11 @@
     }
 
     // ---- package access ----
-    static StackWalker newInstanceNoCheck(EnumSet<Option> options) {
-        return new StackWalker(options, 0, null);
-    }
 
     static StackWalker newInstance(Set<Option> options, ExtendedOption extendedOption) {
-        checkPermission(options);
-        return new StackWalker(toEnumSet(options), 0, extendedOption);
+        EnumSet<Option> optionSet = toEnumSet(options);
+        checkPermission(optionSet);
+        return new StackWalker(optionSet, 0, extendedOption);
     }
 
     int estimateDepth() {
--- a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java	Wed Jul 05 21:46:22 2017 +0200
@@ -46,7 +46,7 @@
  * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
  * field declaration.
  *
- * <p>The constant {@link #TYPE_USE} corresponds to the 15 type contexts in JLS
+ * <p>The constant {@link #TYPE_USE} corresponds to the type contexts in JLS
  * 4.11, as well as to two declaration contexts: type declarations (including
  * annotation type declarations) and type parameter declarations.
  *
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -30,6 +30,7 @@
 import java.io.InputStream;
 import java.net.URI;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 import java.util.Optional;
 
 
@@ -163,9 +164,12 @@
      * @param  bb
      *         The byte buffer to release
      *
-     * @implSpec The default implementation does nothing.
+     * @implSpec The default implementation doesn't do anything except check
+     * if the byte buffer is null.
      */
-    default void release(ByteBuffer bb) { }
+    default void release(ByteBuffer bb) {
+        Objects.requireNonNull(bb);
+    }
 
     /**
      * Closes the module reader. Once closed then subsequent calls to locate or
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Wed Jul 05 21:46:22 2017 +0200
@@ -272,9 +272,9 @@
          * if not found.
          */
         private ImageLocation findImageLocation(String name) throws IOException {
+            Objects.requireNonNull(name);
             if (closed)
                 throw new IOException("ModuleReader is closed");
-
             if (imageReader != null) {
                 return imageReader.findLocation(module, name);
             } else {
@@ -322,6 +322,7 @@
 
         @Override
         public void release(ByteBuffer bb) {
+            Objects.requireNonNull(bb);
             ImageReader.releaseByteBuffer(bb);
         }
 
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java	Wed Jul 05 21:46:22 2017 +0200
@@ -75,11 +75,12 @@
  *
  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  * #boot() boot} layer, that is created when the Java virtual machine is
- * started. The <em>system modules</em>, including {@code java.base}, are in
- * the boot layer. The modules in the boot layer are mapped to the bootstrap
- * class loader and other class loaders that are built-in into the Java virtual
- * machine. The boot layer will often be the {@link #parent() parent} when
- * creating additional layers. </p>
+ * started. The boot layer contains module {@code java.base} and is the only
+ * layer in the Java virtual machine with a module named "{@code java.base}".
+ * The modules in the boot layer are mapped to the bootstrap class loader and
+ * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
+ * built-in</a> into the Java virtual machine. The boot layer will often be
+ * the {@link #parent() parent} when creating additional layers. </p>
  *
  * <p> As when creating a {@code Configuration},
  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive
@@ -204,7 +205,8 @@
      *         for this layer
      * @throws LayerInstantiationException
      *         If all modules cannot be defined to the same class loader for any
-     *         of the reasons listed above
+     *         of the reasons listed above or the layer cannot be created because
+     *         the configuration contains a module named "{@code java.base}"
      * @throws SecurityException
      *         If {@code RuntimePermission("createClassLoader")} or
      *         {@code RuntimePermission("getClassLoader")} is denied by
@@ -219,14 +221,13 @@
         checkCreateClassLoaderPermission();
         checkGetClassLoaderPermission();
 
-        Loader loader;
         try {
-            loader = new Loader(cf.modules(), parentLoader);
+            Loader loader = new Loader(cf.modules(), parentLoader);
             loader.initRemotePackageMap(cf, this);
+            return new Layer(cf, this, mn -> loader);
         } catch (IllegalArgumentException e) {
             throw new LayerInstantiationException(e.getMessage());
         }
-        return new Layer(cf, this, mn -> loader);
     }
 
 
@@ -266,6 +267,9 @@
      * @throws IllegalArgumentException
      *         If the parent of the given configuration is not the configuration
      *         for this layer
+     * @throws LayerInstantiationException
+     *         If the layer cannot be created because the configuration contains
+     *         a module named "{@code java.base}"
      * @throws SecurityException
      *         If {@code RuntimePermission("createClassLoader")} or
      *         {@code RuntimePermission("getClassLoader")} is denied by
@@ -281,7 +285,11 @@
         checkGetClassLoaderPermission();
 
         LoaderPool pool = new LoaderPool(cf, this, parentLoader);
-        return new Layer(cf, this, pool::loaderFor);
+        try {
+            return new Layer(cf, this, pool::loaderFor);
+        } catch (IllegalArgumentException e) {
+            throw new LayerInstantiationException(e.getMessage());
+        }
     }
 
 
@@ -330,7 +338,8 @@
      *         for this layer
      * @throws LayerInstantiationException
      *         If creating the {@code Layer} fails for any of the reasons
-     *         listed above
+     *         listed above or the layer cannot be created because the
+     *         configuration contains a module named "{@code java.base}"
      * @throws SecurityException
      *         If {@code RuntimePermission("getClassLoader")} is denied by
      *         the security manager
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java	Wed Jul 05 21:46:22 2017 +0200
@@ -513,7 +513,7 @@
      * package {@code pn} to the given module.
      *
      * <p> This method has no effect if the package is already exported to the
-     * given module. If also has no effect if invoked on an unnamed module (as
+     * given module. It also has no effect if invoked on an unnamed module (as
      * unnamed modules export all packages). </p>
      *
      * @param  pn
@@ -866,7 +866,7 @@
             URI uri = mref.location().orElse(null);
 
             Module m;
-            if (loader == null && name.equals("java.base")) {
+            if (loader == null && name.equals("java.base") && Layer.boot() == null) {
                 m = Object.class.getModule();
             } else {
                 m = new Module(layer, loader, descriptor, uri);
--- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java	Wed Jul 05 21:46:22 2017 +0200
@@ -55,7 +55,7 @@
  * object to the operation.  In either case, eight <em>rounding
  * modes</em> are provided for the control of rounding.  Using the
  * integer fields in this class (such as {@link #ROUND_HALF_UP}) to
- * represent rounding mode is largely obsolete; the enumeration values
+ * represent rounding mode is deprecated; the enumeration values
  * of the {@code RoundingMode} {@code enum}, (such as {@link
  * RoundingMode#HALF_UP}) should be used instead.
  *
@@ -93,7 +93,7 @@
  * <p>In general the rounding modes and precision setting determine
  * how operations return results with a limited number of digits when
  * the exact result has more digits (perhaps infinitely many in the
- * case of division) than the number of digits returned.
+ * case of division and square root) than the number of digits returned.
  *
  * First, the
  * total number of digits to return is specified by the
@@ -196,18 +196,19 @@
  * {@code BigDecimal} value; for example [19, 2] is the
  * {@code BigDecimal} numerically equal to 0.19 having a scale of 2.
  *
- * <p>Note: care should be exercised if {@code BigDecimal} objects
- * are used as keys in a {@link java.util.SortedMap SortedMap} or
- * elements in a {@link java.util.SortedSet SortedSet} since
- * {@code BigDecimal}'s <i>natural ordering</i> is <i>inconsistent
- * with equals</i>.  See {@link Comparable}, {@link
- * java.util.SortedMap} or {@link java.util.SortedSet} for more
- * information.
  *
  * <p>All methods and constructors for this class throw
  * {@code NullPointerException} when passed a {@code null} object
  * reference for any input parameter.
  *
+ * @apiNote Care should be exercised if {@code BigDecimal} objects
+ * are used as keys in a {@link java.util.SortedMap SortedMap} or
+ * elements in a {@link java.util.SortedSet SortedSet} since
+ * {@code BigDecimal}'s <i>natural ordering</i> is <em>inconsistent
+ * with equals</em>.  See {@link Comparable}, {@link
+ * java.util.SortedMap} or {@link java.util.SortedSet} for more
+ * information.
+ *
  * @see     BigInteger
  * @see     MathContext
  * @see     RoundingMode
@@ -377,10 +378,10 @@
      * same sequence of characters as the {@link #BigDecimal(String)}
      * constructor, while allowing a sub-array to be specified.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * within a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  offset first character in the array to inspect.
@@ -401,14 +402,14 @@
      * constructor, while allowing a sub-array to be specified and
      * with rounding according to the context settings.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * within a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
      * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  offset first character in the array to inspect.
-     * @param  len number of characters to consider..
+     * @param  len number of characters to consider.
      * @param  mc the context to use.
      * @throws ArithmeticException if the result is inexact but the
      *         rounding mode is {@code UNNECESSARY}.
@@ -679,10 +680,10 @@
      * same sequence of characters as the {@link #BigDecimal(String)}
      * constructor.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * as a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param in {@code char} array that is the source of characters.
      * @throws NumberFormatException if {@code in} is not a valid
@@ -700,10 +701,10 @@
      * constructor and with rounding according to the context
      * settings.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * as a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  mc the context to use.
@@ -805,7 +806,7 @@
      * "-0"           [0,0]
      * </pre>
      *
-     * <p>Note: For values other than {@code float} and
+     * @apiNote For values other than {@code float} and
      * {@code double} NaN and &plusmn;Infinity, this constructor is
      * compatible with the values returned by {@link Float#toString}
      * and {@link Double#toString}.  This is generally the preferred
@@ -859,13 +860,13 @@
      * This is because 0.1 cannot be represented exactly as a
      * {@code double} (or, for that matter, as a binary fraction of
      * any finite length).  Thus, the value that is being passed
-     * <i>in</i> to the constructor is not exactly equal to 0.1,
+     * <em>in</em> to the constructor is not exactly equal to 0.1,
      * appearances notwithstanding.
      *
      * <li>
      * The {@code String} constructor, on the other hand, is
      * perfectly predictable: writing {@code new BigDecimal("0.1")}
-     * creates a {@code BigDecimal} which is <i>exactly</i> equal to
+     * creates a {@code BigDecimal} which is <em>exactly</em> equal to
      * 0.1, as one would expect.  Therefore, it is generally
      * recommended that the {@linkplain #BigDecimal(String)
      * String constructor} be used in preference to this one.
@@ -1199,10 +1200,11 @@
 
     /**
      * Translates a {@code long} unscaled value and an
-     * {@code int} scale into a {@code BigDecimal}.  This
-     * {@literal "static factory method"} is provided in preference to
-     * a ({@code long}, {@code int}) constructor because it
-     * allows for reuse of frequently used {@code BigDecimal} values..
+     * {@code int} scale into a {@code BigDecimal}.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}, {@code int}) constructor because it allows
+     * for reuse of frequently used {@code BigDecimal} values.
      *
      * @param unscaledVal unscaled value of the {@code BigDecimal}.
      * @param scale scale of the {@code BigDecimal}.
@@ -1222,10 +1224,11 @@
 
     /**
      * Translates a {@code long} value into a {@code BigDecimal}
-     * with a scale of zero.  This {@literal "static factory method"}
-     * is provided in preference to a ({@code long}) constructor
-     * because it allows for reuse of frequently used
-     * {@code BigDecimal} values.
+     * with a scale of zero.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}) constructor because it allows for reuse of
+     * frequently used {@code BigDecimal} values.
      *
      * @param val value of the {@code BigDecimal}.
      * @return a {@code BigDecimal} whose value is {@code val}.
@@ -1270,11 +1273,11 @@
      * the {@code double}'s canonical string representation provided
      * by the {@link Double#toString(double)} method.
      *
-     * <p><b>Note:</b> This is generally the preferred way to convert
-     * a {@code double} (or {@code float}) into a
-     * {@code BigDecimal}, as the value returned is equal to that
-     * resulting from constructing a {@code BigDecimal} from the
-     * result of using {@link Double#toString(double)}.
+     * @apiNote This is generally the preferred way to convert a
+     * {@code double} (or {@code float}) into a {@code BigDecimal}, as
+     * the value returned is equal to that resulting from constructing
+     * a {@code BigDecimal} from the result of using {@link
+     * Double#toString(double)}.
      *
      * @param  val {@code double} to convert to a {@code BigDecimal}.
      * @return a {@code BigDecimal} whose value is equal to or approximately
@@ -1896,7 +1899,7 @@
      *
      * <p>The remainder is given by
      * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}.
-     * Note that this is not the modulo operation (the result can be
+     * Note that this is <em>not</em> the modulo operation (the result can be
      * negative).
      *
      * @param  divisor value by which this {@code BigDecimal} is to be divided.
@@ -2037,6 +2040,7 @@
      * {@code (mc.getRoundingMode()==RoundingMode.UNNECESSARY}) and
      * the exact result cannot fit in {@code mc.getPrecision()}
      * digits.
+     * @see BigInteger#sqrt()
      * @since  9
      */
     public BigDecimal sqrt(MathContext mc) {
@@ -2694,8 +2698,8 @@
      * in this case, the specified rounding mode is applied to the
      * division.
      *
-     * <p>Note that since BigDecimal objects are immutable, calls of
-     * this method do <i>not</i> result in the original object being
+     * @apiNote Since BigDecimal objects are immutable, calls of
+     * this method do <em>not</em> result in the original object being
      * modified, contrary to the usual convention of having methods
      * named <code>set<i>X</i></code> mutate field <i>{@code X}</i>.
      * Instead, {@code setScale} returns an object with the proper
@@ -2727,8 +2731,8 @@
      * in this case, the specified rounding mode is applied to the
      * division.
      *
-     * <p>Note that since BigDecimal objects are immutable, calls of
-     * this method do <i>not</i> result in the original object being
+     * @apiNote Since BigDecimal objects are immutable, calls of
+     * this method do <em>not</em> result in the original object being
      * modified, contrary to the usual convention of having methods
      * named <code>set<i>X</i></code> mutate field <i>{@code X}</i>.
      * Instead, {@code setScale} returns an object with the proper
@@ -2822,8 +2826,8 @@
      * versions of {@code setScale}, but saves the caller the trouble
      * of specifying a rounding mode in cases where it is irrelevant.
      *
-     * <p>Note that since {@code BigDecimal} objects are immutable,
-     * calls of this method do <i>not</i> result in the original
+     * @apiNote Since {@code BigDecimal} objects are immutable,
+     * calls of this method do <em>not</em> result in the original
      * object being modified, contrary to the usual convention of
      * having methods named <code>set<i>X</i></code> mutate field
      * <i>{@code X}</i>.  Instead, {@code setScale} returns an
@@ -3091,7 +3095,7 @@
     /**
      * Returns the hash code for this {@code BigDecimal}.  Note that
      * two {@code BigDecimal} objects that are numerically equal but
-     * differ in scale (like 2.0 and 2.00) will generally <i>not</i>
+     * differ in scale (like 2.0 and 2.00) will generally <em>not</em>
      * have the same hash code.
      *
      * @return hash code for this {@code BigDecimal}.
@@ -3342,7 +3346,7 @@
      * Converts this {@code BigDecimal} to a {@code BigInteger}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code long} as defined in section 5.1.3 of
+     * {@code long} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded.  Note that this
@@ -3354,6 +3358,7 @@
      * {@link #toBigIntegerExact()} method.
      *
      * @return this {@code BigDecimal} converted to a {@code BigInteger}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public BigInteger toBigInteger() {
         // force to an integer, quietly
@@ -3379,7 +3384,7 @@
      * Converts this {@code BigDecimal} to a {@code long}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code short} as defined in section 5.1.3 of
+     * {@code short} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded, and if the resulting
@@ -3390,6 +3395,7 @@
      * as return a result with the opposite sign.
      *
      * @return this {@code BigDecimal} converted to a {@code long}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     @Override
     public long longValue(){
@@ -3448,7 +3454,7 @@
      * Converts this {@code BigDecimal} to an {@code int}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code short} as defined in section 5.1.3 of
+     * {@code short} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded, and if the resulting
@@ -3459,6 +3465,7 @@
      * value as well as return a result with the opposite sign.
      *
      * @return this {@code BigDecimal} converted to an {@code int}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     @Override
     public int intValue() {
@@ -3531,7 +3538,7 @@
      * Converts this {@code BigDecimal} to a {@code float}.
      * This conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this {@code BigDecimal} has too great a
      * magnitude to represent as a {@code float}, it will be
@@ -3542,6 +3549,7 @@
      * value.
      *
      * @return this {@code BigDecimal} converted to a {@code float}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     @Override
     public float floatValue(){
@@ -3575,7 +3583,7 @@
      * Converts this {@code BigDecimal} to a {@code double}.
      * This conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this {@code BigDecimal} has too great a
      * magnitude represent as a {@code double}, it will be
@@ -3586,6 +3594,7 @@
      * value.
      *
      * @return this {@code BigDecimal} converted to a {@code double}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     @Override
     public double doubleValue(){
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java	Wed Jul 05 21:46:22 2017 +0200
@@ -116,6 +116,7 @@
  * +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive).
  *
  * @see     BigDecimal
+ * @jls     4.2.2 Integer Operations
  * @author  Josh Bloch
  * @author  Michael McCloskey
  * @author  Alan Eliasen
@@ -126,7 +127,7 @@
 public class BigInteger extends Number implements Comparable<BigInteger> {
     /**
      * The signum of this BigInteger: -1 for negative, 0 for zero, or
-     * 1 for positive.  Note that the BigInteger zero <i>must</i> have
+     * 1 for positive.  Note that the BigInteger zero <em>must</em> have
      * a signum of 0.  This is necessary to ensures that there is exactly one
      * representation for each BigInteger value.
      */
@@ -710,7 +711,7 @@
      * Constructs a randomly generated positive BigInteger that is probably
      * prime, with the specified bitLength.
      *
-     * <p>It is recommended that the {@link #probablePrime probablePrime}
+     * @apiNote It is recommended that the {@link #probablePrime probablePrime}
      * method be used in preference to this constructor unless there
      * is a compelling need to specify a certainty.
      *
@@ -1157,9 +1158,11 @@
 
     /**
      * Returns a BigInteger whose value is equal to that of the
-     * specified {@code long}.  This "static factory method" is
-     * provided in preference to a ({@code long}) constructor
-     * because it allows for reuse of frequently used BigIntegers.
+     * specified {@code long}.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}) constructor because it allows for reuse of
+     * frequently used BigIntegers.
      *
      * @param  val value of the BigInteger to return.
      * @return a BigInteger with the specified value.
@@ -3551,13 +3554,13 @@
 
     /**
      * Returns the number of bits in the minimal two's-complement
-     * representation of this BigInteger, <i>excluding</i> a sign bit.
+     * representation of this BigInteger, <em>excluding</em> a sign bit.
      * For positive BigIntegers, this is equivalent to the number of bits in
      * the ordinary binary representation.  (Computes
      * {@code (ceil(log2(this < 0 ? -this : this+1)))}.)
      *
      * @return number of bits in the minimal two's-complement
-     *         representation of this BigInteger, <i>excluding</i> a sign bit.
+     *         representation of this BigInteger, <em>excluding</em> a sign bit.
      */
     public int bitLength() {
         int n = bitLengthPlusOne - 1;
@@ -4034,7 +4037,7 @@
      * Converts this BigInteger to an {@code int}.  This
      * conversion is analogous to a
      * <i>narrowing primitive conversion</i> from {@code long} to
-     * {@code int} as defined in section 5.1.3 of
+     * {@code int} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger is too big to fit in an
      * {@code int}, only the low-order 32 bits are returned.
@@ -4044,6 +4047,7 @@
      *
      * @return this BigInteger converted to an {@code int}.
      * @see #intValueExact()
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public int intValue() {
         int result = 0;
@@ -4055,7 +4059,7 @@
      * Converts this BigInteger to a {@code long}.  This
      * conversion is analogous to a
      * <i>narrowing primitive conversion</i> from {@code long} to
-     * {@code int} as defined in section 5.1.3 of
+     * {@code int} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger is too big to fit in a
      * {@code long}, only the low-order 64 bits are returned.
@@ -4065,6 +4069,7 @@
      *
      * @return this BigInteger converted to a {@code long}.
      * @see #longValueExact()
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public long longValue() {
         long result = 0;
@@ -4078,7 +4083,7 @@
      * Converts this BigInteger to a {@code float}.  This
      * conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger has too great a magnitude
      * to represent as a {@code float}, it will be converted to
@@ -4088,6 +4093,7 @@
      * information about the precision of the BigInteger value.
      *
      * @return this BigInteger converted to a {@code float}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public float floatValue() {
         if (signum == 0) {
@@ -4162,7 +4168,7 @@
      * Converts this BigInteger to a {@code double}.  This
      * conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger has too great a magnitude
      * to represent as a {@code double}, it will be converted to
@@ -4172,6 +4178,7 @@
      * information about the precision of the BigInteger value.
      *
      * @return this BigInteger converted to a {@code double}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public double doubleValue() {
         if (signum == 0) {
--- a/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/Inet6AddressImpl.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,10 @@
  * questions.
  */
 package java.net;
+
 import java.io.IOException;
+import static java.net.InetAddress.PREFER_IPV6_VALUE;
+import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
 
 /*
  * Package private implementation of InetAddressImpl for dual
@@ -35,15 +38,23 @@
  *
  * @since 1.4
  */
+class Inet6AddressImpl implements InetAddressImpl {
 
-class Inet6AddressImpl implements InetAddressImpl {
     public native String getLocalHostName() throws UnknownHostException;
-    public native InetAddress[]
-        lookupAllHostAddr(String hostname) throws UnknownHostException;
+
+    public native InetAddress[] lookupAllHostAddr(String hostname)
+        throws UnknownHostException;
+
     public native String getHostByAddr(byte[] addr) throws UnknownHostException;
-    private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
+
+    private native boolean isReachable0(byte[] addr, int scope, int timeout,
+                                        byte[] inf, int ttl, int if_scope)
+        throws IOException;
 
-    public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
+    public boolean isReachable(InetAddress addr, int timeout,
+                               NetworkInterface netif, int ttl)
+        throws IOException
+    {
         byte[] ifaddr = null;
         int scope = -1;
         int netif_scope = -1;
@@ -79,7 +90,8 @@
 
     public synchronized InetAddress anyLocalAddress() {
         if (anyLocalAddress == null) {
-            if (InetAddress.preferIPv6Address) {
+            if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
+                InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
                 anyLocalAddress = new Inet6Address();
                 anyLocalAddress.holder().hostName = "::";
             } else {
@@ -91,7 +103,8 @@
 
     public synchronized InetAddress loopbackAddress() {
         if (loopbackAddress == null) {
-             if (InetAddress.preferIPv6Address) {
+             if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
+                 InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
                  byte[] loopback =
                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
@@ -103,6 +116,6 @@
         return loopbackAddress;
     }
 
-    private InetAddress      anyLocalAddress;
-    private InetAddress      loopbackAddress;
+    private InetAddress anyLocalAddress;
+    private InetAddress loopbackAddress;
 }
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java	Wed Jul 05 21:46:22 2017 +0200
@@ -26,8 +26,6 @@
 package java.net;
 
 import java.util.NavigableSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Objects;
 import java.util.Scanner;
@@ -41,6 +39,7 @@
 import java.io.ObjectInputStream.GetField;
 import java.io.ObjectOutputStream;
 import java.io.ObjectOutputStream.PutField;
+import java.lang.annotation.Native;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentSkipListSet;
@@ -193,6 +192,11 @@
  */
 public
 class InetAddress implements java.io.Serializable {
+
+    @Native static final int PREFER_IPV4_VALUE = 0;
+    @Native static final int PREFER_IPV6_VALUE = 1;
+    @Native static final int PREFER_SYSTEM_VALUE = 2;
+
     /**
      * Specify the address family: Internet Protocol, Version 4
      * @since 1.4
@@ -206,8 +210,7 @@
     static final int IPv6 = 2;
 
     /* Specify address family preference */
-    static transient boolean preferIPv6Address = false;
-
+    static transient final int preferIPv6Address;
 
     static class InetAddressHolder {
         /**
@@ -293,8 +296,19 @@
      * Load net library into runtime, and perform initializations.
      */
     static {
-        preferIPv6Address = java.security.AccessController.doPrivileged(
-            new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
+        String str = java.security.AccessController.doPrivileged(
+                new GetPropertyAction("java.net.preferIPv6Addresses"));
+        if (str == null) {
+            preferIPv6Address = PREFER_IPV4_VALUE;
+        } else if (str.equalsIgnoreCase("true")) {
+            preferIPv6Address = PREFER_IPV6_VALUE;
+        } else if (str.equalsIgnoreCase("false")) {
+            preferIPv6Address = PREFER_IPV4_VALUE;
+        } else if (str.equalsIgnoreCase("system")) {
+            preferIPv6Address = PREFER_SYSTEM_VALUE;
+        } else {
+            preferIPv6Address = PREFER_IPV4_VALUE;
+        }
         AccessController.doPrivileged(
             new java.security.PrivilegedAction<>() {
                 public Void run() {
--- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 <!--
- Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
 java.net package. Some are checked only once at startup of the VM,
 and therefore are best set using the -D option of the java command,
 while others have a more dynamic nature and can also be changed using
-the <a href="../../lang/System.html#setProperty(java.lang.String,%20java.lang.String)">System.setProperty()</a> API. 
+the <a href="../../lang/System.html#setProperty(java.lang.String,%20java.lang.String)">System.setProperty()</a> API.
 The purpose of this document is to list
 and detail all of these properties.</P>
 <P>If there is no special note, a property value is checked every time it is used.</P>
@@ -58,7 +58,8 @@
 	applications that depend on the representation of an IPv4 address
 	(e.g. 192.168.1.1). This property can be set to <B>true</B> to
 	change that preference and use IPv6 addresses over IPv4 ones where
-	possible.</P>
+	possible, or <B>system</B> to preserve the order of the addresses as
+    returned by the operating system.</P>
 </UL>
 <P>Both of these properties are checked only once, at startup.</P>
 <a name="Proxies"></a>
@@ -73,7 +74,7 @@
 	<P>The following proxy settings are used by the HTTP protocol handler.</P>
 	<UL>
 		<LI><P><B>http.proxyHost</B> (default: &lt;none&gt;)<BR>
-	        The hostname, or address, of the proxy server 
+	        The hostname, or address, of the proxy server
 		</P>
 		<LI><P><B>http.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
@@ -94,7 +95,7 @@
 	<P>The following proxy settings are used by the HTTPS protocol handler.</P>
 	<UL>
 		<LI><P><B>https.proxyHost</B>(default: &lt;none&gt;)<BR>
-	        The hostname, or address, of the proxy server 
+	        The hostname, or address, of the proxy server
 		</P>
 		<LI><P><B>https.proxyPort</B> (default: 443)<BR>
 	        The port number of the proxy server.</P>
@@ -105,7 +106,7 @@
 	<P>The following proxy settings are used by the FTP protocol handler.</P>
 	<UL>
 		<LI><P><B>ftp.proxyHost</B>(default: &lt;none&gt;)<BR>
-	        The hostname, or address, of the proxy server 
+	        The hostname, or address, of the proxy server
 		</P>
 		<LI><P><B>ftp.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
@@ -160,7 +161,7 @@
 	<LI><P><B>http.agent</B> (default: &ldquo;Java/&lt;version&gt;&rdquo;)<BR>
 	Defines the string sent in the User-Agent request header in http
 	requests. Note that the string &ldquo;Java/&lt;version&gt;&rdquo; will
-	be appended to the one provided in the property (e.g. if 
+	be appended to the one provided in the property (e.g. if
 	-Dhttp.agent=&rdquo;foobar&rdquo; is used, the User-Agent header will
 	contain &ldquo;foobar Java/1.5.0&rdquo; if the version of the VM is
 	1.5.0). This property is checked only once at startup.</P>
--- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Wed Jul 05 21:46:22 2017 +0200
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 
@@ -607,7 +608,10 @@
 // ---------- Serialization Proxy ----------
 
 /**
- * Serialization proxy class for immutable collections.
+ * A unified serialization proxy class for the immutable collections.
+ *
+ * @serial
+ * @since 9
  */
 final class CollSer implements Serializable {
     private static final long serialVersionUID = 6309168927139932177L;
@@ -616,14 +620,114 @@
     static final int IMM_SET = 2;
     static final int IMM_MAP = 3;
 
-    private final int flags;
-    private final Object[] array;
+    /**
+     * Indicates the type of collection that is serialized.
+     * The low order 8 bits have the value 1 for an immutable
+     * {@code List}, 2 for an immutable {@code Set}, and 3 for
+     * an immutable {@code Map}. Any other value causes an
+     * {@link InvalidObjectException} to be thrown. The high
+     * order 24 bits are zero when an instance is serialized,
+     * and they are ignored when an instance is deserialized.
+     * They can thus be used by future implementations without
+     * causing compatibility issues.
+     *
+     * <p>The tag value also determines the interpretation of the
+     * transient {@code Object[] array} field.
+     * For {@code List} and {@code Set}, the array's length is the size
+     * of the collection, and the array contains the elements of the collection.
+     * Null elements are not allowed. For {@code Set}, duplicate elements
+     * are not allowed.
+     *
+     * <p>For {@code Map}, the array's length is twice the number of mappings
+     * present in the map. The array length is necessarily even.
+     * The array contains a succession of key and value pairs:
+     * {@code k1, v1, k2, v2, ..., kN, vN.} Nulls are not allowed,
+     * and duplicate keys are not allowed.
+     *
+     * @serial
+     * @since 9
+     */
+    private final int tag;
 
-    CollSer(int f, Object... a) {
-        flags = f;
+    /**
+     * @serial
+     * @since 9
+     */
+    private transient Object[] array;
+
+    CollSer(int t, Object... a) {
+        tag = t;
         array = a;
     }
 
+    /**
+     * Reads objects from the stream and stores them
+     * in the transient {@code Object[] array} field.
+     *
+     * @serialData
+     * A nonnegative int, indicating the count of objects,
+     * followed by that many objects.
+     *
+     * @param ois the ObjectInputStream from which data is read
+     * @throws IOException if an I/O error occurs
+     * @throws ClassNotFoundException if a serialized class cannot be loaded
+     * @throws InvalidObjectException if the count is negative
+     * @since 9
+     */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        ois.defaultReadObject();
+        int len = ois.readInt();
+
+        if (len < 0) {
+            throw new InvalidObjectException("negative length " + len);
+        }
+
+        Object[] a = new Object[len];
+        for (int i = 0; i < len; i++) {
+            a[i] = ois.readObject();
+        }
+
+        array = a;
+    }
+
+    /**
+     * Writes objects to the stream from
+     * the transient {@code Object[] array} field.
+     *
+     * @serialData
+     * A nonnegative int, indicating the count of objects,
+     * followed by that many objects.
+     *
+     * @param oos the ObjectOutputStream to which data is written
+     * @throws IOException if an I/O error occurs
+     * @since 9
+     */
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        oos.defaultWriteObject();
+        oos.writeInt(array.length);
+        for (int i = 0; i < array.length; i++) {
+            oos.writeObject(array[i]);
+        }
+    }
+
+    /**
+     * Creates and returns an immutable collection from this proxy class.
+     * The instance returned is created as if by calling one of the
+     * static factory methods for
+     * <a href="List.html#immutable">List</a>,
+     * <a href="Map.html#immutable">Map</a>, or
+     * <a href="Set.html#immutable">Set</a>.
+     * This proxy class is the serial form for all immutable collection instances,
+     * regardless of implementation type. This is necessary to ensure that the
+     * existence of any particular implementation type is kept out of the
+     * serialized form.
+     *
+     * @return a collection created from this proxy object
+     * @throws InvalidObjectException if the tag value is illegal or if an exception
+     *         is thrown during creation of the collection
+     * @throws ObjectStreamException if another serialization error has occurred
+     * @since 9
+     */
     private Object readResolve() throws ObjectStreamException {
         try {
             if (array == null) {
@@ -631,8 +735,8 @@
             }
 
             // use low order 8 bits to indicate "kind"
-            // ignore high order bits
-            switch (flags & 0xff) {
+            // ignore high order 24 bits
+            switch (tag & 0xff) {
                 case IMM_LIST:
                     return List.of(array);
                 case IMM_SET:
@@ -646,7 +750,7 @@
                         return new ImmutableCollections.MapN<>(array);
                     }
                 default:
-                    throw new InvalidObjectException(String.format("invalid flags 0x%x", flags));
+                    throw new InvalidObjectException(String.format("invalid flags 0x%x", tag));
             }
         } catch (NullPointerException|IllegalArgumentException ex) {
             InvalidObjectException ioe = new InvalidObjectException("invalid object");
--- a/jdk/src/java.base/share/classes/java/util/List.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/List.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,6 +107,9 @@
  * Factories are free to create new instances or reuse existing ones. Therefore,
  * identity-sensitive operations on these instances (reference equality ({@code ==}),
  * identity hash code, and synchronization) are unreliable and should be avoided.
+ * <li>They are serialized as specified on the
+ * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a>
+ * page.
  * </ul>
  *
  * <p>This interface is a member of the
--- a/jdk/src/java.base/share/classes/java/util/Map.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/Map.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -133,6 +133,9 @@
  * Factories are free to create new instances or reuse existing ones. Therefore,
  * identity-sensitive operations on these instances (reference equality ({@code ==}),
  * identity hash code, and synchronization) are unreliable and should be avoided.
+ * <li>They are serialized as specified on the
+ * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a>
+ * page.
  * </ul>
  *
  * <p>This interface is a member of the
--- a/jdk/src/java.base/share/classes/java/util/Set.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/Set.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,6 +84,9 @@
  * Factories are free to create new instances or reuse existing ones. Therefore,
  * identity-sensitive operations on these instances (reference equality ({@code ==}),
  * identity hash code, and synchronization) are unreliable and should be avoided.
+ * <li>They are serialized as specified on the
+ * <a href="{@docRoot}/serialized-form.html#java.util.CollSer">Serialized Form</a>
+ * page.
  * </ul>
  *
  * <p>This interface is a member of the
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1242,7 +1242,8 @@
      */
     public KeySetView<K,V> keySet() {
         KeySetView<K,V> ks;
-        return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySetView<K,V>(this, null);
     }
 
     /**
@@ -1265,7 +1266,8 @@
      */
     public Collection<V> values() {
         ValuesView<K,V> vs;
-        return (vs = values) != null ? vs : (values = new ValuesView<K,V>(this));
+        if ((vs = values) != null) return vs;
+        return values = new ValuesView<K,V>(this);
     }
 
     /**
@@ -1287,7 +1289,8 @@
      */
     public Set<Map.Entry<K,V>> entrySet() {
         EntrySetView<K,V> es;
-        return (es = entrySet) != null ? es : (entrySet = new EntrySetView<K,V>(this));
+        if ((es = entrySet) != null) return es;
+        return entrySet = new EntrySetView<K,V>(this);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 05 21:46:22 2017 +0200
@@ -376,12 +376,12 @@
 
     /** Lazily initialized key set */
     private transient KeySet<K,V> keySet;
+    /** Lazily initialized values collection */
+    private transient Values<K,V> values;
     /** Lazily initialized entry set */
     private transient EntrySet<K,V> entrySet;
-    /** Lazily initialized values collection */
-    private transient Values<K,V> values;
     /** Lazily initialized descending key set */
-    private transient ConcurrentNavigableMap<K,V> descendingMap;
+    private transient SubMap<K,V> descendingMap;
 
     /**
      * Initializes or resets state. Needed by constructors, clone,
@@ -1827,13 +1827,15 @@
      * @return a navigable set view of the keys in this map
      */
     public NavigableSet<K> keySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K,V> ks;
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySet<>(this);
     }
 
     public NavigableSet<K> navigableKeySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K,V> ks;
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySet<>(this);
     }
 
     /**
@@ -1856,8 +1858,9 @@
      * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
      */
     public Collection<V> values() {
-        Values<K,V> vs = values;
-        return (vs != null) ? vs : (values = new Values<>(this));
+        Values<K,V> vs;
+        if ((vs = values) != null) return vs;
+        return values = new Values<>(this);
     }
 
     /**
@@ -1888,14 +1891,16 @@
      *         sorted in ascending key order
      */
     public Set<Map.Entry<K,V>> entrySet() {
-        EntrySet<K,V> es = entrySet;
-        return (es != null) ? es : (entrySet = new EntrySet<K,V>(this));
+        EntrySet<K,V> es;
+        if ((es = entrySet) != null) return es;
+        return entrySet = new EntrySet<K,V>(this);
     }
 
     public ConcurrentNavigableMap<K,V> descendingMap() {
-        ConcurrentNavigableMap<K,V> dm = descendingMap;
-        return (dm != null) ? dm : (descendingMap = new SubMap<K,V>
-                                    (this, null, false, null, false, true));
+        ConcurrentNavigableMap<K,V> dm;
+        if ((dm = descendingMap) != null) return dm;
+        return descendingMap =
+            new SubMap<K,V>(this, null, false, null, false, true);
     }
 
     public NavigableSet<K> descendingKeySet() {
@@ -2564,7 +2569,7 @@
      * @serial include
      */
     static final class SubMap<K,V> extends AbstractMap<K,V>
-        implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {
+        implements ConcurrentNavigableMap<K,V>, Serializable {
         private static final long serialVersionUID = -7647078645895051609L;
 
         /** Underlying map */
@@ -2582,8 +2587,8 @@
 
         // Lazily initialized view holders
         private transient KeySet<K,V> keySetView;
-        private transient Set<Map.Entry<K,V>> entrySetView;
-        private transient Collection<V> valuesView;
+        private transient Values<K,V> valuesView;
+        private transient EntrySet<K,V> entrySetView;
 
         /**
          * Creates a new submap, initializing all fields.
@@ -3049,23 +3054,27 @@
         /* ---------------- Submap Views -------------- */
 
         public NavigableSet<K> keySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K,V> ks;
+            if ((ks = keySetView) != null) return ks;
+            return keySetView = new KeySet<>(this);
         }
 
         public NavigableSet<K> navigableKeySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K,V> ks;
+            if ((ks = keySetView) != null) return ks;
+            return keySetView = new KeySet<>(this);
         }
 
         public Collection<V> values() {
-            Collection<V> vs = valuesView;
-            return (vs != null) ? vs : (valuesView = new Values<>(this));
+            Values<K,V> vs;
+            if ((vs = valuesView) != null) return vs;
+            return valuesView = new Values<>(this);
         }
 
         public Set<Map.Entry<K,V>> entrySet() {
-            Set<Map.Entry<K,V>> es = entrySetView;
-            return (es != null) ? es : (entrySetView = new EntrySet<K,V>(this));
+            EntrySet<K,V> es;
+            if ((es = entrySetView) != null) return es;
+            return entrySetView = new EntrySet<K,V>(this);
         }
 
         public NavigableSet<K> descendingKeySet() {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Wed Jul 05 21:46:22 2017 +0200
@@ -596,7 +596,7 @@
      * not, be invoked for each completer in a computation.
      */
     public final void propagateCompletion() {
-        CountedCompleter<?> a = this, s = a;
+        CountedCompleter<?> a = this, s;
         for (int c;;) {
             if ((c = a.pending) == 0) {
                 if ((a = (s = a).completer) == null) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java	Wed Jul 05 21:46:22 2017 +0200
@@ -56,13 +56,11 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException, ExecutionException {
- *   CompletionService<Result> ecs
- *       = new ExecutorCompletionService<Result>(e);
- *   for (Callable<Result> s : solvers)
- *     ecs.submit(s);
- *   int n = solvers.size();
- *   for (int i = 0; i < n; ++i) {
- *     Result r = ecs.take().get();
+ *   CompletionService<Result> cs
+ *       = new ExecutorCompletionService<>(e);
+ *   solvers.forEach(cs::submit);
+ *   for (int i = solvers.size(); i > 0; i--) {
+ *     Result r = cs.take().get();
  *     if (r != null)
  *       use(r);
  *   }
@@ -76,27 +74,24 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException {
- *   CompletionService<Result> ecs
- *       = new ExecutorCompletionService<Result>(e);
+ *   CompletionService<Result> cs
+ *       = new ExecutorCompletionService<>(e);
  *   int n = solvers.size();
  *   List<Future<Result>> futures = new ArrayList<>(n);
  *   Result result = null;
  *   try {
- *     for (Callable<Result> s : solvers)
- *       futures.add(ecs.submit(s));
- *     for (int i = 0; i < n; ++i) {
+ *     solvers.forEach((solver) -> futures.add(cs.submit(solver)));
+ *     for (int i = n; i > 0; i--) {
  *       try {
- *         Result r = ecs.take().get();
+ *         Result r = cs.take().get();
  *         if (r != null) {
  *           result = r;
  *           break;
  *         }
  *       } catch (ExecutionException ignore) {}
  *     }
- *   }
- *   finally {
- *     for (Future<Result> f : futures)
- *       f.cancel(true);
+ *   } finally {
+ *     futures.forEach((future) -> future.cancel(true));
  *   }
  *
  *   if (result != null)
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Wed Jul 05 21:46:22 2017 +0200
@@ -348,10 +348,6 @@
     private final AtomicReference<QNode> evenQ;
     private final AtomicReference<QNode> oddQ;
 
-    private AtomicReference<QNode> queueFor(int phase) {
-        return ((phase & 1) == 0) ? evenQ : oddQ;
-    }
-
     /**
      * Returns message string for bounds exceptions on arrival.
      */
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -67,9 +67,9 @@
     static private final boolean MAP_ALL =
             isSystemProperty("jdk.image.map.all", "true", IS_64_BIT ? "true" : "false");
 
-    private final String name;
+    private final Path imagePath;
     private final ByteOrder byteOrder;
-    private final Path imagePath;
+    private final String name;
     private final ByteBuffer memoryMap;
     private final FileChannel channel;
     private final ImageHeader header;
@@ -83,11 +83,9 @@
 
     protected BasicImageReader(Path path, ByteOrder byteOrder)
             throws IOException {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(byteOrder);
-        this.name = path.toString();
-        this.byteOrder = byteOrder;
-        imagePath = path;
+        this.imagePath = Objects.requireNonNull(path);
+        this.byteOrder = Objects.requireNonNull(byteOrder);
+        this.name = this.imagePath.toString();
 
         ByteBuffer map;
 
@@ -211,6 +209,8 @@
     }
 
     public static void releaseByteBuffer(ByteBuffer buffer) {
+        Objects.requireNonNull(buffer);
+
         if (!MAP_ALL) {
             ImageBufferCache.releaseBuffer(buffer);
         }
@@ -240,10 +240,14 @@
     }
 
     public ImageLocation findLocation(String mn, String rn) {
+        Objects.requireNonNull(mn);
+        Objects.requireNonNull(rn);
+
         return findLocation("/" + mn + "/" + rn);
     }
 
     public synchronized ImageLocation findLocation(String name) {
+        Objects.requireNonNull(name);
         // Details of the algorithm used here can be found in
         // jdk.tools.jlink.internal.PerfectHashBuilder.
         byte[] bytes = ImageStringsReader.mutf8FromString(name);
@@ -287,16 +291,25 @@
     }
 
     public long[] getAttributes(int offset) {
+        if (offset < 0 || offset >= locations.limit()) {
+            throw new IndexOutOfBoundsException("offset");
+        }
+
         ByteBuffer buffer = slice(locations, offset, locations.limit() - offset);
         return ImageLocation.decompress(buffer);
     }
 
     public String getString(int offset) {
+        if (offset < 0 || offset >= strings.limit()) {
+            throw new IndexOutOfBoundsException("offset");
+        }
+
         ByteBuffer buffer = slice(strings, offset, strings.limit() - offset);
         return ImageStringsReader.stringFromByteBuffer(buffer);
     }
 
     private byte[] getBufferBytes(ByteBuffer buffer) {
+        Objects.requireNonNull(buffer);
         byte[] bytes = new byte[buffer.limit()];
         buffer.get(bytes);
 
@@ -343,6 +356,7 @@
     }
 
     public byte[] getResource(String name) {
+        Objects.requireNonNull(name);
         ImageLocation location = findLocation(name);
 
         return location != null ? getResource(location) : null;
@@ -362,6 +376,7 @@
     }
 
     public ByteBuffer getResourceBuffer(ImageLocation loc) {
+        Objects.requireNonNull(loc);
         long offset = loc.getContentOffset() + indexSize;
         long compressedSize = loc.getCompressedSize();
         long uncompressedSize = loc.getUncompressedSize();
@@ -399,6 +414,7 @@
     }
 
     public InputStream getResourceStream(ImageLocation loc) {
+        Objects.requireNonNull(loc);
         byte[] bytes = getResource(loc);
 
         return new ByteArrayInputStream(bytes);
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageHeader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
+import java.util.Objects;
 
 /**
  * @implNote This class needs to maintain JDK 8 source compatibility.
@@ -75,6 +76,8 @@
     }
 
     static ImageHeader readFrom(IntBuffer buffer) {
+        Objects.requireNonNull(buffer);
+
         if (buffer.capacity() != HEADER_SLOTS) {
             throw new InternalError("jimage header not the correct size");
         }
@@ -94,11 +97,13 @@
     }
 
     public void writeTo(ImageStream stream) {
+        Objects.requireNonNull(stream);
         stream.ensure(getHeaderSize());
         writeTo(stream.getBuffer());
     }
 
     public void writeTo(ByteBuffer buffer) {
+        Objects.requireNonNull(buffer);
         buffer.putInt(magic);
         buffer.putInt(majorVersion << 16 | minorVersion);
         buffer.putInt(flags);
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java	Wed Jul 05 21:46:22 2017 +0200
@@ -26,6 +26,7 @@
 package jdk.internal.jimage;
 
 import java.nio.ByteBuffer;
+import java.util.Objects;
 
 /**
  * @implNote This class needs to maintain JDK 8 source compatibility.
@@ -50,8 +51,8 @@
     protected final ImageStrings strings;
 
     public ImageLocation(long[] attributes, ImageStrings strings) {
-        this.attributes = attributes;
-        this.strings = strings;
+        this.attributes = Objects.requireNonNull(attributes);
+        this.strings = Objects.requireNonNull(strings);
     }
 
     ImageStrings getStrings() {
@@ -67,6 +68,7 @@
     }
 
     static long[] decompress(ByteBuffer bytes) {
+        Objects.requireNonNull(bytes);
         long[] attributes = new long[ATTRIBUTE_COUNT];
 
         if (bytes != null) {
@@ -103,6 +105,7 @@
     }
 
     public static byte[] compress(long[] attributes) {
+        Objects.requireNonNull(attributes);
         ImageStream stream = new ImageStream(16);
 
         for (int kind = ATTRIBUTE_END + 1; kind < ATTRIBUTE_COUNT; kind++) {
@@ -124,6 +127,8 @@
      }
 
     public boolean verify(String name) {
+        Objects.requireNonNull(name);
+
         return name.equals(getFullName());
     }
 
@@ -250,6 +255,7 @@
     }
 
     static ImageLocation readFrom(BasicImageReader reader, int offset) {
+        Objects.requireNonNull(reader);
         long[] attributes = reader.getAttributes(offset);
         ImageStringsReader strings = reader.getStrings();
 
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -59,6 +59,9 @@
     }
 
     public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException {
+        Objects.requireNonNull(imagePath);
+        Objects.requireNonNull(byteOrder);
+
         return SharedImageReader.open(imagePath, byteOrder);
     }
 
@@ -218,6 +221,9 @@
         }
 
         public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException {
+            Objects.requireNonNull(imagePath);
+            Objects.requireNonNull(byteOrder);
+
             synchronized (OPEN_FILES) {
                 SharedImageReader reader = OPEN_FILES.get(imagePath);
 
@@ -237,6 +243,8 @@
         }
 
         public void close(ImageReader image) throws IOException {
+            Objects.requireNonNull(image);
+
             synchronized (OPEN_FILES) {
                 if (!openers.remove(image)) {
                     throw new IOException("image file already closed");
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReaderFactory.java	Wed Jul 05 21:46:22 2017 +0200
@@ -31,6 +31,7 @@
 import java.nio.file.Paths;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Factory to get ImageReader
@@ -54,6 +55,7 @@
      * Returns an {@code ImageReader} to read from the given image file
      */
     public static ImageReader get(Path jimage) throws IOException {
+        Objects.requireNonNull(jimage);
         ImageReader reader = readers.get(jimage);
         if (reader != null) {
             return reader;
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStream.java	Wed Jul 05 21:46:22 2017 +0200
@@ -28,6 +28,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * @implNote This class needs to maintain JDK 8 source compatibility.
@@ -57,16 +58,16 @@
 
     public ImageStream(int size, ByteOrder byteOrder) {
         buffer = ByteBuffer.allocate(size);
-        buffer.order(byteOrder);
+        buffer.order(Objects.requireNonNull(byteOrder));
     }
 
     public ImageStream(byte[] bytes, ByteOrder byteOrder) {
-        buffer = ByteBuffer.wrap(bytes);
-        buffer.order(byteOrder);
+        buffer = ByteBuffer.wrap(Objects.requireNonNull(bytes));
+        buffer.order(Objects.requireNonNull(byteOrder));
     }
 
     public ImageStream(ByteBuffer buffer) {
-        this.buffer = buffer;
+        this.buffer = Objects.requireNonNull(buffer);
     }
 
     public ImageStream align(int alignment) {
--- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -27,6 +27,7 @@
 
 import java.io.UTFDataFormatException;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 
 /**
  * @implNote This class needs to maintain JDK 8 source compatibility.
@@ -40,7 +41,7 @@
     private final BasicImageReader reader;
 
     ImageStringsReader(BasicImageReader reader) {
-        this.reader = reader;
+        this.reader = Objects.requireNonNull(reader);
     }
 
     @Override
@@ -54,7 +55,19 @@
     }
 
     private static int hashCode(byte[] bytes, int offset, int count, int seed) {
-        for (int i = offset, limit = offset + count; i < limit; i++) {
+        Objects.requireNonNull(bytes);
+
+        if (offset < 0 || count < 0 || offset > bytes.length - count) {
+            throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count);
+        }
+
+        int limit = offset + count;
+
+        if (limit < 0 || limit > bytes.length) {
+            throw new IndexOutOfBoundsException("limit=" + limit);
+        }
+
+        for (int i = offset; i < limit; i++) {
             seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
         }
 
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -72,8 +72,8 @@
  * loader. This allows automatic modules (for example) to link to types in the
  * unnamed module of the parent class loader.
  *
- * @see Layer#createWithOneLoader
- * @see Layer#createWithManyLoaders
+ * @see Layer#defineModulesWithOneLoader
+ * @see Layer#defineModulesWithManyLoaders
  */
 
 public final class Loader extends SecureClassLoader {
@@ -315,6 +315,8 @@
                 }, acc);
         } catch (PrivilegedActionException pae) {
             throw (IOException) pae.getCause();
+        } catch (SecurityException se) {
+            return null;
         }
     }
 
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jul 05 21:46:22 2017 +0200
@@ -475,6 +475,23 @@
      */
     public static native long getNanoTimeAdjustment(long offsetInSeconds);
 
+    /**
+     * Returns the VM arguments for this runtime environment.
+     *
+     * @implNote
+     * The HotSpot JVM processes the input arguments from multiple sources
+     * in the following order:
+     * 1. JAVA_TOOL_OPTIONS environment variable
+     * 2. Options from JNI Invocation API
+     * 3. _JAVA_OPTIONS environment variable
+     *
+     * If VM options file is specified via -XX:VMOptionsFile, the vm options
+     * file is read and expanded in place of -XX:VMOptionFile option.
+     *
+     * Open issue with -XX:Flags (see JDK-8157979)
+     */
+    public static native String[] getRuntimeArguments();
+
     static {
         initialize();
     }
--- a/jdk/src/java.base/share/classes/module-info.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/module-info.java	Wed Jul 05 21:46:22 2017 +0200
@@ -165,6 +165,7 @@
         java.sql,
         java.xml,
         jdk.charsets,
+        jdk.compiler,
         jdk.jartool,
         jdk.jlink,
         jdk.net,
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 21:46:22 2017 +0200
@@ -29,6 +29,7 @@
 import java.security.CryptoPrimitive;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Set;
 import java.util.EnumSet;
 import java.math.BigInteger;
@@ -59,7 +60,7 @@
 import sun.security.x509.AlgorithmId;
 
 /**
- * A <code>PKIXCertPathChecker</code> implementation to check whether a
+ * A {@code PKIXCertPathChecker} implementation to check whether a
  * specified certificate contains the required algorithm constraints.
  * <p>
  * Certificate fields such as the subject public key, the signature
@@ -74,6 +75,7 @@
 
     private final AlgorithmConstraints constraints;
     private final PublicKey trustedPubKey;
+    private final Date pkixdate;
     private PublicKey prevPubKey;
 
     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
@@ -99,7 +101,7 @@
     private boolean trustedMatch = false;
 
     /**
-     * Create a new <code>AlgorithmChecker</code> with the algorithm
+     * Create a new {@code AlgorithmChecker} with the algorithm
      * constraints specified in security property
      * "jdk.certpath.disabledAlgorithms".
      *
@@ -107,11 +109,26 @@
      *     certificate
      */
     public AlgorithmChecker(TrustAnchor anchor) {
-        this(anchor, certPathDefaultConstraints);
+        this(anchor, certPathDefaultConstraints, null);
     }
 
     /**
-     * Create a new <code>AlgorithmChecker</code> with the
+     * Create a new {@code AlgorithmChecker} with the
+     * given {@code TrustAnchor} and {@code AlgorithmConstraints}.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     * @param constraints the algorithm constraints (or null)
+     *
+     * @throws IllegalArgumentException if the {@code anchor} is null
+     */
+    public AlgorithmChecker(TrustAnchor anchor,
+            AlgorithmConstraints constraints) {
+        this(anchor, constraints, null);
+    }
+
+    /**
+     * Create a new {@code AlgorithmChecker} with the
      * given {@code AlgorithmConstraints}.
      * <p>
      * Note that this constructor will be used to check a certification
@@ -124,20 +141,24 @@
         this.prevPubKey = null;
         this.trustedPubKey = null;
         this.constraints = constraints;
+        this.pkixdate = null;
     }
 
     /**
-     * Create a new <code>AlgorithmChecker</code> with the
-     * given <code>TrustAnchor</code> and <code>AlgorithmConstraints</code>.
+     * Create a new {@code AlgorithmChecker} with the
+     * given {@code TrustAnchor} and {@code AlgorithmConstraints}.
      *
      * @param anchor the trust anchor selected to validate the target
      *     certificate
      * @param constraints the algorithm constraints (or null)
+     * @param pkixdate Date the constraints are checked against. The value is
+     *             either the PKIXParameter date or null for the current date.
      *
-     * @throws IllegalArgumentException if the <code>anchor</code> is null
+     * @throws IllegalArgumentException if the {@code anchor} is null
      */
     public AlgorithmChecker(TrustAnchor anchor,
-            AlgorithmConstraints constraints) {
+            AlgorithmConstraints constraints,
+            Date pkixdate) {
 
         if (anchor == null) {
             throw new IllegalArgumentException(
@@ -157,6 +178,22 @@
 
         this.prevPubKey = trustedPubKey;
         this.constraints = constraints;
+        this.pkixdate = pkixdate;
+    }
+
+    /**
+     * Create a new {@code AlgorithmChecker} with the
+     * given {@code TrustAnchor} and {@code PKIXParameter} date.
+     *
+     * @param anchor the trust anchor selected to validate the target
+     *     certificate
+     * @param pkixdate Date the constraints are checked against. The value is
+     *             either the PKIXParameter date or null for the current date.
+     *
+     * @throws IllegalArgumentException if the {@code anchor} is null
+     */
+    public AlgorithmChecker(TrustAnchor anchor, Date pkixdate) {
+        this(anchor, certPathDefaultConstraints, pkixdate);
     }
 
     // Check this 'cert' for restrictions in the AnchorCertificates
@@ -259,7 +296,7 @@
         // permits() will throw exception on failure.
         certPathDefaultConstraints.permits(primitives,
                 new CertConstraintParameters((X509Certificate)cert,
-                        trustedMatch));
+                        trustedMatch, pkixdate));
                 // new CertConstraintParameters(x509Cert, trustedMatch));
         // If there is no previous key, set one and exit
         if (prevPubKey == null) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Wed Jul 05 21:46:22 2017 +0200
@@ -172,7 +172,7 @@
         List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
         // add standard checkers that we will be using
         certPathCheckers.add(untrustedChecker);
-        certPathCheckers.add(new AlgorithmChecker(anchor));
+        certPathCheckers.add(new AlgorithmChecker(anchor, params.date()));
         certPathCheckers.add(new KeyChecker(certPathLen,
                                             params.targetCertConstraints()));
         certPathCheckers.add(new ConstraintsChecker(certPathLen));
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Wed Jul 05 21:46:22 2017 +0200
@@ -343,7 +343,8 @@
                 checkers.add(policyChecker);
 
                 // add the algorithm checker
-                checkers.add(new AlgorithmChecker(builder.trustAnchor));
+                checkers.add(new AlgorithmChecker(builder.trustAnchor,
+                        buildParams.date()));
 
                 BasicChecker basicChecker = null;
                 if (nextState.keyParamsNeeded()) {
--- a/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Wed Jul 05 21:46:22 2017 +0200
@@ -26,6 +26,7 @@
 package sun.security.util;
 
 import java.security.cert.X509Certificate;
+import java.util.Date;
 
 /**
  * This class is a wrapper for keeping state and passing objects between PKIX,
@@ -34,18 +35,21 @@
 public class CertConstraintParameters {
     // A certificate being passed to check against constraints.
     private final X509Certificate cert;
-
     // This is true if the trust anchor in the certificate chain matches a cert
     // in AnchorCertificates
     private final boolean trustedMatch;
+    // PKIXParameter date
+    private final Date pkixDate;
 
-    public CertConstraintParameters(X509Certificate c, boolean match) {
+    public CertConstraintParameters(X509Certificate c, boolean match,
+            Date pkixdate) {
         cert = c;
         trustedMatch = match;
+        pkixDate = pkixdate;
     }
 
     public CertConstraintParameters(X509Certificate c) {
-        this(c, false);
+        this(c, false, null);
     }
 
     // Returns if the trust anchor has a match if anchor checking is enabled.
@@ -56,4 +60,9 @@
     public X509Certificate getCertificate() {
         return cert;
     }
+
+    public Date getPKIXParamDate() {
+        return pkixDate;
+    }
+
 }
--- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 21:46:22 2017 +0200
@@ -31,11 +31,15 @@
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CertPathValidatorException.BasicReason;
 import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 
@@ -226,6 +230,8 @@
         private Map<String, Set<Constraint>> constraintsMap = new HashMap<>();
         private static final Pattern keySizePattern = Pattern.compile(
                 "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
+        private static final Pattern denyAfterPattern = Pattern.compile(
+                "denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
 
         public Constraints(String[] constraintArray) {
             for (String constraintEntry : constraintArray) {
@@ -259,6 +265,8 @@
                 Constraint c, lastConstraint = null;
                 // Allow only one jdkCA entry per constraint entry
                 boolean jdkCALimit = false;
+                // Allow only one denyAfter entry per constraint entry
+                boolean denyAfterLimit = false;
 
                 for (String entry : policy.split("&")) {
                     entry = entry.trim();
@@ -284,6 +292,22 @@
                         }
                         c = new jdkCAConstraint(algorithm);
                         jdkCALimit = true;
+
+                    } else if(matcher.usePattern(denyAfterPattern).matches()) {
+                        if (debug != null) {
+                            debug.println("Constraints set to denyAfter");
+                        }
+                        if (denyAfterLimit) {
+                            throw new IllegalArgumentException("Only one " +
+                                    "denyAfter entry allowed in property. " +
+                                    "Constraint: " + constraintEntry);
+                        }
+                        int year = Integer.parseInt(matcher.group(1));
+                        int month = Integer.parseInt(matcher.group(2));
+                        int day = Integer.parseInt(matcher.group(3));
+                        c = new DenyAfterConstraint(algorithm, year, month,
+                                day);
+                        denyAfterLimit = true;
                     } else {
                         throw new IllegalArgumentException("Error in security" +
                                 " property. Constraint unknown: " + entry);
@@ -360,7 +384,15 @@
         }
     }
 
-    // Abstract class for algorithm constraint checking
+    /**
+     * This abstract Constraint class for algorithm-based checking
+     * may contain one or more constraints.  If the '&' on the {@Security}
+     * property is used, multiple constraints have been grouped together
+     * requiring all the constraints to fail for the check to be disallowed.
+     *
+     * If the class contains multiple constraints, the next constraint
+     * is stored in {@code nextConstraint} in linked-list fashion.
+     */
     private abstract static class Constraint {
         String algorithm;
         Constraint nextConstraint = null;
@@ -396,22 +428,79 @@
         }
 
         /**
-         * Check if an algorithm constraint permit this key to be used.
+         * Check if an algorithm constraint is permitted with a given key.
+         *
+         * If the check inside of {@code permit()} fails, it must call
+         * {@code next()} with the same {@code Key} parameter passed if
+         * multiple constraints need to be checked.
+         *
          * @param key Public key
-         * @return true if constraints do not match
+         * @return 'true' if constraint is allowed, 'false' if disallowed.
          */
         public boolean permits(Key key) {
             return true;
         }
 
         /**
-         * Check if an algorithm constraint is permit this certificate to
-         * be used.
-         * @param cp CertificateParameter containing certificate and state info
-         * @return true if constraints do not match
+         * Check if an algorithm constraint is permitted with a given
+         * CertConstraintParameters.
+         *
+         * If the check inside of {@code permits()} fails, it must call
+         * {@code next()} with the same {@code CertConstraintParameters}
+         * parameter passed if multiple constraints need to be checked.
+         *
+         * @param cp CertConstraintParameter containing certificate info
+         * @throws CertPathValidatorException if constraint disallows.
+         *
          */
         public abstract void permits(CertConstraintParameters cp)
                 throws CertPathValidatorException;
+
+        /**
+         * Recursively check if the constraints are allowed.
+         *
+         * If {@code nextConstraint} is non-null, this method will
+         * call {@code nextConstraint}'s {@code permits()} to check if the
+         * constraint is allowed or denied.  If the constraint's
+         * {@code permits()} is allowed, this method will exit this and any
+         * recursive next() calls, returning 'true'.  If the constraints called
+         * were disallowed, the last constraint will throw
+         * {@code CertPathValidatorException}.
+         *
+         * @param cp CertConstraintParameters
+         * @return 'true' if constraint allows the operation, 'false' if
+         * we are at the end of the constraint list or,
+         * {@code nextConstraint} is null.
+         */
+        boolean next(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            if (nextConstraint != null) {
+                nextConstraint.permits(cp);
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Recursively check if this constraint is allowed,
+         *
+         * If {@code nextConstraint} is non-null, this method will
+         * call {@code nextConstraint}'s {@code permit()} to check if the
+         * constraint is allowed or denied.  If the constraint's
+         * {@code permit()} is allowed, this method will exit this and any
+         * recursive next() calls, returning 'true'.  If the constraints
+         * called were disallowed the check will exit with 'false'.
+         *
+         * @param key Public key
+         * @return 'true' if constraint allows the operation, 'false' if
+         * the constraint denies the operation.
+         */
+        boolean next(Key key) {
+            if (nextConstraint != null && nextConstraint.permits(key)) {
+                return true;
+            }
+            return false;
+        }
     }
 
     /*
@@ -424,9 +513,9 @@
         }
 
         /*
-         * Check if each constraint fails and check if there is a linked
-         * constraint  Any permitted constraint will exit the linked list
-         * to allow the operation.
+         * Check if CertConstraintParameters has a trusted match, if it does
+         * call next() for any following constraints. If it does not, exit
+         * as this constraint(s) does not restrict the operation.
          */
         public void permits(CertConstraintParameters cp)
                 throws CertPathValidatorException {
@@ -434,10 +523,9 @@
                 debug.println("jdkCAConstraints.permits(): " + algorithm);
             }
 
-            // Return false if the chain has a trust anchor in cacerts
+            // Check chain has a trust anchor in cacerts
             if (cp.isTrustedMatch()) {
-                if (nextConstraint != null) {
-                    nextConstraint.permits(cp);
+                if (next(cp)) {
                     return;
                 }
                 throw new CertPathValidatorException(
@@ -448,6 +536,99 @@
         }
     }
 
+    /*
+     * This class handles the denyAfter constraint.  The date is in the UTC/GMT
+     * timezone.
+     */
+     private static class DenyAfterConstraint extends Constraint {
+         private Date denyAfterDate;
+         private static final SimpleDateFormat dateFormat =
+                 new SimpleDateFormat("EEE, MMM d HH:mm:ss z YYYY");
+
+         DenyAfterConstraint(String algo, int year, int month, int day) {
+             Calendar c;
+
+             algorithm = algo;
+
+             if (debug != null) {
+                 debug.println("DenyAfterConstraint read in as:  year " +
+                         year + ", month = " + month + ", day = " + day);
+             }
+
+             c = new Calendar.Builder().setTimeZone(TimeZone.getTimeZone("GMT"))
+                     .setDate(year, month - 1, day).build();
+
+             if (year > c.getActualMaximum(Calendar.YEAR) ||
+                     year < c.getActualMinimum(Calendar.YEAR)) {
+                 throw new IllegalArgumentException(
+                         "Invalid year given in constraint: " + year);
+             }
+             if ((month - 1) > c.getActualMaximum(Calendar.MONTH) ||
+                     (month - 1) < c.getActualMinimum(Calendar.MONTH)) {
+                 throw new IllegalArgumentException(
+                         "Invalid month given in constraint: " + month);
+             }
+             if (day > c.getActualMaximum(Calendar.DAY_OF_MONTH) ||
+                     day < c.getActualMinimum(Calendar.DAY_OF_MONTH)) {
+                 throw new IllegalArgumentException(
+                         "Invalid Day of Month given in constraint: " + day);
+             }
+
+             denyAfterDate = c.getTime();
+             if (debug != null) {
+                 debug.println("DenyAfterConstraint date set to: " +
+                         dateFormat.format(denyAfterDate));
+             }
+         }
+
+         /*
+          * Checking that the provided date is not beyond the constraint date.
+          * The provided date can be the PKIXParameter date if given,
+          * otherwise it is the current date.
+          *
+          * If the constraint disallows, call next() for any following
+          * constraints. Throw an exception if this is the last constraint.
+          */
+         @Override
+         public void permits(CertConstraintParameters cp)
+                 throws CertPathValidatorException {
+             Date currentDate;
+
+             if (cp.getPKIXParamDate() != null) {
+                 currentDate = cp.getPKIXParamDate();
+             } else {
+                 currentDate = new Date();
+             }
+
+             if (!denyAfterDate.after(currentDate)) {
+                 if (next(cp)) {
+                     return;
+                 }
+                 throw new CertPathValidatorException(
+                         "denyAfter constraint check failed.  " +
+                                 "Constraint date: " +
+                                 dateFormat.format(denyAfterDate) +
+                                 "; Cert date: " +
+                                 dateFormat.format(currentDate),
+                          null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+             }
+         }
+
+         /*
+          * Return result if the constraint's date is beyond the current date
+          * in UTC timezone.
+          */
+         public boolean permits(Key key) {
+             if (next(key)) {
+                 return true;
+             }
+             if (debug != null) {
+                 debug.println("DenyAfterConstraints.permits(): " + algorithm);
+             }
+
+             return denyAfterDate.after(new Date());
+         }
+     }
 
     /*
      * This class contains constraints dealing with the key size
--- a/jdk/src/java.base/share/conf/security/java.security	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:46:22 2017 +0200
@@ -570,9 +570,7 @@
 # describes the mechanism for disabling algorithms based on algorithm name
 # and/or key length.  This includes algorithms used in certificates, as well
 # as revocation information such as CRLs and signed OCSP Responses.
-#
-# The syntax of the disabled algorithm string is described as this Java
-# BNF-style:
+# The syntax of the disabled algorithm string is described as follows:
 #   DisabledAlgorithms:
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
@@ -583,25 +581,22 @@
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint, CertConstraint
+#       KeySizeConstraint | CAConstraint | DenyAfterConstraint
 #
 #   KeySizeConstraint:
-#       keySize Operator DecimalInteger
+#       keySize Operator KeyLength
 #
 #   Operator:
 #       <= | < | == | != | >= | >
 #
-#   DecimalInteger:
-#       DecimalDigits
-#
-#   DecimalDigits:
-#       DecimalDigit {DecimalDigit}
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
 #
-#   DecimalDigit: one of
-#       1 2 3 4 5 6 7 8 9 0
+#   CAConstraint:
+#       jdkCA
 #
-#   CertConstraint
-#       jdkCA
+#   DenyAfterConstraint:
+#       denyAfter YYYY-MM-DD
 #
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
@@ -615,27 +610,42 @@
 # that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
 # will not disable algorithms related to "ECDSA".
 #
-# A "Constraint" provides further guidance for the algorithm being specified.
-# The "KeySizeConstraint" requires a key of a valid size range if the
-# "AlgorithmName" is of a key algorithm.  The "DecimalInteger" indicates the
-# key size specified in number of bits.  For example, "RSA keySize <= 1024"
-# indicates that any RSA key with key size less than or equal to 1024 bits
-# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates
-# that any RSA key with key size less than 1024 or greater than 2048 should
-# be disabled. Note that the "KeySizeConstraint" only makes sense to key
-# algorithms.
+# A "Constraint" defines restrictions on the keys and/or certificates for
+# a specified AlgorithmName:
+#
+#   KeySizeConstraint:
+#     keySize Operator KeyLength
+#       The constraint requires a key of a valid size range if the
+#       "AlgorithmName" is of a key algorithm.  The "KeyLength" indicates
+#       the key size specified in number of bits.  For example,
+#       "RSA keySize <= 1024" indicates that any RSA key with key size less
+#       than or equal to 1024 bits should be disabled, and
+#       "RSA keySize < 1024, RSA keySize > 2048" indicates that any RSA key
+#       with key size less than 1024 or greater than 2048 should be disabled.
+#       This constraint is only used on algorithms that have a key size.
 #
-# "CertConstraint" specifies additional constraints for
-# certificates that contain algorithms that are restricted:
+#   CAConstraint:
+#     jdkCA
+#       This constraint prohibits the specified algorithm only if the
+#       algorithm is used in a certificate chain that terminates at a marked
+#       trust anchor in the lib/security/cacerts keystore.  If the jdkCA
+#       constraint is not set, then all chains using the specified algorithm
+#       are restricted.  jdkCA may only be used once in a DisabledAlgorithm
+#       expression.
+#       Example:  To apply this constraint to SHA-1 certificates, include
+#       the following:  "SHA1 jdkCA"
 #
-#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
-#     in a certificate chain that terminates at a marked trust anchor in the
-#     lib/security/cacerts keystore.  All other chains are not affected.
-#     If the jdkCA constraint is not set, then all chains using the
-#     specified algorithm are restricted.  jdkCA may only be used once in
-#     a DisabledAlgorithm expression.
-#     Example:  To apply this constraint to SHA-1 certificates, include
-#     the following:  "SHA1 jdkCA"
+#   DenyAfterConstraint:
+#     denyAfter YYYY-MM-DD
+#       This constraint prohibits a certificate with the specified algorithm
+#       from being used after the date regardless of the certificate's
+#       validity.  JAR files that are signed and timestamped before the
+#       constraint date with certificates containing the disabled algorithm
+#       will not be restricted.  The date is processed in the UTC timezone.
+#       This constraint can only be used once in a DisabledAlgorithm
+#       expression.
+#       Example:  To deny usage of RSA 2048 bit certificates after Feb 3 2020,
+#       use the following:  "RSA keySize == 2048 & denyAfter 2020-02-03"
 #
 # When an algorithm must satisfy more than one constraint, it must be
 # delimited by an ampersand '&'.  For example, to restrict certificates in a
--- a/jdk/src/java.base/share/native/libjava/VM.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/native/libjava/VM.c	Wed Jul 05 21:46:22 2017 +0200
@@ -55,3 +55,8 @@
     (*env)->RegisterNatives(env, cls,
                             methods, sizeof(methods)/sizeof(methods[0]));
 }
+
+JNIEXPORT jobjectArray JNICALL
+Java_jdk_internal_misc_VM_getRuntimeArguments(JNIEnv *env, jclass cls) {
+    return JVM_GetVmArguments(env);
+}
--- a/jdk/src/java.base/share/native/libnet/InetAddress.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/native/libnet/InetAddress.c	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@
         CHECK_NULL(iac_class);
         ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
         CHECK_NULL(ia_holderID);
-        ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
+        ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "I");
         CHECK_NULL(ia_preferIPv6AddressID);
 
         iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
--- a/jdk/src/java.base/share/native/libverify/check_code.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/native/libverify/check_code.c	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1744,9 +1744,14 @@
             }
 
         default: {
+            if (instruction < 0 || instruction > JVM_OPC_MAX)
+                return -1;
+
             /* A length of 0 indicates an error. */
-            int length = opcode_length[instruction];
-            return (length <= 0) ? -1 : length;
+            if (opcode_length[instruction] <= 0)
+                return -1;
+
+            return opcode_length[instruction];
         }
     }
 }
--- a/jdk/src/java.base/share/native/libzip/zip_util.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/share/native/libzip/zip_util.c	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,13 @@
 static jint INITIAL_META_COUNT = 2;   /* initial number of entries in meta name array */
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+#ifdef STATIC_BUILD
+DEF_STATIC_JNI_OnLoad
+#endif
+
+/*
  * The ZFILE_* functions exist to provide some platform-independence with
  * respect to file access needs.
  */
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
 
 #include "java_net_Inet4AddressImpl.h"
 #include "java_net_Inet6AddressImpl.h"
+#include "java_net_InetAddress.h"
 
 /* the initial size of our hostent buffers */
 #ifndef NI_MAXHOST
@@ -157,7 +158,10 @@
     }
 
     name = (*env)->NewStringUTF(env, hostname);
-    CHECK_NULL_RETURN(name, NULL);
+    if (name == NULL) {
+        freeifaddrs(ifa);
+        return NULL;
+    }
 
     /* Iterate over the interfaces, and total up the number of IPv4 and IPv6
      * addresses we have. Also keep a count of loopback addresses. We need to
@@ -312,8 +316,8 @@
         JNU_ReleaseStringPlatformChars(env, host, hostname);
         return NULL;
     } else {
-        int i = 0;
-        int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
+        int i = 0, addressPreference = -1;
+        int inetCount = 0, inet6Count = 0, inetIndex = 0, inet6Index = 0, originalIndex = 0;
         struct addrinfo *itr, *last = NULL, *iterator = res;
         while (iterator != NULL) {
             int skip = 0;
@@ -394,14 +398,18 @@
             goto cleanupAndReturn;
         }
 
-        if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) {
+        addressPreference = (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
+
+        if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
             /* AF_INET addresses will be offset by inet6Count */
             inetIndex = inet6Count;
             inet6Index = 0;
-        } else {
+        } else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
             /* AF_INET6 addresses will be offset by inetCount */
             inetIndex = 0;
             inet6Index = inetCount;
+        } else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
+            inetIndex = inet6Index = originalIndex = 0;
         }
 
         while (iterator != NULL) {
@@ -414,7 +422,7 @@
                 }
                 setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
                 setInetAddress_hostName(env, iaObj, host);
-                (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
+                (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
                 inetIndex++;
             } else if (iterator->ai_family == AF_INET6) {
                 jint scope = 0;
@@ -435,9 +443,13 @@
                     setInet6Address_scopeid(env, iaObj, scope);
                 }
                 setInetAddress_hostName(env, iaObj, host);
-                (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
+                (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
                 inet6Index++;
             }
+            if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
+                originalIndex++;
+                inetIndex = inet6Index = 0;
+            }
             iterator = iterator->ai_next;
         }
     }
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Jul 05 21:46:22 2017 +0200
@@ -243,6 +243,7 @@
     if (name_utf == NULL) {
        if (!(*env)->ExceptionCheck(env))
            JNU_ThrowOutOfMemoryError(env, NULL);
+       freeif(ifs);
        return NULL;
     }
 
@@ -519,7 +520,7 @@
     }
     if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
        (*env)->ReleaseStringUTFChars(env, name, name_utf);
-       return JNI_FALSE;
+       return NULL;
     }
 
     if (!IS_NULL(addrArray)) {
@@ -664,7 +665,7 @@
     }
 
     // Create the array of InetAddresses
-    addrArr = (*env)->NewObjectArray(env, addr_count,  ia_class, NULL);
+    addrArr = (*env)->NewObjectArray(env, addr_count, ia_class, NULL);
     if (addrArr == NULL) {
         return NULL;
     }
@@ -1829,7 +1830,7 @@
     strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
 
     if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
-         return -1;
+        return -1;
     }
 
     *flags = if2.lifr_flags;
@@ -1859,8 +1860,7 @@
                                               "IPV6 Socket creation failed");
                  return -1;
               }
-         }
-         else{ // errno is not NOSUPPORT
+         } else { // errno is not NOSUPPORT
              NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                           "IPV4 Socket creation failed");
              return -1;
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c	Wed Jul 05 21:46:22 2017 +0200
@@ -95,8 +95,8 @@
         CHECK_NULL(c);
         c = (*env)->NewGlobalRef(env, c);
         CHECK_NULL(c);
-        ni_defaultIndexID = (*env)->GetStaticFieldID(
-            env, c, "defaultIndex", "I");
+        ni_defaultIndexID = (*env)->GetStaticFieldID(env, c, "defaultIndex", "I");
+        CHECK_NULL(ni_defaultIndexID);
         ni_class = c;
     }
     int defaultIndex;
@@ -118,8 +118,8 @@
         CHECK_NULL_RETURN(c, 0);
         c = (*env)->NewGlobalRef(env, c);
         CHECK_NULL_RETURN(c, 0);
-        ni_defaultIndexID = (*env)->GetStaticFieldID(env, c,
-                                                     "defaultIndex", "I");
+        ni_defaultIndexID = (*env)->GetStaticFieldID(env, c, "defaultIndex", "I");
+        CHECK_NULL_RETURN(ni_defaultIndexID, 0);
         ni_class = c;
     }
     defaultIndex = (*env)->GetStaticIntField(env, ni_class,
--- a/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,7 @@
 
     /* get the address preference */
     preferIPv6Address
-        = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
+        = (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
 
     /* Try once, with our static buffer. */
     memset(&hints, 0, sizeof(hints));
@@ -122,7 +122,7 @@
         }
     } else {
         int i = 0;
-        int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
+        int inetCount = 0, inet6Count = 0, inetIndex = 0, inet6Index = 0, originalIndex = 0;
         struct addrinfo *itr, *last, *iterator = res;
         while (iterator != NULL) {
             int skip = 0;
@@ -203,12 +203,14 @@
             goto cleanupAndReturn;
         }
 
-        if (preferIPv6Address) {
+        if (preferIPv6Address == java_net_InetAddress_PREFER_IPV6_VALUE) {
             inetIndex = inet6Count;
             inet6Index = 0;
-        } else {
+        } else if (preferIPv6Address == java_net_InetAddress_PREFER_IPV4_VALUE) {
             inetIndex = 0;
             inet6Index = inetCount;
+        } else if (preferIPv6Address == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
+            inetIndex = inet6Index = originalIndex = 0;
         }
 
         while (iterator != NULL) {
@@ -220,7 +222,7 @@
               }
               setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
               setInetAddress_hostName(env, iaObj, host);
-              (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
+              (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
                 inetIndex ++;
             } else if (iterator->ai_family == AF_INET6) {
               jint scope = 0;
@@ -240,9 +242,13 @@
                 setInet6Address_scopeid(env, iaObj, scope);
               }
               setInetAddress_hostName(env, iaObj, host);
-              (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
+              (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
               inet6Index ++;
             }
+            if (preferIPv6Address == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
+                originalIndex++;
+                inetIndex = inet6Index = 0;
+            }
             iterator = iterator->ai_next;
         }
     }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Wed Jul 05 21:46:22 2017 +0200
@@ -40,7 +40,7 @@
  * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
  * name}</li>
  * <li>For other files (shared lib, launchers, config, ...):/{module name}/
- * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+ * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name}</li>
  * </ul>
  */
 public interface ModuleEntry {
--- a/jdk/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java	Wed Jul 05 21:46:22 2017 +0200
@@ -296,45 +296,6 @@
         theInternalUnsafe.putDouble(o, offset, x);
     }
 
-
-    // These read VM internal data.
-
-    /**
-     * Fetches an uncompressed reference value from a given native variable
-     * ignoring the VM's compressed references mode.
-     *
-     * @param address a memory address locating the variable
-     * @return the value fetched from the indicated native variable
-     */
-    @ForceInline
-    public Object getUncompressedObject(long address) {
-        return theInternalUnsafe.getUncompressedObject(address);
-    }
-
-    /**
-     * Fetches the {@link java.lang.Class} Java mirror for the given native
-     * metaspace {@code Klass} pointer.
-     *
-     * @param metaspaceKlass a native metaspace {@code Klass} pointer
-     * @return the {@link java.lang.Class} Java mirror
-     */
-    @ForceInline
-    public Class<?> getJavaMirror(long metaspaceKlass) {
-        return theInternalUnsafe.getJavaMirror(metaspaceKlass);
-    }
-
-    /**
-     * Fetches a native metaspace {@code Klass} pointer for the given Java
-     * object.
-     *
-     * @param o Java heap object for which to fetch the class pointer
-     * @return a native metaspace {@code Klass} pointer
-     */
-    @ForceInline
-    public long getKlassPointer(Object o) {
-        return theInternalUnsafe.getKlassPointer(o);
-    }
-
     // These work on values in the C heap.
 
     /**
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java	Wed Jul 05 21:46:22 2017 +0200
@@ -376,12 +376,17 @@
             // count names
             count = 0;
             index = 0;
-            while (index < path.length) {
-                byte c = path[index++];
-                if (c != '/') {
-                    count++;
-                    while (index < path.length && path[index] != '/')
-                        index++;
+            if (path.length == 0) {
+                // empty path has one name
+                count = 1;
+            } else {
+                while (index < path.length) {
+                    byte c = path[index++];
+                    if (c != '/') {
+                        count++;
+                        while (index < path.length && path[index] != '/')
+                             index++;
+                    }
                 }
             }
             // populate offsets
@@ -423,10 +428,11 @@
     // removes redundant slashs, replace "\" to zip separator "/"
     // and check for invalid characters
     private byte[] normalize(byte[] path) {
-        if (path.length == 0)
+        int len = path.length;
+        if (len == 0)
             return path;
         byte prevC = 0;
-        for (int i = 0; i < path.length; i++) {
+        for (int i = 0; i < len; i++) {
             byte c = path[i];
             if (c == '\\' || c == '\u0000')
                 return normalize(path, i);
@@ -434,6 +440,8 @@
                 return normalize(path, i - 1);
             prevC = c;
         }
+        if (len > 1 && prevC == '/')
+            return Arrays.copyOf(path, len - 1);
         return path;
     }
 
@@ -567,7 +575,8 @@
         if (watcher == null || events == null || modifiers == null) {
             throw new NullPointerException();
         }
-        throw new UnsupportedOperationException();
+        // watcher must be associated with a different provider
+        throw new ProviderMismatchException();
     }
 
     @Override
--- a/jdk/test/ProblemList.txt	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -195,8 +195,6 @@
 
 java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java       7191877 generic-all
 
-sun/rmi/transport/proxy/EagerHttpFallback.java                  7195095 generic-all
-
 java/rmi/activation/Activatable/extLoadedImpl/ext.sh            8062724 generic-all
 
 sun/rmi/rmic/newrmic/equivalence/run.sh                         8145980 generic-all
@@ -288,8 +286,6 @@
 
 sun/security/tools/keytool/autotest.sh                          8130302 generic-all
 
-sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java    8137255 generic-all
-
 sun/security/x509/URICertStore/ExtensionsWithLDAP.java          8134577 generic-all
 
 sun/security/provider/SecureRandom/StrongSecureRandom.java      8157387 linux-all
@@ -394,7 +390,5 @@
 
 # core_tools
 
-tools/jimage/JImageTest.java                                    8150975 linux-i586,windows-i586
-
 ############################################################################
 
--- a/jdk/test/TEST.groups	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/TEST.groups	Wed Jul 05 21:46:22 2017 +0200
@@ -527,9 +527,13 @@
   java/net/URLConnection/HandleContentTypeWithAttrs.java \
   java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh \
   java/security/Security/ClassLoaderDeadlock/Deadlock.sh \
+  java/text/AttributedCharacterIterator/Attribute/ReadResolve.java \
+  java/text/AttributedString/TestAttributedStringCtor.java \
+  java/text/AttributedString/getRunStartLimitTest.java \
   java/util/jar/Manifest/CreateManifest.java \
   java/util/logging/TestMainAppContext.java \
   java/util/logging/TestLoggingWithMainAppContext.java \
+  java/util/TimeZone/DefaultTimeZoneTest.java \
   java/text/Bidi/BidiConformance.java \
   java/text/Bidi/BidiEmbeddingTest.java \
   java/text/Bidi/Bug7042148.java \
@@ -724,6 +728,7 @@
   java/util/Collections/UnmodifiableMapEntrySet.java  \
   java/util/Comparator/BasicTest.java  \
   java/util/Comparator/TypeTest.java  \
+  java/util/Date/TimestampTest.java \
   java/util/Iterator/IteratorDefaults.java  \
   java/util/Iterator/PrimitiveIteratorDefaults.java  \
   java/util/List/ListDefaults.java  \
--- a/jdk/test/com/sun/jarsigner/DefaultMethod.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/com/sun/jarsigner/DefaultMethod.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -25,6 +25,7 @@
  * @test
  * @bug 8039358
  * @summary com.sun.jarsigner.ContentSignerParameters.getTSAPolicyID() should be default
+ * @modules jdk.jartool
  * @compile DefaultMethod.java
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/net/httpserver/TEST.properties	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1 @@
+modules = jdk.httpserver
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/BasicTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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     4108453 4778440 6304780 6396378
+ * @summary Basic tests for java.awt.ComponentOrientation
+ * @build TestBundle TestBundle_es TestBundle_iw
+ * @build TestBundle1 TestBundle1_ar
+ *
+ * @run main BasicTest
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.ComponentOrientation;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class BasicTest {
+    public static void main(String args[]) {
+        System.out.println("BasicTest {");
+        TestInvariants();
+        TestLocale();
+        TestBundle();
+
+        System.out.println("} Pass");
+    }
+
+    // TestInvariants
+    //
+    // Various no-brainer tests to make sure the constants behave properly
+    // and so on.
+    //
+    static void TestInvariants() {
+        System.out.println("  TestInvariants {");
+
+        Assert(ComponentOrientation.LEFT_TO_RIGHT.isLeftToRight(),
+               "LEFT_TO_RIGHT.isLeftToRight()");
+
+        Assert(ComponentOrientation.UNKNOWN.isLeftToRight(),
+               "UNKNOWN.isLeftToRight()");
+
+        Assert(!ComponentOrientation.RIGHT_TO_LEFT.isLeftToRight(),
+               "!RIGHT_TO_LEFT.isLeftToRight()");
+
+        Assert(ComponentOrientation.LEFT_TO_RIGHT.isHorizontal(),
+               "LEFT_TO_RIGHT.isHorizontal()");
+
+        Assert(ComponentOrientation.UNKNOWN.isHorizontal(),
+               "UNKNOWN.isHorizontal()");
+
+        Assert(ComponentOrientation.RIGHT_TO_LEFT.isHorizontal(),
+               "RIGHT_TO_LEFT.isHorizontal()");
+
+        System.out.println("  } Pass");
+    }
+
+    // TestLocale
+    //
+    // Make sure that getOrientation(Locale) works, and that the appropriate
+    // system locales are RIGHT_TO_LEFT
+    //
+    static void TestLocale() {
+        System.out.println("  TestLocale {");
+
+        ComponentOrientation orient = ComponentOrientation.getOrientation(Locale.US);
+        Assert(orient == ComponentOrientation.LEFT_TO_RIGHT, "US == LEFT_TO_RIGHT");
+
+        orient = ComponentOrientation.getOrientation(new Locale("iw", ""));
+        Assert(orient == ComponentOrientation.RIGHT_TO_LEFT, "iw == RIGHT_TO_LEFT");
+
+        orient = ComponentOrientation.getOrientation(new Locale("ar", ""));
+        Assert(orient == ComponentOrientation.RIGHT_TO_LEFT, "ar == RIGHT_TO_LEFT");
+
+        System.out.println("  } Pass");
+    }
+
+    // TestBundle
+    //
+    // Make sure that getOrientation(ResourceBundle) works right, especially
+    // the fallback mechasm
+    //
+    static void TestBundle() {
+        System.out.println("  TestBundle {");
+
+        // This will fall back to the default locale's bundle or root bundle
+        ResourceBundle rb = ResourceBundle.getBundle("TestBundle",
+                                                        new Locale("et", ""));
+        if (rb.getLocale().getLanguage().equals(new Locale("iw").getLanguage())) {
+            assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "et == RIGHT_TO_LEFT" );
+        } else if (rb.getLocale().getLanguage() == "es") {
+            assertEquals(rb, ComponentOrientation.LEFT_TO_RIGHT, "et == LEFT_TO_RIGHT" );
+        } else {
+            assertEquals(rb, ComponentOrientation.UNKNOWN, "et == UNKNOWN" );
+        }
+
+        // We have actual bundles for "es" and "iw", so it should just fetch
+        // the orientation object out of them
+        rb = ResourceBundle.getBundle("TestBundle",new Locale("es", ""));
+        assertEquals(rb, ComponentOrientation.LEFT_TO_RIGHT, "es == LEFT_TO_RIGHT" );
+
+        rb = ResourceBundle.getBundle("TestBundle", new Locale("iw", "IL"));
+        assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "iw == RIGHT_TO_LEFT" );
+
+        // This bundle has no orientation setting at all, so we should get
+        // the system's default orientation for Arabic
+        rb = ResourceBundle.getBundle("TestBundle1", new Locale("ar", ""));
+        assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "ar == RIGHT_TO_LEFT" );
+
+        System.out.println("  } Pass");
+    }
+
+    static void assertEquals(ResourceBundle rb, ComponentOrientation o, String str) {
+        Assert(ComponentOrientation.getOrientation(rb) == o, str);
+    }
+
+    static void Assert(boolean condition, String str) {
+        if (!condition) {
+            System.err.println("    ASSERT FAILED: " + str);
+            throw new RuntimeException("Assert Failed: " + str);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/BorderTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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     4108453
+ * @summary Test ComponentOrientation (Bidi) support in BorderLayout
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.Applet;
+
+public class BorderTest extends Applet {
+    Panel       panel1;
+    Panel       panel2;
+
+    public BorderTest() {
+        setLayout(new GridLayout(0,2));
+
+        // Create a panel with a BorderLayout and a bunch of buttons in it
+        panel1 = new Panel();
+        panel1.setLayout(new BorderLayout());
+        panel1.add("North", new Button("North"));
+        panel1.add("South", new Button("South"));
+        panel1.add("East", new Button("East"));
+        panel1.add("West", new Button("West"));
+        panel1.add("Center", new Button("Center"));
+        add(panel1);
+
+        // Create a panel with a BorderLayout and a bunch of buttons in it
+        panel2 = new Panel();
+        panel2.setLayout(new BorderLayout());
+        panel2.add(BorderLayout.BEFORE_FIRST_LINE, new Button("FirstLine"));
+        panel2.add(BorderLayout.AFTER_LAST_LINE, new Button("LastLine"));
+        panel2.add(BorderLayout.BEFORE_LINE_BEGINS, new Button("FirstItem"));
+        panel2.add(BorderLayout.AFTER_LINE_ENDS, new Button("LastItem"));
+        panel2.add("Center", new Button("Center"));
+        add(panel2);
+
+        // Create a popup menu for switching between orientations
+        {
+            Choice c = new Choice();
+            c.addItem("LEFT_TO_RIGHT");
+            c.addItem("RIGHT_TO_LEFT");
+            c.addItem("UNKNOWN");
+            c.addItemListener( new ItemListener() {
+                public void itemStateChanged(ItemEvent e) {
+                    String item = (String)(e.getItem());
+
+                    ComponentOrientation o = ComponentOrientation.UNKNOWN;
+                    if (item.equals("LEFT_TO_RIGHT")) {
+                        o = ComponentOrientation.LEFT_TO_RIGHT;
+                    } else if (item.equals("RIGHT_TO_LEFT")) {
+                        o = ComponentOrientation.RIGHT_TO_LEFT;
+                    }
+                    panel1.setComponentOrientation(o);
+                    panel2.setComponentOrientation(o);
+                    panel1.layout();
+                    panel2.layout();
+                    panel1.repaint();
+                    panel2.repaint();
+                }
+            } );
+            add(c);
+        }
+    }
+
+    public static void main(String args[]) {
+        Frame f = new Frame("BorderTest");
+
+        f.addWindowListener( new WindowAdapter() {
+            public void windowClosing(WindowEvent e) {
+                e.getWindow().hide();
+                e.getWindow().dispose();
+                System.exit(0);
+            };
+        } );
+
+        BorderTest BorderTest = new BorderTest();
+        BorderTest.init();
+        BorderTest.start();
+
+        f.add("Center", BorderTest);
+        f.setSize(450, 300);
+        f.show();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/FlowTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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     4108453
+ * @summary Test ComponentOrientation (Bidi) support in FlowLayout
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.Applet;
+
+public class FlowTest extends Applet {
+    Panel       panel;
+
+    public FlowTest() {
+        setLayout(new BorderLayout());
+
+        // Create a panel with a FlowLayout and a bunch of buttons in it
+        panel = new Panel();
+        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        panel.add(new Button("one"));
+        panel.add(new Button("two"));
+        panel.add(new Button("three"));
+        panel.add(new Button("four"));
+        panel.add(new Button("five"));
+        panel.add(new Button("six"));
+        panel.add(new Button("seven"));
+        panel.add(new Button("eight"));
+        panel.add(new Button("nine"));
+        panel.add(new Button("ten"));
+        panel.add(new Button("eleven"));
+
+        add("Center", panel);
+
+        Panel controls = new Panel();
+        controls.setLayout(new GridLayout(0, 2));
+
+        // Menu for setting the alignment of the main FlowLayout panel
+        {
+            Choice c = new Choice();
+            c.addItem("LEFT");
+            c.addItem("CENTER");
+            c.addItem("RIGHT");
+            c.addItem("LEADING");
+            c.addItem("TRAILING");
+            c.addItemListener( new ItemListener() {
+                public void itemStateChanged(ItemEvent e) {
+                    String item = (String)(e.getItem());
+                    FlowLayout layout = (FlowLayout) panel.getLayout();
+
+                    if (item.equals("LEFT")) {
+                        layout.setAlignment(FlowLayout.LEFT);
+                    } else if (item.equals("CENTER")) {
+                        layout.setAlignment(FlowLayout.CENTER);
+                    } else if (item.equals("RIGHT")) {
+                        layout.setAlignment(FlowLayout.RIGHT);
+                    } else if (item.equals("LEADING")) {
+                        layout.setAlignment(FlowLayout.LEADING);
+                    } else if (item.equals("TRAILING")) {
+                        layout.setAlignment(FlowLayout.TRAILING);
+                    }
+                    panel.layout();
+                    panel.repaint();
+                }
+            } );
+            controls.add(new Label("FlowLayout Alignment:"));
+            controls.add(c);
+        }
+
+        // Create a popup menu for switching the Panel between orientations
+        {
+            Choice c = new Choice();
+            c.addItem("LEFT_TO_RIGHT");
+            c.addItem("RIGHT_TO_LEFT");
+            c.addItem("UNKNOWN");
+            c.addItemListener( new ItemListener() {
+                public void itemStateChanged(ItemEvent e) {
+                    String item = (String)(e.getItem());
+
+                    if (item.equals("LEFT_TO_RIGHT")) {
+                        panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
+                    } else if (item.equals("RIGHT_TO_LEFT")) {
+                        panel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
+                    } else {
+                        panel.setComponentOrientation(ComponentOrientation.UNKNOWN);
+                    }
+                    panel.layout();
+                    panel.repaint();
+                }
+            } );
+
+            controls.add(new Label("ComponentOrientation:"));
+            controls.add(c);
+        }
+
+        add("South", controls);
+
+    }
+
+    public static void main(String args[]) {
+        Frame f = new Frame("FlowTest");
+
+        f.addWindowListener( new WindowAdapter() {
+            public void windowClosing(WindowEvent e) {
+                e.getWindow().hide();
+                e.getWindow().dispose();
+                System.exit(0);
+            };
+        } );
+
+        FlowTest flowTest = new FlowTest();
+        flowTest.init();
+        flowTest.start();
+
+        f.add("Center", flowTest);
+        f.setSize(300, 300);
+        f.show();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/TestBundle.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * TestBundle.java -- used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+            { "Orientation", ComponentOrientation.UNKNOWN },
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/TestBundle1.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * TestBundle1.java -- used by BasicTest
+ *
+ * @bug     4108453
+ * @summary Basic tests for java.awt.ComponentOrientation
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle1 extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+            {  },
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/TestBundle1_ar.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * TestBundle1_ar.java -- used by BasicTest
+ *
+ * @bug     4108453
+ * @summary Basic tests for java.awt.ComponentOrientation
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle1_ar extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+            {  },
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/TestBundle_es.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * TestBundle_es.java -- used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle_es extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+            { "Orientation", ComponentOrientation.LEFT_TO_RIGHT },
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/TestBundle_iw.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ *
+ *
+ * used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle_iw extends ListResourceBundle {
+
+    protected Object[][] getContents() {
+        return new Object[][] {
+            { "Orientation", ComponentOrientation.RIGHT_TO_LEFT },
+        };
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/ComponentOrientation/WindowTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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     4108453 4778440 6304785
+ * @summary Test Window.applyResourceBundle orientation support
+ *
+ * @build TestBundle TestBundle_es TestBundle_iw
+ * @build TestBundle1 TestBundle1_ar
+ * @run main WindowTest
+ */
+
+import java.awt.*;
+import java.applet.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class WindowTest extends Applet {
+    static Exception failure=null;
+    static Thread mainThread=null;
+
+    public static void main(String args[]) throws Exception {
+        mainThread = Thread.currentThread();
+        WindowTest app = new WindowTest();
+        app.start();
+        try {
+            Thread.sleep(300000);
+        } catch (InterruptedException e) {
+            if (failure != null) {
+                throw failure;
+            }
+        }
+    }
+
+    public void start() {
+        try {
+            doTest();
+        } catch (Exception e) {
+            failure = e;
+        }
+        mainThread.interrupt();
+    }
+
+    public void doTest() {
+        System.out.println("WindowTest {");
+
+        ResourceBundle rb;
+        Frame myFrame;
+
+        // Create a window containing a hierarchy of components.
+        System.out.println("  Creating component hierarchy...");
+        myFrame = new Frame();
+        myFrame.setLayout(new FlowLayout());
+        Panel panel1 = new Panel();
+        panel1.setLayout(new BorderLayout());
+        panel1.add("North", new Button("North"));
+        panel1.add("South", new Button("South"));
+        panel1.add("East", new Button("East"));
+        panel1.add("West", new Button("West"));
+        panel1.add("Center", new Button("Center"));
+        myFrame.add(panel1);
+
+        Panel panel2 = new Panel();
+        panel2.setLayout(new BorderLayout());
+        panel2.add(BorderLayout.BEFORE_FIRST_LINE, new Button("FirstLine"));
+        panel2.add(BorderLayout.AFTER_LAST_LINE, new Button("LastLine"));
+        panel2.add(BorderLayout.BEFORE_LINE_BEGINS, new Button("FirstItem"));
+        panel2.add(BorderLayout.AFTER_LINE_ENDS, new Button("LastItem"));
+        panel2.add("Center", new Button("Center"));
+        myFrame.add(panel2);
+
+        // After construction, all of the components' orientations should be
+        // set to ComponentOrientation.UNKNOWN.
+        System.out.println("  Verifying orientation is UNKNOWN...");
+        verifyOrientation(myFrame, ComponentOrientation.UNKNOWN);
+
+        // This will load TestBundle1 using the default locale and apply
+        // it to the component hierarchy.  Since the bundle has no Orientation
+        // specified, this should fall back to the bundle-locale's orientation
+        System.out.println("  Applying TestBundle1 by name and verifying...");
+        myFrame.applyResourceBundle("TestBundle1");
+        verifyOrientation(myFrame,
+                    ComponentOrientation.getOrientation(
+                        ResourceBundle.getBundle("TestBundle1", Locale.getDefault())));
+
+        System.out.println("  Applying TestBundle_iw and verifying...");
+        rb = ResourceBundle.getBundle("TestBundle", new Locale("iw", ""));
+        myFrame.applyResourceBundle(rb);
+        verifyOrientation(myFrame, ComponentOrientation.RIGHT_TO_LEFT);
+
+        System.out.println("  Applying TestBundle_es and verifying...");
+        rb = ResourceBundle.getBundle("TestBundle", new Locale("es", ""));
+        myFrame.applyResourceBundle(rb);
+        verifyOrientation(myFrame, ComponentOrientation.LEFT_TO_RIGHT);
+
+
+        myFrame.setVisible(false);
+        myFrame.dispose();
+        System.out.println("}");
+    }
+
+    static void verifyOrientation(Component c, ComponentOrientation orient) {
+
+        ComponentOrientation o = c.getComponentOrientation();
+
+        if (o != orient) {
+            throw new RuntimeException("ERROR: expected " + oString(orient) +
+                                        ", got " + oString(o) +
+                                        " on component " + c);
+        }
+
+        if (c instanceof Container) {
+            Container cont = (Container) c;
+            int ncomponents = cont.getComponentCount();
+
+            for (int i = 0 ; i < ncomponents ; ++i) {
+                Component comp = cont.getComponent(i);
+                verifyOrientation(comp, orient);
+            }
+        }
+    }
+
+    static String oString(ComponentOrientation o) {
+        if (o == ComponentOrientation.LEFT_TO_RIGHT) {
+            return "LEFT_TO_RIGHT";
+        }
+        else if (o == ComponentOrientation.RIGHT_TO_LEFT) {
+            return "RIGHT_TO_LEFT";
+        }
+        else {
+            return "UNKNOWN";
+        }
+    }
+}
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Wed Jul 05 21:46:22 2017 +0200
@@ -202,7 +202,7 @@
             // synthetic frames introduced by lambdas & method handles
             return produced.replaceAll(":[1-9][0-9]*\\)", ":00)")
                     .replaceAll("-internal/", "/").replaceAll("-ea/", "/")
-                    .replaceAll("java.base@[0-9]+/", "java.base/")
+                    .replaceAll("java.base@(\\d+\\.){0,3}(\\d+)/", "java.base/")
                     .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
                     .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
                     .replaceAll("\\$[0-9]+", "\\$??");
--- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -38,6 +38,7 @@
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
+import java.lang.reflect.Module;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
@@ -64,16 +65,24 @@
     private static final Path SRC_DIR    = Paths.get(TEST_SRC, "src");
     private static final Path MODS_DIR   = Paths.get("mods");
 
+    // the module name of the base module
+    private static final String BASE_MODULE = "java.base";
+
     // the module name of the test module
     private static final String TEST_MODULE = "m";
 
+    // resources in the base module
+    private static final String[] BASE_RESOURCES = {
+        "java/lang/Object.class"
+    };
+
     // resources in test module (can't use module-info.class as a test
     // resource as it will be modified by the jmod tool)
-    private static final String[] RESOURCES = {
+    private static final String[] TEST_RESOURCES = {
         "p/Main.class"
     };
 
-    // a resource that is not in the test module
+    // a resource that is not in the base or test module
     private static final String NOT_A_RESOURCE = "NotAResource";
 
 
@@ -89,7 +98,74 @@
 
 
     /**
-     * Test exploded module
+     * Test ModuleReader to module in runtime image
+     */
+    public void testImage() throws Exception {
+
+        ModuleFinder finder = ModuleFinder.ofSystem();
+        ModuleReference mref = finder.find(BASE_MODULE).get();
+        ModuleReader reader = mref.open();
+
+        try (reader) {
+
+            for (String name : BASE_RESOURCES) {
+                byte[] expectedBytes;
+                Module baseModule = Object.class.getModule();
+                try (InputStream in = baseModule.getResourceAsStream(name)) {
+                    expectedBytes = in.readAllBytes();
+                }
+
+                testFind(reader, name, expectedBytes);
+                testOpen(reader, name, expectedBytes);
+                testRead(reader, name, expectedBytes);
+
+            }
+
+            // test "not found"
+            assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
+            assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
+            assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
+
+
+            // test nulls
+            try {
+                reader.find(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.open(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.read(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.release(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+        }
+
+        // test closed ModuleReader
+        try {
+            reader.open(BASE_RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+
+
+        try {
+            reader.read(BASE_RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+    }
+
+
+    /**
+     * Test ModuleReader to exploded module
      */
     public void testExplodedModule() throws Exception {
         test(MODS_DIR);
@@ -97,7 +173,7 @@
 
 
     /**
-     * Test modular JAR
+     * Test ModuleReader to modular JAR
      */
     public void testModularJar() throws Exception {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@@ -111,7 +187,7 @@
 
 
     /**
-     * Test JMOD
+     * Test ModuleReader to JMOD
      */
     public void testJMod() throws Exception {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@@ -145,7 +221,7 @@
         try (reader) {
 
             // test each of the known resources in the module
-            for (String name : RESOURCES) {
+            for (String name : TEST_RESOURCES) {
                 byte[] expectedBytes
                     = Files.readAllBytes(MODS_DIR
                         .resolve(TEST_MODULE)
@@ -157,6 +233,7 @@
             }
 
             // test "not found"
+            assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
             assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
             assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
 
@@ -176,19 +253,22 @@
                 assertTrue(false);
             } catch (NullPointerException expected) { }
 
-            // should release(null) throw NPE?
+            try {
+                reader.release(null);
+                throw new RuntimeException();
+            } catch (NullPointerException expected) { }
 
         }
 
         // test closed ModuleReader
         try {
-            reader.open(RESOURCES[0]);
+            reader.open(TEST_RESOURCES[0]);
             assertTrue(false);
         } catch (IOException expected) { }
 
 
         try {
-            reader.read(RESOURCES[0]);
+            reader.read(TEST_RESOURCES[0]);
             assertTrue(false);
         } catch (IOException expected) { }
     }
--- a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -103,7 +103,7 @@
 
 
     /**
-     * Exercise Layer.create, created on an empty layer
+     * Exercise Layer defineModules, created with empty layer as parent
      */
     public void testLayerOnEmpty() {
         ModuleDescriptor descriptor1
@@ -184,7 +184,7 @@
 
 
     /**
-     * Exercise Layer.create, created over the boot layer
+     * Exercise Layer defineModules, created with boot layer as parent
      */
     public void testLayerOnBoot() {
         ModuleDescriptor descriptor1
@@ -247,8 +247,8 @@
 
 
     /**
-     * Layer.create with a configuration of two modules that have the same
-     * module-private package.
+     * Exercise Layer defineModules with a configuration of two modules that
+     * have the same module-private package.
      */
     public void testSameConcealedPackage() {
         ModuleDescriptor descriptor1
@@ -281,8 +281,8 @@
 
 
     /**
-     * Layer.create with a configuration with a partitioned graph. The same
-     * package is exported in both partitions.
+     * Exercise Layer defineModules with a configuration that is a partitioned
+     * graph. The same package is exported in both partitions.
      */
     public void testSameExportInPartitionedGraph() {
 
@@ -338,9 +338,9 @@
 
 
     /**
-     * Layer.create with a configuration that contains a module that has a
-     * concealed package that is the same name as a non-exported package
-     * in a parent layer.
+     * Exercise Layer defineModules with a configuration that contains a module
+     * that has a concealed package that is the same name as a non-exported
+     * package in a parent layer.
      */
     public void testConcealSamePackageAsBootLayer() {
 
@@ -667,9 +667,9 @@
 
 
     /**
-     * Attempt to use Layer.create to create a layer with a module defined to a
-     * class loader that already has a module of the same name defined to the
-     * class loader.
+     * Attempt to use Layer defineModules to create a layer with a module
+     * defined to a class loader that already has a module of the same name
+     * defined to the class loader.
      */
     @Test(expectedExceptions = { LayerInstantiationException.class })
     public void testModuleAlreadyDefinedToLoader() {
@@ -696,9 +696,9 @@
 
 
     /**
-     * Attempt to use Layer.create to create a Layer with a module containing
-     * package {@code p} where the class loader already has a module defined
-     * to it containing package {@code p}.
+     * Attempt to use Layer defineModules to create a Layer with a module
+     * containing package {@code p} where the class loader already has a module
+     * defined to it containing package {@code p}.
      */
     @Test(expectedExceptions = { LayerInstantiationException.class })
     public void testPackageAlreadyInNamedModule() {
@@ -738,8 +738,9 @@
 
 
     /**
-     * Attempt to use Layer.create to create a Layer with a module containing
-     * a package in which a type is already loaded by the class loader.
+     * Attempt to use Layer defineModules to create a Layer with a module
+     * containing a package in which a type is already loaded by the class
+     * loader.
      */
     @Test(expectedExceptions = { LayerInstantiationException.class })
     public void testPackageAlreadyInUnnamedModule() throws Exception {
@@ -763,6 +764,46 @@
 
 
     /**
+     * Attempt to create a Layer with a module named "java.base".
+     */
+    public void testLayerWithJavaBase() {
+        ModuleDescriptor descriptor
+            = new ModuleDescriptor.Builder("java.base")
+                .exports("java.lang")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+        Configuration cf = Layer.boot()
+            .configuration()
+            .resolveRequires(finder, ModuleFinder.of(), Set.of("java.base"));
+        assertTrue(cf.modules().size() == 1);
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        try {
+            Layer.boot().defineModules(cf, loader -> null );
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        try {
+            Layer.boot().defineModules(cf, loader -> new ClassLoader() { });
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        try {
+            Layer.boot().defineModulesWithOneLoader(cf, scl);
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        try {
+            Layer.boot().defineModulesWithManyLoaders(cf, scl);
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+    }
+
+
+    /**
      * Parent of configuration != configuration of parent Layer
      */
     @Test(expectedExceptions = { IllegalArgumentException.class })
@@ -812,7 +853,6 @@
 
     @Test(expectedExceptions = { NullPointerException.class })
     public void testCreateWithNull2() {
-        ClassLoader loader = new ClassLoader() { };
         Configuration cf = resolveRequires(Layer.boot().configuration(), ModuleFinder.of());
         Layer.boot().defineModules(cf, null);
     }
--- a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -70,7 +70,7 @@
 
 
     /**
-     * Basic test of Layer.defineModulesWithOneLoader
+     * Basic test of Layer defineModulesWithOneLoader
      *
      * Test scenario:
      *   m1 requires m2 and m3
@@ -99,7 +99,7 @@
 
 
     /**
-     * Basic test of Layer.defineModulesWithManyLoaders
+     * Basic test of Layer defineModulesWithManyLoaders
      *
      * Test scenario:
      *   m1 requires m2 and m3
@@ -131,7 +131,7 @@
 
 
     /**
-     * Basic test of Layer.defineModulesWithOneLoader where one of the modules
+     * Basic test of Layer defineModulesWithOneLoader where one of the modules
      * is a service provider module.
      *
      * Test scenario:
@@ -172,8 +172,8 @@
 
 
     /**
-     * Basic test of Layer.defineModulesWithManyLoaders where one of the modules
-     * is a service provider module.
+     * Basic test of Layer defineModulesWithManyLoaders where one of the
+     * modules is a service provider module.
      *
      * Test scenario:
      *    m1 requires m2 and m3
@@ -224,7 +224,7 @@
 
 
     /**
-     * Tests that the class loaders created by Layer.createWithXXX delegate
+     * Tests that the class loaders created by defineModulesWithXXX delegate
      * to the given parent class loader.
      */
     public void testDelegationToParent() throws Exception {
@@ -254,7 +254,7 @@
 
 
     /**
-     * Test Layer.createWithXXX when modules that have overlapping packages.
+     * Test defineModulesWithXXX when modules that have overlapping packages.
      *
      * Test scenario:
      *   m1 exports p
@@ -288,7 +288,7 @@
 
 
     /**
-     * Test Layer.createWithXXX with split delegation.
+     * Test Layer defineModulesWithXXX with split delegation.
      *
      * Test scenario:
      *   layer1: m1 exports p, m2 exports p
@@ -319,7 +319,8 @@
 
         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
 
-        Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(), Set.of("m3", "m4"));
+        Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(),
+                                                Set.of("m3", "m4"));
 
         // package p cannot be supplied by two class loaders
         try {
@@ -335,8 +336,8 @@
 
 
     /**
-     * Test Layer.createWithXXX when the modules that override same named
-     * modules in the parent layer.
+     * Test Layer defineModulesWithXXX when the modules that override same
+     * named modules in the parent layer.
      *
      * Test scenario:
      *   layer1: m1, m2, m3 => same loader
@@ -350,7 +351,8 @@
         checkLayer(layer1, "m1", "m2", "m3");
 
         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
-        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(),
+                                                Set.of("m1"));
 
         Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
         checkLayer(layer2, "m1", "m2", "m3");
@@ -383,8 +385,8 @@
 
 
     /**
-     * Test Layer.createWithXXX when the modules that override same named
-     * modules in the parent layer.
+     * Test Layer defineModulesWithXXX when the modules that override same
+     * named modules in the parent layer.
      *
      * Test scenario:
      *   layer1: m1, m2, m3 => loader pool
@@ -398,7 +400,8 @@
         checkLayer(layer1, "m1", "m2", "m3");
 
         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
-        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(),
+                                                Set.of("m1"));
 
         Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
         checkLayer(layer2, "m1", "m2", "m3");
@@ -477,8 +480,8 @@
 
 
     /**
-     * Test Layer.createWithXXX when the modules that override same named
-     * modules in the parent layer.
+     * Test Layer defineModulesWithXXX when the modules that override same
+     * named modules in the parent layer.
      *
      * layer1: m1, m2, m3 => same loader
      * layer2: m1, m3 => same loader
@@ -492,7 +495,8 @@
 
         ModuleFinder finder = finderFor("m1", "m3");
 
-        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(),
+                                                Set.of("m1"));
 
         Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
         checkLayer(layer2, "m1", "m3");
@@ -513,8 +517,8 @@
 
 
     /**
-     * Test Layer.createWithXXX when the modules that override same named
-     * modules in the parent layer.
+     * Test Layer defineModulesWithXXX when the modules that override same
+     * named modules in the parent layer.
      *
      * layer1: m1, m2, m3 => loader pool
      * layer2: m1, m3 => loader pool
@@ -528,7 +532,8 @@
 
         ModuleFinder finder = finderFor("m1", "m3");
 
-        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+        Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(),
+                                                Set.of("m1"));
 
         Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
         checkLayer(layer2, "m1", "m3");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Module/WithSecurityManager.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * @modules java.logging
+ * @summary Test java.lang.reflect.Module methods that specify permission checks
+ * @run main/othervm -Djava.security.policy=${test.src}/allow.policy WithSecurityManager allow
+ * @run main/othervm WithSecurityManager deny
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Test java.lang.reflect.Module methods that specify permission checks.
+ */
+
+public class WithSecurityManager {
+
+    // a module that will be loaded into a child layer
+    static final String ANOTHER_MODULE          = "java.logging";
+    static final String ANOTHER_MODULE_RESOURCE = "java/util/logging/Logger.class";
+
+    public static void main(String[] args) throws IOException {
+        boolean allow = args[0].equals("allow");
+
+        // base module, in the boot layer
+        Module base = Object.class.getModule();
+
+        // another module, in a child layer
+        Module other = loadModuleInChildLayer(ANOTHER_MODULE);
+        assertTrue(other.getLayer() != Layer.boot());
+
+        System.setSecurityManager(new SecurityManager());
+
+        test(base, "java/lang/Object.class", allow);
+        test(other, ANOTHER_MODULE_RESOURCE, allow);
+    }
+
+    /**
+     * Test the permission checks by invoking methods on the given module.
+     *
+     * If {@code allow} is {@code true} then the permission checks should succeed.
+     */
+    static void test(Module m, String name, boolean allow) throws IOException {
+
+        // test Module::getClassLoader
+        System.out.format("Test getClassLoader on %s ...%n", m);
+        try {
+            ClassLoader cl = m.getClassLoader();
+            System.out.println(cl);
+            if (!allow)
+                assertTrue("getClassLoader should have failed", false);
+        } catch (SecurityException e) {
+            System.out.println(e + " thrown");
+            if (allow)
+                throw e;
+        }
+
+        // test Module::getResourceAsStream
+        System.out.format("Test getResourceAsStream(\"%s\") on %s ...%n", name, m);
+        try (InputStream in = m.getResourceAsStream(name)) {
+            System.out.println(in);
+            if (allow && (in == null))
+                assertTrue(name + " not found", false);
+            if (!allow && (in != null))
+                assertTrue(name + " should not be found", false);
+        }
+
+    }
+
+    /**
+     * Create a module layer that contains the given system module.
+     */
+    static Module loadModuleInChildLayer(String mn) {
+        Optional<ModuleReference> omref = ModuleFinder.ofSystem().find(mn);
+        assertTrue("module " + mn + " not a system module", omref.isPresent());
+
+        // create a ModuleFinder that only finds this module
+        ModuleReference mref = omref.get();
+        ModuleFinder finder = new ModuleFinder() {
+            @Override
+            public Optional<ModuleReference> find(String name) {
+                if (name.equals(mn))
+                    return Optional.of(mref);
+                else
+                    return Optional.empty();
+            }
+
+            @Override
+            public Set<ModuleReference> findAll() {
+                return Collections.singleton(mref);
+            }
+        };
+
+        // create a child configuration and layer with this module
+        Layer bootLayer = Layer.boot();
+        Configuration cf = bootLayer
+            .configuration()
+            .resolveRequires(finder, ModuleFinder.of(), Set.of(ANOTHER_MODULE));
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, null);
+
+        Optional<Module> om = layer.findModule(mn);
+        assertTrue("module " + mn + " not in child layer", om.isPresent());
+        return om.get();
+    }
+
+    static void assertTrue(String msg, boolean e) {
+        if (!e)
+            throw new RuntimeException(msg);
+    }
+
+    static void assertTrue(boolean e) {
+        if (!e)
+            throw new RuntimeException();
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Module/allow.policy	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+grant {
+    permission java.lang.RuntimePermission "getClassLoader";
+    permission java.io.FilePermission "${java.home}/-", "read";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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 8016521
+ * @summary InetAddress should not always re-order addresses returned from name
+ *          service
+ * @run main/othervm -Djava.net.preferIPv6Addresses=false PreferIPv6AddressesTest
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true PreferIPv6AddressesTest
+ * @run main/othervm -Djava.net.preferIPv6Addresses=system PreferIPv6AddressesTest
+ * @run main/othervm PreferIPv6AddressesTest
+ */
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.channels.DatagramChannel;
+import java.util.Arrays;
+import java.util.stream.IntStream;
+import static java.lang.System.out;
+
+public class PreferIPv6AddressesTest {
+
+    // A name, that if resolves, returns both IPv4 and IPv6 addresses.
+    static final String HOST_NAME = "www.google.com";
+
+    static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
+
+    static final String preferIPV6Address =
+            System.getProperty("java.net.preferIPv6Addresses", "false");
+
+    public static void main(String args[]) throws IOException {
+
+        InetAddress addrs[];
+        try {
+            addrs = InetAddress.getAllByName(HOST_NAME);
+        } catch (UnknownHostException e) {
+            out.println("Unknown host " + HOST_NAME + ", cannot run test.");
+            return;
+        }
+
+        int firstIPv4Address = IntStream.range(0, addrs.length)
+                .filter(x -> addrs[x] instanceof Inet4Address)
+                .findFirst().orElse(-1);
+        int firstIPv6Address = IntStream.range(0, addrs.length)
+                .filter(x -> addrs[x] instanceof Inet6Address)
+                .findFirst().orElse(-1);
+
+        out.println("IPv6 supported: " + IPv6Supported());
+        out.println("Addresses: " + Arrays.asList(addrs));
+
+        if (preferIPV6Address.equalsIgnoreCase("true") && firstIPv6Address != -1) {
+            int off = firstIPv4Address != -1 ? firstIPv4Address : addrs.length;
+            assertAllv6Addresses(addrs, 0, off);
+            assertAllv4Addresses(addrs, off, addrs.length);
+            assertLoopbackAddress(Inet6Address.class);
+            assertAnyLocalAddress(Inet6Address.class);
+        } else if (preferIPV6Address.equalsIgnoreCase("false") && firstIPv4Address != -1) {
+            int off = firstIPv6Address != -1 ? firstIPv6Address : addrs.length;
+            assertAllv4Addresses(addrs, 0, off);
+            assertAllv6Addresses(addrs, off, addrs.length);
+            assertLoopbackAddress(Inet4Address.class);
+            assertAnyLocalAddress(Inet4Address.class);
+        } else if (preferIPV6Address.equalsIgnoreCase("system") && IPv6Supported()) {
+            assertLoopbackAddress(Inet6Address.class);
+            assertAnyLocalAddress(Inet6Address.class);
+        } else if (preferIPV6Address.equalsIgnoreCase("system") && !IPv6Supported()) {
+            assertLoopbackAddress(Inet4Address.class);
+            assertAnyLocalAddress(Inet4Address.class);
+        }
+    }
+
+    static void assertAllv4Addresses(InetAddress[] addrs, int off, int len) {
+        IntStream.range(off, len)
+                 .mapToObj(x -> addrs[x])
+                 .forEach(x -> {
+                     if (!(x instanceof Inet4Address))
+                         throw new RuntimeException("Expected IPv4, got " + x);
+                 });
+    }
+
+    static void assertAllv6Addresses(InetAddress[] addrs, int off, int len) {
+        IntStream.range(off, len)
+                .mapToObj(x -> addrs[x])
+                .forEach(x -> {
+                    if (!(x instanceof Inet6Address))
+                        throw new RuntimeException("Expected IPv6, got " + x);
+                });
+    }
+
+    static void assertLoopbackAddress(Class<?> expectedType) {
+        if (!LOOPBACK.getClass().isAssignableFrom(expectedType))
+            throw new RuntimeException("Expected " + expectedType
+                    + ", got " + LOOPBACK.getClass());
+    }
+
+    static void assertAnyLocalAddress(Class<?> expectedType) {
+        InetAddress anyAddr = (new InetSocketAddress(0)).getAddress();
+        if (!anyAddr.getClass().isAssignableFrom(expectedType))
+            throw new RuntimeException("Expected " + expectedType
+                    + ", got " + anyAddr.getClass());
+    }
+
+    static boolean IPv6Supported() throws IOException {
+        try {
+            DatagramChannel.open(StandardProtocolFamily.INET6);
+            return true;
+        } catch (UnsupportedOperationException x) {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/module/ModuleTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.ProcessTools
+ *        ModuleTest CompilerUtils JarUtils
+ * @run testng ModuleTest
+ * @summary Basic tests for using rmi in module world
+ */
+
+import static jdk.testlibrary.ProcessTools.executeTestJava;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.nio.file.Paths;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class ModuleTest {
+
+    static String fileJoin(String... names) {
+        return String.join(File.separator, names);
+    }
+
+    static String pathJoin(String... paths) {
+        return String.join(File.pathSeparator, paths);
+    }
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+    private static final String CLIENT_EXP = fileJoin("exploded", "mclient");
+    private static final String SERVER_EXP = fileJoin("exploded", "mserver");
+    private static final String MTEST_EXP  = fileJoin("exploded", "mtest");
+    private static final String CLIENT_JAR = fileJoin("mods", "mclient.jar");
+    private static final String SERVER_JAR = fileJoin("mods", "mserver.jar");
+    private static final String MTEST_JAR  = fileJoin("mods", "mtest.jar");
+
+    private static final String DUMMY_MAIN = "testpkg.DummyApp";
+
+    /**
+     * Compiles all sample classes
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        assertTrue(CompilerUtils.compile(
+                Paths.get(TEST_SRC, "src", "mserver"),
+                Paths.get(SERVER_EXP)));
+
+        JarUtils.createJarFile(
+                Paths.get(SERVER_JAR),
+                Paths.get(SERVER_EXP));
+
+        assertTrue(CompilerUtils.compile(
+                Paths.get(TEST_SRC, "src", "mclient"),
+                Paths.get(CLIENT_EXP),
+                "-cp", SERVER_JAR));
+
+        JarUtils.createJarFile(
+                Paths.get(CLIENT_JAR),
+                Paths.get(CLIENT_EXP));
+
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "mtest"),
+                Paths.get(MTEST_EXP),
+                "-cp", pathJoin(CLIENT_JAR, SERVER_JAR)));
+
+        JarUtils.createJarFile(
+                Paths.get(MTEST_JAR),
+                Paths.get(MTEST_EXP));
+    }
+
+    /**
+     * Test the client, server and dummy application in different modules
+     * @throws Exception
+     */
+    @Test
+    public void testAllInModule() throws Exception {
+        assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, CLIENT_JAR, SERVER_JAR),
+                "-addmods", "mclient,mserver",
+                "-m", "mtest/" + DUMMY_MAIN)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue(),
+                0);
+    }
+
+    /**
+     * Test the client and server in unnamed modules,
+     * while the dummy application is in automatic module
+     * @throws Exception
+     */
+    @Test
+    public void testAppInModule() throws Exception {
+        assertEquals(executeTestJava("-mp", MTEST_JAR,
+                "-cp", pathJoin(CLIENT_JAR, SERVER_JAR),
+                "-m", "mtest/" + DUMMY_MAIN)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue(),
+                0);
+    }
+
+    /**
+     * Test the client and server in automatic modules,
+     * while the dummy application is in unnamed module
+     * @throws Exception
+     */
+    @Test
+    public void testAppInUnnamedModule() throws Exception {
+        assertEquals(executeTestJava("-mp", pathJoin(CLIENT_JAR, SERVER_JAR),
+                "-addmods", "mclient,mserver",
+                "-cp", MTEST_JAR,
+                DUMMY_MAIN)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue(),
+                0);
+    }
+
+    /**
+     * Test the server and test application in automatic modules,
+     * with client in unnamed module
+     * @throws Exception
+     */
+    @Test
+    public void testClientInUnamedModule() throws Exception {
+        assertEquals(executeTestJava("-mp", pathJoin(MTEST_JAR, SERVER_JAR),
+                "-addmods", "mserver",
+                "-cp", CLIENT_JAR,
+                "-m", "mtest/" + DUMMY_MAIN)
+                .outputTo(System.out)
+                .errorTo(System.out)
+                .getExitValue(),
+                0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/module/src/mclient/clientpkg/Client.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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 clientpkg;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+import serverpkg.Hello;
+
+public class Client {
+    int port;
+    Hello stub;
+
+    public Client(Hello stub) {
+        this.stub = stub;
+    }
+
+    public String testStub() throws Exception {
+        try {
+            return stub.sayHello();
+        } catch (Exception e) {
+            System.err.println("Client exception: " + e.toString());
+            throw e;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Hello.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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.
+ */
+
+package serverpkg;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Hello extends Remote {
+
+    String sayHello() throws RemoteException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/module/src/mserver/serverpkg/Server.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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.
+ */
+
+package serverpkg;
+
+public class Server implements Hello {
+
+    private final String hello = "Hello world!";
+
+    public Server() {
+    }
+
+    @Override
+    public String sayHello() {
+        return hello;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/module/src/mtest/testpkg/DummyApp.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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 testpkg;
+
+import java.rmi.server.UnicastRemoteObject;
+
+import clientpkg.Client;
+import serverpkg.Hello;
+import serverpkg.Server;
+
+public class DummyApp {
+
+    public static void main(String args[]) {
+        try {
+            Hello obj = new Server();
+            Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
+
+            Client client = new Client(stub);
+            String testStubReturn = client.testStub();
+            System.out.println("Stub is: " + testStubReturn);
+            if (!testStubReturn.equals(obj.sayHello())) {
+                throw new RuntimeException("Unexpected string from stub call, expected \""
+                        + testStubReturn + "\", actual \"" + obj.sayHello() + "\"");
+            } else {
+                System.out.println("Test passed");
+            }
+
+            System.exit(0);
+        } catch (Throwable e) {
+            e.printStackTrace();
+            System.exit(-1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4136620 4144590
+   @summary Make sure that Attribute & subclasses are serialized and deserialized correctly
+   @modules java.desktop
+ */
+
+import java.text.AttributedCharacterIterator.Attribute;
+import java.awt.font.TextAttribute;
+import java.io.*;
+
+public class ReadResolve {
+
+    public static void main(String[] args) throws Exception {
+        testSerializationCycle(Attribute.LANGUAGE);
+        testSerializationCycle(TextAttribute.INPUT_METHOD_HIGHLIGHT);
+
+        boolean gotException = false;
+        Attribute result = null;
+        try {
+            result = doSerializationCycle(FakeAttribute.LANGUAGE);
+        } catch (Throwable e) {
+            gotException = true;
+        }
+        if (!gotException) {
+            throw new RuntimeException("Attribute should throw an exception when given a fake \"language\" attribute. Deserialized object: " + result);
+        }
+    }
+
+    static Attribute doSerializationCycle(Attribute attribute) throws Exception {
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream  oos  =  new  ObjectOutputStream(baos);
+        oos.writeObject(attribute);
+        oos.flush();
+
+        byte[] data = baos.toByteArray();
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        Attribute result = (Attribute) ois.readObject();
+
+        return result;
+    }
+
+    static void testSerializationCycle(Attribute attribute) throws Exception {
+        Attribute result = doSerializationCycle(attribute);
+        if (result != attribute) {
+            throw new RuntimeException("attribute changed identity during serialization/deserialization");
+        }
+    }
+
+    private static class FakeAttribute extends Attribute {
+
+        // This LANGUAGE attribute should never be confused with the
+        // Attribute.LANGUAGE attribute. However, we don't override
+        // readResolve here, so that deserialization goes
+        // to Attribute. Attribute has to catch this problem and reject
+        // the fake attribute.
+        static final FakeAttribute LANGUAGE = new FakeAttribute("language");
+
+        FakeAttribute(String name) {
+            super(name);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/AttributedString/AttributedStringTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4139771
+ * @summary test all aspects of AttributedString class
+ */
+
+import java.text.Annotation;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+
+public class AttributedStringTest {
+
+    private static final String text = "Hello, world!";
+    private static final Annotation hi = new Annotation("hi");
+    private static final int[] array5_13 = {5, 13};
+    private static final int[] array3_9_13 = {3, 9, 13};
+    private static final int[] array5_9_13 = {5, 9, 13};
+    private static final int[] array3_5_9_13 = {3, 5, 9, 13};
+    private static final Attribute[] arrayLanguage = {Attribute.LANGUAGE};
+    private static final Attribute[] arrayLanguageReading = {Attribute.LANGUAGE, Attribute.READING};
+    private static final Set setLanguageReading = new HashSet();
+    static {
+        setLanguageReading.add(Attribute.LANGUAGE);
+        setLanguageReading.add(Attribute.READING);
+    }
+
+
+    public static final void main(String argv[]) throws Exception {
+
+
+        AttributedString string;
+        AttributedCharacterIterator iterator;
+
+        // create a string with text, but no attributes
+        string = new AttributedString(text);
+        iterator = string.getIterator();
+
+        // make sure the text is there and attributes aren't
+        checkIteratorText(iterator, text);
+        if (!iterator.getAllAttributeKeys().isEmpty()) {
+            throwException(iterator, "iterator provides attributes where none are defined");
+        }
+
+        // add an attribute to a subrange
+        string.addAttribute(Attribute.LANGUAGE, Locale.ENGLISH, 3, 9);
+        iterator = string.getIterator();
+
+        // make sure the attribute is defined, and it's on the correct subrange
+        checkIteratorAttributeKeys(iterator, arrayLanguage);
+        checkIteratorSubranges(iterator, array3_9_13);
+        checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null);
+        checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH);
+        checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+        // add an attribute to a subrange
+        string.addAttribute(Attribute.READING, hi, 0, 5);
+        iterator = string.getIterator();
+
+        // make sure the attribute is defined, and it's on the correct subrange
+        checkIteratorAttributeKeys(iterator, arrayLanguageReading);
+        checkIteratorSubranges(iterator, array3_5_9_13);
+        checkIteratorAttribute(iterator, 0, Attribute.READING, hi);
+        checkIteratorAttribute(iterator, 3, Attribute.READING, hi);
+        checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+        checkIteratorAttribute(iterator, 9, Attribute.READING, null);
+
+        // make sure the first attribute wasn't adversely affected
+        // in particular, we shouldn't see separate subranges (3,5) and (5,9).
+        checkIteratorSubranges(iterator, Attribute.LANGUAGE, array3_9_13);
+        checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null);
+        checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH);
+        checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH);
+        checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+        // for the entire set of attributes, we expect four subranges
+        checkIteratorSubranges(iterator, setLanguageReading, array3_5_9_13);
+
+        // redefine the language attribute so that both language and reading are continuous from 0 to 5
+        string.addAttribute(Attribute.LANGUAGE, Locale.US, 0, 5);
+        iterator = string.getIterator();
+
+        // make sure attributes got changed and merged correctly
+        checkIteratorAttributeKeys(iterator, arrayLanguageReading);
+        checkIteratorSubranges(iterator, array3_5_9_13);
+        checkIteratorSubranges(iterator, Attribute.LANGUAGE, array5_9_13);
+        checkIteratorSubranges(iterator, Attribute.READING, array5_13);
+        checkIteratorSubranges(iterator, setLanguageReading, array5_9_13);
+        checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, Locale.US);
+        checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.US);
+        checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH);
+        checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+        // make sure an annotation is only returned if its range is contained in the iterator's range
+        iterator = string.getIterator(null, 3, 5);
+        checkIteratorAttribute(iterator, 3, Attribute.READING, null);
+        checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+        iterator = string.getIterator(null, 0, 4);
+        checkIteratorAttribute(iterator, 0, Attribute.READING, null);
+        checkIteratorAttribute(iterator, 3, Attribute.READING, null);
+        iterator = string.getIterator(null, 0, 5);
+        checkIteratorAttribute(iterator, 0, Attribute.READING, hi);
+        checkIteratorAttribute(iterator, 4, Attribute.READING, hi);
+        checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+
+    }
+
+    private static final void checkIteratorText(AttributedCharacterIterator iterator, String expectedText) throws Exception {
+        if (iterator.getEndIndex() - iterator.getBeginIndex() != expectedText.length()) {
+            throwException(iterator, "text length doesn't match between original text and iterator");
+        }
+
+        char c = iterator.first();
+        for (int i = 0; i < expectedText.length(); i++) {
+            if (c != expectedText.charAt(i)) {
+                throwException(iterator, "text content doesn't match between original text and iterator");
+            }
+            c = iterator.next();
+        }
+        if (c != CharacterIterator.DONE) {
+            throwException(iterator, "iterator text doesn't end with DONE");
+        }
+    }
+
+    private static final void checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys) throws Exception {
+         Set iteratorKeys = iterator.getAllAttributeKeys();
+         if (iteratorKeys.size() != expectedKeys.length) {
+             throwException(iterator, "number of keys returned by iterator doesn't match expectation");
+         }
+         for (int i = 0; i < expectedKeys.length; i++) {
+             if (!iteratorKeys.contains(expectedKeys[i])) {
+                 throwException(iterator, "expected key wasn't found in iterator's key set");
+             }
+         }
+    }
+
+    private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits) throws Exception {
+        int previous = 0;
+        char c = iterator.first();
+        for (int i = 0; i < expectedLimits.length; i++) {
+             if (iterator.getRunStart() != previous || iterator.getRunLimit() != expectedLimits[i]) {
+                 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart() + ", " + iterator.getRunLimit());
+             }
+             previous = expectedLimits[i];
+             c = iterator.setIndex(previous);
+        }
+        if (c != CharacterIterator.DONE) {
+            throwException(iterator, "iterator's run sequence doesn't end with DONE");
+        }
+    }
+
+    private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception {
+        int previous = 0;
+        char c = iterator.first();
+        for (int i = 0; i < expectedLimits.length; i++) {
+             if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) {
+                 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key);
+             }
+             previous = expectedLimits[i];
+             c = iterator.setIndex(previous);
+        }
+        if (c != CharacterIterator.DONE) {
+            throwException(iterator, "iterator's run sequence doesn't end with DONE");
+        }
+    }
+
+    private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits) throws Exception {
+        int previous = 0;
+        char c = iterator.first();
+        for (int i = 0; i < expectedLimits.length; i++) {
+             if (iterator.getRunStart(keys) != previous || iterator.getRunLimit(keys) != expectedLimits[i]) {
+                 throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(keys) + ", " + iterator.getRunLimit(keys) + " for keys " + keys);
+             }
+             previous = expectedLimits[i];
+             c = iterator.setIndex(previous);
+        }
+        if (c != CharacterIterator.DONE) {
+            throwException(iterator, "iterator's run sequence doesn't end with DONE");
+        }
+    }
+
+    private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception {
+        iterator.setIndex(index);
+        Object value = iterator.getAttribute(key);
+        if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) {
+            throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue);
+        }
+        value = iterator.getAttributes().get(key);
+        if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) {
+            throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue);
+        }
+    }
+
+    private static final void throwException(AttributedCharacterIterator iterator, String details) throws Exception {
+        dumpIterator(iterator);
+        throw new Exception(details);
+    }
+
+    private static final void dumpIterator(AttributedCharacterIterator iterator) {
+        Set attributeKeys = iterator.getAllAttributeKeys();
+        System.out.print("All attributes: ");
+        Iterator keyIterator = attributeKeys.iterator();
+        while (keyIterator.hasNext()) {
+            Attribute key = (Attribute) keyIterator.next();
+            System.out.print(key);
+        }
+        for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) {
+            if (iterator.getIndex() == iterator.getBeginIndex() ||
+                        iterator.getIndex() == iterator.getRunStart()) {
+                System.out.println();
+                Map attributes = iterator.getAttributes();
+                Set entries = attributes.entrySet();
+                Iterator attributeIterator = entries.iterator();
+                while (attributeIterator.hasNext()) {
+                    Map.Entry entry = (Map.Entry) attributeIterator.next();
+                    System.out.print("<" + entry.getKey() + ": "
+                                + entry.getValue() + ">");
+                }
+            }
+            System.out.print(" ");
+            System.out.print(c);
+        }
+        System.out.println();
+        System.out.println("done");
+        System.out.println();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/AttributedString/TestAttributedStringCtor.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4146853
+ * @summary Make sure we can construct an AttributedString from
+ * an AttributedCharacterIterator covering only a subrange
+ * @modules java.desktop
+ */
+
+import java.awt.font.TextAttribute;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Hashtable;
+
+public class TestAttributedStringCtor {
+
+    public static void main(String[] args) {
+
+        // Create a new AttributedString with one attribute.
+        Hashtable attributes = new Hashtable();
+        attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
+        AttributedString origString = new AttributedString("Hello world.", attributes);
+
+        // Create an iterator over part of the AttributedString.
+        AttributedCharacterIterator iter = origString.getIterator(null, 4, 6);
+
+        // Attempt to create a new AttributedString from the iterator.
+        // This will throw IllegalArgumentException.
+        AttributedString newString = new AttributedString(iter);
+
+        // Without the exception this would get executed.
+        System.out.println("DONE");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/AttributedString/getRunStartLimitTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4151160
+ * @summary Make sure to return correct run start and limit values
+ * when the iterator has been created with begin and end index values.
+ * @modules java.desktop
+ */
+
+import java.awt.font.TextAttribute;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.text.Annotation;
+
+public class getRunStartLimitTest {
+
+    public static void main(String[] args) throws Exception {
+
+        String text = "Hello world";
+        AttributedString as = new AttributedString(text);
+
+        // add non-Annotation attributes
+        as.addAttribute(TextAttribute.WEIGHT,
+                        TextAttribute.WEIGHT_LIGHT,
+                        0,
+                        3);
+        as.addAttribute(TextAttribute.WEIGHT,
+                        TextAttribute.WEIGHT_BOLD,
+                        3,
+                        5);
+        as.addAttribute(TextAttribute.WEIGHT,
+                        TextAttribute.WEIGHT_EXTRABOLD,
+                        5,
+                        text.length());
+
+        // add Annotation attributes
+        as.addAttribute(TextAttribute.WIDTH,
+                        new Annotation(TextAttribute.WIDTH_EXTENDED),
+                        0,
+                        3);
+        as.addAttribute(TextAttribute.WIDTH,
+                        new Annotation(TextAttribute.WIDTH_CONDENSED),
+                        3,
+                        4);
+
+        AttributedCharacterIterator aci = as.getIterator(null, 2, 4);
+
+        aci.first();
+        int runStart = aci.getRunStart();
+        if (runStart != 2) {
+            throw new Exception("1st run start is wrong. ("+runStart+" should be 2.)");
+        }
+
+        int runLimit = aci.getRunLimit();
+        if (runLimit != 3) {
+            throw new Exception("1st run limit is wrong. ("+runLimit+" should be 3.)");
+        }
+
+        Object value = aci.getAttribute(TextAttribute.WEIGHT);
+        if (value != TextAttribute.WEIGHT_LIGHT) {
+            throw new Exception("1st run attribute is wrong. ("
+                                +value+" should be "+TextAttribute.WEIGHT_LIGHT+".)");
+        }
+
+        value = aci.getAttribute(TextAttribute.WIDTH);
+        if (value != null) {
+            throw new Exception("1st run annotation is wrong. ("
+                                +value+" should be null.)");
+        }
+
+        aci.setIndex(runLimit);
+        runStart = aci.getRunStart();
+        if (runStart != 3) {
+            throw new Exception("2nd run start is wrong. ("+runStart+" should be 3.)");
+        }
+
+        runLimit = aci.getRunLimit();
+        if (runLimit != 4) {
+            throw new Exception("2nd run limit is wrong. ("+runLimit+" should be 4.)");
+        }
+        value = aci.getAttribute(TextAttribute.WEIGHT);
+        if (value != TextAttribute.WEIGHT_BOLD) {
+            throw new Exception("2nd run attribute is wrong. ("
+                                +value+" should be "+TextAttribute.WEIGHT_BOLD+".)");
+        }
+
+        value = aci.getAttribute(TextAttribute.WIDTH);
+        if (!(value instanceof Annotation)
+            || (((Annotation)value).getValue() !=  TextAttribute.WIDTH_CONDENSED)) {
+            throw new Exception("2nd run annotation is wrong. (" + value + " should be "
+                                + new Annotation(TextAttribute.WIDTH_CONDENSED)+".)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/BreakIteratorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1438 @@
+/*
+ * 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
+ * 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 4035266 4052418 4068133 4068137 4068139 4086052 4095322 4097779
+ *      4097920 4098467 4111338 4113835 4117554 4143071 4146175 4152117
+ *      4152416 4153072 4158381 4214367 4217703 4638433
+ * @library /java/text/testlib
+ * @run main/timeout=2000 BreakIteratorTest
+ * @summary test BreakIterator
+ */
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * 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.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.*;
+
+public class BreakIteratorTest extends IntlTest
+{
+    private BreakIterator characterBreak;
+    private BreakIterator wordBreak;
+    private BreakIterator lineBreak;
+    private BreakIterator sentenceBreak;
+
+    public static void main(String[] args) throws Exception {
+        new BreakIteratorTest().run(args);
+    }
+
+    public BreakIteratorTest()
+    {
+        characterBreak = BreakIterator.getCharacterInstance();
+        wordBreak = BreakIterator.getWordInstance();
+        lineBreak = BreakIterator.getLineInstance();
+        sentenceBreak = BreakIterator.getSentenceInstance();
+    }
+
+    //=========================================================================
+    // general test subroutines
+    //=========================================================================
+
+    private void generalIteratorTest(BreakIterator bi, Vector expectedResult) {
+        StringBuffer buffer = new StringBuffer();
+        String text;
+        for (int i = 0; i < expectedResult.size(); i++) {
+            text = (String)expectedResult.elementAt(i);
+            buffer.append(text);
+        }
+        text = buffer.toString();
+
+        bi.setText(text);
+
+        Vector nextResults = testFirstAndNext(bi, text);
+        Vector previousResults = testLastAndPrevious(bi, text);
+
+        logln("comparing forward and backward...");
+        int errs = getErrorCount();
+        compareFragmentLists("forward iteration", "backward iteration", nextResults,
+                        previousResults);
+        if (getErrorCount() == errs) {
+            logln("comparing expected and actual...");
+            compareFragmentLists("expected result", "actual result", expectedResult,
+                            nextResults);
+        }
+
+        int[] boundaries = new int[expectedResult.size() + 3];
+        boundaries[0] = BreakIterator.DONE;
+        boundaries[1] = 0;
+        for (int i = 0; i < expectedResult.size(); i++)
+            boundaries[i + 2] = boundaries[i + 1] + ((String)expectedResult.elementAt(i)).
+                            length();
+        boundaries[boundaries.length - 1] = BreakIterator.DONE;
+
+        testFollowing(bi, text, boundaries);
+        testPreceding(bi, text, boundaries);
+        testIsBoundary(bi, text, boundaries);
+
+        doMultipleSelectionTest(bi, text);
+    }
+
+    private Vector testFirstAndNext(BreakIterator bi, String text) {
+        int p = bi.first();
+        int lastP = p;
+        Vector<String> result = new Vector<String>();
+
+        if (p != 0)
+            errln("first() returned " + p + " instead of 0");
+        while (p != BreakIterator.DONE) {
+            p = bi.next();
+            if (p != BreakIterator.DONE) {
+                if (p <= lastP)
+                    errln("next() failed to move forward: next() on position "
+                                    + lastP + " yielded " + p);
+
+                result.addElement(text.substring(lastP, p));
+            }
+            else {
+                if (lastP != text.length())
+                    errln("next() returned DONE prematurely: offset was "
+                                    + lastP + " instead of " + text.length());
+            }
+            lastP = p;
+        }
+        return result;
+    }
+
+    private Vector testLastAndPrevious(BreakIterator bi, String text) {
+        int p = bi.last();
+        int lastP = p;
+        Vector<String> result = new Vector<String>();
+
+        if (p != text.length())
+            errln("last() returned " + p + " instead of " + text.length());
+        while (p != BreakIterator.DONE) {
+            p = bi.previous();
+            if (p != BreakIterator.DONE) {
+                if (p >= lastP)
+                    errln("previous() failed to move backward: previous() on position "
+                                    + lastP + " yielded " + p);
+
+                result.insertElementAt(text.substring(p, lastP), 0);
+            }
+            else {
+                if (lastP != 0)
+                    errln("previous() returned DONE prematurely: offset was "
+                                    + lastP + " instead of 0");
+            }
+            lastP = p;
+        }
+        return result;
+    }
+
+    private void compareFragmentLists(String f1Name, String f2Name, Vector f1, Vector f2) {
+        int p1 = 0;
+        int p2 = 0;
+        String s1;
+        String s2;
+        int t1 = 0;
+        int t2 = 0;
+
+        while (p1 < f1.size() && p2 < f2.size()) {
+            s1 = (String)f1.elementAt(p1);
+            s2 = (String)f2.elementAt(p2);
+            t1 += s1.length();
+            t2 += s2.length();
+
+            if (s1.equals(s2)) {
+                debugLogln("   >" + s1 + "<");
+                ++p1;
+                ++p2;
+            }
+            else {
+                int tempT1 = t1;
+                int tempT2 = t2;
+                int tempP1 = p1;
+                int tempP2 = p2;
+
+                while (tempT1 != tempT2 && tempP1 < f1.size() && tempP2 < f2.size()) {
+                    while (tempT1 < tempT2 && tempP1 < f1.size()) {
+                        tempT1 += ((String)f1.elementAt(tempP1)).length();
+                        ++tempP1;
+                    }
+                    while (tempT2 < tempT1 && tempP2 < f2.size()) {
+                        tempT2 += ((String)f2.elementAt(tempP2)).length();
+                        ++tempP2;
+                    }
+                }
+                logln("*** " + f1Name + " has:");
+                while (p1 <= tempP1 && p1 < f1.size()) {
+                    s1 = (String)f1.elementAt(p1);
+                    t1 += s1.length();
+                    debugLogln(" *** >" + s1 + "<");
+                    ++p1;
+                }
+                logln("***** " + f2Name + " has:");
+                while (p2 <= tempP2 && p2 < f2.size()) {
+                    s2 = (String)f2.elementAt(p2);
+                    t2 += s2.length();
+                    debugLogln(" ***** >" + s2 + "<");
+                    ++p2;
+                }
+                errln("Discrepancy between " + f1Name + " and " + f2Name + "\n---\n" + f1 +"\n---\n" + f2);
+            }
+        }
+    }
+
+    private void testFollowing(BreakIterator bi, String text, int[] boundaries) {
+        logln("testFollowing():");
+        int p = 2;
+        int i = 0;
+        try {
+            for (i = 0; i <= text.length(); i++) {  // change to <= when new BI code goes in
+                if (i == boundaries[p])
+                    ++p;
+
+                int b = bi.following(i);
+                logln("bi.following(" + i + ") -> " + b);
+                if (b != boundaries[p])
+                    errln("Wrong result from following() for " + i + ": expected " + boundaries[p]
+                          + ", got " + b);
+            }
+        } catch (IllegalArgumentException illargExp) {
+            errln("IllegalArgumentException caught from following() for offset: " + i);
+        }
+    }
+
+    private void testPreceding(BreakIterator bi, String text, int[] boundaries) {
+        logln("testPreceding():");
+        int p = 0;
+        int i = 0;
+        try {
+            for (i = 0; i <= text.length(); i++) {  // change to <= when new BI code goes in
+                int b = bi.preceding(i);
+                logln("bi.preceding(" + i + ") -> " + b);
+                if (b != boundaries[p])
+                    errln("Wrong result from preceding() for " + i + ": expected " + boundaries[p]
+                          + ", got " + b);
+
+                if (i == boundaries[p + 1])
+                    ++p;
+            }
+        } catch (IllegalArgumentException illargExp) {
+            errln("IllegalArgumentException caught from preceding() for offset: " + i);
+        }
+    }
+
+    private void testIsBoundary(BreakIterator bi, String text, int[] boundaries) {
+        logln("testIsBoundary():");
+        int p = 1;
+        boolean isB;
+        for (int i = 0; i <= text.length(); i++) {  // change to <= when new BI code goes in
+            isB = bi.isBoundary(i);
+            logln("bi.isBoundary(" + i + ") -> " + isB);
+
+            if (i == boundaries[p]) {
+                if (!isB)
+                    errln("Wrong result from isBoundary() for " + i + ": expected true, got false");
+                ++p;
+            }
+            else {
+                if (isB)
+                    errln("Wrong result from isBoundary() for " + i + ": expected false, got true");
+            }
+        }
+    }
+
+    private void doMultipleSelectionTest(BreakIterator iterator, String testText)
+    {
+        logln("Multiple selection test...");
+        BreakIterator testIterator = (BreakIterator)iterator.clone();
+        int offset = iterator.first();
+        int testOffset;
+        int count = 0;
+
+        do {
+            testOffset = testIterator.first();
+            testOffset = testIterator.next(count);
+            logln("next(" + count + ") -> " + testOffset);
+            if (offset != testOffset)
+                errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);
+
+            if (offset != BreakIterator.DONE) {
+                count++;
+                offset = iterator.next();
+            }
+        } while (offset != BreakIterator.DONE);
+
+        // now do it backwards...
+        offset = iterator.last();
+        count = 0;
+
+        do {
+            testOffset = testIterator.last();
+            testOffset = testIterator.next(count);
+            logln("next(" + count + ") -> " + testOffset);
+            if (offset != testOffset)
+                errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);
+
+            if (offset != BreakIterator.DONE) {
+                count--;
+                offset = iterator.previous();
+            }
+        } while (offset != BreakIterator.DONE);
+    }
+
+    private void doBreakInvariantTest(BreakIterator tb, String testChars)
+    {
+        StringBuffer work = new StringBuffer("aaa");
+        int errorCount = 0;
+
+        // a break should always occur after CR (unless followed by LF), LF, PS, and LS
+        String breaks = /*"\r\n\u2029\u2028"*/"\n\u2029\u2028";
+                            // change this back when new BI code is added
+
+        for (int i = 0; i < breaks.length(); i++) {
+            work.setCharAt(1, breaks.charAt(i));
+            for (int j = 0; j < testChars.length(); j++) {
+                work.setCharAt(0, testChars.charAt(j));
+                for (int k = 0; k < testChars.length(); k++) {
+                    char c = testChars.charAt(k);
+
+                    // if a cr is followed by lf, don't do the check (they stay together)
+                    if (work.charAt(1) == '\r' && (c == '\n'))
+                        continue;
+
+                    // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+                    // for breaking purposes as per UTR14
+                    int type1 = Character.getType(work.charAt(1));
+                    int type2 = Character.getType(c);
+                    if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+                        type2 == Character.CONTROL || type2 == Character.FORMAT) {
+                        continue;
+                    }
+
+                    work.setCharAt(2, c);
+                    tb.setText(work.toString());
+                    boolean seen2 = false;
+                    for (int l = tb.first(); l != BreakIterator.DONE; l = tb.next()) {
+                        if (l == 2)
+                            seen2 = true;
+                    }
+                    if (!seen2) {
+                        errln("No break between U+" + Integer.toHexString((int)(work.charAt(1)))
+                                    + " and U+" + Integer.toHexString((int)(work.charAt(2))));
+                        errorCount++;
+                        if (errorCount >= 75)
+                            return;
+                    }
+                }
+            }
+        }
+    }
+
+    private void doOtherInvariantTest(BreakIterator tb, String testChars)
+    {
+        StringBuffer work = new StringBuffer("a\r\na");
+        int errorCount = 0;
+
+        // a break should never occur between CR and LF
+        for (int i = 0; i < testChars.length(); i++) {
+            work.setCharAt(0, testChars.charAt(i));
+            for (int j = 0; j < testChars.length(); j++) {
+                work.setCharAt(3, testChars.charAt(j));
+                tb.setText(work.toString());
+                for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next())
+                    if (k == 2) {
+                        errln("Break between CR and LF in string U+" + Integer.toHexString(
+                                (int)(work.charAt(0))) + ", U+d U+a U+" + Integer.toHexString(
+                                (int)(work.charAt(3))));
+                        errorCount++;
+                        if (errorCount >= 75)
+                            return;
+                    }
+            }
+        }
+
+        // a break should never occur before a non-spacing mark, unless it's preceded
+        // by a line terminator
+        work.setLength(0);
+        work.append("aaaa");
+        for (int i = 0; i < testChars.length(); i++) {
+            char c = testChars.charAt(i);
+            if (c == '\n' || c == '\r' || c == '\u2029' || c == '\u2028' || c == '\u0003')
+                continue;
+            work.setCharAt(1, c);
+            for (int j = 0; j < testChars.length(); j++) {
+                c = testChars.charAt(j);
+                if (Character.getType(c) != Character.NON_SPACING_MARK && Character.getType(c)
+                        != Character.ENCLOSING_MARK)
+                    continue;
+                work.setCharAt(2, c);
+
+                // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+                // for breaking purposes as per UTR14
+                int type1 = Character.getType(work.charAt(1));
+                int type2 = Character.getType(work.charAt(2));
+                if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+                    type2 == Character.CONTROL || type2 == Character.FORMAT) {
+                    continue;
+                }
+
+                tb.setText(work.toString());
+                for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next())
+                    if (k == 2) {
+                        errln("Break between U+" + Integer.toHexString((int)(work.charAt(1)))
+                                + " and U+" + Integer.toHexString((int)(work.charAt(2))));
+                        errorCount++;
+                        if (errorCount >= 75)
+                            return;
+                    }
+            }
+        }
+    }
+
+    public void debugLogln(String s) {
+        final String zeros = "0000";
+        String temp;
+        StringBuffer out = new StringBuffer();
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c >= ' ' && c < '\u007f')
+                out.append(c);
+            else {
+                out.append("\\u");
+                temp = Integer.toHexString((int)c);
+                out.append(zeros.substring(0, 4 - temp.length()));
+                out.append(temp);
+            }
+        }
+        logln(out.toString());
+    }
+
+    //=========================================================================
+    // tests
+    //=========================================================================
+
+    public void TestWordBreak() {
+
+        Vector<String> wordSelectionData = new Vector<String>();
+
+        wordSelectionData.addElement("12,34");
+
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\u00A2"); //cent sign
+        wordSelectionData.addElement("\u00A3"); //pound sign
+        wordSelectionData.addElement("\u00A4"); //currency sign
+        wordSelectionData.addElement("\u00A5"); //yen sign
+        wordSelectionData.addElement("alpha-beta-gamma");
+        wordSelectionData.addElement(".");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("Badges");
+        wordSelectionData.addElement("?");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("BADGES");
+        wordSelectionData.addElement("!");
+        wordSelectionData.addElement("?");
+        wordSelectionData.addElement("!");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("We");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("don't");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("need");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("no");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("STINKING");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("BADGES");
+        wordSelectionData.addElement("!");
+        wordSelectionData.addElement("!");
+        wordSelectionData.addElement("!");
+
+        wordSelectionData.addElement("012.566,5");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("123.3434,900");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("1000,233,456.000");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("1,23.322%");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("123.1222");
+
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\u0024123,000.20");
+
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("179.01\u0025");
+
+        wordSelectionData.addElement("Hello");
+        wordSelectionData.addElement(",");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("how");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("are");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("you");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("X");
+        wordSelectionData.addElement(" ");
+
+        wordSelectionData.addElement("Now");
+        wordSelectionData.addElement("\r");
+        wordSelectionData.addElement("is");
+        wordSelectionData.addElement("\n");
+        wordSelectionData.addElement("the");
+        wordSelectionData.addElement("\r\n");
+        wordSelectionData.addElement("time");
+        wordSelectionData.addElement("\n");
+        wordSelectionData.addElement("\r");
+        wordSelectionData.addElement("for");
+        wordSelectionData.addElement("\r");
+        wordSelectionData.addElement("\r");
+        wordSelectionData.addElement("all");
+        wordSelectionData.addElement(" ");
+
+        generalIteratorTest(wordBreak, wordSelectionData);
+    }
+
+    public void TestBug4097779() {
+        Vector<String> wordSelectionData = new Vector<String>();
+
+        wordSelectionData.addElement("aa\u0300a");
+        wordSelectionData.addElement(" ");
+
+        generalIteratorTest(wordBreak, wordSelectionData);
+    }
+
+    public void TestBug4098467Words() {
+        Vector<String> wordSelectionData = new Vector<String>();
+
+        // What follows is a string of Korean characters (I found it in the Yellow Pages
+        // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+        // it correctly), first as precomposed syllables, and then as conjoining jamo.
+        // Both sequences should be semantically identical and break the same way.
+        // precomposed syllables...
+        wordSelectionData.addElement("\uc0c1\ud56d");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\ud55c\uc778");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\uc5f0\ud569");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\uc7a5\ub85c\uad50\ud68c");
+        wordSelectionData.addElement(" ");
+        // conjoining jamo...
+        wordSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8");
+        wordSelectionData.addElement(" ");
+        wordSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c");
+        wordSelectionData.addElement(" ");
+
+        generalIteratorTest(wordBreak, wordSelectionData);
+    }
+
+    public void TestBug4117554Words() {
+        Vector<String> wordSelectionData = new Vector<String>();
+
+        // this is a test for bug #4117554: the ideographic iteration mark (U+3005) should
+        // count as a Kanji character for the purposes of word breaking
+        wordSelectionData.addElement("abc");
+        wordSelectionData.addElement("\u4e01\u4e02\u3005\u4e03\u4e03");
+        wordSelectionData.addElement("abc");
+
+        generalIteratorTest(wordBreak, wordSelectionData);
+    }
+
+    public void TestSentenceBreak() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        sentenceSelectionData.addElement("This is a simple sample sentence. ");
+        sentenceSelectionData.addElement("(This is it.) ");
+        sentenceSelectionData.addElement("This is a simple sample sentence. ");
+        sentenceSelectionData.addElement("\"This isn\'t it.\" ");
+        sentenceSelectionData.addElement("Hi! ");
+        sentenceSelectionData.addElement("This is a simple sample sentence. ");
+        sentenceSelectionData.addElement("It does not have to make any sense as you can see. ");
+        sentenceSelectionData.addElement("Nel mezzo del cammin di nostra vita, mi ritrovai in una selva oscura. ");
+        sentenceSelectionData.addElement("Che la dritta via aveo smarrita. ");
+        sentenceSelectionData.addElement("He said, that I said, that you said!! ");
+
+        sentenceSelectionData.addElement("Don't rock the boat.\u2029");
+
+        sentenceSelectionData.addElement("Because I am the daddy, that is why. ");
+        sentenceSelectionData.addElement("Not on my time (el timo.)! ");
+
+        sentenceSelectionData.addElement("So what!!\u2029");
+
+        sentenceSelectionData.addElement("\"But now,\" he said, \"I know!\" ");
+        sentenceSelectionData.addElement("Harris thumbed down several, including \"Away We Go\" (which became the huge success Oklahoma!). ");
+        sentenceSelectionData.addElement("One species, B. anthracis, is highly virulent.\n");
+        sentenceSelectionData.addElement("Wolf said about Sounder:\"Beautifully thought-out and directed.\" ");
+        sentenceSelectionData.addElement("Have you ever said, \"This is where \tI shall live\"? ");
+        sentenceSelectionData.addElement("He answered, \"You may not!\" ");
+        sentenceSelectionData.addElement("Another popular saying is: \"How do you do?\". ");
+        sentenceSelectionData.addElement("Yet another popular saying is: \'I\'m fine thanks.\' ");
+        sentenceSelectionData.addElement("What is the proper use of the abbreviation pp.? ");
+        sentenceSelectionData.addElement("Yes, I am definatelly 12\" tall!!");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4113835() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // test for bug #4113835: \n and \r count as spaces, not as paragraph breaks
+        sentenceSelectionData.addElement("Now\ris\nthe\r\ntime\n\rfor\r\rall\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4111338() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // test for bug #4111338: Don't break sentences at the boundary between CJK
+        // and other letters
+        sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165:\"JAVA\u821c"
+                + "\u8165\u7fc8\u51ce\u306d,\u2494\u56d8\u4ec0\u60b1\u8560\u51ba"
+                + "\u611d\u57b6\u2510\u5d46\".\u2029");
+        sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8"
+                + "\u97e4JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0"
+                + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+        sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8\u97e4"
+                + "\u6470\u8790JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8"
+                + "\u4ec0\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+        sentenceSelectionData.addElement("He said, \"I can go there.\"\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4117554Sentences() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // Treat fullwidth variants of .!? the same as their
+        // normal counterparts
+        sentenceSelectionData.addElement("I know I'm right\uff0e ");
+        sentenceSelectionData.addElement("Right\uff1f ");
+        sentenceSelectionData.addElement("Right\uff01 ");
+
+        // Don't break sentences at boundary between CJK and digits
+        sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8"
+                + "\u97e48888\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0"
+                + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+
+        // Break sentence between a sentence terminator and
+        // opening punctuation
+        sentenceSelectionData.addElement("no?");
+        sentenceSelectionData.addElement("(yes)");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4158381() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // Don't break sentence after period if it isn't followed by a space
+        sentenceSelectionData.addElement("Test <code>Flags.Flag</code> class.  ");
+        sentenceSelectionData.addElement("Another test.\u2029");
+
+        // No breaks when there are no terminators around
+        sentenceSelectionData.addElement("<P>Provides a set of "
+                + "&quot;lightweight&quot; (all-java<FONT SIZE=\"-2\"><SUP>TM"
+                + "</SUP></FONT> language) components that, "
+                + "to the maximum degree possible, work the same on all platforms.  ");
+        sentenceSelectionData.addElement("Another test.\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4143071() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // Make sure sentences that end with digits work right
+        sentenceSelectionData.addElement("Today is the 27th of May, 1998.  ");
+        sentenceSelectionData.addElement("Tomorrow with be 28 May 1998.  ");
+        sentenceSelectionData.addElement("The day after will be the 30th.\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4152416() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // Make sure sentences ending with a capital letter are treated correctly
+        sentenceSelectionData.addElement("The type of all primitive "
+                + "<code>boolean</code> values accessed in the target VM.  ");
+        sentenceSelectionData.addElement("Calls to xxx will return an "
+                + "implementor of this interface.\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4152117() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // Make sure sentence breaking is handling punctuation correctly
+        // [COULD NOT REPRODUCE THIS BUG, BUT TEST IS HERE TO MAKE SURE
+        // IT DOESN'T CROP UP]
+        sentenceSelectionData.addElement("Constructs a randomly generated "
+                + "BigInteger, uniformly distributed over the range <tt>0</tt> "
+                + "to <tt>(2<sup>numBits</sup> - 1)</tt>, inclusive.  ");
+        sentenceSelectionData.addElement("The uniformity of the distribution "
+                + "assumes that a fair source of random bits is provided in "
+                + "<tt>rnd</tt>.  ");
+        sentenceSelectionData.addElement("Note that this constructor always "
+                + "constructs a non-negative BigInteger.\u2029");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestLineBreak() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        lineSelectionData.addElement("Multi-");
+        lineSelectionData.addElement("Level ");
+        lineSelectionData.addElement("example ");
+        lineSelectionData.addElement("of ");
+        lineSelectionData.addElement("a ");
+        lineSelectionData.addElement("semi-");
+        lineSelectionData.addElement("idiotic ");
+        lineSelectionData.addElement("non-");
+        lineSelectionData.addElement("sensical ");
+        lineSelectionData.addElement("(non-");
+        lineSelectionData.addElement("important) ");
+        lineSelectionData.addElement("sentence. ");
+
+        lineSelectionData.addElement("Hi  ");
+        lineSelectionData.addElement("Hello ");
+        lineSelectionData.addElement("How\n");
+        lineSelectionData.addElement("are\r");
+        lineSelectionData.addElement("you\u2028");
+        lineSelectionData.addElement("fine.\t");
+        lineSelectionData.addElement("good.  ");
+
+        lineSelectionData.addElement("Now\r");
+        lineSelectionData.addElement("is\n");
+        lineSelectionData.addElement("the\r\n");
+        lineSelectionData.addElement("time\n");
+        lineSelectionData.addElement("\r");
+        lineSelectionData.addElement("for\r");
+        lineSelectionData.addElement("\r");
+        lineSelectionData.addElement("all");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4068133() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        lineSelectionData.addElement("\u96f6");
+        lineSelectionData.addElement("\u4e00\u3002");
+        lineSelectionData.addElement("\u4e8c\u3001");
+        lineSelectionData.addElement("\u4e09\u3002\u3001");
+        lineSelectionData.addElement("\u56db\u3001\u3002\u3001");
+        lineSelectionData.addElement("\u4e94,");
+        lineSelectionData.addElement("\u516d.");
+        lineSelectionData.addElement("\u4e03.\u3001,\u3002");
+        lineSelectionData.addElement("\u516b");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4086052() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        lineSelectionData.addElement("foo\u00a0bar ");
+//        lineSelectionData.addElement("foo\ufeffbar");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4097920() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        lineSelectionData.addElement("dog,");
+        lineSelectionData.addElement("cat,");
+        lineSelectionData.addElement("mouse ");
+        lineSelectionData.addElement("(one)");
+        lineSelectionData.addElement("(two)\n");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+    /*
+    public void TestBug4035266() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        lineSelectionData.addElement("The ");
+        lineSelectionData.addElement("balance ");
+        lineSelectionData.addElement("is ");
+        lineSelectionData.addElement("$-23,456.78, ");
+        lineSelectionData.addElement("not ");
+        lineSelectionData.addElement("-$32,456.78!\n");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+    */
+    public void TestBug4098467Lines() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        // What follows is a string of Korean characters (I found it in the Yellow Pages
+        // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+        // it correctly), first as precomposed syllables, and then as conjoining jamo.
+        // Both sequences should be semantically identical and break the same way.
+        // precomposed syllables...
+        lineSelectionData.addElement("\uc0c1");
+        lineSelectionData.addElement("\ud56d ");
+        lineSelectionData.addElement("\ud55c");
+        lineSelectionData.addElement("\uc778 ");
+        lineSelectionData.addElement("\uc5f0");
+        lineSelectionData.addElement("\ud569 ");
+        lineSelectionData.addElement("\uc7a5");
+        lineSelectionData.addElement("\ub85c");
+        lineSelectionData.addElement("\uad50");
+        lineSelectionData.addElement("\ud68c ");
+        // conjoining jamo...
+        lineSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc ");
+        lineSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab ");
+        lineSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8 ");
+        lineSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c");
+
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4117554Lines() {
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        // Fullwidth .!? should be treated as postJwrd
+        lineSelectionData.addElement("\u4e01\uff0e");
+        lineSelectionData.addElement("\u4e02\uff01");
+        lineSelectionData.addElement("\u4e03\uff1f");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4217703() {
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        // There shouldn't be a line break between sentence-ending punctuation
+        // and a closing quote
+        lineSelectionData.addElement("He ");
+        lineSelectionData.addElement("said ");
+        lineSelectionData.addElement("\"Go!\"  ");
+        lineSelectionData.addElement("I ");
+        lineSelectionData.addElement("went.  ");
+
+        lineSelectionData.addElement("Hashtable$Enumeration ");
+        lineSelectionData.addElement("getText().");
+        lineSelectionData.addElement("getIndex()");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    private static final String graveS = "S\u0300";
+    private static final String acuteBelowI = "i\u0317";
+    private static final String acuteE = "e\u0301";
+    private static final String circumflexA = "a\u0302";
+    private static final String tildeE = "e\u0303";
+
+    public void TestCharacterBreak() {
+        Vector<String> characterSelectionData = new Vector<String>();
+
+        characterSelectionData.addElement(graveS);
+        characterSelectionData.addElement(acuteBelowI);
+        characterSelectionData.addElement("m");
+        characterSelectionData.addElement("p");
+        characterSelectionData.addElement("l");
+        characterSelectionData.addElement(acuteE);
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("s");
+        characterSelectionData.addElement(circumflexA);
+        characterSelectionData.addElement("m");
+        characterSelectionData.addElement("p");
+        characterSelectionData.addElement("l");
+        characterSelectionData.addElement(tildeE);
+        characterSelectionData.addElement(".");
+        characterSelectionData.addElement("w");
+        characterSelectionData.addElement(circumflexA);
+        characterSelectionData.addElement("w");
+        characterSelectionData.addElement("a");
+        characterSelectionData.addElement("f");
+        characterSelectionData.addElement("q");
+        characterSelectionData.addElement("\n");
+        characterSelectionData.addElement("\r");
+        characterSelectionData.addElement("\r\n");
+        characterSelectionData.addElement("\n");
+
+        generalIteratorTest(characterBreak, characterSelectionData);
+    }
+
+    public void TestBug4098467Characters() {
+        Vector<String> characterSelectionData = new Vector<String>();
+
+        // What follows is a string of Korean characters (I found it in the Yellow Pages
+        // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+        // it correctly), first as precomposed syllables, and then as conjoining jamo.
+        // Both sequences should be semantically identical and break the same way.
+        // precomposed syllables...
+        characterSelectionData.addElement("\uc0c1");
+        characterSelectionData.addElement("\ud56d");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\ud55c");
+        characterSelectionData.addElement("\uc778");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\uc5f0");
+        characterSelectionData.addElement("\ud569");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\uc7a5");
+        characterSelectionData.addElement("\ub85c");
+        characterSelectionData.addElement("\uad50");
+        characterSelectionData.addElement("\ud68c");
+        characterSelectionData.addElement(" ");
+        // conjoining jamo...
+        characterSelectionData.addElement("\u1109\u1161\u11bc");
+        characterSelectionData.addElement("\u1112\u1161\u11bc");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\u1112\u1161\u11ab");
+        characterSelectionData.addElement("\u110b\u1175\u11ab");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\u110b\u1167\u11ab");
+        characterSelectionData.addElement("\u1112\u1161\u11b8");
+        characterSelectionData.addElement(" ");
+        characterSelectionData.addElement("\u110c\u1161\u11bc");
+        characterSelectionData.addElement("\u1105\u1169");
+        characterSelectionData.addElement("\u1100\u116d");
+        characterSelectionData.addElement("\u1112\u116c");
+
+        generalIteratorTest(characterBreak, characterSelectionData);
+    }
+
+    public void TestBug4153072() {
+        BreakIterator iter = BreakIterator.getWordInstance();
+        String str = "...Hello, World!...";
+        int begin = 3;
+        int end = str.length() - 3;
+        boolean gotException = false;
+        boolean dummy;
+
+        iter.setText(new StringCharacterIterator(str, begin, end, begin));
+        for (int index = -1; index < begin + 1; ++index) {
+            try {
+                dummy = iter.isBoundary(index);
+                if (index < begin)
+                    errln("Didn't get exception with offset = " + index +
+                                    " and begin index = " + begin);
+            }
+            catch (IllegalArgumentException e) {
+                if (index >= begin)
+                    errln("Got exception with offset = " + index +
+                                    " and begin index = " + begin);
+            }
+        }
+    }
+
+    public void TestBug4146175Sentences() {
+        Vector<String> sentenceSelectionData = new Vector<String>();
+
+        // break between periods and opening punctuation even when there's no
+        // intervening space
+        sentenceSelectionData.addElement("end.");
+        sentenceSelectionData.addElement("(This is\u2029");
+
+        // treat the fullwidth period as an unambiguous sentence terminator
+        sentenceSelectionData.addElement("\u7d42\u308f\u308a\uff0e");
+        sentenceSelectionData.addElement("\u300c\u3053\u308c\u306f");
+
+        generalIteratorTest(sentenceBreak, sentenceSelectionData);
+    }
+
+    public void TestBug4146175Lines() {
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        Vector<String> lineSelectionData = new Vector<String>();
+
+        // the fullwidth comma should stick to the preceding Japanese character
+        lineSelectionData.addElement("\u7d42\uff0c");
+        lineSelectionData.addElement("\u308f");
+
+        generalIteratorTest(lineBreak, lineSelectionData);
+    }
+
+    public void TestBug4214367() {
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        Vector<String> wordSelectionData = new Vector<String>();
+
+        // the hiragana and katakana iteration marks and the long vowel mark
+        // are not being treated correctly by the word-break iterator
+        wordSelectionData.addElement("\u3042\u3044\u309d\u3042\u309e\u3042\u30fc\u3042");
+        wordSelectionData.addElement("\u30a2\u30a4\u30fd\u30a2\u30fe\u30a2\u30fc\u30a2");
+
+        generalIteratorTest(wordBreak, wordSelectionData);
+    }
+
+    private static final String cannedTestChars // characters fo the class Cc are ignorable for breaking
+        = /*"\u0000\u0001\u0002\u0003\u0004*/" !\"#$%&()+-01234<=>ABCDE[]^_`abcde{}|\u00a0\u00a2"
+        + "\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00ab\u00ad\u00ae\u00af\u00b0\u00b2\u00b3"
+        + "\u00b4\u00b9\u00bb\u00bc\u00bd\u02b0\u02b1\u02b2\u02b3\u02b4\u0300\u0301\u0302\u0303"
+        + "\u0304\u05d0\u05d1\u05d2\u05d3\u05d4\u0903\u093e\u093f\u0940\u0949\u0f3a\u0f3b\u2000"
+        + "\u2001\u2002\u200c\u200d\u200e\u200f\u2010\u2011\u2012\u2028\u2029\u202a\u203e\u203f"
+        + "\u2040\u20dd\u20de\u20df\u20e0\u2160\u2161\u2162\u2163\u2164";
+
+    public void TestSentenceInvariants()
+    {
+        BreakIterator e = BreakIterator.getSentenceInstance();
+        doOtherInvariantTest(e, cannedTestChars + ".,\u3001\u3002\u3041\u3042\u3043\ufeff");
+    }
+
+    public void TestWordInvariants()
+    {
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        BreakIterator e = BreakIterator.getWordInstance();
+        doBreakInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2"
+            + "\u30a3\u4e00\u4e01\u4e02");
+        doOtherInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2"
+            + "\u30a3\u4e00\u4e01\u4e02");
+    }
+
+    public void TestLineInvariants()
+    {
+        if (Locale.getDefault().getLanguage().equals("th")) {
+            logln("This test is skipped in th locale.");
+            return;
+        }
+
+        BreakIterator e = BreakIterator.getLineInstance();
+        String testChars = cannedTestChars + ".,;:\u3001\u3002\u3041\u3042\u3043\u3044\u3045"
+            + "\u30a3\u4e00\u4e01\u4e02";
+        doBreakInvariantTest(e, testChars);
+        doOtherInvariantTest(e, testChars);
+
+        int errorCount = 0;
+
+        // in addition to the other invariants, a line-break iterator should make sure that:
+        // it doesn't break around the non-breaking characters
+        String noBreak = "\u00a0\u2007\u2011\ufeff";
+        StringBuffer work = new StringBuffer("aaa");
+        for (int i = 0; i < testChars.length(); i++) {
+            char c = testChars.charAt(i);
+            if (c == '\r' || c == '\n' || c == '\u2029' || c == '\u2028' || c == '\u0003')
+                continue;
+            work.setCharAt(0, c);
+            for (int j = 0; j < noBreak.length(); j++) {
+                work.setCharAt(1, noBreak.charAt(j));
+                for (int k = 0; k < testChars.length(); k++) {
+                    work.setCharAt(2, testChars.charAt(k));
+                    // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+                    // for breaking purposes as per UTR14
+                    int type1 = Character.getType(work.charAt(1));
+                    int type2 = Character.getType(work.charAt(2));
+                    if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+                        type2 == Character.CONTROL || type2 == Character.FORMAT) {
+                        continue;
+                    }
+                    e.setText(work.toString());
+                    for (int l = e.first(); l != BreakIterator.DONE; l = e.next()) {
+                        if (l == 1 || l == 2) {
+                            //errln("Got break between U+" + Integer.toHexString((int)
+                            //        (work.charAt(l - 1))) + " and U+" + Integer.toHexString(
+                            //        (int)(work.charAt(l))) + "\ntype1 = " + type1 + "\ntype2 = " + type2);
+                            // as per UTR14 spaces followed by a GLUE character should allow
+                            // line breaking
+                            if (work.charAt(l-1) == '\u0020' && (work.charAt(l) == '\u00a0' ||
+                                                                 work.charAt(l) == '\u0f0c' ||
+                                                                 work.charAt(l) == '\u2007' ||
+                                                                 work.charAt(l) == '\u2011' ||
+                                                                 work.charAt(l) == '\u202f' ||
+                                                                 work.charAt(l) == '\ufeff')) {
+                                continue;
+                            }
+                            errln("Got break between U+" + Integer.toHexString((int)
+                                    (work.charAt(l - 1))) + " and U+" + Integer.toHexString(
+                                    (int)(work.charAt(l))));
+                            errorCount++;
+                            if (errorCount >= 75)
+                                return;
+                        }
+                    }
+                }
+            }
+        }
+
+        // The following test has so many exceptions that it would be better to write a new set of data
+        // that tested exactly what should be tested
+        // Until that point it will be commented out
+        /*
+
+        // it does break after dashes (unless they're followed by a digit, a non-spacing mark,
+        // a currency symbol, a space, a format-control character, a regular control character,
+        // a line or paragraph separator, or another dash)
+        String dashes = "-\u00ad\u2010\u2012\u2013\u2014";
+        for (int i = 0; i < testChars.length(); i++) {
+            work.setCharAt(0, testChars.charAt(i));
+            for (int j = 0; j < dashes.length(); j++) {
+                work.setCharAt(1, dashes.charAt(j));
+                for (int k = 0; k < testChars.length(); k++) {
+                    char c = testChars.charAt(k);
+                    if (Character.getType(c) == Character.DECIMAL_DIGIT_NUMBER ||
+                        Character.getType(c) == Character.OTHER_NUMBER ||
+                        Character.getType(c) == Character.NON_SPACING_MARK ||
+                        Character.getType(c) == Character.ENCLOSING_MARK ||
+                        Character.getType(c) == Character.CURRENCY_SYMBOL ||
+                        Character.getType(c) == Character.DASH_PUNCTUATION ||
+                        Character.getType(c) == Character.SPACE_SEPARATOR ||
+                        Character.getType(c) == Character.FORMAT ||
+                        Character.getType(c) == Character.CONTROL ||
+                        Character.getType(c) == Character.END_PUNCTUATION ||
+                        Character.getType(c) == Character.FINAL_QUOTE_PUNCTUATION ||
+                        Character.getType(c) == Character.OTHER_PUNCTUATION ||
+                        c == '\'' || c == '\"' ||
+                        // category EX as per UTR14
+                        c == '!' || c == '?' || c == '\ufe56' || c == '\ufe57' || c == '\uff01' || c == '\uff1f' ||
+                        c == '\n' || c == '\r' || c == '\u2028' || c == '\u2029' ||
+                        c == '\u0003' || c == '\u2007' || c == '\u2011' ||
+                        c == '\ufeff')
+                        continue;
+                    work.setCharAt(2, c);
+                    e.setText(work.toString());
+                    boolean saw2 = false;
+                    for (int l = e.first(); l != BreakIterator.DONE; l = e.next())
+                        if (l == 2)
+                            saw2 = true;
+                    if (!saw2) {
+                        errln("Didn't get break between U+" + Integer.toHexString((int)
+                                    (work.charAt(1))) + " and U+" + Integer.toHexString(
+                                    (int)(work.charAt(2))));
+                        errorCount++;
+                        if (errorCount >= 75)
+                            return;
+                    }
+                }
+            }
+        }
+        */
+    }
+
+    public void TestCharacterInvariants()
+    {
+        BreakIterator e = BreakIterator.getCharacterInstance();
+        doBreakInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8"
+            + "\u11a9\u11aa");
+        doOtherInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8"
+            + "\u11a9\u11aa");
+    }
+
+    public void TestEmptyString()
+    {
+        String text = "";
+        Vector<String> x = new Vector<String>();
+        x.addElement(text);
+
+        generalIteratorTest(lineBreak, x);
+    }
+
+    public void TestGetAvailableLocales()
+    {
+        Locale[] locList = BreakIterator.getAvailableLocales();
+
+        if (locList.length == 0)
+            errln("getAvailableLocales() returned an empty list!");
+        // I have no idea how to test this function...
+    }
+
+
+    /**
+     * Bug 4095322
+     */
+    public void TestJapaneseLineBreak()
+    {
+        StringBuffer testString = new StringBuffer("\u4e00x\u4e8c");
+        // Breaking on <Kanji>$<Kanji> is inconsistent
+
+        /* Characters in precedingChars and followingChars have been updated
+         * from Unicode 2.0.14-based to 3.0.0-based when 4638433 was fixed.
+         * In concrete terms,
+         *   0x301F : Its category was changed from Ps to Pe since Unicode 2.1.
+         *   0x169B & 0x169C : added since Unicode 3.0.0.
+         */
+        String precedingChars =
+            /* Puctuation, Open */
+          "([{\u201a\u201e\u2045\u207d\u208d\u2329\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff62\u169b"
+            /* Punctuation, Initial quote */
+          + "\u00ab\u2018\u201b\u201c\u201f\u2039"
+            /* Symbol, Currency */
+          + "\u00a5\u00a3\u00a4\u20a0";
+
+        String followingChars =
+            /* Puctuation, Close */
+          ")]}\u2046\u207e\u208e\u232a\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e\u301f\ufd3e\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff63\u169c"
+            /* Punctuation, Final quote */
+          + "\u00bb\u2019\u201d\u203a"
+            /* Punctuation, Other */
+          + "!%,.:;\u3001\u3002\u2030\u2031\u2032\u2033\u2034"
+            /* Punctuation, Dash */
+          + "\u2103\u2109"
+            /* Symbol, Currency */
+          + "\u00a2"
+            /* Letter, Modifier */
+          + "\u3005\u309d\u309e"
+            /* Letter, Other */
+          + "\u3063\u3083\u3085\u3087\u30c3\u30e3\u30e5\u30e7\u30fc\u30fd\u30fe"
+           /* Mark, Non-Spacing */
+          + "\u0300\u0301\u0302"
+            /* Symbol, Modifier */
+          + "\u309b\u309c"
+            /* Symbol, Other */
+          + "\u00b0";
+
+        BreakIterator iter = BreakIterator.getLineInstance(Locale.JAPAN);
+
+        for (int i = 0; i < precedingChars.length(); i++) {
+            testString.setCharAt(1, precedingChars.charAt(i));
+            iter.setText(testString.toString());
+            int j = iter.first();
+            if (j != 0) {
+                errln("ja line break failure: failed to start at 0 and bounced at " + j);
+            }
+            j = iter.next();
+            if (j != 1) {
+                errln("ja line break failure: failed to stop before '"
+                        + precedingChars.charAt(i) + "' (\\u"
+                        + Integer.toString(precedingChars.charAt(i), 16)
+                        + ") at 1 and bounded at " + j);
+            }
+            j = iter.next();
+            if (j != 3) {
+                errln("ja line break failure: failed to skip position after '"
+                        + precedingChars.charAt(i) + "' (\\u"
+                        + Integer.toString(precedingChars.charAt(i), 16)
+                        + ") at 3 and bounded at " + j);
+            }
+        }
+
+        for (int i = 0; i < followingChars.length(); i++) {
+            testString.setCharAt(1, followingChars.charAt(i));
+            iter.setText(testString.toString());
+            int j = iter.first();
+            if (j != 0) {
+                errln("ja line break failure: failed to start at 0 and bounded at " + j);
+            }
+            j = iter.next();
+            if (j != 2) {
+                errln("ja line break failure: failed to skip position before '"
+                        + followingChars.charAt(i) + "' (\\u"
+                        + Integer.toString(followingChars.charAt(i), 16)
+                        + ") at 2 and bounded at " + j);
+            }
+            j = iter.next();
+            if (j != 3) {
+                errln("ja line break failure: failed to stop after '"
+                        + followingChars.charAt(i) + "' (\\u"
+                        + Integer.toString(followingChars.charAt(i), 16)
+                        + ") at 3 and bounded at " + j);
+            }
+        }
+    }
+
+    /**
+     * Bug 4638433
+     */
+    public void TestLineBreakBasedOnUnicode3_0_0()
+    {
+        BreakIterator iter;
+        int i;
+
+        /* Latin Extend-B characters
+         * 0x0218-0x0233 which have been added since Unicode 3.0.0.
+         */
+        iter = BreakIterator.getWordInstance(Locale.US);
+        iter.setText("\u0216\u0217\u0218\u0219\u021A");
+        i = iter.first();
+        i = iter.next();
+        if (i != 5) {
+            errln("Word break failure: failed to stop at 5 and bounded at " + i);
+        }
+
+
+        iter = BreakIterator.getLineInstance(Locale.US);
+
+        /* <Three(Nd)><Two(Nd)><Low Double Prime Quotation Mark(Pe)><One(Nd)>
+         * \u301f has changed its category from Ps to Pe since Unicode 2.1.
+         */
+        iter.setText("32\u301f1");
+        i = iter.first();
+        i = iter.next();
+        if (i != 3) {
+            errln("Line break failure: failed to skip before \\u301F(Pe) at 3 and bounded at " + i);
+        }
+
+        /* Mongolian <Letter A(Lo)><Todo Soft Hyphen(Pd)><Letter E(Lo)>
+         * which have been added since Unicode 3.0.0.
+         */
+        iter.setText("\u1820\u1806\u1821");
+        i = iter.first();
+        i = iter.next();
+        if (i != 2) {
+            errln("Mongolian line break failure: failed to skip position before \\u1806(Pd) at 2 and bounded at " + i);
+        }
+
+        /* Khmer <ZERO(Nd)><Currency Symbol(Sc)><ONE(Nd)> which have
+         * been added since Unicode 3.0.0.
+         */
+        iter.setText("\u17E0\u17DB\u17E1");
+        i = iter.first();
+        i = iter.next();
+        if (i != 1) {
+            errln("Khmer line break failure: failed to stop before \\u17DB(Sc) at 1 and bounded at " + i);
+        }
+        i = iter.next();
+        if (i != 3) {
+            errln("Khmer line break failure: failed to skip position after \\u17DB(Sc) at 3 and bounded at " + i);
+        }
+
+        /* Ogham <Letter UR(Lo)><Space Mark(Zs)><Letter OR(Lo)> which have
+         * been added since Unicode 3.0.0.
+         */
+        iter.setText("\u1692\u1680\u1696");
+        i = iter.first();
+        i = iter.next();
+        if (i != 2) {
+            errln("Ogham line break failure: failed to skip postion before \\u1680(Zs) at 2 and bounded at " + i);
+        }
+
+
+        // Confirm changes in BreakIteratorRules_th.java have been reflected.
+        iter = BreakIterator.getLineInstance(new Locale("th", ""));
+
+        /* Thai <Seven(Nd)>
+         *      <Left Double Quotation Mark(Pi)>
+         *      <Five(Nd)>
+         *      <Right Double Quotation Mark(Pf)>
+         *      <Three(Nd)>
+         */
+        iter.setText("\u0E57\u201C\u0E55\u201D\u0E53");
+        i = iter.first();
+        i = iter.next();
+        if (i != 1) {
+            errln("Thai line break failure: failed to stop before \\u201C(Pi) at 1 and bounded at " + i);
+        }
+        i = iter.next();
+        if (i != 4) {
+            errln("Thai line break failure: failed to stop after \\u201D(Pf) at 4 and bounded at " + i);
+        }
+    }
+
+    /**
+     * Bug 4068137
+     */
+    public void TestEndBehavior()
+    {
+        String testString = "boo.";
+        BreakIterator wb = BreakIterator.getWordInstance();
+        wb.setText(testString);
+
+        if (wb.first() != 0)
+            errln("Didn't get break at beginning of string.");
+        if (wb.next() != 3)
+            errln("Didn't get break before period in \"boo.\"");
+        if (wb.current() != 4 && wb.next() != 4)
+            errln("Didn't get break at end of string.");
+    }
+
+    // [serialization test has been removed pursuant to bug #4152965]
+
+    /**
+     * Bug 4450804
+     */
+    public void TestLineBreakContractions() {
+        Vector<String> expected = new Vector<String>();
+
+        expected.add("These ");
+        expected.add("are ");
+        expected.add("'foobles'. ");
+        expected.add("Don't ");
+        expected.add("you ");
+        expected.add("like ");
+        expected.add("them?");
+        generalIteratorTest(lineBreak, expected);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/Bug4533872.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,261 @@
+/*
+ * 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
+ * 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 4533872 4640853
+ * @library /java/text/testlib
+ * @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support
+ */
+
+import java.text.BreakIterator;
+import java.util.Locale;
+
+public class Bug4533872 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new Bug4533872().run(args);
+    }
+
+    static final String[] given = {
+      /* Lu Nd    Lu     Ll    */
+        "XYZ12345 ABCDE  abcde",
+      /* Nd Lo          Nd  Lu Po    Lu   Ll    */
+        "123\uD800\uDC00345 ABC\uFF61XYZ  abc",
+      /* Nd Lo          Nd  Lu Po          Lu   Ll    */
+        "123\uD800\uDC00345 ABC\uD800\uDD00XYZ  abc",
+      /* Lu Ll Cs    Ll Cs    Lu Lo          Lu  */
+        "ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ",
+    };
+
+    // Golden data for TestNext(), TestBoundar() and TestPrintEach*ward()
+    static final String[][] expected = {
+        {"XYZ12345", " ", "ABCDE", "  ", "abcde"},
+        {"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", "  ", "abc"},
+        {"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", "  ", "abc"},
+        {"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"},
+    };
+
+    BreakIterator iter;
+    int start, end, current;
+
+    /*
+     * Test for next(int n)
+     */
+    void TestNext() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+            start = iter.first();
+            int j = expected[i].length - 1;
+            start = iter.next(j);
+            end = iter.next();
+
+            if (!expected[i][j].equals(given[i].substring(start, end))) {
+                errln("Word break failure: printEachForward() expected:<" +
+                      expected[i][j] + ">, got:<" +
+                      given[i].substring(start, end) +
+                      "> start=" + start + "  end=" + end);
+            }
+        }
+    }
+
+    /*
+     * Test for isBoundary(int n)
+     */
+    void TestIsBoundary() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+
+            start = iter.first();
+            end = iter.next();
+
+            while (end < given[i].length()) {
+                if (!iter.isBoundary(end)) {
+                    errln("Word break failure: isBoundary() This should be a boundary. Index=" +
+                          end + " for " + given[i]);
+                }
+                end = iter.next();
+            }
+        }
+    }
+
+
+    /*
+     * The followig test cases were made based on examples in BreakIterator's
+     * API Doc.
+     */
+
+    /*
+     * Test mainly for next() and current()
+     */
+    void TestPrintEachForward() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+            start = iter.first();
+
+            // Check current()'s return value - should be same as first()'s.
+            current = iter.current();
+            if (start != current) {
+                errln("Word break failure: printEachForward() Unexpected current value: current()=" +
+                      current + ", expected(=first())=" + start);
+            }
+
+            int j = 0;
+            for (end = iter.next();
+                 end != BreakIterator.DONE;
+                 start = end, end = iter.next(), j++) {
+
+                // Check current()'s return value - should be same as next()'s.
+                current = iter.current();
+                if (end != current) {
+                    errln("Word break failure: printEachForward() Unexpected current value: current()=" +
+                          current + ", expected(=next())=" + end);
+                }
+
+                if (!expected[i][j].equals(given[i].substring(start, end))) {
+                    errln("Word break failure: printEachForward() expected:<" +
+                          expected[i][j] + ">, got:<" +
+                          given[i].substring(start, end) +
+                          "> start=" + start + "  end=" + end);
+                }
+            }
+        }
+    }
+
+    /*
+     * Test mainly for previous() and current()
+     */
+    void TestPrintEachBackward() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+            end = iter.last();
+
+            // Check current()'s return value - should be same as last()'s.
+            current = iter.current();
+            if (end != current) {
+                errln("Word break failure: printEachBackward() Unexpected current value: current()=" +
+                      current + ", expected(=last())=" + end);
+            }
+
+            int j;
+            for (start = iter.previous(), j = expected[i].length-1;
+                 start != BreakIterator.DONE;
+                 end = start, start = iter.previous(), j--) {
+
+                // Check current()'s return value - should be same as previous()'s.
+                current = iter.current();
+                if (start != current) {
+                    errln("Word break failure: printEachBackward() Unexpected current value: current()=" +
+                          current + ", expected(=previous())=" + start);
+                }
+
+                if (!expected[i][j].equals(given[i].substring(start, end))) {
+                    errln("Word break failure: printEachBackward() expected:<" +
+                          expected[i][j] + ">, got:<" +
+                          given[i].substring(start, end) +
+                          "> start=" + start + "  end=" + end);
+                }
+            }
+        }
+    }
+
+    /*
+     * Test mainly for following() and previous()
+     */
+    void TestPrintAt_1() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        int[][] index = {
+            {2, 8, 10, 15, 17},
+            {1, 8, 10, 12, 15, 17, 20},
+            {3, 8, 10, 13, 16, 18, 20},
+            {4, 6,  9, 10, 16},
+        };
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+            for (int j = index[i].length-1; j >= 0; j--) {
+                end = iter.following(index[i][j]);
+                start = iter.previous();
+
+                if (!expected[i][j].equals(given[i].substring(start, end))) {
+                    errln("Word break failure: printAt_1() expected:<" +
+                          expected[i][j] + ">, got:<" +
+                          given[i].substring(start, end) +
+                          "> start=" + start + "  end=" + end);
+                }
+            }
+        }
+    }
+
+    /*
+     * Test mainly for preceding() and next()
+     */
+    void TestPrintAt_2() {
+        iter = BreakIterator.getWordInstance(Locale.US);
+
+        int[][] index = {
+            {2, 9, 10, 15, 17},
+            {1, 9, 10, 13, 16, 18, 20},
+            {4, 9, 10, 13, 16, 18, 20},
+            {6, 7, 10, 11, 15},
+        };
+
+        for (int i = 0; i < given.length; i++) {
+            iter.setText(given[i]);
+
+            // Check preceding(0)'s return value - should equals BreakIterator.DONE.
+            if (iter.preceding(0) != BreakIterator.DONE) {
+                 errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" +
+                       iter.preceding(0));
+            }
+
+            for (int j = 0; j < index[i].length; j++) {
+                start = iter.preceding(index[i][j]);
+                end = iter.next();
+
+                if (!expected[i][j].equals(given[i].substring(start, end))) {
+                    errln("Word break failure: printAt_2() expected:<" +
+                          expected[i][j] + ">, got:<" +
+                          given[i].substring(start, end) +
+                          "> start=" + start + "  end=" + end);
+                }
+            }
+
+            // Check next()'s return value - should equals BreakIterator.DONE.
+            end = iter.last();
+            start = iter.next();
+            if (start != BreakIterator.DONE) {
+                 errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/Bug4740757.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 4740757
+ * @summary Confirm line-breaking behavior of Hangul
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug4740757 {
+
+    private static boolean err = false;
+
+    public static void main(String[] args) {
+        Locale defaultLocale = Locale.getDefault();
+        if (defaultLocale.getLanguage().equals("th")) {
+            Locale.setDefault(Locale.KOREA);
+            test4740757();
+            Locale.setDefault(defaultLocale);
+        } else {
+            test4740757();
+        }
+
+        if (err) {
+            throw new RuntimeException("Incorrect Line-breaking");
+        }
+    }
+
+    private static void test4740757() {
+        String source = "\uc548\ub155\ud558\uc138\uc694? \uc88b\uc740 \uc544\uce68, \uc5ec\ubcf4\uc138\uc694! \uc548\ub155. End.";
+        String expected = "\uc548/\ub155/\ud558/\uc138/\uc694? /\uc88b/\uc740 /\uc544/\uce68, /\uc5ec/\ubcf4/\uc138/\uc694! /\uc548/\ub155. /End./";
+
+        BreakIterator bi = BreakIterator.getLineInstance(Locale.KOREAN);
+        bi.setText(source);
+        int start = bi.first();
+        int end = bi.next();
+        StringBuilder sb =  new StringBuilder();
+
+        for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
+            sb.append(source.substring(start,end));
+            sb.append('/');
+        }
+
+        if (!expected.equals(sb.toString())) {
+            System.err.println("Failed: Hangul line-breaking failed." +
+                "\n\tExpected: " + expected +
+                "\n\tGot:      " + sb +
+                "\nin " + Locale.getDefault() + " locale.");
+            err = true;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/Bug4912404.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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 4912404
+ * @summary Confirm that BreakIterator.equals(null) return false.
+ */
+
+import java.text.BreakIterator;
+
+public class Bug4912404 {
+
+    public static void main(String[] args) {
+        BreakIterator b = BreakIterator.getWordInstance();
+        b.setText("abc");
+        if (b.equals(null)) {
+            throw new RuntimeException("BreakIterator.equals(null) should return false.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/Bug4932583.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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
+ * 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
+ * @run main/timeout=60 Bug4932583
+ * @bug 4932583
+ * @summary Confirm that BreakIterator doesn't get caught in an infinite loop.
+ */
+
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class Bug4932583 {
+    public static void main(String[] args) {
+        BreakIterator iterator = BreakIterator.getCharacterInstance();
+        iterator.setText("\uDB40\uDFFF");
+        int boundary = iterator.next();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/Bug6513074.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 6513074
+ * @summary Confirm that JIS X 0213 characters are processed in line-breaking properly.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug6513074 {
+
+    private static final String[][] source = {
+        {"\ufa30\ufa31 \ufa69\ufa6a",
+         "JIS X 0213 compatibility additions (\\uFA30-\\uFA6A)"},
+    };
+
+    private static final String[] expected_line = {
+        "\ufa30/\ufa31 /\ufa69/\ufa6a/",
+    };
+
+    private static final String[] expected_word = {
+        "\ufa30\ufa31/ /\ufa69\ufa6a/",
+    };
+
+    private static final String[] expected_char = {
+        "\ufa30/\ufa31/ /\ufa69/\ufa6a/",
+    };
+
+
+    private static boolean err = false;
+
+    public static void main(String[] args) {
+        Locale defaultLocale = Locale.getDefault();
+        if (defaultLocale.getLanguage().equals("th")) {
+            Locale.setDefault(Locale.JAPAN);
+            test6513074();
+            Locale.setDefault(defaultLocale);
+        } else {
+            test6513074();
+        }
+
+        if (err) {
+            throw new RuntimeException("Failed: Incorrect Text-breaking.");
+        }
+    }
+
+
+    private static void test6513074() {
+        BreakIterator bi = BreakIterator.getLineInstance(Locale.JAPAN);
+        for (int i = 0; i < source.length; i++) {
+            testBreakIterator(bi, "Line", source[i][0], expected_line[i], source[i][1]);
+        }
+
+        bi = BreakIterator.getWordInstance(Locale.JAPAN);
+        for (int i = 0; i < source.length; i++) {
+            testBreakIterator(bi, "Word", source[i][0], expected_word[i], source[i][1]);
+        }
+
+        bi = BreakIterator.getCharacterInstance(Locale.JAPAN);
+        for (int i = 0; i < source.length; i++) {
+            testBreakIterator(bi, "Character", source[i][0], expected_char[i], source[i][1]);
+        }
+    }
+
+    private static void testBreakIterator(BreakIterator bi,
+                                          String type,
+                                          String source,
+                                          String expected,
+                                          String description) {
+        bi.setText(source);
+        int start = bi.first();
+        int end = bi.next();
+        StringBuilder sb =  new StringBuilder();
+
+        for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
+            sb.append(source.substring(start,end));
+            sb.append('/');
+        }
+
+        if (!expected.equals(sb.toString())) {
+            System.err.println("Failed: Incorrect " + type + "-breaking for " +
+                description +
+                "\n\tExpected: " + toString(expected) +
+                "\n\tGot:      " + toString(sb.toString()));
+            err = true;
+        }
+    }
+
+    private static String toString(String s) {
+        StringBuilder sb = new StringBuilder();
+
+        for (int i = 0; i < s.length(); i++) {
+            sb.append("  0x" + Integer.toHexString(s.charAt(i)));
+        }
+
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/NewVSOld_th_TH.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+    @summary test Comparison of New Collators against Old Collators in the en_US locale
+*/
+
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Locale;
+import java.text.BreakIterator;
+import java.lang.Math;
+
+public class NewVSOld_th_TH {
+    public static void main(String args[]) throws FileNotFoundException,
+                                                  UnsupportedEncodingException,
+                                                  IOException {
+        final String ENCODING = "UTF-8";
+        final Locale THAI_LOCALE = new Locale("th", "TH");
+
+        String rawFileName = "test_th_TH.txt";
+        String oldFileName = "broken_th_TH.txt";
+        StringBuilder rawText = new StringBuilder();
+        StringBuilder oldText = new StringBuilder();
+        StringBuilder cookedText = new StringBuilder();
+
+        File f;
+        f = new File(System.getProperty("test.src", "."), rawFileName);
+
+        try (InputStreamReader rawReader =
+                 new InputStreamReader(new FileInputStream(f), ENCODING)) {
+            int c;
+            while ((c = rawReader.read()) != -1) {
+                rawText.append((char) c);
+            }
+        }
+
+        f = new File(System.getProperty("test.src", "."), oldFileName);
+        try (InputStreamReader oldReader =
+                 new InputStreamReader(new FileInputStream(f), ENCODING)) {
+            int c;
+            while ((c = oldReader.read()) != -1) {
+                oldText.append((char) c);
+            }
+        }
+
+        BreakIterator breakIterator = BreakIterator.getWordInstance(THAI_LOCALE);
+        breakIterator.setText(rawText.toString());
+
+        int start = breakIterator.first();
+        for (int end = breakIterator.next();
+             end != BreakIterator.DONE;
+             start = end, end = breakIterator.next()) {
+             cookedText.append(rawText.substring(start, end));
+             cookedText.append("\n");
+        }
+
+        String cooked = cookedText.toString();
+        String old = oldText.toString();
+        if (cooked.compareTo(old) != 0) {
+            throw new RuntimeException("Text not broken the same as with the old BreakIterators");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/broken_th_TH.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,13 @@
+การ
+เก็บ
+ภาษีประเทศ
+ไทยและ
+ประเทศ
+เดนมาร์ค
+อนุสัญญา
+ระหว่าง
+รัฐบาล
+แห่ง
+ประเทศ
+ไทย
+กับ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/BreakIterator/test_th_TH.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1 @@
+การเก็บภาษีประเทศไทยและประเทศเดนมาร์คอนุสัญญาระหว่างรัฐบาลแห่งประเทศไทยกับ
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/CharacterIterator/CharacterIteratorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test for Character Iterator
+ */
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * 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.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+
+import java.text.*;
+
+public class CharacterIteratorTest extends IntlTest {
+    public static void main(String[] args) throws Exception {
+        new CharacterIteratorTest().run(args);
+    }
+
+    public CharacterIteratorTest() {
+    }
+
+    public void TestConstructionAndEquality() {
+        String  testText = "Now is the time for all good men to come to the aid of their country.";
+        String  testText2 = "Don't bother using this string.";
+
+        CharacterIterator test1 = new StringCharacterIterator(testText);
+        CharacterIterator test2 = new StringCharacterIterator(testText, 5);
+        CharacterIterator test3 = new StringCharacterIterator(testText, 2, 20, 5);
+        CharacterIterator test4 = new StringCharacterIterator(testText2);
+        CharacterIterator test5 = (CharacterIterator)test1.clone();
+
+        if (test1.equals(test2) || test1.equals(test3) || test1.equals(test4))
+            errln("Construation or equals() failed: Two unequal iterators tested equal");
+
+        if (!test1.equals(test5))
+            errln("clone() or equals() failed: Two clones tested unequal");
+
+        if (test1.hashCode() == test2.hashCode() || test1.hashCode() == test3.hashCode()
+                        || test1.hashCode() == test4.hashCode())
+            errln("hash() failed:  different objects have same hash code");
+
+        if (test1.hashCode() != test5.hashCode())
+            errln("hash() failed:  identical objects have different hash codes");
+
+        test1.setIndex(5);
+        if (!test1.equals(test2) || test1.equals(test5))
+            errln("setIndex() failed");
+    }
+
+    public void TestIteration() {
+        String text = "Now is the time for all good men to come to the aid of their country.";
+
+        CharacterIterator   iter = new StringCharacterIterator(text, 5);
+
+        if (iter.current() != text.charAt(5))
+            errln("Iterator didn't start out in the right place.");
+
+        char c = iter.first();
+        int     i = 0;
+
+        if (iter.getBeginIndex() != 0 || iter.getEndIndex() != text.length())
+            errln("getBeginIndex() or getEndIndex() failed");
+
+        logln("Testing forward iteration...");
+        do {
+            if (c == CharacterIterator.DONE && i != text.length())
+                errln("Iterator reached end prematurely");
+            else if (c != text.charAt(i))
+                errln("Character mismatch at position " + i + ", iterator has " + c +
+                                    ", string has " + text.charAt(c));
+
+            if (iter.current() != c)
+                errln("current() isn't working right");
+            if (iter.getIndex() != i)
+                errln("getIndex() isn't working right");
+
+            if (c != CharacterIterator.DONE) {
+                c = iter.next();
+                i++;
+            }
+        } while (c != CharacterIterator.DONE);
+
+        c = iter.last();
+        i = text.length() - 1;
+
+        logln("Testing backward iteration...");
+        do {
+            if (c == CharacterIterator.DONE && i >= 0)
+                errln("Iterator reached end prematurely");
+            else if (c != text.charAt(i))
+                errln("Character mismatch at position " + i + ", iterator has " + c +
+                                    ", string has " + text.charAt(c));
+
+            if (iter.current() != c)
+                errln("current() isn't working right");
+            if (iter.getIndex() != i)
+                errln("getIndex() isn't working right");
+
+            if (c != CharacterIterator.DONE) {
+                c = iter.previous();
+                i--;
+            }
+        } while (c != CharacterIterator.DONE);
+
+        iter = new StringCharacterIterator(text, 5, 15, 10);
+        if (iter.getBeginIndex() != 5 || iter.getEndIndex() != 15)
+            errln("creation of a restricted-range iterator failed");
+
+        if (iter.getIndex() != 10 || iter.current() != text.charAt(10))
+            errln("starting the iterator in the middle didn't work");
+
+        c = iter.first();
+        i = 5;
+
+        logln("Testing forward iteration over a range...");
+        do {
+            if (c == CharacterIterator.DONE && i != 15)
+                errln("Iterator reached end prematurely");
+            else if (c != text.charAt(i))
+                errln("Character mismatch at position " + i + ", iterator has " + c +
+                                    ", string has " + text.charAt(c));
+
+            if (iter.current() != c)
+                errln("current() isn't working right");
+            if (iter.getIndex() != i)
+                errln("getIndex() isn't working right");
+
+            if (c != CharacterIterator.DONE) {
+                c = iter.next();
+                i++;
+            }
+        } while (c != CharacterIterator.DONE);
+
+        c = iter.last();
+        i = 14;
+
+        logln("Testing backward iteration over a range...");
+        do {
+            if (c == CharacterIterator.DONE && i >= 5)
+                errln("Iterator reached end prematurely");
+            else if (c != text.charAt(i))
+                errln("Character mismatch at position " + i + ", iterator has " + c +
+                                    ", string has " + text.charAt(c));
+
+            if (iter.current() != c)
+                errln("current() isn't working right");
+            if (iter.getIndex() != i)
+                errln("getIndex() isn't working right");
+
+            if (c != CharacterIterator.DONE) {
+                c = iter.previous();
+                i--;
+            }
+        } while (c != CharacterIterator.DONE);
+    }
+
+    /**
+     * @bug 4082050 4078261 4078255
+     */
+    public void TestPathologicalCases() {
+        String text = "This is only a test.";
+
+/*
+This test is commented out until API-change approval for bug #4082050 goes through.
+        // test for bug #4082050 (don't get an error if begin == end, even though all
+        // operations on the iterator will cause exceptions)
+        // [I actually fixed this so that you CAN create an iterator with begin == end,
+        // but all operations on it return DONE.]
+        CharacterIterator iter = new StringCharacterIterator(text, 5, 5, 5);
+        if (iter.first() != CharacterIterator.DONE
+            || iter.next() != CharacterIterator.DONE
+            || iter.last() != CharacterIterator.DONE
+            || iter.previous() != CharacterIterator.DONE
+            || iter.current() != CharacterIterator.DONE
+            || iter.getIndex() != 5)
+            errln("Got something other than DONE when performing operations on an empty StringCharacterIterator");
+*/
+CharacterIterator iter = null;
+
+        // if we try to construct a StringCharacterIterator with an endIndex that's off
+        // the end of the String under iterator, we're supposed to get an
+        // IllegalArgumentException
+        boolean gotException = false;
+        try {
+            iter = new StringCharacterIterator(text, 5, 100, 5);
+        }
+        catch (IllegalArgumentException e) {
+            gotException = true;
+        }
+        if (!gotException)
+            errln("StringCharacterIterator didn't throw an exception when given an invalid substring range.");
+
+        // test for bug #4078255 (getting wrong value from next() when we're at the end
+        // of the string)
+        iter = new StringCharacterIterator(text);
+        int expectedIndex = iter.getEndIndex();
+        int actualIndex;
+
+        iter.last();
+        actualIndex = iter.getIndex();
+        if (actualIndex != expectedIndex - 1)
+            errln("last() failed: expected " + (expectedIndex - 1) + ", got " + actualIndex);
+
+        iter.next();
+        actualIndex = iter.getIndex();
+        if (actualIndex != expectedIndex)
+            errln("next() after last() failed: expected " + expectedIndex + ", got " + actualIndex);
+
+        iter.next();
+        actualIndex = iter.getIndex();
+        if (actualIndex != expectedIndex)
+            errln("second next() after last() failed: expected " + expectedIndex + ", got " + actualIndex);
+    }
+
+    /*
+     * @bug 4123771 4051073
+     * #4123771 is actually a duplicate of bug #4051073, which was fixed some time ago, but
+     * no one ever added a regression test for it.
+     */
+    public void TestBug4123771() {
+        String text = "Some string for testing";
+        StringCharacterIterator iter = new StringCharacterIterator(text);
+        int index = iter.getEndIndex();
+        try {
+            char c = iter.setIndex(index);
+        }
+        catch (Exception e) {
+            System.out.println("method setIndex(int position) throws unexpected exception " + e);
+            System.out.println(" position: " + index);
+            System.out.println(" getEndIndex(): " + iter.getEndIndex());
+            System.out.println(" text.length(): " + text.length());
+            errln(""); // re-throw the exception through our test framework
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/APITest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Collation API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+import java.text.CollationElementIterator;
+
+public class APITest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new APITest().run(args);
+    }
+
+    final void doAssert(boolean condition, String message)
+    {
+        if (!condition) {
+            err("ERROR: ");
+            errln(message);
+        }
+    }
+
+    public final void TestProperty( )
+    {
+        Collator col = null;
+        try {
+            col = Collator.getInstance(Locale.ROOT);
+            logln("The property tests begin : ");
+            logln("Test ctors : ");
+            doAssert(col.compare("ab", "abc") < 0, "ab < abc comparison failed");
+            doAssert(col.compare("ab", "AB") < 0, "ab < AB comparison failed");
+            doAssert(col.compare("black-bird", "blackbird") > 0, "black-bird > blackbird comparison failed");
+            doAssert(col.compare("black bird", "black-bird") < 0, "black bird < black-bird comparison failed");
+            doAssert(col.compare("Hello", "hello") > 0, "Hello > hello comparison failed");
+
+            logln("Test ctors ends.");
+            logln("testing Collator.getStrength() method ...");
+            doAssert(col.getStrength() == Collator.TERTIARY, "collation object has the wrong strength");
+            doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+
+            logln("testing Collator.setStrength() method ...");
+            col.setStrength(Collator.SECONDARY);
+            doAssert(col.getStrength() != Collator.TERTIARY, "collation object's strength is secondary difference");
+            doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+            doAssert(col.getStrength() == Collator.SECONDARY, "collation object has the wrong strength");
+
+            logln("testing Collator.setDecomposition() method ...");
+            col.setDecomposition(Collator.NO_DECOMPOSITION);
+            doAssert(col.getDecomposition() != Collator.FULL_DECOMPOSITION, "collation object's strength is secondary difference");
+            doAssert(col.getDecomposition() != Collator.CANONICAL_DECOMPOSITION, "collation object's strength is primary difference");
+            doAssert(col.getDecomposition() == Collator.NO_DECOMPOSITION, "collation object has the wrong strength");
+        } catch (Exception foo) {
+            errln("Error : " + foo.getMessage());
+            errln("Default Collator creation failed.");
+        }
+        logln("Default collation property test ended.");
+        logln("Collator.getRules() testing ...");
+        doAssert(((RuleBasedCollator)col).getRules().length() != 0, "getRules() result incorrect" );
+        logln("getRules tests end.");
+        try {
+            col = Collator.getInstance(Locale.FRENCH);
+            col.setStrength(Collator.PRIMARY);
+            logln("testing Collator.getStrength() method again ...");
+            doAssert(col.getStrength() != Collator.TERTIARY, "collation object has the wrong strength");
+            doAssert(col.getStrength() == Collator.PRIMARY, "collation object's strength is not primary difference");
+
+            logln("testing French Collator.setStrength() method ...");
+            col.setStrength(Collator.TERTIARY);
+            doAssert(col.getStrength() == Collator.TERTIARY, "collation object's strength is not tertiary difference");
+            doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+            doAssert(col.getStrength() != Collator.SECONDARY, "collation object's strength is secondary difference");
+
+        } catch (Exception bar) {
+            errln("Error :  " + bar.getMessage());
+            errln("Creating French collation failed.");
+        }
+
+        logln("Create junk collation: ");
+        Locale abcd = new Locale("ab", "CD", "");
+        Collator junk = null;
+        try {
+            junk = Collator.getInstance(abcd);
+        } catch (Exception err) {
+            errln("Error : " + err.getMessage());
+            errln("Junk collation creation failed, should at least return the collator for the base bundle.");
+        }
+        try {
+            col = Collator.getInstance(Locale.ROOT);
+            doAssert(col.equals(junk), "The base bundle's collation should be returned.");
+        } catch (Exception exc) {
+            errln("Error : " + exc.getMessage());
+            errln("Default collation comparison, caching not working.");
+        }
+
+        logln("Collator property test ended.");
+    }
+
+    public final void TestHashCode( )
+    {
+        logln("hashCode tests begin.");
+        Collator col1 = null;
+        try {
+            col1 = Collator.getInstance(Locale.ROOT);
+        } catch (Exception foo) {
+            errln("Error : " + foo.getMessage());
+            errln("Default collation creation failed.");
+        }
+        Collator col2 = null;
+        Locale dk = new Locale("da", "DK", "");
+        try {
+            col2 = Collator.getInstance(dk);
+        } catch (Exception bar) {
+            errln("Error : " + bar.getMessage());
+            errln("Danish collation creation failed.");
+            return;
+        }
+        Collator col3 = null;
+        try {
+            col3 = Collator.getInstance(Locale.ROOT);
+        } catch (Exception err) {
+            errln("Error : " + err.getMessage());
+            errln("2nd default collation creation failed.");
+        }
+        logln("Collator.hashCode() testing ...");
+
+        if (col1 != null) {
+            doAssert(col1.hashCode() != col2.hashCode(), "Hash test1 result incorrect");
+            if (col3 != null) {
+                doAssert(col1.hashCode() == col3.hashCode(), "Hash result not equal");
+            }
+        }
+
+        logln("hashCode tests end.");
+    }
+
+    //----------------------------------------------------------------------------
+    // ctor -- Tests the constructor methods
+    //
+    public final void TestCollationKey( )
+    {
+        logln("testing CollationKey begins...");
+        Collator col = null;
+        try {
+            col = Collator.getInstance(Locale.ROOT);
+        } catch (Exception foo) {
+            errln("Error : " + foo.getMessage());
+            errln("Default collation creation failed.");
+        }
+        if (col == null) {
+            return;
+        }
+
+        String test1 = "Abcda", test2 = "abcda";
+        logln("Use tertiary comparison level testing ....");
+        CollationKey sortk1 = col.getCollationKey(test1);
+        CollationKey sortk2 = col.getCollationKey(test2);
+        doAssert(sortk1.compareTo(sortk2) > 0,
+                    "Result should be \"Abcda\" >>> \"abcda\"");
+        CollationKey sortk3 = sortk2;
+        CollationKey sortkNew = sortk1;
+        doAssert(sortk1 != sortk2, "The sort keys should be different");
+        doAssert(sortk1.hashCode() != sortk2.hashCode(), "sort key hashCode() failed");
+        doAssert(sortk2.compareTo(sortk3) == 0, "The sort keys should be the same");
+        doAssert(sortk1 == sortkNew, "The sort keys assignment failed");
+        doAssert(sortk1.hashCode() == sortkNew.hashCode(), "sort key hashCode() failed");
+        doAssert(sortkNew != sortk3, "The sort keys should be different");
+        doAssert(sortk1.compareTo(sortk3) > 0, "Result should be \"Abcda\" >>> \"abcda\"");
+        doAssert(sortk2.compareTo(sortk3) == 0, "Result should be \"abcda\" == \"abcda\"");
+        long    cnt1, cnt2;
+        byte byteArray1[] = sortk1.toByteArray();
+        byte byteArray2[] = sortk2.toByteArray();
+        doAssert(byteArray1 != null && byteArray2 != null, "CollationKey.toByteArray failed.");
+        logln("testing sortkey ends...");
+    }
+    //----------------------------------------------------------------------------
+    // ctor -- Tests the constructor methods
+    //
+    public final void TestElemIter( )
+    {
+        logln("testing sortkey begins...");
+        Collator col = null;
+        try {
+            col = Collator.getInstance();
+        } catch (Exception foo) {
+            errln("Error : " + foo.getMessage());
+            errln("Default collation creation failed.");
+        }
+        RuleBasedCollator rbCol;
+        if (col instanceof RuleBasedCollator) {
+            rbCol = (RuleBasedCollator) col;
+        } else {
+            return;
+        }
+        String testString1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?";
+        String testString2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?";
+        logln("Constructors and comparison testing....");
+        CollationElementIterator iterator1 = rbCol.getCollationElementIterator(testString1);
+        CollationElementIterator iterator2 = rbCol.getCollationElementIterator(testString1);
+        CollationElementIterator iterator3 = rbCol.getCollationElementIterator(testString2);
+        int order1, order2, order3;
+        order1 = iterator1.next();
+        order2 = iterator2.next();
+        doAssert(order1 == order2, "The order result should be the same");
+
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.primaryOrder(order1)
+                     == CollationElementIterator.primaryOrder(order3),
+                 "The primary orders should be the same");
+        doAssert(CollationElementIterator.secondaryOrder(order1)
+                     == CollationElementIterator.secondaryOrder(order3),
+                 "The secondary orders should be the same");
+        doAssert(CollationElementIterator.tertiaryOrder(order1)
+                     == CollationElementIterator.tertiaryOrder(order3),
+                 "The tertiary orders should be the same");
+
+        order1 = iterator1.next();
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.primaryOrder(order1)
+                     == CollationElementIterator.primaryOrder(order3),
+                 "The primary orders should be identical");
+        doAssert(CollationElementIterator.tertiaryOrder(order1)
+                     != CollationElementIterator.tertiaryOrder(order3),
+                 "The tertiary orders should be different");
+
+        order1 = iterator1.next();
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.secondaryOrder(order1)
+                     != CollationElementIterator.secondaryOrder(order3),
+                 "The secondary orders should be different");
+        doAssert(order1 != CollationElementIterator.NULLORDER,
+                 "Unexpected end of iterator reached");
+
+        iterator1.reset();
+        iterator2.reset();
+        iterator3.reset();
+        order1 = iterator1.next();
+        order2 = iterator2.next();
+        doAssert(order1 == order2, "The order result should be the same");
+
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.primaryOrder(order1)
+                     == CollationElementIterator.primaryOrder(order3),
+                 "The orders should be the same");
+        doAssert(CollationElementIterator.secondaryOrder(order1)
+                     == CollationElementIterator.secondaryOrder(order3),
+                 "The orders should be the same");
+        doAssert(CollationElementIterator.tertiaryOrder(order1)
+                     == CollationElementIterator.tertiaryOrder(order3),
+                 "The orders should be the same");
+
+        order1 = iterator1.next();
+        order2 = iterator2.next();
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.primaryOrder(order1)
+                     == CollationElementIterator.primaryOrder(order3),
+                 "The primary orders should be identical");
+        doAssert(CollationElementIterator.tertiaryOrder(order1)
+                     != CollationElementIterator.tertiaryOrder(order3),
+                 "The tertiary orders should be different");
+
+        order1 = iterator1.next();
+        order3 = iterator3.next();
+        doAssert(CollationElementIterator.secondaryOrder(order1)
+                     != CollationElementIterator.secondaryOrder(order3),
+                 "The secondary orders should be different");
+        doAssert(order1 != CollationElementIterator.NULLORDER, "Unexpected end of iterator reached");
+        logln("testing CollationElementIterator ends...");
+    }
+
+    public final void TestGetAll()
+    {
+        Locale[] list = Collator.getAvailableLocales();
+        for (int i = 0; i < list.length; ++i) {
+            log("Locale name: ");
+            log(list[i].toString());
+            log(" , the display name is : ");
+            logln(list[i].getDisplayName());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/Bug6271411.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6271411
+ * @library /java/text/testlib
+ * @summary Confirm that three JCK testcases for CollationElementIterator pass.
+ */
+
+import java.text.*;
+
+/*
+ * Based on JCK-runtime-15/tests/api/java_text/CollationElementIterator/ColltnElmtIterTests.java.
+ */
+public class Bug6271411 extends IntlTest {
+
+    public static void main(String argv[]) throws Exception {
+        Bug6271411 test = new Bug6271411();
+        test.run(argv);
+    }
+
+    /*
+     * Rule for RuleBasedCollator
+     */
+    static final String rule = "< c, C < d; D";
+
+    /*
+     * Textdata
+     */
+    static final String[] values = {
+        "", "c", "cH522Yd", "Hi, high school", "abcchCHidD"
+    };
+
+
+    /*
+     * Confirm that setOffset() throws IllegalArgumentException
+     * (not IndexOutOfBoundsException) if the given offset is invalid.
+     * Use CollationElementIterator.setText(String).
+     */
+    public void Test_CollationElementIterator0007() throws Exception {
+        int[] offsets = {
+            Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000, -2, -1,
+            100, 101, // These two are customized for every test data later.
+            12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
+        };
+        boolean err = false;
+
+        RuleBasedCollator rbc = new RuleBasedCollator(rule);
+        CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+        for (int i = 0; i < values.length; i++) {
+            String source = values[i];
+            iterator.setText(source);
+
+            int len = source.length();
+            offsets[5] = len + 1;
+            offsets[6] = len + 2;
+
+            for (int j = 0; j < offsets.length; j++) {
+                try {
+                    iterator.setOffset(offsets[j]);
+                    System.out.println("IllegalArgumentException should be thrown for setOffset(" +
+                                       offsets[j] + ") for <" + source + ">.");
+                    err = true;
+                }
+                catch (IllegalArgumentException e) {
+                }
+            }
+        }
+
+        if (err) {
+            errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException.");
+        }
+    }
+
+    /*
+     * Confirm that setText() doesn't throw an exception and setOffset() throws
+     * IllegalArgumentException if the given offset is invalid.
+     * Use CollationElementIterator.setText(CharacterIterator).
+     */
+    public void Test_CollationElementIterator0010() throws Exception {
+        String prefix = "xyz abc";
+        String suffix = "1234567890";
+        int begin = prefix.length();
+        int[] offsets = {
+            Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000,
+            -2, -1, 0, 1, begin - 2, begin - 1, 9, 10, 11, 12, 13, 14,
+            15, 12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
+        };
+        boolean err = false;
+
+        RuleBasedCollator rbc = new RuleBasedCollator(rule);
+        CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+        for (int i = 0; i < values.length; i++) {
+            String str = prefix + values[i] + suffix;
+            int len = str.length();
+            int end = len - suffix.length();
+
+            CharacterIterator source =
+                new StringCharacterIterator(str, begin, end, begin);
+            iterator.setText(source);
+
+            offsets[9] = end + 1;
+            offsets[10] = end + 2;
+            offsets[11] = (end + len) / 2;
+            offsets[12] = len - 1;
+            offsets[13] = len;
+            offsets[14] = len + 1;
+            offsets[15] = len + 2;
+
+            for (int j = 0; j < offsets.length; j++) {
+                try {
+                    iterator.setOffset(offsets[j]);
+
+                    System.out.println("IllegalArgumentException should be thrown for setOffset(" +
+                                       offsets[j] + ") for <" + str + ">.");
+                    err = true;
+                }
+                catch (IllegalArgumentException e) {
+                }
+            }
+        }
+
+        if (err) {
+            errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException.");
+        }
+    }
+
+    /*
+     * Confirm that setText() doesn't throw an exception and setOffset() sets
+     * an offset as expected.
+     * Use CollationElementIterator.setText(CharacterIterator).
+     */
+    public void Test_CollationElementIterator0011() throws Exception {
+        String prefix = "xyz abc";
+        String suffix = "1234567890";
+        int begin = prefix.length();
+        int[] offsets = { begin, begin + 1, 2, 3, 4 };
+
+        RuleBasedCollator rbc = new RuleBasedCollator(rule);
+        CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+        for (int i = 0; i < values.length; i++) {
+            String str = prefix + values[i] + suffix;
+            int len = str.length();
+            int end = len - suffix.length();
+            CharacterIterator source =
+                new StringCharacterIterator(str, begin, end, begin);
+            iterator.setText(source);
+
+            offsets[2] = (end + len) / 2;
+            offsets[3] = len - 1;
+            offsets[4] = len;
+
+            for (int j = 0; j < offsets.length; j++) {
+                int offset = offsets[j];
+
+                if (offset < begin || offset > end) {
+                    break;
+                }
+
+                iterator.setOffset(offset);
+                int newOffset = iterator.getOffset();
+
+                if (newOffset != offset) {
+                    throw new RuntimeException("setOffset() didn't set a correct offset. Got: " +
+                    newOffset + " Expected: " + offset + " for <" + str + ">.");
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/CollationKeyTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4106263
+ * @summary Tests on the bug 4106263 - CollationKey became non-final extendable class.
+ *          The implementation of CollationKey is moved to the new private class,
+ *          RuleBasedCollationKey. This test basically tests on the two features:
+ *          1. Existing code using CollationKey works (backward compatiblility)
+ *          2. CollationKey can be extended by its subclass.
+ */
+
+
+public class CollationKeyTest {
+
+    public static void main(String[] args) {
+        CollationKeyTestImpl ck = new CollationKeyTestImpl("Testing the CollationKey");
+        ck.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/CollationKeyTestImpl.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ *
+ * A part of tests on the bug 4106263. CollationKey became non-final extendable class.
+ *          The implementation of CollationKey is moved to the new private class,
+ *          RuleBasedCollationKey. This test basically tests on the two features:
+ *          1. Existing code using CollationKey works (backward compatiblility)
+ *          2. CollationKey can be extended by its subclass.
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.CollationKey;
+import java.io.*;
+
+import java.text.*;
+
+
+public class CollationKeyTestImpl extends CollationKey {
+
+    private static String[] sourceData_ja = {
+        "\u3042\u3044\u3046\u3048\u3048",
+        "\u3041\u3043\u3045\u3047\u3049",
+        "\u3052\u3054\u3056\u3058\u3058",
+        "\u3051\u3053\u3055\u3057\u3059",
+        "\u3062\u3064\u3066\u3068\u3068",
+        "\u3061\u3063\u3065\u3067\u3069",
+        "\u3072\u3074\u3075\u3078\u3078",
+        "\u3071\u3073\u3075\u3077\u3079",
+        "\u3082\u3084\u3085\u3088\u3088",
+        "\u3081\u3083\u3085\u3087\u3089",
+        "\u30a2\u30a4\u30a6\u30a8\u30aa",
+        "\u30a1\u30a3\u30a5\u30a7\u30a9",
+        "\u30c2\u30c4\u30c6\u30c8\u30ca",
+        "\u30c1\u30c3\u30c5\u30c7\u30c9",
+        "\u30b2\u30b4\u30b6\u30b8\u30ba",
+        "\u30b1\u30b3\u30b5\u30b7\u30b9",
+        "\u30d2\u30d4\u30d6\u30d8\u30da",
+        "\u30d1\u30d3\u30d5\u30d7\u30d9",
+        "\u30e2\u30e4\u30e6\u30e8\u30ea",
+        "\u30e1\u30e3\u30e5\u30e7\u30e9"
+        };
+    private static final String[] targetData_ja = {
+        "\u3042\u3044\u3046\u3048\u3048",
+        "\u3041\u3043\u3045\u3047\u3049",
+        "\u30a2\u30a4\u30a6\u30a8\u30aa",
+        "\u30a1\u30a3\u30a5\u30a7\u30a9",
+        "\u3052\u3054\u3056\u3058\u3058",
+        "\u3051\u3053\u3055\u3057\u3059",
+        "\u30b1\u30b3\u30b5\u30b7\u30b9",
+        "\u30b2\u30b4\u30b6\u30b8\u30ba",
+        "\u3061\u3063\u3065\u3067\u3069",
+        "\u30c1\u30c3\u30c5\u30c7\u30c9",
+        "\u3062\u3064\u3066\u3068\u3068",
+        "\u30c2\u30c4\u30c6\u30c8\u30ca",
+        "\u3071\u3073\u3075\u3077\u3079",
+        "\u30d1\u30d3\u30d5\u30d7\u30d9",
+        "\u3072\u3074\u3075\u3078\u3078",
+        "\u30d2\u30d4\u30d6\u30d8\u30da",
+        "\u3081\u3083\u3085\u3087\u3089",
+        "\u30e1\u30e3\u30e5\u30e7\u30e9",
+        "\u3082\u3084\u3085\u3088\u3088",
+        "\u30e2\u30e4\u30e6\u30e8\u30ea"
+        };
+
+    public void run() {
+        /** debug: printout the test data
+        for (int i=0; i<sourceData_ja.length; i++){
+                System.out.println(i+": "+sourceData_ja[i]);
+        }
+        **/
+       /*
+        * 1. Test the backward compatibility
+        *    note: targetData_ja.length is equal to sourceData_ja.length
+        */
+        Collator myCollator = Collator.getInstance(Locale.JAPAN);
+        CollationKey[] keys = new CollationKey[sourceData_ja.length];
+        CollationKey[] target_keys = new CollationKey[targetData_ja.length];
+        for (int i=0; i<sourceData_ja.length; i++){
+                keys[i] = myCollator.getCollationKey(sourceData_ja[i]);
+                target_keys[i] = myCollator.getCollationKey(targetData_ja[i]); //used later
+        }
+        /* Sort the string using CollationKey */
+        InsertionSort(keys);
+        /** debug: printout the result after sort
+        System.out.println("--- After Sorting ---");
+        for (int i=0; i<sourceData_ja.length; i++){
+                System.out.println(i+" :"+keys[i].getSourceString());
+        }
+        **/
+       /*
+        * Compare the result using equals method and getSourceString method.
+        */
+        boolean pass = true;
+        for (int i=0; i<sourceData_ja.length; i++){
+                /* Comparing using String.equals: in order to use getStringSource() */
+                if (! targetData_ja[i].equals(keys[i].getSourceString())){
+                        throw new RuntimeException("FAILED: CollationKeyTest backward compatibility "
+                                  +"while comparing" +targetData_ja[i]+" vs "
+                                  +keys[i].getSourceString());
+                }
+                /* Comparing using CollaionKey.equals: in order to use equals() */
+                if (! target_keys[i].equals(keys[i])){
+                        throw new RuntimeException("FAILED: CollationKeyTest backward compatibility."
+                                  +" Using CollationKey.equals " +targetData_ja[i]
+                                  +" vs " +keys[i].getSourceString());
+                }
+                /* Comparing using CollaionKey.hashCode(): in order to use hashCode() */
+                if (target_keys[i].hashCode() != keys[i].hashCode()){
+                        throw new RuntimeException("FAILED: CollationKeyTest backward compatibility."
+                                  +" Using CollationKey.hashCode " +targetData_ja[i]
+                                  +" vs " +keys[i].getSourceString());
+                }
+                /* Comparing using CollaionKey.toByteArray(): in order to use toByteArray() */
+                byte[] target_bytes = target_keys[i].toByteArray();
+                byte[] source_bytes = keys[i].toByteArray();
+                for (int j=0; j<target_bytes.length; j++){
+                        Byte targetByte = new Byte(target_bytes[j]);
+                        Byte sourceByte = new Byte(source_bytes[j]);
+                        if (targetByte.compareTo(sourceByte)!=0){
+                            throw new RuntimeException("FAILED: CollationKeyTest backward "
+                                  +"compatibility. Using Byte.compareTo from CollationKey.toByteArray "
+                                  +targetData_ja[i]
+                                  +" vs " +keys[i].getSourceString());
+                        }
+                }
+        }
+        testSubclassMethods();
+        testConstructor();
+    }
+
+   /*
+    * Sort the array of CollationKey using compareTo method in insertion sort.
+    */
+    private  void  InsertionSort(CollationKey[] keys){
+        int f, i;
+        CollationKey tmp;
+
+        for (f=1; f < keys.length; f++){
+            if(keys[f].compareTo( keys[f-1]) > 0){
+                continue;
+            }
+            tmp = keys[f];
+            i = f-1;
+            while ( (i>=0) && (keys[i].compareTo(tmp) > 0) ) {
+                keys[i+1] = keys[i];
+                i--;
+            }
+            keys[i+1]=tmp;
+        }
+    }
+
+
+  /*
+   * From here is the bogus methods to test the subclass of
+   * the CollationKey class.
+   */
+    public CollationKeyTestImpl(String str){
+        super (str);
+        // debug: System.out.println("CollationKeyTest extends CollationKey class: "+str);
+    }
+    /* abstract method: needs to be implemented */
+    public byte[] toByteArray(){
+        String foo= "Hello";
+        return foo.getBytes();
+    }
+   /* abstract method: needs to be implemented */
+   public int compareTo(CollationKey target){
+        return 0;
+   }
+   public boolean equals(Object target){
+        return true;
+   }
+   public String getSourceString(){
+        return "CollationKeyTestImpl";
+   }
+  /*
+   * This method tests the collection of bugus methods from the extended
+   * subclass of CollationKey class.
+   */
+   private void testSubclassMethods() {
+        CollationKeyTestImpl clt1  = new CollationKeyTestImpl("testSubclassMethods-1");
+        CollationKeyTestImpl clt2  = new CollationKeyTestImpl("testSubclassMethods-2");
+        // extended method, equals always returns true
+        if (!clt1.equals(clt2)){
+            throw new RuntimeException("Failed: equals(CollationKeySubClass)");
+        }
+        // extended method, compareTo always returns 0
+        if (clt1.compareTo(clt2)!=0){
+            throw new RuntimeException("Failed: compareTo(CollationKeySubClass)");
+        }
+        // overriding extended method, getSourceString always returns "CollationKeyTestImpl"
+        if (! clt1.getSourceString().equals("CollationKeyTestImpl")){
+            throw new RuntimeException("Failed: CollationKey subclass overriding getSourceString()");
+        }
+        // extended method, toByteArray always returns bytes from "Hello"
+        String str2 = new String( clt2.toByteArray());
+        if (! clt2.equals("Hello")){
+            throw new RuntimeException("Failed: CollationKey subclass toByteArray()");
+        }
+    }
+
+  /*
+   * This method tests CollationKey constructor with null source string.
+   * It should throw NPE.
+   */
+   private void testConstructor() {
+       boolean npe=false;
+       try{
+            CollationKeyTestImpl cltNull  = new CollationKeyTestImpl(null);
+        } catch (NullPointerException npException){
+            npe=true;
+            // debug: System.out.println("--- NPE is thrown with NULL arguement: PASS ---");
+        }
+        if(!npe){
+           throw new RuntimeException("Failed: CollationKey Constructor with null source"+
+                                   " didn't throw NPE!");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/CollatorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.lang.reflect.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.io.*;
+import java.text.*;
+
+/**
+ * CollatorTest is a base class for tests that can be run conveniently from
+ * the command line as well as under the Java test harness.
+ * <p>
+ * Sub-classes implement a set of methods named Test<something>. Each
+ * of these methods performs some test. Test methods should indicate
+ * errors by calling either err or errln.  This will increment the
+ * errorCount field and may optionally print a message to the log.
+ * Debugging information may also be added to the log via the log
+ * and logln methods.  These methods will add their arguments to the
+ * log only if the test is being run in verbose mode.
+ */
+public abstract class CollatorTest extends IntlTest {
+
+    //------------------------------------------------------------------------
+    // These methods are utilities specific to the Collation tests..
+    //------------------------------------------------------------------------
+
+    protected void assertEqual(CollationElementIterator i1, CollationElementIterator i2) {
+        int c1, c2, count = 0;
+        do {
+            c1 = i1.next();
+            c2 = i2.next();
+            if (c1 != c2) {
+                errln("    " + count + ": " + c1 + " != " + c2);
+                break;
+            }
+            count++;
+        } while (c1 != CollationElementIterator.NULLORDER);
+    }
+
+    // Replace nonprintable characters with unicode escapes
+    static protected String prettify(String str) {
+        StringBuffer result = new StringBuffer();
+
+        String zero = "0000";
+
+        for (int i = 0; i < str.length(); i++) {
+            char ch = str.charAt(i);
+            if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| (ch > 0x7E && ch < 0xA0) || ch > 0x100) {
+                String hex = Integer.toString((int)ch,16);
+
+                result.append("\\u" + zero.substring(0, 4 - hex.length()) + hex);
+            } else {
+                result.append(ch);
+            }
+        }
+        return result.toString();
+    }
+
+    // Produce a printable representation of a CollationKey
+    static protected String prettify(CollationKey key) {
+        StringBuffer result = new StringBuffer();
+        byte[] bytes = key.toByteArray();
+
+        for (int i = 0; i < bytes.length; i += 2) {
+            int val = (bytes[i] << 8) + bytes[i+1];
+            result.append(Integer.toString(val, 16) + " ");
+        }
+        return result.toString();
+    }
+
+    //------------------------------------------------------------------------
+    // Everything below here is boilerplate code that makes it possible
+    // to add a new test by simply adding a function to an existing class
+    //------------------------------------------------------------------------
+
+    protected void doTest(Collator col, int strength,
+                          String[] source, String[] target, int[] result) {
+        if (source.length != target.length) {
+            errln("Data size mismatch: source = " +
+                  source.length + ", target = " + target.length);
+
+            return; // Return if "-nothrow" is specified.
+        }
+        if (source.length != result.length) {
+            errln("Data size mismatch: source & target = " +
+                  source.length + ", result = " + result.length);
+
+            return; // Return if "-nothrow" is specified.
+        }
+
+        col.setStrength(strength);
+        for (int i = 0; i < source.length ; i++) {
+            doTest(col, source[i], target[i], result[i]);
+        }
+    }
+
+    protected void doTest(Collator col,
+                          String source, String target, int result) {
+        char relation = '=';
+        if (result <= -1) {
+            relation = '<';
+        } else if (result >= 1) {
+            relation = '>';
+        }
+
+        int compareResult = col.compare(source, target);
+        CollationKey sortKey1 = col.getCollationKey(source);
+        CollationKey sortKey2 = col.getCollationKey(target);
+        int keyResult = sortKey1.compareTo(sortKey2);
+        if (compareResult != keyResult) {
+            errln("Compare and Collation Key results are different! Source = " +
+                  source + " Target = " + target);
+        }
+        if (keyResult != result) {
+            errln("Collation Test failed! Source = " + source + " Target = " +
+                  target + " result should be " + relation);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/CurrencyCollate.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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      4114080 4150807
+ * @summary Test currency collation.  For bug 4114080, make sure the collation
+ * of the euro sign behaves properly. For bug 4150807, make sure the collation
+ * order of ALL the current symbols is correct.  This means they sort
+ * in English alphabetical order of their English names.  This test can be
+ * easily extended to do simple spot checking.  See other collation tests for
+ * more sophisticated testing.
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+
+/* Author: Alan Liu
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ */
+public class CurrencyCollate {
+    static Collator myCollation = Collator.getInstance(Locale.US);
+
+    public static void main(String[] args) {
+        String[] DATA = {
+            "\u20AC", ">", "$",     // euro > dollar
+            "\u20AC", "<", "\u00A3", // euro < pound
+
+            // additional tests for general currency sort order (bug #4150807)
+            "\u00a4", "<", "\u0e3f", // generic currency < baht
+            "\u0e3f", "<", "\u00a2", // baht < cent
+            "\u00a2", "<", "\u20a1", // cent < colon
+            "\u20a1", "<", "\u20a2", // colon < cruzeiro
+            "\u20a2", "<", "\u0024", // cruzeiro < dollar
+            "\u0024", "<", "\u20ab", // dollar < dong
+            "\u20ab", "<", "\u20a3", // dong < franc
+            "\u20a3", "<", "\u20a4", // franc < lira
+            "\u20a4", "<", "\u20a5", // lira < mill
+            "\u20a5", "<", "\u20a6", // mill < naira
+            "\u20a6", "<", "\u20a7", // naira < peseta
+            "\u20a7", "<", "\u00a3", // peseta < pound
+            "\u00a3", "<", "\u20a8", // pound < rupee
+            "\u20a8", "<", "\u20aa", // rupee < shekel
+            "\u20aa", "<", "\u20a9", // shekel < won
+            "\u20a9", "<", "\u00a5"  // won < yen
+        };
+        for (int i=0; i<DATA.length; i+=3) {
+            int expected = DATA[i+1].equals(">") ? 1 : (DATA[i+1].equals("<") ? -1 : 0);
+            int actual = myCollation.compare(DATA[i], DATA[i+2]);
+            if (actual != expected) {
+                throw new RuntimeException("Collation of " +
+                                           DATA[i] + " vs. " +
+                                           DATA[i+2] + " yields " + actual +
+                                           "; expected " + expected);
+            }
+        }
+        System.out.println("Ok");
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/DanishTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4930708 4174436 5008498
+ * @library /java/text/testlib
+ * @summary test Danish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class DanishTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new DanishTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "Lvi",
+        "L\u00E4vi",
+        "L\u00FCbeck",
+        "ANDR\u00C9",
+        "ANDRE",
+        "ANNONCERER"
+    };
+
+    private static final String[] primaryTargetData = {
+            "Lwi",
+            "L\u00F6wi",
+            "Lybeck",
+            "ANDR\u00E9",
+            "ANDR\u00C9",
+            "ANN\u00D3NCERER"
+    };
+
+    private static final int[] primaryResults = {
+            -1, -1, 0, 0, 0, 0
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final String[] tertiarySourceData = {
+            "Luc",
+            "luck",
+            "L\u00FCbeck",
+            "L\u00E4vi",
+            "L\u00F6ww"
+    };
+
+    private static final String[] tertiaryTargetData = {
+            "luck",
+            "L\u00FCbeck",
+            "lybeck",
+            "L\u00F6we",
+            "mast"
+    };
+
+    private static final int[] tertiaryResults = {
+            -1, -1,  1, -1, -1
+    };
+
+    /*
+     * Data for TestExtra()
+     */
+    private static final String[] testData = {
+            "A/S",
+            "ANDRE",
+            "ANDR\u00C9", // E-acute
+            "ANDR\u00C8", // E-grave
+            "ANDR\u00E9", // e-acute
+            "ANDR\u00EA", // e-circ
+            "Andre",
+            "Andr\u00E9", // e-acute
+            "\u00C1NDRE", // A-acute
+            "\u00C0NDRE", // A-grave
+            "andre",
+            "\u00E1ndre", // a-acute
+            "\u00E0ndre", // a-grave
+            "ANDREAS",
+            "ANNONCERER",
+            "ANN\u00D3NCERER", // O-acute
+            "annoncerer",
+            "ann\u00F3ncerer", // o-acute
+            "AS",
+            "A\u00e6RO", // ae-ligature
+            "CA",
+            "\u00C7A", // C-cedilla
+            "CB",
+            "\u00C7C", // C-cedilla
+            "D.S.B.",
+            "DA",
+            "DB",
+            "\u00D0ORA", // capital eth
+            "DSB",
+            "\u00D0SB", // capital eth
+            "DSC",
+            "EKSTRA_ARBEJDE",
+            "EKSTRABUD",
+            "H\u00D8ST",  // could the 0x00D8 be 0x2205?
+            "HAAG",
+            "H\u00C5NDBOG", // A-ring
+            "HAANDV\u00C6RKSBANKEN", // AE-ligature
+            "INTERNETFORBINDELSE",
+            "Internetforbindelse",
+            "\u00CDNTERNETFORBINDELSE", // I-acute
+            "internetforbindelse",
+            "\u00EDnternetforbindelse", // i-acute
+            "Karl",
+            "karl",
+            "NIELSEN",
+            "NIELS J\u00D8RGEN", // O-slash
+            "NIELS-J\u00D8RGEN", // O-slash
+            "OERVAL",
+            "\u0152RVAL", // OE-ligature
+            "\u0153RVAL", // oe-ligature
+            "R\u00C9E, A", // E-acute
+            "REE, B",
+            "R\u00C9E, L", // E-acute
+            "REE, V",
+            "SCHYTT, B",
+            "SCHYTT, H",
+            "SCH\u00DCTT, H", // U-diaeresis
+            "SCHYTT, L",
+            "SCH\u00DCTT, M", // U-diaeresis
+            "SS",
+            "ss",
+            "\u00DF", // sharp S
+            "SSA",
+            "\u00DFA", // sharp S
+            "STOREK\u00C6R", // AE-ligature
+            "STORE VILDMOSE",
+            "STORMLY",
+            "STORM PETERSEN",
+            "THORVALD",
+            "THORVARDUR",
+            "\u00DEORVAR\u0110UR", //  capital thorn, capital d-stroke(like eth) (sami)
+            "THYGESEN",
+            "VESTERG\u00C5RD, A",
+            "VESTERGAARD, A",
+            "VESTERG\u00C5RD, B",                // 50
+            "Westmalle",
+            "YALLE",
+            "Yderligere",
+            "\u00DDderligere", // Y-acute
+            "\u00DCderligere", // U-diaeresis
+            "\u00FDderligere", // y-acute
+            "\u00FCderligere", // u-diaeresis
+            "U\u0308ruk-hai",
+            "ZORO",
+            "\u00C6BLE",  // AE-ligature
+            "\u00E6BLE",  // ae-ligature
+            "\u00C4BLE",  // A-diaeresis
+            "\u00E4BLE",  // a-diaeresis
+            "\u00D8BERG", // O-stroke
+            "\u00F8BERG", // o-stroke
+            "\u00D6BERG", // O-diaeresis
+            "\u00F6BERG"  // o-diaeresis
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+        for (int i = 0; i < testData.length-1; i++) {
+            for (int j = i+1; j < testData.length; j++) {
+                doTest(myCollation, testData[i], testData[j], -1);
+            }
+        }
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("da", "", ""));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/DummyTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Dummy Collation
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+public class DummyTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new DummyTest().run(args);
+    }
+
+    private static final String DEFAULTRULES =
+        "='\u200B'=\u200C=\u200D=\u200E=\u200F"
+        // Control Characters
+        + "=\u0000 =\u0001 =\u0002 =\u0003 =\u0004" //null, .. eot
+        + "=\u0005 =\u0006 =\u0007 =\u0008 ='\u0009'" //enq, ...
+        + "='\u000b' =\u000e" //vt,, so
+        + "=\u000f ='\u0010' =\u0011 =\u0012 =\u0013" //si, dle, dc1, dc2, dc3
+        + "=\u0014 =\u0015 =\u0016 =\u0017 =\u0018" //dc4, nak, syn, etb, can
+        + "=\u0019 =\u001a =\u001b =\u001c =\u001d" //em, sub, esc, fs, gs
+        + "=\u001e =\u001f =\u007f"                   //rs, us, del
+        //....then the C1 Latin 1 reserved control codes
+        + "=\u0080 =\u0081 =\u0082 =\u0083 =\u0084 =\u0085"
+        + "=\u0086 =\u0087 =\u0088 =\u0089 =\u008a =\u008b"
+        + "=\u008c =\u008d =\u008e =\u008f =\u0090 =\u0091"
+        + "=\u0092 =\u0093 =\u0094 =\u0095 =\u0096 =\u0097"
+        + "=\u0098 =\u0099 =\u009a =\u009b =\u009c =\u009d"
+        + "=\u009e =\u009f"
+        // IGNORE except for secondary, tertiary difference
+        // Spaces
+        + ";'\u0020';'\u00A0'"                  // spaces
+        + ";'\u2000';'\u2001';'\u2002';'\u2003';'\u2004'"  // spaces
+        + ";'\u2005';'\u2006';'\u2007';'\u2008';'\u2009'"  // spaces
+        + ";'\u200A';'\u3000';'\uFEFF'"                // spaces
+        + ";'\r' ;'\t' ;'\n';'\f';'\u000b'"  // whitespace
+
+        // Non-spacing accents
+
+        + ";\u0301"          // non-spacing acute accent
+        + ";\u0300"          // non-spacing grave accent
+        + ";\u0306"          // non-spacing breve accent
+        + ";\u0302"          // non-spacing circumflex accent
+        + ";\u030c"          // non-spacing caron/hacek accent
+        + ";\u030a"          // non-spacing ring above accent
+        + ";\u030d"          // non-spacing vertical line above
+        + ";\u0308"          // non-spacing diaeresis accent
+        + ";\u030b"          // non-spacing double acute accent
+        + ";\u0303"          // non-spacing tilde accent
+        + ";\u0307"          // non-spacing dot above/overdot accent
+        + ";\u0304"          // non-spacing macron accent
+        + ";\u0337"          // non-spacing short slash overlay (overstruck diacritic)
+        + ";\u0327"          // non-spacing cedilla accent
+        + ";\u0328"          // non-spacing ogonek accent
+        + ";\u0323"          // non-spacing dot-below/underdot accent
+        + ";\u0332"          // non-spacing underscore/underline accent
+        // with the rest of the general diacritical marks in binary order
+        + ";\u0305"          // non-spacing overscore/overline
+        + ";\u0309"          // non-spacing hook above
+        + ";\u030e"          // non-spacing double vertical line above
+        + ";\u030f"          // non-spacing double grave
+        + ";\u0310"          // non-spacing chandrabindu
+        + ";\u0311"          // non-spacing inverted breve
+        + ";\u0312"          // non-spacing turned comma above/cedilla above
+        + ";\u0313"          // non-spacing comma above
+        + ";\u0314"          // non-spacing reversed comma above
+        + ";\u0315"          // non-spacing comma above right
+        + ";\u0316"          // non-spacing grave below
+        + ";\u0317"          // non-spacing acute below
+        + ";\u0318"          // non-spacing left tack below
+        + ";\u0319"          // non-spacing tack below
+        + ";\u031a"          // non-spacing left angle above
+        + ";\u031b"          // non-spacing horn
+        + ";\u031c"          // non-spacing left half ring below
+        + ";\u031d"          // non-spacing up tack below
+        + ";\u031e"          // non-spacing down tack below
+        + ";\u031f"          // non-spacing plus sign below
+        + ";\u0320"          // non-spacing minus sign below
+        + ";\u0321"          // non-spacing palatalized hook below
+        + ";\u0322"          // non-spacing retroflex hook below
+        + ";\u0324"          // non-spacing double dot below
+        + ";\u0325"          // non-spacing ring below
+        + ";\u0326"          // non-spacing comma below
+        + ";\u0329"          // non-spacing vertical line below
+        + ";\u032a"          // non-spacing bridge below
+        + ";\u032b"          // non-spacing inverted double arch below
+        + ";\u032c"          // non-spacing hacek below
+        + ";\u032d"          // non-spacing circumflex below
+        + ";\u032e"          // non-spacing breve below
+        + ";\u032f"          // non-spacing inverted breve below
+        + ";\u0330"          // non-spacing tilde below
+        + ";\u0331"          // non-spacing macron below
+        + ";\u0333"          // non-spacing double underscore
+        + ";\u0334"          // non-spacing tilde overlay
+        + ";\u0335"          // non-spacing short bar overlay
+        + ";\u0336"          // non-spacing long bar overlay
+        + ";\u0338"          // non-spacing long slash overlay
+        + ";\u0339"          // non-spacing right half ring below
+        + ";\u033a"          // non-spacing inverted bridge below
+        + ";\u033b"          // non-spacing square below
+        + ";\u033c"          // non-spacing seagull below
+        + ";\u033d"          // non-spacing x above
+        + ";\u033e"          // non-spacing vertical tilde
+        + ";\u033f"          // non-spacing double overscore
+        + ";\u0340"          // non-spacing grave tone mark
+        + ";\u0341"          // non-spacing acute tone mark
+        + ";\u0342;\u0343;\u0344;\u0345;\u0360;\u0361"    // newer
+        + ";\u0483;\u0484;\u0485;\u0486"    // Cyrillic accents
+
+        + ";\u20D0;\u20D1;\u20D2"           // symbol accents
+        + ";\u20D3;\u20D4;\u20D5"           // symbol accents
+        + ";\u20D6;\u20D7;\u20D8"           // symbol accents
+        + ";\u20D9;\u20DA;\u20DB"           // symbol accents
+        + ";\u20DC;\u20DD;\u20DE"           // symbol accents
+        + ";\u20DF;\u20E0;\u20E1"           // symbol accents
+
+        + ",'\u002D';\u00AD"                // dashes
+        + ";\u2010;\u2011;\u2012"           // dashes
+        + ";\u2013;\u2014;\u2015"           // dashes
+        + ";\u2212"                         // dashes
+
+        // other punctuation
+
+        + "<'\u005f'"        // underline/underscore (spacing)
+        + "<\u00af"          // overline or macron (spacing)
+//        + "<\u00ad"        // syllable hyphen (SHY) or soft hyphen
+        + "<'\u002c'"        // comma (spacing)
+        + "<'\u003b'"        // semicolon
+        + "<'\u003a'"        // colon
+        + "<'\u0021'"        // exclamation point
+        + "<\u00a1"          // inverted exclamation point
+        + "<'\u003f'"        // question mark
+        + "<\u00bf"          // inverted question mark
+        + "<'\u002f'"        // slash
+        + "<'\u002e'"        // period/full stop
+        + "<\u00b4"          // acute accent (spacing)
+        + "<'\u0060'"        // grave accent (spacing)
+        + "<'\u005e'"        // circumflex accent (spacing)
+        + "<\u00a8"          // diaresis/umlaut accent (spacing)
+        + "<'\u007e'"        // tilde accent (spacing)
+        + "<\u00b7"          // middle dot (spacing)
+        + "<\u00b8"          // cedilla accent (spacing)
+        + "<'\u0027'"        // apostrophe
+        + "<'\"'"            // quotation marks
+        + "<\u00ab"          // left angle quotes
+        + "<\u00bb"          // right angle quotes
+        + "<'\u0028'"        // left parenthesis
+        + "<'\u0029'"        // right parenthesis
+        + "<'\u005b'"        // left bracket
+        + "<'\u005d'"        // right bracket
+        + "<'\u007b'"        // left brace
+        + "<'\u007d'"        // right brace
+        + "<\u00a7"          // section symbol
+        + "<\u00b6"          // paragraph symbol
+        + "<\u00a9"          // copyright symbol
+        + "<\u00ae"          // registered trademark symbol
+        + "<'\u0040'"          // at sign
+        + "<\u00a4"          // international currency symbol
+        + "<\u00a2"          // cent sign
+        + "<'\u0024'"        // dollar sign
+        + "<\u00a3"          // pound-sterling sign
+        + "<\u00a5"          // yen sign
+        + "<'\u002a'"        // asterisk
+        + "<'\\u005c'"       // backslash
+        + "<'\u0026'"        // ampersand
+        + "<'\u0023'"        // number sign
+        + "<'\u0025'"        // percent sign
+        + "<'\u002b'"        // plus sign
+//        + "<\u002d"        // hyphen or minus sign
+        + "<\u00b1"          // plus-or-minus sign
+        + "<\u00f7"          // divide sign
+        + "<\u00d7"          // multiply sign
+        + "<'\u003c'"        // less-than sign
+        + "<'\u003d'"        // equal sign
+        + "<'\u003e'"        // greater-than sign
+        + "<\u00ac"          // end of line symbol/logical NOT symbol
+        + "<'\u007c'"          // vertical line/logical OR symbol
+        + "<\u00a6"          // broken vertical line
+        + "<\u00b0"          // degree symbol
+        + "<\u00b5"          // micro symbol
+
+        // NUMERICS
+
+        + "<0<1<2<3<4<5<6<7<8<9"
+        + "<\u00bc<\u00bd<\u00be"   // 1/4,1/2,3/4 fractions
+
+        // NON-IGNORABLES
+        + "<a,A"
+        + "<b,B"
+        + "<c,C"
+        + "<d,D"
+        + "<\u00F0,\u00D0"                  // eth
+        + "<e,E"
+        + "<f,F"
+        + "<g,G"
+        + "<h,H"
+        + "<i,I"
+        + "<j,J"
+        + "<k,K"
+        + "<l,L"
+        + "<m,M"
+        + "<n,N"
+        + "<o,O"
+        + "<p,P"
+        + "<q,Q"
+        + "<r,R"
+        + "<s, S & SS,\u00DF"             // s-zet
+        + "<t,T"
+        + "&th, \u00FE & TH, \u00DE"           // thorn
+        + "<u,U"
+        + "<v,V"
+        + "<w,W"
+        + "<x,X"
+        + "<y,Y"
+        + "<z,Z"
+        + "&AE,\u00C6"                    // ae & AE ligature
+        + "&AE,\u00E6"
+        + "&OE,\u0152"                    // oe & OE ligature
+        + "&OE,\u0153";
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "p\u00EAche",
+        "abc",
+        "abc",
+        "abc",
+        "abc",
+        "abc",
+        "a\u00E6c",
+        "acHc",
+        "black"
+    };
+
+    private static final String[] primaryTargetData = {
+        "p\u00E9ch\u00E9",
+        "abc",
+        "aBC",
+        "abch",
+        "abd",
+        "\u00E4bc",
+        "a\u00C6c",
+        "aCHc",
+        "black-bird"
+    };
+
+    private static final int[] primaryResults = {
+         0,  0,  0, -1, -1,  0,  0,  0, -1
+    };
+
+    /*
+     * Data for TestSecondary()
+     */
+    private static final String[] secondarySourceData = {
+        "four",
+        "five",
+        "1",
+        "abc",
+        "abc",
+        "abcH",
+        "abc",
+        "acHc"
+    };
+
+    private static final String[] secondaryTargetData = {
+
+        "4",
+        "5",
+        "one",
+        "abc",
+        "aBc",
+        "abch",
+        "abd",
+        "aCHc"
+    };
+
+    private static final int[] secondaryResults = {
+         0,  0,  0,  0,  0,  0, -1,  0
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final String[] tertiarySourceData = {
+        "ab'c",
+        "co-op",
+        "ab",
+        "ampersad",
+        "all",
+        "four",
+        "five",
+        "1",
+        "1",
+        "1",
+        "2",
+        "2",
+        "Hello",
+        "a<b",
+        "a<b",
+        "acc",
+        "acHc"
+    };
+
+    private static final String[] tertiaryTargetData = {
+        "abc",
+        "COOP",
+        "abc",
+        "&",
+        "&",
+        "4",
+        "5",
+        "one",
+        "nne",
+        "pne",
+        "two",
+        "uwo",
+        "hellO",
+        "a<=b",
+        "abc",
+        "aCHc",
+        "aCHc"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1,  1, -1, -1, -1, -1, -1,  1,  1, -1,
+         1, -1,  1,  1, -1, -1, -1
+    };
+
+
+    private static final String[] testData = {
+        "a",
+        "A",
+        "\u00e4",
+        "\u00c4",
+        "ae",
+        "aE",
+        "Ae",
+        "AE",
+        "\u00e6",
+        "\u00c6",
+        "b",
+        "c",
+        "z"
+    };
+
+    public void TestPrimary() {
+        doTest(getCollator(), Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestSecondary() {
+        doTest(getCollator(), Collator.SECONDARY,
+               secondarySourceData, secondaryTargetData, secondaryResults);
+    }
+
+    public void TestTertiary() {
+        Collator col = getCollator();
+
+        doTest(col, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+        for (int i = 0; i < testData.length-1; i++) {
+            for (int j = i+1; j < testData.length; j++) {
+                doTest(col, testData[i], testData[j], -1);
+            }
+        }
+    }
+
+    private RuleBasedCollator myCollation = null;
+    private Collator getCollator() {
+        if (myCollation == null) {
+            try {
+                myCollation = new RuleBasedCollator
+                    (DEFAULTRULES + "& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ");
+            } catch (Exception foo) {
+                errln("Collator creation failed.");
+                myCollation = (RuleBasedCollator)Collator.getInstance();
+            }
+        }
+        return myCollation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/EnglishTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test English Collation
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+public class EnglishTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new EnglishTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "p\u00EAche",
+        "abc",
+        "abc",
+        "abc",
+        "a\u00E6c"
+    };
+
+    private static final String[] primaryTargetData = {
+        "p\u00E9ch\u00E9",
+        "aBC",
+        "abd",
+        "\u00E4bc",
+        "a\u00C6c"
+    };
+
+    private static final int[] primaryResults = {
+         0,  0, -1,  0,  0,
+    };
+
+    /*
+     * Data for TestSecondary()
+     */
+    private static final String[] secondarySourceData = {
+        "abc",
+        "abc",
+        "a\u00E6c",
+        "abc",
+        "abc",
+        "p\u00e9ch\u00e9"
+    };
+
+    private static final String[] secondaryTargetData = {
+        "aBd",
+        "\u00E4bc",
+        "a\u00C6c",
+        "aBd",
+        "\u00E4bc",
+        "p\u00eache"
+    };
+
+    private static final int[] secondaryResults = {
+        -1, -1,  0, -1, -1, -1
+    };
+
+    /*
+     * Data for TestTertiary() {
+     */
+    private static final String[] tertiarySourceData = {
+        "ab",
+        "black-bird",
+        "black bird",
+        "black-bird",
+        "Hello",
+        "ABC",
+        "abc",
+        "blackbird",
+        "black-bird",
+        "black-bird",
+        "p\u00EAche",
+        "p\u00E9ch\u00E9",
+        "\u00C4B\u0308C\u0308",
+        "a\u0308bc",
+        "p\u00E9cher",
+        "roles",
+        "abc",
+        "A",
+        "A",
+        "ab",
+        "tcompareplain",
+        "ab",
+        "a#b",
+        "a#b",
+        "abc",
+        "Abcda",
+        "abcda",
+        "abcda",
+        "\u00E6bcda",
+        "\u00E4bcda",
+        "abc",
+        "abc",
+        "abc",
+        "abc",
+        "abc",
+        "acHc",
+        "a\u0308bc",
+        "thi\u0302s"
+    };
+
+    private static final String[] tertiaryTargetData = {
+        "abc",
+        "blackbird",
+        "black-bird",
+        "black",
+        "hello",
+        "ABC",
+        "ABC",
+        "blackbirds",
+        "blackbirds",
+        "blackbird",
+        "p\u00E9ch\u00E9",
+        "p\u00E9cher",
+        "\u00C4B\u0308C\u0308",
+        "A\u0308bc",
+        "p\u00E9che",
+        "ro\u0302le",
+        "A\u00E1cd",
+        "A\u00E1cd",
+        "abc",
+        "abc",
+        "TComparePlain",
+        "aBc",
+        "a#B",
+        "a&b",
+        "a#c",
+        "abcda",
+        "\u00C4bcda",
+        "\u00E4bcda",
+        "\u00C4bcda",
+        "\u00C4bcda",
+        "ab#c",
+        "abc",
+        "ab=c",
+        "abd",
+        "\u00E4bc",
+        "aCHc",
+        "\u00E4bc",
+        "th\u00EEs"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1,  1, -1,  1,  1,  0, -1, -1, -1,  1,
+         1, -1,  0, -1,  1,  1,  1, -1, -1, -1,
+        -1, -1, -1,  1,  1,  1, -1, -1,  1, -1,
+         1,  0,  1, -1, -1, -1,  0,  0
+    };
+
+    private static final String testData[] = {
+        "a",
+        "A",
+        "e",
+        "E",
+        "\u00e9",
+        "\u00e8",
+        "\u00ea",
+        "\u00eb",
+        "ea",
+        "x"
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestSecondary() {
+        doTest(myCollation, Collator.SECONDARY,
+               secondarySourceData, secondaryTargetData, secondaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+        for (int i = 0; i < testData.length-1; i++) {
+            for (int j = i+1; j < testData.length; j++) {
+                doTest(myCollation, testData[i], testData[j], -1);
+            }
+        }
+    }
+
+    private final Collator myCollation = Collator.getInstance(Locale.ENGLISH);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/FinnishTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Finnish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class FinnishTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new FinnishTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "L\u00E5vi",
+        "wat"
+    };
+
+    private static final String[] primaryTargetData = {
+        "L\u00E4we",
+        "vat"
+    };
+
+    private static final int[] primaryResults = {
+        -1,  0
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final String tertiarySourceData[] = {
+        "wat",
+        "vat",
+        "a\u00FCbeck"
+    };
+
+    private static final String tertiaryTargetData[] = {
+        "vat",
+        "way",
+        "axbeck"
+    };
+
+    private static final int[] tertiaryResults = {
+         1, -1,  1
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+              tertiarySourceData, tertiaryTargetData, tertiaryResults);
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("fi", "FI", ""));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/FrenchTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test French Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class FrenchTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new FrenchTest().run(args);
+    }
+
+    private static final String[] tertiarySourceData = {
+        "abc",
+        "COTE",
+        "p\u00EAche",
+        "p\u00EAcher",
+        "p\u00E9cher",
+        "p\u00E9cher",
+        "Hello"
+    };
+
+    private static final String[] tertiaryTargetData = {
+        "ABC",
+        "c\u00f4te",
+        "p\u00E9ch\u00E9",
+        "p\u00E9ch\u00E9",
+        "p\u00EAche",
+        "p\u00EAcher",
+        "hellO"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1, -1, -1,  1,  1, -1,  1
+    };
+
+    private static final String[] testData = {
+        "a",
+        "A",
+        "e",
+        "E",
+        "\u00e9",
+        "\u00e8",
+        "\u00ea",
+        "\u00eb",
+        "ea",
+        "x"
+    };
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+        for (int i = 0; i < testData.length-1; i++) {
+            for (int j = i+1; j < testData.length; j++) {
+                doTest(myCollation, testData[i], testData[j], -1);
+            }
+        }
+    }
+
+    private final Collator myCollation = Collator.getInstance(Locale.FRANCE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/G7Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test G7 Collation
+ */
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc. 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.
+ *
+*/
+
+/**
+ * G7 Test cases
+ *
+ * @author     Helena Shih
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.util.Locale;
+
+// G7 test program for printing out test results
+
+public class G7Test extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new G7Test().run(args);
+    }
+
+    private static final String testCases[] = {
+        "black-birds",              // 0
+        "Pat",                      // 1
+        "p\u00E9ch\u00E9",          // 2
+        "p\u00EAche",               // 3
+        "p\u00E9cher",              // 4
+        "p\u00EAcher",              // 5
+        "Tod",                      // 6
+        "T\u00F6ne",                // 7
+        "Tofu",                     // 8
+        "blackbirds",               // 9
+        "Ton",                      // 10
+        "PAT",                      // 11
+        "blackbird",                // 12
+        "black-bird",               // 13
+        "pat",                      // 14
+        // Additional tests
+        "czar",                     // 15
+        "churo",                    // 16
+        "cat",                      // 17
+        "darn",                     // 18
+        "?",                        // 19
+        "quick",                    // 20
+        "#",                        // 21
+        "&",                        // 22
+        "aardvark",                 // 23
+        "a-rdvark",                 // 24
+        "abbot",                    // 25
+        "coop",                     // 26
+        "co-p",                     // 27
+        "cop",                      // 28
+        "zebra"                     // 29
+    };
+
+    // loop to TOTALTESTSET
+    private static final int[][] G7Results = {
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_US
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_GB
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_CA
+        { 12, 13,  9,  0, 14,  1, 11,  3,  2,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // fr_FR
+        { 12, 13,  9,  0, 14,  1, 11,  3,  2,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // fr_CA
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // de_DE
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // it_IT
+        { 12, 13,  9,  0, 14,  1, 11,  2,  3,  4,
+           5,  6,  8, 10,  7, 31, 31, 31, 31, 31,
+          31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // ja_JP
+    };
+
+    // new table collation with rules "& Z < p, P"
+    // loop to FIXEDTESTSET
+    private static final int[] Test1Results = {
+        12, 13,  9,  0,  6,  8, 10,  7, 14,  1,
+        11,  2,  3,  4,  5, 31, 31, 31, 31, 31,
+        31, 31, 31, 31, 31, 31, 31, 31, 31, 31
+    };
+
+    // new table collation with rules "& C < ch , cH, Ch, CH "
+    // loop to TOTALTESTSET
+    private static final int[] Test2Results = {
+        19, 22, 21, 23, 25, 24, 12, 13,  9,  0,
+        17, 26, 28, 27, 15, 16, 18, 14,  1, 11,
+         2,  3,  4,  5, 20,  6,  8, 10,  7, 29
+    };
+
+    // new table collation with rules
+    //     "& Question-mark ; ? & Hash-mark ; # & Ampersand ; '&'  "
+    // loop to TOTALTESTSET
+    private static final int[] Test3Results = {
+        23, 25, 22, 24, 12, 13,  9,  0, 17, 16,
+        26, 28, 27, 15, 18, 21, 14,  1, 11,  2,
+         3,  4,  5, 19, 20,  6,  8, 10,  7, 29
+    };
+
+    // analogous to Japanese rules
+    //     " & aa ; a- & ee ; e- & ii ; i- & oo ; o- & uu ; u- "
+    // loop to TOTALTESTSET
+    private static final int[] Test4Results = {
+        19, 22, 21, 23, 24, 25, 12, 13,  9,  0,
+        17, 16, 26, 27, 28, 15, 18, 14,  1, 11,
+         2,  3,  4,  5, 20,  6,  8, 10,  7, 29
+    };
+
+    public void TestG7Data() {
+        for (int i = 0; i < locales.length; i++) {
+            Collator myCollation= null;
+            RuleBasedCollator tblColl1 = null;
+
+            try {
+                myCollation = Collator.getInstance(locales[i]);
+                tblColl1 = new RuleBasedCollator(((RuleBasedCollator)myCollation).getRules());
+            } catch (Exception foo) {
+                errln("Exception: " + foo.getMessage() +
+                      " Locale : " + locales[i].getDisplayName() +
+                      " getRules failed\n");
+                continue;
+            }
+            for (int j = 0; j < FIXEDTESTSET; j++) {
+                for (int n = j+1; n < FIXEDTESTSET; n++) {
+                    doTest(tblColl1, testCases[G7Results[i][j]],
+                           testCases[G7Results[i][n]], -1);
+                }
+            }
+            myCollation = null;
+        }
+    }
+
+    /*
+     * Demo Test 1 : Create a new table collation with rules "& Z < p, P"
+     */
+    public void TestDemoTest1() {
+        int j = 0;
+        final Collator myCollation = Collator.getInstance(Locale.US);
+        final String defRules = ((RuleBasedCollator)myCollation).getRules();
+        RuleBasedCollator tblColl = null;
+        String newRules = defRules + " & Z < p, P";
+
+        try {
+            tblColl = new RuleBasedCollator(newRules);
+            for (j = 0; j < FIXEDTESTSET; j++) {
+                for (int n = j+1; n < FIXEDTESTSET; n++) {
+                    doTest(tblColl, testCases[Test1Results[j]],
+                           testCases[Test1Results[n]], -1);
+                }
+            }
+            tblColl = null;
+        } catch (Exception foo) {
+            errln("Exception: " + foo.getMessage() +
+                  "\nDemo Test 1 Table Collation object creation failed.");
+        }
+    }
+
+    /*
+     * Demo Test 2 : Create a new table collation with rules
+     *     "& C < ch , cH, Ch, CH"
+     */
+    public void TestDemoTest2() {
+        final Collator myCollation = Collator.getInstance(Locale.US);
+        final String defRules = ((RuleBasedCollator)myCollation).getRules();
+        String newRules = defRules + "& C < ch , cH, Ch, CH";
+
+        try {
+            RuleBasedCollator tblColl = new RuleBasedCollator(newRules);
+            for (int j = 0; j < TOTALTESTSET; j++) {
+                for (int n = j+1; n < TOTALTESTSET; n++) {
+                    doTest(tblColl, testCases[Test2Results[j]],
+                           testCases[Test2Results[n]], -1);
+                }
+            }
+        } catch (Exception foo) {
+            errln("Exception: " + foo.getMessage() +
+                  "\nDemo Test 2 Table Collation object creation failed.\n");
+        }
+    }
+
+    /*
+     * Demo Test 3 : Create a new table collation with rules
+     *     "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'"
+     */
+    public void TestDemoTest3() {
+        final Collator myCollation = Collator.getInstance(Locale.US);
+        final String defRules = ((RuleBasedCollator)myCollation).getRules();
+        RuleBasedCollator tblColl = null;
+        String newRules = defRules + "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&";
+
+        try {
+            tblColl = new RuleBasedCollator(newRules);
+            for (int j = 0; j < TOTALTESTSET; j++) {
+                for (int n = j+1; n < TOTALTESTSET; n++) {
+                    doTest(tblColl, testCases[Test3Results[j]],
+                           testCases[Test3Results[n]], -1);
+                }
+            }
+        } catch (Exception foo) {
+            errln("Exception: " + foo.getMessage() +
+                  "\nDemo Test 3 Table Collation object creation failed.");
+        }
+    }
+
+    /*
+     * Demo Test 4 : Create a new table collation with rules
+     *     " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' "
+     */
+    public void TestDemoTest4() {
+        final Collator myCollation = Collator.getInstance(Locale.US);
+        final String defRules = ((RuleBasedCollator)myCollation).getRules();
+        RuleBasedCollator tblColl = null;
+        String newRules = defRules + " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' ";
+
+        try {
+            tblColl = new RuleBasedCollator(newRules);
+            for (int j = 0; j < TOTALTESTSET; j++) {
+                for (int n = j+1; n < TOTALTESTSET; n++) {
+                    doTest(tblColl, testCases[Test4Results[j]],
+                           testCases[Test4Results[n]], -1);
+                }
+            }
+        } catch (Exception foo) {
+            errln("Exception: " + foo.getMessage() +
+                  "\nDemo Test 4 Table Collation object creation failed.");
+        }
+        tblColl = null;
+    }
+
+    private static final int FIXEDTESTSET = 15;
+    private static final int TOTALTESTSET = 30;
+
+    private static final Locale locales[] = {
+        Locale.US,
+        Locale.UK,
+        Locale.CANADA,
+        Locale.FRANCE,
+        Locale.CANADA_FRENCH,
+        Locale.GERMANY,
+        Locale.JAPAN,
+        Locale.ITALY
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/GermanTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test German Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class GermanTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new GermanTest().run(args);
+    }
+
+    /*
+     * Shared data for TestPrimary() and TestTertiary()
+     */
+    private static final String testSourceData[] = {
+        "Gr\u00F6\u00DFe",
+        "abc",
+        "T\u00F6ne",
+        "T\u00F6ne",
+        "T\u00F6ne",
+        "a\u0308bc",
+        "\u00E4bc",
+        "\u00E4bc",
+        "Stra\u00DFe",
+        "efg",
+        "\u00E4bc",
+        "Stra\u00DFe"
+    };
+
+    private static final String testTargetData[] = {
+        "Grossist",
+        "a\u0308bc",
+        "Ton",
+        "Tod",
+        "Tofu",
+        "A\u0308bc",
+        "a\u0308bc",
+        "aebc",
+        "Strasse",
+        "efg",
+        "aebc",
+        "Strasse"
+    };
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final int[] primaryResults = {
+        -1,  0,  1,  1,  1,  0,  0, -1,  0,  0,
+        -1,  0
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final int[] tertiaryResults = {
+        -1, -1,  1,  1,  1, -1,  0, -1,  1,  0,
+        -1,  1
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               testSourceData, testTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               testSourceData, testTargetData, tertiaryResults);
+    }
+
+    private final Collator myCollation = Collator.getInstance(Locale.GERMAN);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/IteratorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4062985 4108758 4108762 4157299
+ * @library /java/text/testlib
+ * @summary Test CollationElementIterator, particularly the new methods in 1.2
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.Locale;
+import java.text.*;
+
+public class IteratorTest extends CollatorTest {
+    // TODO:
+    //  - Test previous() with contracting character sequences, which don't work
+    //      at the moment.
+    //  - Test edge cases on setOffset(), e.g. offset > length, etc.
+    //
+    public static void main(String[] args) throws Exception {
+        new IteratorTest().run(args);
+    }
+
+    /**
+     * Test for CollationElementIterator.previous()
+     *
+     * @bug 4108758 - Make sure it works with contracting characters
+     *
+     */
+    public void TestPrevious() throws ParseException {
+        // A basic test to see if it's working at all
+        backAndForth(en_us.getCollationElementIterator(test1));
+
+        // Test with a contracting character sequence
+        RuleBasedCollator c1 = new RuleBasedCollator(
+            "< a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH" );
+
+        backAndForth(c1.getCollationElementIterator("abchdcba"));
+
+        // Test with an expanding character sequence
+        RuleBasedCollator c2 = new RuleBasedCollator(
+            "< a < b < c/abd < d" );
+
+        backAndForth(c2.getCollationElementIterator("abcd"));
+
+        // Now try both
+        RuleBasedCollator c3 = new RuleBasedCollator(
+            "< a < b < c/aba < d < z < ch" );
+
+        backAndForth(c3.getCollationElementIterator("abcdbchdc"));
+    }
+
+    /**
+     * Test for getOffset() and setOffset()
+     */
+    public void TestOffset() {
+        CollationElementIterator iter = en_us.getCollationElementIterator(test1);
+
+        // Run all the way through the iterator, then get the offset
+        int orders[] = getOrders(iter);
+
+        int offset = iter.getOffset();
+        if (offset != test1.length()) {
+            System.out.println("offset at end != length: "
+                                + offset + " vs " + test1.length());
+        }
+
+        // Now set the offset back to the beginning and see if it works
+        iter.setOffset(0);
+        assertEqual(iter, en_us.getCollationElementIterator(test1));
+
+        // TODO: try iterating halfway through a messy string.
+    }
+
+    /**
+     * Test for setText()
+     */
+    public void TestSetText() {
+        CollationElementIterator iter1 = en_us.getCollationElementIterator(test1);
+        CollationElementIterator iter2 = en_us.getCollationElementIterator(test2);
+
+        // Run through the second iterator just to exercise it
+        int c = iter2.next();
+        int i = 0;
+        while ( ++i < 10 && c != CollationElementIterator.NULLORDER) {
+            c = iter2.next();
+        }
+
+        // Now set it to point to the same string as the first iterator
+        iter2.setText(test1);
+        assertEqual(iter1, iter2);
+    }
+
+    /** @bug 4108762
+     * Test for getMaxExpansion()
+     */
+    public void TestMaxExpansion() throws ParseException {
+        // Try a simple one first:
+        // The only expansion ends with 'e' and has length 2
+        String[][] test1 = {
+            { "< a & ae = \u00e4 < b < e", "" },
+            { "a",  "1" },
+            { "b",  "1" },
+            { "e",  "2" },
+        };
+        verifyExpansion(test1);
+
+        // Now a more complicated one:
+        //   "a1" --> "ae"
+        //   "z" --> "aeef"
+        //
+        String[][] test2 = {
+            { "< a & ae = a1 & aeef = z < b < e < f", "" },
+            { "a",  "1" },
+            { "b",  "1" },
+            { "e",  "2" },
+            { "f",  "4" },
+        };
+        verifyExpansion(test2);
+    }
+
+    /*
+     * @bug 4157299
+     */
+    public void TestClearBuffers() throws ParseException {
+        RuleBasedCollator c = new RuleBasedCollator("< a < b < c & ab = d");
+        CollationElementIterator i = c.getCollationElementIterator("abcd");
+        int e0 = i.next();   // save the first collation element
+        i.setOffset(3);      // go to the expanding character
+        i.next();            // but only use up half of it
+        i.setOffset(0);      // go back to the beginning
+        int e = i.next();    // and get this one again
+        if (e != e0) {
+           errln("got " + Integer.toString(e, 16) + ", expected " +
+                       Integer.toString(e0, 16));
+        }
+    }
+
+    //------------------------------------------------------------------------
+    // Internal utilities
+    //
+
+    private void backAndForth(CollationElementIterator iter) {
+        // Run through the iterator forwards and stick it into an array
+        int [] orders = getOrders(iter);
+
+        // Now go through it backwards and make sure we get the same values
+        int index = orders.length;
+        int o;
+
+        while ((o = iter.previous()) != CollationElementIterator.NULLORDER) {
+            if (o != orders[--index]) {
+                errln("Mismatch at index " + index + ": "
+                        + orders[index] + " vs " + o);
+                break;
+            }
+        }
+        if (index != 0) {
+            errln("Didn't get back to beginning - index is " + index);
+
+            iter.reset();
+            err("next: ");
+            while ((o = iter.next()) != NULLORDER) {
+                err( Integer.toHexString(o) + " ");
+            }
+            errln("");
+
+            err("prev: ");
+            while ((o = iter.previous()) != NULLORDER) {
+                 err( Integer.toHexString(o) + " ");
+            }
+            errln("");
+        }
+    }
+
+    /**
+     * Verify that getMaxExpansion works on a given set of collation rules
+     *
+     * The first row of the "tests" array contains the collation rules
+     * at index 0, and the string at index 1 is ignored.
+     *
+     * Subsequent rows of the array contain a character and a number, both
+     * represented as strings.  The character's collation order is determined,
+     * and getMaxExpansion is called for that character.  If its value is
+     * not equal to the specified number, an error results.
+     */
+    private void verifyExpansion(String[][] tests) throws ParseException
+    {
+        RuleBasedCollator coll = new RuleBasedCollator(tests[0][0]);
+        CollationElementIterator iter = coll.getCollationElementIterator("");
+
+        for (int i = 1; i < tests.length; i++) {
+            // First get the collation key that the test string expands to
+            iter.setText(tests[i][0]);
+
+            int order = iter.next();
+
+            if (order == NULLORDER || iter.next() != NULLORDER) {
+                iter.reset();
+                errln("verifyExpansion: '" + tests[i][0] +
+                    "' has multiple orders:" + orderString(iter));
+            }
+
+            int expansion = iter.getMaxExpansion(order);
+            int expect = new Integer(tests[i][1]).intValue();
+
+            if (expansion != expect) {
+                errln("expansion for '" + tests[i][0] + "' is wrong: " +
+                    "expected " + expect + ", got " + expansion);
+            }
+        }
+    }
+
+    /**
+     * Return an integer array containing all of the collation orders
+     * returned by calls to next on the specified iterator
+     */
+    private int[] getOrders(CollationElementIterator iter)
+    {
+        int maxSize = 100;
+        int size = 0;
+        int[] orders = new int[maxSize];
+
+        int order;
+        while ((order = iter.next()) != NULLORDER) {
+            if (size == maxSize) {
+                maxSize *= 2;
+                int[] temp = new int[maxSize];
+                System.arraycopy(orders, 0, temp, 0, size);
+                orders = temp;
+            }
+            orders[size++] = order;
+        }
+
+        if (orders.length > size) {
+            int[] temp = new int[size];
+            System.arraycopy(orders, 0, temp, 0, size);
+            orders = temp;
+        }
+        return orders;
+    };
+
+    /**
+     * Return a string containing all of the collation orders
+     * returned by calls to next on the specified iterator
+     */
+    private String orderString(CollationElementIterator iter) {
+        StringBuffer buf = new StringBuffer();
+
+        int order;
+        while ((order = iter.next()) != NULLORDER) {
+            buf.append( Integer.toHexString(order) + " ");
+        }
+        return buf.toString();
+    }
+
+    static final private int NULLORDER = CollationElementIterator.NULLORDER;
+    RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US);
+
+    String test1 = "What subset of all possible test cases?";
+    String test2 = "has the highest probability of detecting";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/JapaneseTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 1.1 02/09/11
+ * @bug 4176141 4655819
+ * @summary Regression tests for Japanese Collation
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class JapaneseTest {
+
+    // NOTE:
+    //   Golden data in this test case is locale data dependent and
+    //   may need to be changed if the Japanese locale collation rules
+    //   are changed.
+
+    /*
+     *                    | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+     * -------------------+--------------------+------------------+-------------
+     *  PRIMARY           | s1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     *  SECONDARY         | s1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     *  TERTIARY(default) | S1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     */
+    static final int[][] results1 = {
+        { -1, -1, -1},
+        { -1, -1, -1},
+        { -1, -1, -1},
+    };
+    static final String[][] compData1 = {
+        /*
+         * Data to verify '<' relationship in LocaleElements_ja.java
+         */
+        {"\u3084", "\u30E6",
+         "Hiragana \"YA\"(0x3084) <---> Katakana \"YU\"(0x30E6)"},
+        {"\u30E6", "\u3088",
+         "Katakana \"YU\"(0x30E6) <---> Hiragana \"YO\"(0x3088)"},
+        {"\u00B1", "\u2260",
+         "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"},
+        {"\u3011", "\u2260",
+         "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"},
+        {"\u2260", "\u2103",
+         "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"},
+        {"\u2260", "\u2606",
+         "Not Equal To(0x2260) <---> White Star(0x2606)"},
+        {"\u30FD", "\u309E",
+         "Katakana Iteration Mark(0x30FD) <---> Hiragana Voiced Iteration Mark(0x309E)"},
+        {"\u3059\u309D", "\u3059\u309E",
+         "Hiragana \"SU\"(0x3059)Hiragana Iteration Mark(0x309D) <---> Hiragana \"SU\"(0x3059)Hiragana Voiced Iteration Mark(0x309E)"},
+        {"\u821E", "\u798F",
+         "CJK Unified Ideograph(0x821E) <---> CJK Unified Ideograph(0x798F)"},
+
+        /*
+         * Data to verify normalization
+         */
+        {"\u2260", "\u225F",
+         "Not Equal To(0x2260) <---> Questioned Equal To(0x225F)"},
+        {"\u226E", "\u2260",
+         "Not Less-than(0x226E) <---> Not Equal To(0x2260)"},
+        {"\u226E", "\u226D",
+         "Not Less-than(0x226E) <---> Not Equivalent To(0x226D)"},
+    };
+
+    /*
+     *                    | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+     * -------------------+--------------------+------------------+-------------
+     *  PRIMARY           | s1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  SECONDARY         | s1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     *  TERTIARY(default) | S1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     */
+    static final int[][] results2 = {
+        {  0,  0,  0},
+        { -1, -1, -1},
+        { -1, -1, -1},
+    };
+    static final String[][] compData2 = {
+        /*
+         * Data to verify ';' relationship in LocaleElements_ja.java
+         */
+        {"\u3099", "\u309A",
+         "Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A)"},
+        {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3068\u3099\u3046",
+         "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUTO\"(0x3053 0x3046 0x3068)Combining Katakana-Hiragana Voiced Sound Mark(0X3099)\"U\"(0x3046)"},
+        {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3069\u3046",
+         "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUDOU\"(0x3053 0x3046 0x3069 0x3046)"},
+        {"\u3053\u3046\u3069\u3046", "\u3054\u3046\u3068\u3046",
+         "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3069 0x3046) <---> Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046)"},
+        {"\u3054\u3046\u3068\u3046", "\u3054\u3046\u3069\u3046",
+         "Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046) <---> Hiragana \"GOUDOU\"(0x3054 0x3046 0x3069 0x3046)"},
+    };
+
+    /*
+     *                    | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+     * -------------------+--------------------+------------------+-------------
+     *  PRIMARY           | s1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  SECONDARY         | s1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  TERTIARY(default) | S1 < s2 (-1)       | s1 < s2 (-1)     | s1 < s2 (-1)
+     */
+    static final int[][] results3 = {
+        {  0,  0,  0},
+        {  0,  0,  0},
+        { -1, -1, -1},
+    };
+    static final String[][] compData3 = {
+        /*
+         * Data to verify ',' relationship in LocaleElements_ja.java
+         */
+        {"\u3042", "\u3041",
+         "Hiragana \"A\"(0x3042) <---> Hiragana \"a\"(0x3041)"},
+        {"\u3041", "\u30A2",
+         "Hiragana \"a\"(0x3041) <---> Katakana \"A\"(0x30A2)"},
+        {"\u30A2", "\u30A1",
+         "Katakana \"A\"(0x30A2) <---> Katakana \"a\"(0x30A1)"},
+        {"\u3094", "\u30F4",
+         "Hiragana \"VU\"(0x3094) <---> Katakana \"VU\"(0x30F4)"},
+        {"\u3094", "\u30A6\u3099",
+         "Hiragana \"VU\"(0x3094) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+        {"\u3046\u3099", "\u30F4",
+         "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"},
+        {"\u3046\u3099", "\u30A6\u3099",
+         "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+        {"\u30AB\u30A2", "\u30AB\u30FC",
+         "Katakana \"KAA\"(0x30AB 0x30A2) <---> Katakana \"KA-\"(0x30AB 0x30FC)"},
+        {"\u30CB\u30A1\u30A2", "\u30CB\u30A1\u30FC",
+         "Katakana \"NyaA\"(0x30CB 0x30A1 0x30A2) <---> Katakana \"Nya-\"(0x30CB 0x30A1 0x30FC)"},
+        {"\u30B3\u30AA\u30D2\u30A4", "\u30B3\u30FC\u30D2\u30FC",
+         "Katakana \"KOOHII\"(0x30B3 0x30AA 0x30D2 0x30A4) <---> Katakana \"KO-HI-\"(0x30B3 0x30FC 0x30D2 0x30FC)"},
+        {"\u308A\u3088\u3046", "\u308A\u3087\u3046",
+         "Hiragana \"RIYOU\"(0x308A 0x3088 0x3046) <---> Hiragana \"Ryou\"(0x308A 0x3087 0x3046)"},
+        {"\u3081\u3064\u304D", "\u3081\u3063\u304D",
+         "Hiragana \"METSUKI\"(0x3081 0x3064 0x304D) <---> Hiragana \"MEKKI\"(0x3081 0x3063 0x304D)"},
+        {"\u3075\u3042\u3093", "\u30D5\u30A1\u30F3",
+         "Hiragana \"FUAN\"(0x3075 0x3042 0x3093) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"},
+        {"\u3075\u3041\u3093", "\u30D5\u30A2\u30F3",
+         "Hiragana \"FUaN\"(0x3075 0x3041 0x3093) <---> Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3)"},
+        {"\u30D5\u30A2\u30F3", "\u30D5\u30A1\u30F3",
+         "Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"},
+    };
+
+    /*
+     *                    | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+     * -------------------+--------------------+------------------+-------------
+     *  PRIMARY           | s1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  SECONDARY         | s1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  TERTIARY(default) | S1 = s2 (0)        | s1 = s2 (0)      | s1 = s2 (0)
+     */
+    static final int[][] results4 = {
+        {  0,  0,  0},
+        {  0,  0,  0},
+        {  0,  0,  0},
+    };
+    static final String[][] compData4 = {
+        /*
+         * Data to verify Japanese normalization
+         */
+        {"\u309E", "\u309D\u3099",
+         "Hiragana Voiced Iteration Mark(0x309E) <---> Hiragana Iteration Mark(0x309D)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+        {"\u30FE", "\u30FD\u3099",
+         "Katakana Voiced Iteration Mark(0x30FE) <---> Katakana iteration mark(0x30FD)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+        {"\u306F\u3099", "\u3070",
+         "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"BA\"(0x3070)"},
+        {"\u306F\u309A", "\u3071",
+         "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A) <---> Hiragana \"PA\"(0x3071)"},
+        {"\u30EF\u3099", "\u30F7",
+         "Katakana \"WA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VA\"(0x30F7)"},
+        {"\u30F0\u3099", "\u30F8",
+         "Katakana \"WI\"(0x30F0)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VI\"(0x30F8)"},
+        {"\u30F1\u3099", "\u30F9",
+         "Katakana \"WE\"(0x30F1)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VE\"(0x30F9)"},
+        {"\u30F2\u3099", "\u30FA",
+         "Katakana \"WO\"(0x30F2)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VO\"(0x30FA)"},
+        {"\u3046\u3099", "\u3094",
+         "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"VU\"(0x3094)"},
+        {"\u30A6\u3099", "\u30F4",
+         "Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"},
+
+        // verify normalization
+        {"\u2260", "\u003D\u0338",
+         "Not Equal To(0x2260) <---> Equal(0x003D)Combining Long Solidus Overlay(0x0338)"},
+        {"\u2262", "\u2261\u0338",
+         "Not Identical To(0x2262) <---> Identical To(0x2261)Combining Long Solidus Overlay(0x0338)"},
+        {"\u226E", "\u003C\u0338",
+         "Not Less-than(0x226E) <---> Less-than Sign(0x003C)Combining Long Solidus Overlay(0x0338)"},
+
+        // Verify a character which has been added since Unicode 2.1.X.
+        {"\u798F", "\uFA1B",
+         "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"},
+    };
+
+    /*
+     *                    | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+     * -------------------+--------------------+------------------+-------------
+     *  PRIMARY           | s1 > s2 (1)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  SECONDARY         | s1 > s2 (1)        | s1 = s2 (0)      | s1 = s2 (0)
+     *  TERTIARY(default) | S1 > s2 (1)        | s1 = s2 (0)      | s1 = s2 (0)
+     */
+    static final int[][] results5 = {
+        {  1,  0,  0},
+        {  1,  0,  0},
+        {  1,  0,  0},
+    };
+    static final String[][] compData5 = {
+        /*
+         * Data to verify normalization
+         */
+        {"\u226D", "\u224D\u0338",
+         "Not Equivalent To(0x226D) <---> Equivalent To(0x224D)Combining Long Solidus Overlay(0x0338)"},
+    };
+
+    static final int[][] results6 = {
+        {  1, -1, -1},
+        {  1, -1, -1},
+        {  1, -1, -1},
+    };
+    static final String[][] compData6 = {
+        /*
+         * Data to verify normalization
+         */
+        {"\u226D", "\u226C",
+         "Not Equivalent To(0x226D) <---> Between(0x226C)"},
+        {"\u226D", "\u225F",
+         "Not Equivalent To(0x226D) <---> Questioned Equal To(0x225F)"},
+    };
+
+
+    /*
+     * The following data isn't used at the moment because iteration marks
+     * aren't supported now.
+     */
+    static final String[][] compData0 = {
+        {"\u307F\u307F", "\u307F\u309D",
+         "Hiragana \"MIMI\"(0x307F 0x307F) <---> Hiragana \"MI\"(0x307F)Hiragana Iteration Mark(0x309D)"},
+        {"\u3044\u3059\u305A", "\u3044\u3059\u309E",
+         "Hiragana \"ISUZU\"(0x3044 0x3059 0x305A) <---> Hiragana \"ISU\"(0x3044 0x3059)Hiragana Voiced Iteration Mark(0x309E)"},
+        {"\u30DF\u30DF", "\u30DF\u30FD",
+         "Katakana \"MIMI\"(0x30DF 0x30DF) <---> Katakana \"MI\"(0x30DF)Katakana Iteration Mark(0x30FD)"},
+        {"\u30A4\u30B9\u30BA", "\u30A4\u30B9\u30FE",
+         "Katakana \"ISUZU\"(0x30A4 0x30B9 0x30BA) <---> Katakana \"ISU\"(0x30A4 0x30B9)Katakana Voiced Iteration Mark(0x30FE)"},
+    };
+
+
+    static final String[] decomp_name = {
+        "NO_DECOMP", "CANONICAL_DECOMP", "FULL_DECOMP"
+    };
+
+    static final String[] strength_name = {
+        "PRIMARY", "SECONDARY", "TERTIARY"
+    };
+
+
+    Collator col = Collator.getInstance(Locale.JAPAN);
+    int result = 0;
+
+    public static void main(String[] args) throws Exception {
+        new JapaneseTest().run();
+    }
+
+    public void run() {
+        // Use all available localse on the initial testing....
+        // Locale[] locales = Locale.getAvailableLocales();
+        Locale[] locales = { Locale.getDefault() };
+
+        for (int l = 0; l < locales.length; l++) {
+            Locale.setDefault(locales[l]);
+
+            for (int decomp = 0; decomp < 3; decomp++) {// See decomp_name.
+                col.setDecomposition(decomp);
+
+                for (int strength = 0; strength < 3; strength++) {// See strength_name.
+//                  System.err.println("\n" + locales[l] + ": " + strength_name[strength] + " --- " + decomp_name[decomp]);
+
+                    col.setStrength(strength);
+                    doCompare(compData1, results1[strength][decomp], strength, decomp);
+                    doCompare(compData2, results2[strength][decomp], strength, decomp);
+                    doCompare(compData3, results3[strength][decomp], strength, decomp);
+                    doCompare(compData4, results4[strength][decomp], strength, decomp);
+                    doCompare(compData5, results5[strength][decomp], strength, decomp);
+                    doCompare(compData6, results6[strength][decomp], strength, decomp);
+                }
+            }
+        }
+
+        /* Check result */
+        if (result !=0) {
+            throw new RuntimeException("Unexpected results on Japanese collation.");
+        }
+    }
+
+    void doCompare(String[][] s, int expectedValue, int strength, int decomp) {
+        int value;
+        for (int i=0; i < s.length; i++) {
+            if ((value = col.compare(s[i][0], s[i][1])) != expectedValue) {
+                result++;
+                System.err.println(strength_name[strength] +
+                                   ": compare() returned unexpected value.(" +
+                                   value + ") on " + decomp_name[decomp] +
+                                   "     Expected(" + expectedValue +
+                                   ") for " + s[i][2]);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/KoreanTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 1.1 02/09/12
+ * @bug 4176141 4655819
+ * @summary Regression tests for Korean Collation
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class KoreanTest {
+
+    // NOTE:
+    //   Golden data in this test case is locale data dependent and
+    //   may need to be changed if the Korean locale collation rules
+    //   are changed.
+
+    // And, CollationDecomp has been set to 0(NO_DECOMPOSITION) in
+    // LocaleElements_ko.java.
+    // This is very important to consider what is correct behavior in
+    // Korean Collator. Sometimes different from other locales.
+
+    /*
+     * TERTIARY(default): s1 < s2,  SECONDARY: s1 < s2,  PRIMARY: s1 < s2
+     */
+    static final String[][] compData1 = {
+        /*
+         * Data to verify '<' relationship in LocaleElements_ja.java
+         */
+        {"\uACE0\uC591\uC774", "\u732B",
+         "Hangul \"Cat\"(0xACE0 0xC591 0xC774) <---> Chinese Kanji \"Cat\"(0x732B)"},
+        {"\u30FB", "\u2025",
+         "Katakana middle dot(0x30FB) <---> Two dot leader(0x2025)"},
+
+        {"\u00B1", "\u2260",
+         "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"},
+        {"\u3011", "\u2260",
+         "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"},
+        {"\u2260", "\u2103",
+         "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"},
+        {"\u2260", "\u2606",
+         "Not Equal To(0x2260) <---> White Star(0x2606)"},
+
+        // Unlike other locales' Collator, compare() returns -1 because of
+        // NO_DECOMPOSITION.
+        /* above "assumption" is no longer true, now we do normalize ("decomposition")
+           for the pattern in ko locale, but exclude those hangul syllables, so the
+           test case below need to be excluded from tiger/1.5
+        {"\u003D\u0338", "\u2260",
+         "Equal(0x003D)Combining Long Solidus Overlay(0x0338) <---> Not Equal To(0x2260)"},
+         */
+    };
+
+    /*
+     * TERTIARY(default): s1 = s2,  SECONDARY: s1 = s2,  PRIMARY: s1 = s2
+     */
+    static final String[][] compData2 = {
+        // Verify a character which has been added since Unicode 2.1.X.
+        {"\u798F", "\uFA1B",
+         "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"},
+
+    };
+
+    Collator col = Collator.getInstance(Locale.KOREA);
+    int result = 0;
+
+    public static void main(String[] args) throws Exception {
+        new KoreanTest().run();
+    }
+
+    public void run() {
+        //
+        // Test for TERTIARY(default)
+        //
+        doCompare(compData1);
+        doEquals(compData2);
+
+        //
+        // Test for SECONDARY
+        //
+        col.setStrength(Collator.SECONDARY);
+        doCompare(compData1);
+        doEquals(compData2);
+
+        //
+        // Test for PRIMARY
+        //
+        col.setStrength(Collator.PRIMARY);
+        doCompare(compData1);
+        doEquals(compData2);
+
+        if (result !=0) {
+            throw new RuntimeException("Unexpected results on Korean collation.");
+        }
+    }
+
+    /* compare() should return -1 for each combination. */
+    void doCompare(String[][] s) {
+        int value;
+        for (int i=0; i < s.length; i++) {
+            if ((value = col.compare(s[i][0], s[i][1])) > -1) {
+                result++;
+                System.err.println("TERTIARY: The first string should be less than the second string:  " +
+                    s[i][2] + "  compare() returned " + value + ".");
+            }
+        }
+    }
+
+    /* equals() should return true for each combination. */
+    void doEquals(String[][] s) {
+        for (int i=0; i < s.length; i++) {
+            if (!col.equals(s[i][0], s[i][1])) {
+                result++;
+                System.err.println("TERTIARY: The first string should be equals to the second string:  " +
+                    s[i][2] + "  compare() returned " +
+                    col.compare(s[i][0], s[i][1] + "."));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/MonkeyTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Collation, Monkey style
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.io.IOException;
+import java.util.Random;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+
+public class MonkeyTest extends CollatorTest
+{
+    public static void main(String[] args) throws Exception {
+        new MonkeyTest().run(args);
+    }
+
+    public void report(String s, String t, int result, int revResult)
+    {
+        if (result == -1)
+        {
+            if (revResult != 1)
+                errln(" --> Test Failed");
+        }
+        else if (result == 1)
+        {
+            if (revResult != -1)
+                errln(" --> Test Failed");
+        }
+        else if (result == 0)
+        {
+            if (revResult != 0)
+                errln(" --> Test Failed");
+        }
+    }
+
+    public void TestCollationKey()
+    {
+        String source = "-abcdefghijklmnopqrstuvwxyz#&^$@";
+        Random r = new Random(3);
+        int s = checkValue(r.nextInt() % source.length());
+        int t = checkValue(r.nextInt() % source.length());
+        int slen = checkValue((r.nextInt() - source.length()) % source.length());
+        int tlen = checkValue((r.nextInt() - source.length()) % source.length());
+        String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen));
+        String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen));
+        myCollator.setStrength(Collator.TERTIARY);
+        CollationKey CollationKey1 = myCollator.getCollationKey(subs);
+        CollationKey CollationKey2 = myCollator.getCollationKey(subt);
+        int result = CollationKey1.compareTo(CollationKey2);  // Tertiary
+        int revResult = CollationKey2.compareTo(CollationKey1);  // Tertiary
+        report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult);
+        myCollator.setStrength(Collator.SECONDARY);
+        CollationKey1 = myCollator.getCollationKey(subs);
+        CollationKey2 = myCollator.getCollationKey(subt);
+        result = CollationKey1.compareTo(CollationKey2);  // Secondary
+        revResult = CollationKey2.compareTo(CollationKey1);   // Secondary
+        report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult);
+        myCollator.setStrength(Collator.PRIMARY);
+        CollationKey1 = myCollator.getCollationKey(subs);
+        CollationKey2 = myCollator.getCollationKey(subt);
+        result = CollationKey1.compareTo(CollationKey2);  // Primary
+        revResult = CollationKey2.compareTo(CollationKey1);   // Primary
+        report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult);
+        String addOne = subs + "\uE000";
+        CollationKey1 = myCollator.getCollationKey(subs);
+        CollationKey2 = myCollator.getCollationKey(addOne);
+        result = CollationKey1.compareTo(CollationKey2);
+        if (result != -1)
+            errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed.");
+        result = CollationKey2.compareTo(CollationKey1);
+        if (result != 1)
+            errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed.");
+    }
+    private static int checkValue(int value)
+    {
+        value *= (value > 0) ? 1 : -1;
+        return value;
+    }
+    public void TestCompare()
+    {
+        String source = "-abcdefghijklmnopqrstuvwxyz#&^$@";
+        Random r = new Random(3);
+        int s = checkValue(r.nextInt() % source.length());
+        int t = checkValue(r.nextInt() % source.length());
+        int slen = checkValue((r.nextInt() - source.length()) % source.length());
+        int tlen = checkValue((r.nextInt() - source.length()) % source.length());
+        String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen));
+        String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen));
+        myCollator.setStrength(Collator.TERTIARY);
+        int result = myCollator.compare(subs, subt);  // Tertiary
+        int revResult = myCollator.compare(subt, subs);  // Tertiary
+        report(subs, subt, result, revResult);
+        myCollator.setStrength(Collator.SECONDARY);
+        result = myCollator.compare(subs, subt);  // Secondary
+        revResult = myCollator.compare(subt, subs);  // Secondary
+        report(subs, subt, result, revResult);
+        myCollator.setStrength(Collator.PRIMARY);
+        result = myCollator.compare(subs, subt);  // Primary
+        revResult = myCollator.compare(subt, subs);  // Primary
+        report(subs, subt, result, revResult);
+        String addOne = subs + "\uE000";
+        result = myCollator.compare(subs, addOne);
+        if (result != -1)
+            errln("Test : " + subs + " .LT. " + addOne + " Failed.");
+        result = myCollator.compare(addOne, subs);
+        if (result != 1)
+            errln("Test : " + addOne + " .GE. " + subs + " Failed.");
+    }
+    private static Collator myCollator = Collator.getInstance();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/Regression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,940 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4048446 4051866 4053636 4054238 4054734 4054736 4058613 4059820 4060154
+ *      4062418 4065540 4066189 4066696 4076676 4078588 4079231 4081866 4087241
+ *      4087243 4092260 4095316 4101940 4103436 4114076 4114077 4124632 4132736
+ *      4133509 4139572 4141640 4179126 4179686 4244884 4663220
+ * @library /java/text/testlib
+ * @summary Regression tests for Collation and associated classes
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.text.*;
+import java.util.Locale;
+import java.util.Vector;
+
+
+public class Regression extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new Regression().run(args);
+    }
+
+    // CollationElementIterator.reset() doesn't work
+    //
+    public void Test4048446() {
+        CollationElementIterator i1 = en_us.getCollationElementIterator(test1);
+        CollationElementIterator i2 = en_us.getCollationElementIterator(test1);
+
+        while ( i1.next() != CollationElementIterator.NULLORDER ) {
+        }
+        i1.reset();
+
+        assertEqual(i1, i2);
+    }
+
+
+    // Collator -> rules -> Collator round-trip broken for expanding characters
+    //
+    public void Test4051866() throws ParseException {
+        // Build a collator containing expanding characters
+        RuleBasedCollator c1 = new RuleBasedCollator("< o "
+                                                    +"& oe ,o\u3080"
+                                                    +"& oe ,\u1530 ,O"
+                                                    +"& OE ,O\u3080"
+                                                    +"& OE ,\u1520"
+                                                    +"< p ,P");
+
+        // Build another using the rules from  the first
+        RuleBasedCollator c2 = new RuleBasedCollator(c1.getRules());
+
+        // Make sure they're the same
+        if (!c1.getRules().equals(c2.getRules())) {
+            errln("Rules are not equal");
+        }
+    }
+
+    // Collator thinks "black-bird" == "black"
+    //
+    public void Test4053636() {
+        if (en_us.equals("black-bird","black")) {
+            errln("black-bird == black");
+        }
+    }
+
+
+    // CollationElementIterator will not work correctly if the associated
+    // Collator object's mode is changed
+    //
+    public void Test4054238() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+        CollationElementIterator i1 = en_us.getCollationElementIterator(test3);
+
+        c.setDecomposition(Collator.NO_DECOMPOSITION);
+        CollationElementIterator i2 = en_us.getCollationElementIterator(test3);
+
+        // At this point, BOTH iterators should use NO_DECOMPOSITION, since the
+        // collator itself is in that mode
+        assertEqual(i1, i2);
+    }
+
+    // Collator.IDENTICAL documented but not implemented
+    //
+    public void Test4054734() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        try {
+            c.setStrength(Collator.IDENTICAL);
+        }
+        catch (Exception e) {
+            errln("Caught " + e.toString() + " setting Collator.IDENTICAL");
+        }
+
+        String[] decomp = {
+            "\u0001",   "<",    "\u0002",
+            "\u0001",   "=",    "\u0001",
+            "A\u0001",  ">",    "~\u0002",      // Ensure A and ~ are not compared bitwise
+            "\u00C0",   "=",    "A\u0300"       // Decomp should make these equal
+        };
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+        compareArray(c, decomp);
+
+        String[] nodecomp = {
+            "\u00C0",   ">",    "A\u0300"       // A-grave vs. A combining-grave
+        };
+        c.setDecomposition(Collator.NO_DECOMPOSITION);
+        compareArray(c, nodecomp);
+    }
+
+    // Full Decomposition mode not implemented
+    //
+    public void Test4054736() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+        String[] tests = {
+            "\uFB4f", "=", "\u05D0\u05DC",  // Alef-Lamed vs. Alef, Lamed
+        };
+
+        compareArray(c, tests);
+    }
+
+    // Collator.getInstance() causes an ArrayIndexOutofBoundsException for Korean
+    //
+    public void Test4058613() {
+        // Creating a default collator doesn't work when Korean is the default
+        // locale
+
+        Locale oldDefault = Locale.getDefault();
+
+        Locale.setDefault( Locale.KOREAN );
+        try {
+            Collator c = Collator.getInstance();
+
+            // Since the fix to this bug was to turn of decomposition for Korean collators,
+            // ensure that's what we got
+            if (c.getDecomposition() != Collator.NO_DECOMPOSITION) {
+              errln("Decomposition is not set to NO_DECOMPOSITION");
+            }
+        }
+        finally {
+            Locale.setDefault(oldDefault);
+        }
+    }
+
+    // RuleBasedCollator.getRules does not return the exact pattern as input
+    // for expanding character sequences
+    //
+    public void Test4059820() {
+        RuleBasedCollator c = null;
+        try {
+            c = new RuleBasedCollator("< a < b , c/a < d < z");
+        } catch (ParseException e) {
+            errln("Exception building collator: " + e.toString());
+            return;
+        }
+        if ( c.getRules().indexOf("c/a") == -1) {
+            errln("returned rules do not contain 'c/a'");
+        }
+    }
+
+    // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I"
+    //
+    public void Test4060154() {
+        RuleBasedCollator c = null;
+        try {
+            c = new RuleBasedCollator("< g, G < h, H < i, I < j, J"
+                                      + " & H < \u0131, \u0130, i, I" );
+        } catch (ParseException e) {
+            errln("Exception building collator: " + e.toString());
+            return;
+        }
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+
+        String[] tertiary = {
+            "A",        "<",    "B",
+            "H",        "<",    "\u0131",
+            "H",        "<",    "I",
+            "\u0131",   "<",    "\u0130",
+            "\u0130",   "<",    "i",
+            "\u0130",   ">",    "H",
+        };
+        c.setStrength(Collator.TERTIARY);
+        compareArray(c, tertiary);
+
+        String[] secondary = {
+            "H",        "<",    "I",
+            "\u0131",   "=",    "\u0130",
+        };
+        c.setStrength(Collator.PRIMARY);
+        compareArray(c, secondary);
+    };
+
+    // Secondary/Tertiary comparison incorrect in French Secondary
+    //
+    public void Test4062418() throws ParseException {
+        RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE);
+        c.setStrength(Collator.SECONDARY);
+
+        String[] tests = {
+                "p\u00eache",    "<",    "p\u00e9ch\u00e9",    // Comparing accents from end, p\u00e9ch\u00e9 is greater
+        };
+
+        compareArray(c, tests);
+    }
+
+    // Collator.compare() method broken if either string contains spaces
+    //
+    public void Test4065540() {
+        if (en_us.compare("abcd e", "abcd f") == 0) {
+            errln("'abcd e' == 'abcd f'");
+        }
+    }
+
+    // Unicode characters need to be recursively decomposed to get the
+    // correct result. For example,
+    // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300.
+    //
+    public void Test4066189() {
+        String test1 = "\u1EB1";
+        String test2 = "a\u0306\u0300";
+
+        RuleBasedCollator c1 = (RuleBasedCollator) en_us.clone();
+        c1.setDecomposition(Collator.FULL_DECOMPOSITION);
+        CollationElementIterator i1 = en_us.getCollationElementIterator(test1);
+
+        RuleBasedCollator c2 = (RuleBasedCollator) en_us.clone();
+        c2.setDecomposition(Collator.NO_DECOMPOSITION);
+        CollationElementIterator i2 = en_us.getCollationElementIterator(test2);
+
+        assertEqual(i1, i2);
+    }
+
+    // French secondary collation checking at the end of compare iteration fails
+    //
+    public void Test4066696() {
+        RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE);
+        c.setStrength(Collator.SECONDARY);
+
+        String[] tests = {
+            "\u00e0",   "<",     "\u01fa",       // a-grave <  A-ring-acute
+        };
+
+        compareArray(c, tests);
+    }
+
+
+    // Bad canonicalization of same-class combining characters
+    //
+    public void Test4076676() {
+        // These combining characters are all in the same class, so they should not
+        // be reordered, and they should compare as unequal.
+        String s1 = "A\u0301\u0302\u0300";
+        String s2 = "A\u0302\u0300\u0301";
+
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        if (c.compare(s1,s2) == 0) {
+            errln("Same-class combining chars were reordered");
+        }
+    }
+
+
+    // RuleBasedCollator.equals(null) throws NullPointerException
+    //
+    public void Test4079231() {
+        try {
+            if (en_us.equals(null)) {
+                errln("en_us.equals(null) returned true");
+            }
+        }
+        catch (Exception e) {
+            errln("en_us.equals(null) threw " + e.toString());
+        }
+    }
+
+    // RuleBasedCollator breaks on "< a < bb" rule
+    //
+    public void Test4078588() throws ParseException {
+        RuleBasedCollator rbc=new RuleBasedCollator("< a < bb");
+
+        int result = rbc.compare("a","bb");
+
+        if (result != -1) {
+            errln("Compare(a,bb) returned " + result + "; expected -1");
+        }
+    }
+
+    // Combining characters in different classes not reordered properly.
+    //
+    public void Test4081866() throws ParseException {
+        // These combining characters are all in different classes,
+        // so they should be reordered and the strings should compare as equal.
+        String s1 = "A\u0300\u0316\u0327\u0315";
+        String s2 = "A\u0327\u0316\u0315\u0300";
+
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        // Now that the default collators are set to NO_DECOMPOSITION
+        // (as a result of fixing bug 4114077), we must set it explicitly
+        // when we're testing reordering behavior.  -- lwerner, 5/5/98
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+
+        if (c.compare(s1,s2) != 0) {
+            errln("Combining chars were not reordered");
+        }
+    }
+
+    // string comparison errors in Scandinavian collators
+    //
+    public void Test4087241() {
+        RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(
+                                                        new Locale("da", "DK"));
+        c.setStrength(Collator.SECONDARY);
+
+        String[] tests = {
+            "\u007a",   "<",    "\u00e6",       // z        < ae
+            "a\u0308",  "<",    "a\u030a",      // a-unlaut < a-ring
+            "Y",        "<",    "u\u0308",      // Y        < u-umlaut
+        };
+
+        compareArray(c, tests);
+    }
+
+    // CollationKey takes ignorable strings into account when it shouldn't
+    //
+    public void Test4087243() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        String[] tests = {
+            "123",      "=",    "123\u0001",        // 1 2 3  =  1 2 3 ctrl-A
+        };
+
+        compareArray(c, tests);
+    }
+
+    // Mu/micro conflict
+    // Micro symbol and greek lowercase letter Mu should sort identically
+    //
+    public void Test4092260() {
+        Collator c = Collator.getInstance(new Locale("el", ""));
+
+        // will only be equal when FULL_DECOMPOSITION is used
+        c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+        String[] tests = {
+            "\u00B5",      "=",    "\u03BC",
+        };
+
+        compareArray(c, tests);
+    }
+
+    void Test4095316() {
+        Collator c = Collator.getInstance(new Locale("el", "GR"));
+        c.setStrength(Collator.TERTIARY);
+        // javadocs for RuleBasedCollator clearly specify that characters containing compatability
+        // chars MUST use FULL_DECOMPOSITION to get accurate comparisons.
+        c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+        String[] tests = {
+            "\u03D4",      "=",    "\u03AB",
+        };
+
+        compareArray(c, tests);
+    }
+
+    public void Test4101940() {
+        try {
+            RuleBasedCollator c = new RuleBasedCollator("< a < b");
+            CollationElementIterator i = c.getCollationElementIterator("");
+            i.reset();
+
+            if (i.next() != i.NULLORDER) {
+                errln("next did not return NULLORDER");
+            }
+        }
+        catch (Exception e) {
+            errln("Caught " + e );
+        }
+    }
+
+    // Collator.compare not handling spaces properly
+    //
+    public void Test4103436() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        String[] tests = {
+            "file",      "<",    "file access",
+            "file",      "<",    "fileaccess",
+        };
+
+        compareArray(c, tests);
+    }
+
+    // Collation not Unicode conformant with Hangul syllables
+    //
+    public void Test4114076() {
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        //
+        // With Canonical decomposition, Hangul syllables should get decomposed
+        // into Jamo, but Jamo characters should not be decomposed into
+        // conjoining Jamo
+        //
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+        String[] test1 = {
+            "\ud4db",   "=",    "\u1111\u1171\u11b6",
+        };
+        compareArray(c, test1);
+
+        // Full decomposition result should be the same as canonical decomposition
+        // for all hangul.
+        c.setDecomposition(Collator.FULL_DECOMPOSITION);
+        compareArray(c, test1);
+
+    }
+
+
+    // Collator.getCollationKey was hanging on certain character sequences
+    //
+    public void Test4124632() throws Exception {
+        Collator coll = Collator.getInstance(Locale.JAPAN);
+
+        try {
+            coll.getCollationKey("A\u0308bc");
+        } catch (OutOfMemoryError e) {
+            errln("Ran out of memory -- probably an infinite loop");
+        }
+    }
+
+    // sort order of french words with multiple accents has errors
+    //
+    public void Test4132736() {
+        Collator c = Collator.getInstance(Locale.FRANCE);
+
+        String[] test1 = {
+            "e\u0300e\u0301",   "<",    "e\u0301e\u0300",
+            "e\u0300\u0301",    ">",    "e\u0301\u0300",
+        };
+        compareArray(c, test1);
+    }
+
+    // The sorting using java.text.CollationKey is not in the exact order
+    //
+    public void Test4133509() {
+        String[] test1 = {
+            "Exception",    "<",    "ExceptionInInitializerError",
+            "Graphics",     "<",    "GraphicsEnvironment",
+            "String",       "<",    "StringBuffer",
+        };
+        compareArray(en_us, test1);
+    }
+
+    // Collation with decomposition off doesn't work for Europe
+    //
+    public void Test4114077() {
+        // Ensure that we get the same results with decomposition off
+        // as we do with it on....
+
+        RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+        c.setStrength(Collator.TERTIARY);
+
+        String[] test1 = {
+            "\u00C0",        "=", "A\u0300",        // Should be equivalent
+            "p\u00eache",         ">", "p\u00e9ch\u00e9",
+            "\u0204",        "=", "E\u030F",
+            "\u01fa",        "=", "A\u030a\u0301",  // a-ring-acute -> a-ring, acute
+                                                    //   -> a, ring, acute
+            "A\u0300\u0316", "<", "A\u0316\u0300",  // No reordering --> unequal
+        };
+        c.setDecomposition(Collator.NO_DECOMPOSITION);
+        compareArray(c, test1);
+
+        String[] test2 = {
+            "A\u0300\u0316", "=", "A\u0316\u0300",      // Reordering --> equal
+        };
+        c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+        compareArray(c, test2);
+    }
+
+    // Support for Swedish gone in 1.1.6 (Can't create Swedish collator)
+    //
+    public void Test4141640() {
+        //
+        // Rather than just creating a Swedish collator, we might as well
+        // try to instantiate one for every locale available on the system
+        // in order to prevent this sort of bug from cropping up in the future
+        //
+        Locale[] locales = Collator.getAvailableLocales();
+
+        for (int i = 0; i < locales.length; i++) {
+            try {
+                Collator c = Collator.getInstance(locales[i]);
+            } catch (Exception e) {
+                errln("Caught " + e + " creating collator for " + locales[i]);
+            }
+        }
+    }
+
+    // getCollationKey throws exception for spanish text
+    // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6
+    //
+    public void Test4139572() {
+        //
+        // Code pasted straight from the bug report
+        //
+        // create spanish locale and collator
+        Locale l = new Locale("es", "es");
+        Collator col = Collator.getInstance(l);
+
+        // this spanish phrase kills it!
+        col.getCollationKey("Nombre De Objeto");
+    }
+
+    // RuleBasedCollator doesn't use getCollationElementIterator internally
+    //
+    public void Test4146160() throws ParseException {
+        //
+        // Use a custom collator class whose getCollationElementIterator
+        // methods increment a count....
+        //
+        My4146160Collator.count = 0;
+        new My4146160Collator().getCollationKey("1");
+        if (My4146160Collator.count < 1) {
+            errln("getCollationElementIterator not called");
+        }
+
+        My4146160Collator.count = 0;
+        new My4146160Collator().compare("1", "2");
+        if (My4146160Collator.count < 1) {
+            errln("getCollationElementIterator not called");
+        }
+    }
+
+    static class My4146160Collator extends RuleBasedCollator {
+        public My4146160Collator() throws ParseException {
+            super(Regression.en_us.getRules());
+        }
+
+        public CollationElementIterator getCollationElementIterator(
+                                            String text) {
+            count++;
+            return super.getCollationElementIterator(text);
+        }
+        public CollationElementIterator getCollationElementIterator(
+                                            CharacterIterator text) {
+            count++;
+            return super.getCollationElementIterator(text);
+        }
+
+        public static int count = 0;
+    };
+
+    // CollationElementIterator.previous broken for expanding char sequences
+    //
+    public void Test4179686() throws ParseException {
+
+        // Create a collator with a few expanding character sequences in it....
+        RuleBasedCollator coll = new RuleBasedCollator(en_us.getRules()
+                                                    + " & ae ; \u00e4 & AE ; \u00c4"
+                                                    + " & oe ; \u00f6 & OE ; \u00d6"
+                                                    + " & ue ; \u00fc & UE ; \u00dc");
+
+        String text = "T\u00f6ne"; // o-umlaut
+
+        CollationElementIterator iter = coll.getCollationElementIterator(text);
+        Vector elements = new Vector();
+        int elem;
+
+        // Iterate forward and collect all of the elements into a Vector
+        while ((elem = iter.next()) != iter.NULLORDER) {
+            elements.addElement(new Integer(elem));
+        }
+
+        // Now iterate backward and make sure they're the same
+        int index = elements.size() - 1;
+        while ((elem = iter.previous()) != iter.NULLORDER) {
+            int expect = ((Integer)elements.elementAt(index)).intValue();
+
+            if (elem != expect) {
+                errln("Mismatch at index " + index
+                      + ": got " + Integer.toString(elem,16)
+                      + ", expected " + Integer.toString(expect,16));
+            }
+            index--;
+        }
+    }
+
+    public void Test4244884() throws ParseException {
+        RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US);
+        coll = new RuleBasedCollator(coll.getRules()
+                + " & C < ch , cH , Ch , CH < cat < crunchy");
+
+        String[] testStrings = new String[] {
+            "car",
+            "cave",
+            "clamp",
+            "cramp",
+            "czar",
+            "church",
+            "catalogue",
+            "crunchy",
+            "dog"
+        };
+
+        for (int i = 1; i < testStrings.length; i++) {
+            if (coll.compare(testStrings[i - 1], testStrings[i]) >= 0) {
+                errln("error: \"" + testStrings[i - 1]
+                    + "\" is greater than or equal to \"" + testStrings[i]
+                    + "\".");
+            }
+        }
+    }
+
+    public void Test4179216() throws ParseException {
+        // you can position a CollationElementIterator in the middle of
+        // a contracting character sequence, yielding a bogus collation
+        // element
+        RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US);
+        coll = new RuleBasedCollator(coll.getRules()
+                + " & C < ch , cH , Ch , CH < cat < crunchy");
+        String testText = "church church catcatcher runcrunchynchy";
+        CollationElementIterator iter = coll.getCollationElementIterator(
+                testText);
+
+        // test that the "ch" combination works properly
+        iter.setOffset(4);
+        int elt4 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.reset();
+        int elt0 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(5);
+        int elt5 = CollationElementIterator.primaryOrder(iter.next());
+
+        if (elt4 != elt0 || elt5 != elt0)
+            errln("The collation elements at positions 0 (" + elt0 + "), 4 ("
+                    + elt4 + "), and 5 (" + elt5 + ") don't match.");
+
+        // test that the "cat" combination works properly
+        iter.setOffset(14);
+        int elt14 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(15);
+        int elt15 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(16);
+        int elt16 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(17);
+        int elt17 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(18);
+        int elt18 = CollationElementIterator.primaryOrder(iter.next());
+
+        iter.setOffset(19);
+        int elt19 = CollationElementIterator.primaryOrder(iter.next());
+
+        if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17
+                || elt14 != elt18 || elt14 != elt19)
+            errln("\"cat\" elements don't match: elt14 = " + elt14 + ", elt15 = "
+            + elt15 + ", elt16 = " + elt16 + ", elt17 = " + elt17
+            + ", elt18 = " + elt18 + ", elt19 = " + elt19);
+
+        // now generate a complete list of the collation elements,
+        // first using next() and then using setOffset(), and
+        // make sure both interfaces return the same set of elements
+        iter.reset();
+
+        int elt = iter.next();
+        int count = 0;
+        while (elt != CollationElementIterator.NULLORDER) {
+            ++count;
+            elt = iter.next();
+        }
+
+        String[] nextElements = new String[count];
+        String[] setOffsetElements = new String[count];
+        int lastPos = 0;
+
+        iter.reset();
+        elt = iter.next();
+        count = 0;
+        while (elt != CollationElementIterator.NULLORDER) {
+            nextElements[count++] = testText.substring(lastPos, iter.getOffset());
+            lastPos = iter.getOffset();
+            elt = iter.next();
+        }
+        count = 0;
+        for (int i = 0; i < testText.length(); ) {
+            iter.setOffset(i);
+            lastPos = iter.getOffset();
+            elt = iter.next();
+            setOffsetElements[count++] = testText.substring(lastPos, iter.getOffset());
+            i = iter.getOffset();
+        }
+        for (int i = 0; i < nextElements.length; i++) {
+            if (nextElements[i].equals(setOffsetElements[i])) {
+                logln(nextElements[i]);
+            } else {
+                errln("Error: next() yielded " + nextElements[i] + ", but setOffset() yielded "
+                    + setOffsetElements[i]);
+            }
+        }
+    }
+
+    public void Test4216006() throws Exception {
+        // rule parser barfs on "<\u00e0=a\u0300", and on other cases
+        // where the same token (after normalization) appears twice in a row
+        boolean caughtException = false;
+        try {
+            RuleBasedCollator dummy = new RuleBasedCollator("\u00e0<a\u0300");
+        }
+        catch (ParseException e) {
+            caughtException = true;
+        }
+        if (!caughtException) {
+            throw new Exception("\"a<a\" collation sequence didn't cause parse error!");
+        }
+
+        RuleBasedCollator collator = new RuleBasedCollator("<\u00e0=a\u0300");
+        collator.setDecomposition(Collator.FULL_DECOMPOSITION);
+        collator.setStrength(Collator.IDENTICAL);
+
+        String[] tests = {
+            "a\u0300", "=", "\u00e0",
+            "\u00e0",  "=", "a\u0300"
+        };
+
+        compareArray(collator, tests);
+    }
+
+    public void Test4171974() {
+        // test French accent ordering more thoroughly
+        String[] frenchList = {
+            "\u0075\u0075",     // u u
+            "\u00fc\u0075",     // u-umlaut u
+            "\u01d6\u0075",     // u-umlaut-macron u
+            "\u016b\u0075",     // u-macron u
+            "\u1e7b\u0075",     // u-macron-umlaut u
+            "\u0075\u00fc",     // u u-umlaut
+            "\u00fc\u00fc",     // u-umlaut u-umlaut
+            "\u01d6\u00fc",     // u-umlaut-macron u-umlaut
+            "\u016b\u00fc",     // u-macron u-umlaut
+            "\u1e7b\u00fc",     // u-macron-umlaut u-umlaut
+            "\u0075\u01d6",     // u u-umlaut-macron
+            "\u00fc\u01d6",     // u-umlaut u-umlaut-macron
+            "\u01d6\u01d6",     // u-umlaut-macron u-umlaut-macron
+            "\u016b\u01d6",     // u-macron u-umlaut-macron
+            "\u1e7b\u01d6",     // u-macron-umlaut u-umlaut-macron
+            "\u0075\u016b",     // u u-macron
+            "\u00fc\u016b",     // u-umlaut u-macron
+            "\u01d6\u016b",     // u-umlaut-macron u-macron
+            "\u016b\u016b",     // u-macron u-macron
+            "\u1e7b\u016b",     // u-macron-umlaut u-macron
+            "\u0075\u1e7b",     // u u-macron-umlaut
+            "\u00fc\u1e7b",     // u-umlaut u-macron-umlaut
+            "\u01d6\u1e7b",     // u-umlaut-macron u-macron-umlaut
+            "\u016b\u1e7b",     // u-macron u-macron-umlaut
+            "\u1e7b\u1e7b"      // u-macron-umlaut u-macron-umlaut
+        };
+        Collator french = Collator.getInstance(Locale.FRENCH);
+
+        logln("Testing French order...");
+        checkListOrder(frenchList, french);
+
+        logln("Testing French order without decomposition...");
+        french.setDecomposition(Collator.NO_DECOMPOSITION);
+        checkListOrder(frenchList, french);
+
+        String[] englishList = {
+            "\u0075\u0075",     // u u
+            "\u0075\u00fc",     // u u-umlaut
+            "\u0075\u01d6",     // u u-umlaut-macron
+            "\u0075\u016b",     // u u-macron
+            "\u0075\u1e7b",     // u u-macron-umlaut
+            "\u00fc\u0075",     // u-umlaut u
+            "\u00fc\u00fc",     // u-umlaut u-umlaut
+            "\u00fc\u01d6",     // u-umlaut u-umlaut-macron
+            "\u00fc\u016b",     // u-umlaut u-macron
+            "\u00fc\u1e7b",     // u-umlaut u-macron-umlaut
+            "\u01d6\u0075",     // u-umlaut-macron u
+            "\u01d6\u00fc",     // u-umlaut-macron u-umlaut
+            "\u01d6\u01d6",     // u-umlaut-macron u-umlaut-macron
+            "\u01d6\u016b",     // u-umlaut-macron u-macron
+            "\u01d6\u1e7b",     // u-umlaut-macron u-macron-umlaut
+            "\u016b\u0075",     // u-macron u
+            "\u016b\u00fc",     // u-macron u-umlaut
+            "\u016b\u01d6",     // u-macron u-umlaut-macron
+            "\u016b\u016b",     // u-macron u-macron
+            "\u016b\u1e7b",     // u-macron u-macron-umlaut
+            "\u1e7b\u0075",     // u-macron-umlaut u
+            "\u1e7b\u00fc",     // u-macron-umlaut u-umlaut
+            "\u1e7b\u01d6",     // u-macron-umlaut u-umlaut-macron
+            "\u1e7b\u016b",     // u-macron-umlaut u-macron
+            "\u1e7b\u1e7b"      // u-macron-umlaut u-macron-umlaut
+        };
+        Collator english = Collator.getInstance(Locale.ENGLISH);
+
+        logln("Testing English order...");
+        checkListOrder(englishList, english);
+
+        logln("Testing English order without decomposition...");
+        english.setDecomposition(Collator.NO_DECOMPOSITION);
+        checkListOrder(englishList, english);
+    }
+
+    private void checkListOrder(String[] sortedList, Collator c) {
+        // this function uses the specified Collator to make sure the
+        // passed-in list is already sorted into ascending order
+        for (int i = 0; i < sortedList.length - 1; i++) {
+            if (c.compare(sortedList[i], sortedList[i + 1]) >= 0) {
+                errln("List out of order at element #" + i + ": "
+                        + prettify(sortedList[i]) + " >= "
+                        + prettify(sortedList[i + 1]));
+            }
+        }
+    }
+
+    // CollationElementIterator set doesn't work propertly with next/prev
+    public void Test4663220() {
+        RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(Locale.US);
+        CharacterIterator stringIter = new StringCharacterIterator("fox");
+        CollationElementIterator iter = collator.getCollationElementIterator(stringIter);
+
+        int[] elements_next = new int[3];
+        logln("calling next:");
+        for (int i = 0; i < 3; ++i) {
+            logln("[" + i + "] " + (elements_next[i] = iter.next()));
+        }
+
+        int[] elements_fwd = new int[3];
+        logln("calling set/next:");
+        for (int i = 0; i < 3; ++i) {
+            iter.setOffset(i);
+            logln("[" + i + "] " + (elements_fwd[i] = iter.next()));
+        }
+
+        for (int i = 0; i < 3; ++i) {
+            if (elements_next[i] != elements_fwd[i]) {
+                errln("mismatch at position " + i +
+                      ": " + elements_next[i] +
+                      " != " + elements_fwd[i]);
+            }
+        }
+    }
+
+    //------------------------------------------------------------------------
+    // Internal utilities
+    //
+    private void compareArray(Collator c, String[] tests) {
+        for (int i = 0; i < tests.length; i += 3) {
+
+            int expect = 0;
+            if (tests[i+1].equals("<")) {
+                expect = -1;
+            } else if (tests[i+1].equals(">")) {
+                expect = 1;
+            } else if (tests[i+1].equals("=")) {
+                expect = 0;
+            } else {
+                expect = Integer.decode(tests[i+1]).intValue();
+            }
+
+            int result = c.compare(tests[i], tests[i+2]);
+            if (sign(result) != sign(expect))
+            {
+                errln( i/3 + ": compare(" + prettify(tests[i])
+                                    + " , " + prettify(tests[i+2])
+                                    + ") got " + result + "; expected " + expect);
+            }
+            else
+            {
+                // Collator.compare worked OK; now try the collation keys
+                CollationKey k1 = c.getCollationKey(tests[i]);
+                CollationKey k2 = c.getCollationKey(tests[i+2]);
+
+                result = k1.compareTo(k2);
+                if (sign(result) != sign(expect)) {
+                    errln( i/3 + ": key(" + prettify(tests[i])
+                                        + ").compareTo(key(" + prettify(tests[i+2])
+                                        + ")) got " + result + "; expected " + expect);
+
+                    errln("  " + prettify(k1) + " vs. " + prettify(k2));
+                }
+            }
+        }
+    }
+
+    private static final int sign(int i) {
+        if (i < 0) return -1;
+        if (i > 0) return 1;
+        return 0;
+    }
+
+
+    static RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US);
+
+    String test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?";
+    String test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?";
+    String test3 = "a\u00FCbeck Gr\u00F6\u00DFe L\u00FCbeck";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/SpanishTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Spanish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class SpanishTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new SpanishTest().run(args);
+    }
+
+    /*
+     * TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "alias",
+        "acHc",
+        "acc",
+        "Hello"
+    };
+
+    private static final String[] primaryTargetData = {
+        "allias",
+        "aCHc",
+        "aCHc",
+        "hellO"
+    };
+
+    private static final int[] primaryResults = {
+        -1,  0, -1,  0
+    };
+
+    /*
+     * TestTertiary()
+     */
+    private static final String[] tertiarySourceData = {
+        "alias",
+        "Elliot",
+        "Hello",
+        "acHc",
+        "acc"
+    };
+
+    private static final String[] tertiaryTargetData = {
+        "allias",
+        "Emiot",
+        "hellO",
+        "aCHc",
+        "aCHc"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1, -1,  1, -1, -1
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("es", "ES", ""));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/SurrogatesTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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
+ * 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
+ * @library /java/text/testlib
+ * @summary test Supplementary Character Collation
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+// Quick dummy program for printing out test results
+public class SurrogatesTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new SurrogatesTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "A\ud800\udc04BCD"
+    };
+
+    private static final String[] primaryTargetData = {
+        "A\ud800\udc05BCD"
+    };
+
+    private static final int[] primaryResults = {
+         0
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final String[] tertiarySourceData = {
+        "ABCD",
+        "ABCD",
+        "A\ud800\udc00CD",
+        "WXYZ",
+        "WXYZ",
+        "AFEM",
+        "FGM",
+        "BB",
+        "BB"
+    };
+
+    private static final String[] tertiaryTargetData = {
+        "A\ud800\udc00CD",
+        "AB\ud800\udc00D",
+        "A\ud800\udc01CD",
+        "W\ud800\udc0aYZ",
+        "W\ud800\udc0bYZ",
+        "A\ud800\udc08M",
+        "\ud800\udc08M",
+        "\ud800\udc04\ud800\udc02",
+        "\ud800\udc04\ud800\udc05"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1,  1,  1,  1, -1, -1, -1, -1,  1
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+    }
+
+    private Collator getCollator() {
+        RuleBasedCollator base = (RuleBasedCollator)Collator.getInstance();
+        String rule = base.getRules();
+        try {
+            return new RuleBasedCollator(rule
+                                     + "&B < \ud800\udc01 < \ud800\udc00"
+                                     + ", \ud800\udc02, \ud800\udc03"
+                                     + "; \ud800\udc04, \ud800\udc05"
+                                     + "< \ud800\udc06 < \ud800\udc07"
+                                     + "&FE < \ud800\udc08"
+                                     + "&PE, \ud800\udc09"
+                                     + "&Z < \ud800\udc0a < \ud800\udc0b < \ud800\udc0c"
+                                     + "&\ud800\udc0a < x, X"
+                                     + "&A < \ud800\udc04\ud800\udc05");
+        } catch (Exception e) {
+            errln("Failed to create new RulebasedCollator object");
+            return null;
+        }
+    }
+
+    private Collator myCollation = getCollator();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/Test4401726.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4401726
+ * @author John O'Conner
+ * @library /java/text/testlib
+ * @summary Regression tests for Collation and associated classes
+ */
+
+
+import java.text.*;
+import java.util.Locale;
+import java.util.Vector;
+
+public class Test4401726 extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new Test4401726().run(args);
+    }
+
+   public void TestSetOffSet() {
+
+       int[] expected = {0, -1, 65536};
+       int[] actual = new int[expected.length];
+
+        try {
+            String rule = "< a, A < d; D";
+
+            RuleBasedCollator rbc = new RuleBasedCollator(rule);
+            String str = "aD";
+            CollationElementIterator iterator =
+                rbc.getCollationElementIterator(str);
+
+            iterator.setOffset(0);
+            actual[0] = iterator.getOffset();
+            actual[1] = iterator.previous();
+            iterator.setOffset(0);
+            actual[2] = iterator.next();
+
+            if (compareArray(expected, actual) == false) {
+                errln("Failed.");
+            }
+
+            str = "a";
+            iterator = rbc.getCollationElementIterator(str);
+            iterator.setOffset(0);
+            actual[0] = iterator.getOffset();
+            actual[1] = iterator.previous();
+            iterator.setOffset(0);
+            actual[2] = iterator.next();
+
+            if (compareArray(expected, actual) == false) {
+                errln("Failed.");
+            }
+
+        } catch (ParseException e) {
+            errln("Unexpected ParseException: " + e);
+        }
+
+
+    }
+
+    boolean compareArray(int[] expected, int[] actual) {
+        boolean retVal = false;
+        if (expected.length == actual.length) {
+            int errors = 0;
+            for(int x=0; x< expected.length; ++x) {
+                if (expected[x] != actual[x]) {
+                    ++errors;
+                }
+            }
+            if (errors == 0) retVal = true;
+        }
+        return retVal;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/ThaiTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Thai Collation
+ */
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * This software is the proprietary information of Oracle.
+ * Use is subject to license terms.
+ *
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+public class ThaiTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new ThaiTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "\u0e01\u0e01",
+        "\u0e07\u0e42\u0e01\u0e49",
+        "\u0e10\u0e34\u0e19",
+        "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32",
+        "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22",
+        "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22",
+        "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30",
+        "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07",
+        "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c",
+        "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07",
+        "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25",
+        "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c",
+        "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21",
+        "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19",
+        "\u0e2a\u0e49\u0e28\u0e36\u0e01",
+        "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27",
+        "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19",
+        "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19",
+        "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19",
+        "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07",
+        "\u0e2a\u0e49\u0e44\u0e01\u0e48",
+        "\u0e2b",
+        "\u0e2b\u0e0b\u0e2d\u0e07",
+        "\u0e2b\u0e19",
+        "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32",
+        "\u0e2b\u0e21",
+        "\u0e2b\u0e21\u0e17\u0e2d\u0e07",
+        "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14",
+        "\u0e2b\u0e21\u0e49",
+        "\u0e2b\u0e23\u0e13\u0e22\u0e4c",
+        "\u0e2b\u0e25",
+        "\u0e2b\u0e25\u0e19\u0e49\u0e33",
+        "\u0e2b\u0e25\u0e48",
+        "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19",
+        "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b",
+        "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07",
+        "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a",
+        "\u0e2b\u0e49",
+        "\u0e2d",
+        "\u0e2d\u0e49",
+        "\u0e2e\u0e42\u0e25",
+        "\u0e2e\u0e44\u0e1f",
+        "\u0e2e\u0e49"
+    };
+
+    private static final String[] primaryTargetData = {
+        "\u0e01\u0e01",
+        "\u0e07\u0e42\u0e01\u0e49",
+        "\u0e10\u0e34\u0e19",
+        "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32",
+        "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22",
+        "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22",
+        "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30",
+        "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07",
+        "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c",
+        "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07",
+        "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25",
+        "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c",
+        "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21",
+        "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19",
+        "\u0e2a\u0e49\u0e28\u0e36\u0e01",
+        "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27",
+        "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19",
+        "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19",
+        "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19",
+        "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07",
+        "\u0e2a\u0e49\u0e44\u0e01\u0e48",
+        "\u0e2b",
+        "\u0e2b\u0e0b\u0e2d\u0e07",
+        "\u0e2b\u0e19",
+        "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32",
+        "\u0e2b\u0e21",
+        "\u0e2b\u0e21\u0e17\u0e2d\u0e07",
+        "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14",
+        "\u0e2b\u0e21\u0e49",
+        "\u0e2b\u0e23\u0e13\u0e22\u0e4c",
+        "\u0e2b\u0e25",
+        "\u0e2b\u0e25\u0e19\u0e49\u0e33",
+        "\u0e2b\u0e25\u0e48",
+        "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19",
+        "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b",
+        "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07",
+        "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a",
+        "\u0e2b\u0e49",
+        "\u0e2d",
+        "\u0e2d\u0e49",
+        "\u0e2e\u0e42\u0e25",
+        "\u0e2e\u0e44\u0e1f",
+        "\u0e2e\u0e49"
+    };
+
+    private static final int[] primaryResults = {
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("th"));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/TurkishTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Turkish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class TurkishTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new TurkishTest().run(args);
+    }
+
+    /*
+     * Data for TestPrimary()
+     */
+    private static final String[] primarySourceData = {
+        "\u00FCoid",
+        "vo\u0131d",
+        "idea",
+        "Idea",
+        "\u0130dea"
+    };
+
+    private static final String[] primaryTargetData = {
+        "void",
+        "void",
+        "Idea",
+        "\u0130dea",
+        "\u0131dea"
+    };
+
+    private static final int[] primaryResults = {
+        -1,  -1,  1, -1, 1
+    };
+
+    /*
+     * Data for TestTertiary()
+     */
+    private static final String[] tertiarySourceData = {
+        "s\u0327",
+        "v\u00E4t",
+        "old",
+        "\u00FCoid",
+        "h\u011Ealt",
+        "stres\u015E",
+        "vo\u0131d",
+        "idea",
+       "idea",
+       "\u0131dea"
+    };
+
+    private static final String tertiaryTargetData[] = {
+        "u\u0308",
+        "vbt",
+        "\u00D6ay",
+        "void",
+        "halt",
+        "\u015Etre\u015Es",
+        "void",
+        "Idea",
+       "\u0130dea",
+       "Idea"
+    };
+
+    private static final int[] tertiaryResults = {
+        -1, -1, -1, -1,  1, -1, -1,  1, -1, -1
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY,
+               primarySourceData, primaryTargetData, primaryResults);
+    }
+
+    public void TestTertiary() {
+        doTest(myCollation, Collator.TERTIARY,
+               tertiarySourceData, tertiaryTargetData, tertiaryResults);
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("tr", "TR", ""));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Collator/VietnameseTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,364 @@
+/*
+ * 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
+ * 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 4932968 5015215
+ * @library /java/text/testlib
+ * @summary test Vietnamese Collation
+ */
+
+/*
+ *******************************************************************************
+ * (C) Copyright IBM Corp. 1996-2003 - All Rights Reserved                     *
+ *                                                                             *
+ * The original version of this source code and documentation is copyrighted   *
+ * and owned by IBM, These materials are provided under terms of a License     *
+ * Agreement between IBM and Sun. This technology is protected by multiple     *
+ * US and International patents. This notice and attribution to IBM may not    *
+ * to removed.                                                                 *
+ *******************************************************************************
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class VietnameseTest extends CollatorTest {
+
+    public static void main(String[] args) throws Exception {
+        new VietnameseTest().run(args);
+    }
+
+    private final static String testPS[] = {
+        "a",
+        "a",
+        "\u00c2",
+        "Cz",
+        "d",
+        "e",
+        "e",
+        "\u1ec7",
+        "gz",
+        "i",
+        "kz",
+        "nz",
+        "nh",
+        "o",
+        "o",
+        "\u01a0",
+        "pz",
+        "tz",
+        "tr",
+        "u",
+        "u",
+        "y"
+    };
+
+    private final static String testPT[] = {
+        "\u00e0",
+        "\u0102",
+        "\u0102",
+        "Ch",
+        "\u0110",
+        "\u0111",
+        "\u1eb9",
+        "\u1eb9",
+        "gi",
+        "\u0128",
+        "kh",
+        "ng",
+        "ng",
+        "\u00f2",
+        "\u00f4",
+        "\u00f4",
+        "ph",
+        "th",
+        "th",
+        "\u1ee5",
+        "\u01b0",
+        "\u1ef4"
+    };
+
+    private final static int testPR[] = {
+        0,
+        -1,
+        1,
+        1,
+        -1,
+        1,
+        0,
+        1,
+        1,
+        0,
+        1,
+        1,
+        1,
+        0,
+        -1,
+        1,
+        1,
+        1,
+        1,
+        0,
+        -1,
+        0
+    };
+
+    private final static String testT[] = {
+        "a",
+        "A",
+        "\u00e0",
+        "\u00c0",
+        "\u1ea3",
+        "\u1ea2",
+        "\u00e3",
+        "\u00c3",
+        "\u00e1",
+        "\u00c1",
+        "\u1ea1",
+        "\u1ea0",
+        "\u0103",
+        "\u0102",
+        "\u1eb1",
+        "\u1eb0",
+        "\u1eb3",
+        "\u1eb2",
+        "\u1eb5",
+        "\u1eb4",
+        "\u1eaf",
+        "\u1eae",
+        "\u1eb7",
+        "\u1eb6",
+        "\u00e2",
+        "\u00c2",
+        "\u1ea7",
+        "\u1ea6",
+        "\u1ea9",
+        "\u1ea8",
+        "\u1eab",
+        "\u1eaa",
+        "\u1ea5",
+        "\u1ea4",
+        "\u1ead",
+        "\u1eac",
+        "b",
+        "B",
+        "c",
+        "C",
+        "ch",
+        "Ch",
+        "CH",
+        "d",
+        "D",
+        "\u0111",
+        "\u0110",
+        "e",
+        "E",
+        "\u00e8",
+        "\u00c8",
+        "\u1ebb",
+        "\u1eba",
+        "\u1ebd",
+        "\u1ebc",
+        "\u00e9",
+        "\u00c9",
+        "\u1eb9",
+        "\u1eb8",
+        "\u00ea",
+        "\u00ca",
+        "\u1ec1",
+        "\u1ec0",
+        "\u1ec3",
+        "\u1ec2",
+        "\u1ec5",
+        "\u1ec4",
+        "\u1ebf",
+        "\u1ebe",
+        "\u1ec7",
+        "\u1ec6",
+        "f",
+        "F",
+        "g",
+        "G",
+        "gi",
+        "Gi",
+        "GI",
+        "gz",
+        "h",
+        "H",
+        "i",
+        "I",
+        "\u00ec",
+        "\u00cc",
+        "\u1ec9",
+        "\u1ec8",
+        "\u0129",
+        "\u0128",
+        "\u00ed",
+        "\u00cd",
+        "\u1ecb",
+        "\u1eca",
+        "j",
+        "J",
+        "k",
+        "K",
+        "kh",
+        "Kh",
+        "KH",
+        "kz",
+        "l",
+        "L",
+        "m",
+        "M",
+        "n",
+        "N",
+        "ng",
+        "Ng",
+        "NG",
+        "ngz",
+        "nh",
+        "Nh",
+        "NH",
+        "nz",
+        "o",
+        "O",
+        "\u00f2",
+        "\u00d2",
+        "\u1ecf",
+        "\u1ece",
+        "\u00f5",
+        "\u00d5",
+        "\u00f3",
+        "\u00d3",
+        "\u1ecd",
+        "\u1ecc",
+        "\u00f4",
+        "\u00d4",
+        "\u1ed3",
+        "\u1ed2",
+        "\u1ed5",
+        "\u1ed4",
+        "\u1ed7",
+        "\u1ed6",
+        "\u1ed1",
+        "\u1ed0",
+        "\u1ed9",
+        "\u1ed8",
+        "\u01a1",
+        "\u01a0",
+        "\u1edd",
+        "\u1edc",
+        "\u1edf",
+        "\u1ede",
+        "\u1ee1",
+        "\u1ee0",
+        "\u1edb",
+        "\u1eda",
+        "\u1ee3",
+        "\u1ee2",
+        "p",
+        "P",
+        "ph",
+        "Ph",
+        "PH",
+        "pz",
+        "q",
+        "Q",
+        "r",
+        "R",
+        "s",
+        "S",
+        "t",
+        "T",
+        "th",
+        "Th",
+        "TH",
+        "thz",
+        "tr",
+        "Tr",
+        "TR",
+        "tz",
+        "u",
+        "U",
+        "\u00f9",
+        "\u00d9",
+        "\u1ee7",
+        "\u1ee6",
+        "\u0169",
+        "\u0168",
+        "\u00fa",
+        "\u00da",
+        "\u1ee5",
+        "\u1ee4",
+        "\u01b0",
+        "\u01af",
+        "\u1eeb",
+        "\u1eea",
+        "\u1eed",
+        "\u1eec",
+        "\u1eef",
+        "\u1eee",
+        "\u1ee9",
+        "\u1ee8",
+        "\u1ef1",
+        "\u1ef0",
+        "v",
+        "V",
+        "w",
+        "W",
+        "x",
+        "X",
+        "y",
+        "Y",
+        "\u1ef3",
+        "\u1ef2",
+        "\u1ef7",
+        "\u1ef6",
+        "\u1ef9",
+        "\u1ef8",
+        "\u00fd",
+        "\u00dd",
+        "\u1ef5",
+        "\u1ef4",
+        "z",
+        "Z"
+    };
+
+    public void TestPrimary() {
+        doTest(myCollation, Collator.PRIMARY, testPS, testPT, testPR);
+    }
+
+    public void TestTertiary() {
+        int testLength = testT.length;
+
+        myCollation.setStrength(Collator.TERTIARY);
+        for (int i = 0; i < testLength - 1; i++) {
+            for (int j = i+1; j < testLength; j++) {
+                doTest(myCollation, testT[i], testT[j], -1);
+            }
+        }
+    }
+
+    private final Collator myCollation = Collator.getInstance(new Locale("vi", "VN"));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a serialized ChiceFormat for Bug4185732Test.
+
+aced0005737200166a6176612e746578742e43686f696365466f726d617418e9
+c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61
+76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400
+025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3
+bf137d07e803000b5a000c67726f7570696e67557365644200116d6178467261
+6374696f6e4469676974734200106d6178496e74656765724469676974734900
+156d6178696d756d4672616374696f6e4469676974734900146d6178696d756d
+496e74656765724469676974734200116d696e4672616374696f6e4469676974
+734200106d696e496e74656765724469676974734900156d696e696d756d4672
+616374696f6e4469676974734900146d696e696d756d496e7465676572446967
+6974735a00107061727365496e74656765724f6e6c7949001573657269616c56
+657273696f6e4f6e53747265616d787200106a6176612e746578742e466f726d
+6174fbd8bc12e90f184302000078700103280000000300000028000100000000
+00000001000000000178757200135b4c6a6176612e6c616e672e537472696e67
+3badd256e7e91d7b470200007870000000067400034d6f6e7400035475657400
+0357656474000454687572740003467269740003536174757200025b443ea68c
+14ab635a1e0200007870000000073ff000000000000040000000000000004008
+000000000000401000000000000040140000000000004018000000000000401c
+000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4185732Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ *
+ * 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 4185732
+ * @library /java/text/testlib
+ * @build Bug4185732Test IntlTest HexDumpReader
+ * @run main Bug4185732Test
+ * @summary test that ChoiceFormat invariants are preserved across serialization
+ */
+/*
+ *
+ *
+ * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * 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.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.ChoiceFormat;
+
+/**
+ *  A Locale can never contains language codes of he, yi or id.
+ */
+public class Bug4185732Test extends IntlTest {
+    public static void main(String[] args) throws Exception {
+        if (args.length == 1 && args[0].equals("prepTest")) {
+            prepTest();
+        } else {
+            new Bug4185732Test().run(args);
+        }
+    }
+
+    public void testIt() throws Exception {
+        try {
+            final ObjectInputStream in
+                = new ObjectInputStream(HexDumpReader.getStreamFromHexDump("Bug4185732.ser.txt"));
+            final ChoiceFormat loc = (ChoiceFormat)in.readObject();
+            if (loc.getFormats().length != loc.getLimits().length) {
+                errln("ChoiceFormat did not properly check stream");
+            } else {
+                //for some reason, the data file was VALID.  This test
+                //requires a corrupt data file the format and limit
+                //arrays are of different length.
+                errln("Test data file was not properly created");
+            }
+        } catch (InvalidObjectException e) {
+            //this is what we want to have happen
+        } catch (Exception e) {
+            errln(e.toString());
+        }
+    }
+
+    /**
+     * Create a data file for this test.  The data file must be corrupted by hand.
+     */
+    private static void prepTest() {
+        try {
+            ObjectOutputStream out = new ObjectOutputStream(
+                    new FileOutputStream("Bug4185732.ser"));
+            final double[] limits = {1,2,3,4,5,6,7};
+            final String[] formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
+            final ChoiceFormat fmt = new ChoiceFormat(limits, formats);
+            out.writeObject(fmt);
+            out.close();
+            System.out.println("You must invalidate the output file before running the test");
+            System.out.println("by modifying the length of one of the array");
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/ChoiceFormat/Bug4387255.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4387255
+ * @summary Verifies that ChoiceFormat can handle large numbers of choices
+ */
+
+import java.text.ChoiceFormat;
+
+public class Bug4387255 {
+
+    private static final double[] doubles = {
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+            10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+            20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+            30, 31, 32, 33, 34, 35};
+
+    private static final String[] strings = {
+            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+            "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+            "U", "V", "W", "X", "Y", "Z"};
+
+    private static final String pattern =
+            "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" +
+            "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" +
+            "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" +
+            "|30#U|31#V|32#W|33#X|34#Y|35#Z";
+
+    public static void main(String[] args) throws Exception {
+        ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings);
+        ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern);
+        if (!choiceFormat1.equals(choiceFormat2)) {
+            System.out.println("choiceFormat1: " + choiceFormat1.toPattern());
+            System.out.println("choiceFormat2: " + choiceFormat2.toPattern());
+            throw new RuntimeException();
+        }
+
+        for (int i = 0; i < doubles.length; i++) {
+            String result = choiceFormat2.format(doubles[i]);
+            if (!result.equals(strings[i])) {
+                throw new RuntimeException("Wrong format result - expected " +
+                        strings[i] + ", got " + result);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug4322313.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4322313 4833268 6302990 6304305
+ * @library /java/text/testlib
+ * @summary Make sure that new implementation for
+ * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly.
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4322313 extends IntlTest {
+
+    public void Test4322313() {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        boolean err = false;
+        long mpm = 60 * 1000;   /* Milliseconds per a minute */
+
+        Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")};
+
+        String[] formats = {
+            "z",
+            "Z",
+        };
+
+        Object[][] valids = {
+          /* given ID      offset                format('z'), ('Z')    index */
+            {"GMT+03:04",  new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)},
+            {"GMT+13:42",  new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)},
+            {"GMT+00:00",  new Long(0),          "GMT+00:00", "+0000", new Integer(9)},
+            {"GMT+1:11",   new Long(-71 * mpm),  "GMT+01:11", "+0111", new Integer(8)},
+            {"GMT +13:42", new Long(0),          "GMT",       "+0000", new Integer(3)},
+            {" GMT",       new Long(0),          "GMT",       "+0000", new Integer(4)},
+            {"+0304",      new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)},
+            {"+1342",      new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)},
+            {"+0000",      new Long(0),          "GMT+00:00", "+0000", new Integer(5)},
+            {" +1342",     new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)},
+            /* ISO-LATIN-1 digits */
+            {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)},
+
+           /* In fact, this test case is skipped because TimeZone class can't
+            * recognize TimeZone IDs like "+00234" or "-00234".
+            */
+            {"+00234",     new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)},
+
+            {"GMT-03:04",  new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)},
+            {"GMT-13:42",  new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)},
+            {"GMT-00:00",  new Long(0),         "GMT+00:00", "+0000", new Integer(9)},
+            {"GMT-1:11",   new Long(71 * mpm),  "GMT-01:11", "-0111", new Integer(8)},
+            {"GMT -13:42", new Long(0),         "GMT",       "+0000", new Integer(3)},
+            {"-0304",      new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)},
+            {"-1342",      new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)},
+            {" -1342",     new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)},
+            /* ISO-LATIN-1 digits */
+            {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)},
+           /* In fact, this test case is skipped because TimeZone class can't
+            * recognize TimeZone IDs like "+00234" or "-00234".
+            */
+            {"-00234",     new Long(23 * mpm),  "GMT+00:23", "-0023", new Integer(5)},
+        };
+
+        Object[][] invalids = {
+          /* given ID       error index   */
+            {"GMT+8",       new Integer(5)},
+            {"GMT+18",      new Integer(6)},
+            {"GMT+208",     new Integer(6)},
+            {"GMT+0304",    new Integer(6)},
+            {"GMT+42195",   new Integer(5)},
+            {"GMT+5:8",     new Integer(7)},
+            {"GMT+23:60",   new Integer(8)},
+            {"GMT+11:1",    new Integer(8)},
+            {"GMT+24:13",   new Integer(5)},
+            {"GMT+421:950", new Integer(5)},
+            {"GMT+0a:0A",   new Integer(5)},
+            {"GMT+ 13:42",  new Integer(4)},
+            {"GMT+13 :42",  new Integer(6)},
+            {"GMT+13: 42",  new Integer(7)},
+            {"GMT+-13:42",  new Integer(4)},
+            {"G M T",       new Integer(0)},
+            {"+8",          new Integer(2)},
+            {"+18",         new Integer(3)},
+            {"+208",        new Integer(4)},
+            {"+2360",       new Integer(4)},
+            {"+2413",       new Integer(2)},
+            {"+42195",      new Integer(2)},
+            {"+0AbC",       new Integer(2)},
+            {"+ 1342",      new Integer(1)},
+            {"+-1342",      new Integer(1)},
+            {"1342",        new Integer(0)},
+          /* Arabic-Indic digits */
+            {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)},
+          /* Extended Arabic-Indic digits */
+            {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)},
+          /* Devanagari digits */
+            {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)},
+          /* Fullwidth digits */
+            {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)},
+
+            {"GMT-8",       new Integer(5)},
+            {"GMT-18",      new Integer(6)},
+            {"GMT-208",     new Integer(6)},
+            {"GMT-0304",    new Integer(6)},
+            {"GMT-42195",   new Integer(5)},
+            {"GMT-5:8",     new Integer(7)},
+            {"GMT-23:60",   new Integer(8)},
+            {"GMT-11:1",    new Integer(8)},
+            {"GMT-24:13",   new Integer(5)},
+            {"GMT-421:950", new Integer(5)},
+            {"GMT-0a:0A",   new Integer(5)},
+            {"GMT- 13:42",  new Integer(4)},
+            {"GMT-13 :42",  new Integer(6)},
+            {"GMT-13: 42",  new Integer(7)},
+            {"GMT-+13:42",  new Integer(4)},
+            {"-8",          new Integer(2)},
+            {"-18",         new Integer(3)},
+            {"-208",        new Integer(4)},
+            {"-2360",       new Integer(4)},
+            {"-2413",       new Integer(2)},
+            {"-42195",      new Integer(2)},
+            {"-0AbC",       new Integer(2)},
+            {"- 1342",      new Integer(1)},
+            {"--1342",      new Integer(1)},
+            {"-802",        new Integer(2)},
+          /* Arabic-Indic digits */
+            {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)},
+          /* Extended Arabic-Indic digits */
+            {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)},
+          /* Devanagari digits */
+            {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)},
+          /* Fullwidth digits */
+            {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)},
+        };
+
+        try {
+            for (int i=0; i < locs.length; i++) {
+                Locale.setDefault(locs[i]);
+
+                for (int j=0; j < formats.length; j++) {
+                    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+                    SimpleDateFormat sdf = new SimpleDateFormat(formats[j]);
+                    Date date;
+
+                    /* Okay case */
+                    for (int k=0; k < valids.length; k++) {
+                        ParsePosition pos = new ParsePosition(0);
+                        try {
+                            date = sdf.parse((String)valids[k][0], pos);
+                        }
+                        catch (Exception e) {
+                            err = true;
+                            System.err.println("\tParse  Error [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + valids[k][0] +
+                                "\"] Unexpected Exception occurred: " + e);
+                            continue;
+                        }
+
+                        int offset = pos.getIndex();
+                        if (offset != ((Integer)valids[k][4]).intValue()) {
+                            err = true;
+                            System.err.println("\tParse  Error [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + valids[k][0] +
+                                "\"] invalid index: expected:" + valids[k][4] +
+                                ", got:" + offset);
+                        }
+
+                        if (date.getTime() != ((Long)valids[k][1]).longValue()) {
+                            err = true;
+                            System.err.println("\tParse  Error [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + valids[k][0] +
+                                "\"] expected:" + valids[k][1] +
+                                ", got:" + date.getTime() + ", " + date);
+                        } else {
+/*
+                            logln("\tParse  Okay  [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + valids[k][0] +
+                                "\"] expected:" + valids[k][1] +
+                                ", got:" + date.getTime() + ", " + date);
+*/
+
+                            try {
+                                date = sdf.parse((String)valids[k][0]);
+                            }
+                            catch (Exception e) {
+                                err = true;
+                                System.err.println("\tParse  Error [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + valids[k][0] +
+                                    "\"] Unexpected Exception occurred: " + e);
+                                continue;
+                            }
+
+                            /* Since TimeZone.getTimeZone() don't treat
+                             * "+00234" or "-00234" as a valid ID, skips.
+                             */
+                            if (((String)valids[k][0]).length() == 6) {
+                                continue;
+                            }
+
+                            /* Since TimeZone.getTimeZone() don't recognize
+                             * +hhmm/-hhmm format, add "GMT" as prefix.
+                             */
+                            sdf.setTimeZone(TimeZone.getTimeZone(
+                                (((((String)valids[k][0]).charAt(0) != 'G') ?
+                                "GMT" : "") + valids[k][0])));
+                            StringBuffer s = new StringBuffer();
+                            sdf.format(date, s, new FieldPosition(0));
+                            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+                            String got = s.toString();
+                            String expected = (String)valids[k][2+j];
+                            if (!got.equals(expected) &&
+                                // special case to allow the difference between
+                                // DateFormatSymbols.getZoneStrings() and
+                                // TimeZone.getDisplayName() for "GMT+-00:00"
+                                !(got.equals("GMT-00:00") &&
+                                  expected.equals("GMT+00:00"))) {
+                                err = true;
+                                System.err.println("\tFormat Error [Locale=" +
+                                    Locale.getDefault() + ", " +
+                                    formats[j] + "/\"" + valids[k][0] +
+                                    "\"] expected:" + valids[k][2+j] +
+                                    ", got:" + s + ", " + date);
+                            } else {
+/*
+                                logln("\tFormat Okay  [Locale=" +
+                                    Locale.getDefault() + ", " +
+                                    formats[j] + "/\"" + valids[k][0] +
+                                    "\"] expected:" + valids[k][2+j] +
+                                    ", got:" + s + ", " + date);
+*/
+                            }
+                        }
+                    }
+
+                    /* Error case 1
+                     *   using SimpleDateFormat.parse(String, ParsePosition)
+                     */
+                    for (int k=0; k < invalids.length; k++) {
+                        ParsePosition pos = new ParsePosition(0);
+                        try {
+                            date = sdf.parse((String)invalids[k][0], pos);
+                            if (date != null) {
+                                err = true;
+                                System.err.println("\tParse  Error [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] expected:null , got:" + date);
+                            }
+                            int offset = pos.getErrorIndex();
+                            if (offset != ((Integer)invalids[k][1]).intValue()) {
+                                err = true;
+                                System.err.println("\tParse  Error [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] incorrect offset. expected:" +
+                                    invalids[k][1] + ", got: " + offset);
+                            } else {
+/*
+                                logln("\tParse  Okay  [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] correct offset: " + offset);
+*/
+                            }
+                        }
+                        catch (Exception e) {
+                            err = true;
+                            System.err.println("\tParse  Error [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + invalids[k][0] +
+                                "\"] Unexpected Exception occurred: " + e);
+                        }
+                    }
+
+                    /* Error case 2
+                     *   using DateFormat.parse(String)
+                     */
+                    boolean correctParseException = false;
+                    for (int k=0; k < invalids.length; k++) {
+                        try {
+                            date = sdf.parse((String)invalids[k][0]);
+                        }
+                        catch (ParseException e) {
+                            correctParseException = true;
+                            int offset = e.getErrorOffset();
+                            if (offset != ((Integer)invalids[k][1]).intValue()) {
+                                err = true;
+                                System.err.println("\tParse  Error [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] Expected exception occurred with an incorrect offset. expected:" +
+                                    invalids[k][1] + ", got: " + offset);
+                            } else {
+/*
+                                logln("\tParse  Okay  [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] Expected exception occurred with an correct offset: "
+                                    + offset);
+*/
+                            }
+                        }
+                        catch (Exception e) {
+                            err = true;
+                            System.err.println("\tParse  Error [Locale=" +
+                                Locale.getDefault() + ", " + formats[j] +
+                                "/\"" + invalids[k][0] +
+                                "\"] Invalid exception occurred: " + e);
+                        }
+                        finally {
+                            if (!correctParseException) {
+                                err = true;
+                                System.err.println("\tParse  Error: [Locale=" +
+                                    Locale.getDefault() + ", " + formats[j] +
+                                    "/\"" + invalids[k][0] +
+                                    "\"] Expected exception didn't occur.");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+            if (err) {
+                errln("SimpleDateFormat.parse()/format() test failed");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        new Bug4322313().run(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug4407042.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4407042
+ * @summary Make sure that cloned SimpleDateFormat objects work
+ * independently in multiple threads.
+ * @run main Bug4407042 10
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+// Usage: java Bug4407042 [duration]
+public class Bug4407042 {
+
+    static final String TIME_STRING = "2000/11/18 00:01:00";
+    static final long UTC_LONG = 974534460000L;
+    static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+    static boolean runrun = true;
+    static int duration = 100;
+
+    void test() {
+        Locale locale = Locale.getDefault();
+        if (locale.equals(new Locale("th", "TH")) ||
+            locale.equals(new Locale("hi", "IN"))) {
+            return;
+        }
+
+        masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+        DateParseThread d1 = new DateParseThread();
+        DateFormatThread d2 = new DateFormatThread();
+        d1.start();
+        d2.start();
+        int n = Thread.activeCount();
+        boolean failed = false;
+
+        for (int i = 0; i < duration; i++) {
+            try {
+                Thread.sleep(1000);
+                if (Thread.activeCount() != n) {
+                    failed = true;
+                    break;
+                }
+            } catch (InterruptedException e) {
+            }
+        }
+        runrun = false;
+        try {
+            d1.join();
+            d2.join();
+        } catch (InterruptedException e) {
+        }
+        if (failed) {
+            throw new RuntimeException("Failed");
+        }
+    }
+
+    synchronized static SimpleDateFormat getFormatter() {
+        return (SimpleDateFormat) masterFormat.clone();
+    }
+
+    static class DateParseThread extends Thread {
+        public void run() {
+            SimpleDateFormat sdf = getFormatter();
+            Calendar cal = null;
+
+            try {
+                int i = 0;
+                while (runrun) {
+                    Date date =sdf.parse(TIME_STRING);
+                    long t = date.getTime();
+                    i++;
+                    if (t != UTC_LONG) {
+                        throw new RuntimeException("Parse Error: " + i +
+                                                   " (" + sdf.format(date) + ") " + t +
+                                                   " != " + UTC_LONG);
+                    }
+                }
+            } catch (ParseException e) {
+                e.printStackTrace();
+                throw new RuntimeException("Parse Error");
+            }
+        }
+    }
+
+    static class DateFormatThread extends Thread {
+        public  void run () {
+            SimpleDateFormat sdf = getFormatter();
+            Calendar cal = null;
+
+            int i = 0;
+            while (runrun) {
+                i++;
+                String s = sdf.format(new Date(UTC_LONG));
+                if (!s.equals(TIME_STRING)) {
+                    throw new RuntimeException("Format Error: " + i + " " +
+                                               s + " != " + TIME_STRING);
+                }
+            }
+        }
+    }
+
+    public static void main (String[] args) {
+        if (args.length == 1) {
+            duration = Math.max(10, Integer.parseInt(args[0]));
+        }
+        new Bug4407042().test();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug4736959.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4736959
+ * @summary Make sure to parse "PM" (only) and produce the correct value.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug4736959 {
+    /**
+     * 4736959: JSpinner won't work for AM/PM field
+     */
+    public static void main(String[] args) {
+        SimpleDateFormat f = new SimpleDateFormat("a", Locale.US);
+
+        Date d1 = f.parse("AM", new ParsePosition(0));
+        System.out.println("d1: " + d1);
+        if (d1.getHours() != 0) {
+            throw new RuntimeException("Parsing \"AM\": expected 0 (midnight), got " +
+                                       d1.getHours());
+        }
+        Date d2 = f.parse("PM", new ParsePosition(0));
+        System.out.println("d2: " + d2);
+        if (d2.getHours() != 12) {
+            throw new RuntimeException("Parsing \"PM\": expected 12 (noon), got " +
+                                       d2.getHours());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug4845901.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * 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
+ * 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 4845901
+ * @summary Make sure that SimpleDateFormat.parse() can distinguish
+ * the same time zone abbreviation for standard and daylight saving
+ * time.
+ */
+
+import java.util.*;
+import java.text.SimpleDateFormat;
+
+public class Bug4845901 {
+    public static void main (String args[]) {
+        TimeZone savedTZ = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney"));
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z");
+        try {
+            testParse(sdf, "2003.01.13 11:10:00.802 AEDT", 11);
+            testParse(sdf, "2003.06.12 11:10:00.802 AEST", 11);
+            testParse(sdf, "2004.12.24 10:10:00.002 AEDT", 10);
+            testParse(sdf, "2004.08.10 10:10:00.002 AEST", 10);
+        } finally {
+            TimeZone.setDefault(savedTZ);
+        }
+    }
+
+    static void testParse(SimpleDateFormat sdf, String str, int expectedHour) {
+        try {
+            Date parsedDate = sdf.parse(str);
+            if (parsedDate.getHours() != expectedHour) {
+                throw new RuntimeException(
+                        "parsed date has wrong hour: " + parsedDate.getHours()
+                        + ", expected: " + expectedHour
+                        + "\ngiven string: " + str
+                        + "\nparsedDate = " + parsedDate);
+            }
+        } catch (java.text.ParseException e) {
+            throw new RuntimeException("parse exception", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug6251817.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6251817
+ * @summary Confirm that a typo was corrected.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug6251817 {
+
+    public static void main(String[] args) {
+        SimpleDateFormat sdf = new SimpleDateFormat("zzzz", Locale.US);
+        sdf.setTimeZone(TimeZone.getTimeZone("Australia/Lord_Howe"));
+        String got = sdf.format(new Date());
+
+        if (!got.equals("Lord Howe Standard Time") &&
+            !got.equals("Lord Howe Daylight Time")) {
+            throw new RuntimeException("Timezone display name for Australia/Lord_Howe is incorrect. Got:" + got);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug6335238.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2006, 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 1.1 06/01/24
+ * @bug 6335238
+ * @summary Make sure that both the original and cloned SimpleDateFormat coexistindependently and don't cut off each other.
+ * @run main Bug6335238 10
+ */
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+// Usage: java Bug6335238 [duration]
+public class Bug6335238 {
+
+    static final long UTC_LONG = 974534460000L;
+    static final String TIME_STRING = "2000/11/18 00:01:00";
+    static SimpleDateFormat masterSdf;
+    static int duration = 180;
+    static boolean stopped = false;
+    static boolean err = false;
+
+    public static void main(String[] args) {
+        if (args.length == 1) {
+            duration = Math.max(10, Integer.parseInt(args[0]));
+        }
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+
+        TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific"));
+        Locale.setDefault(Locale.US);
+
+        masterSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+        try {
+            // Once it is used, DecimalFormat becomes not thread-safe.
+            Date d = masterSdf.parse(TIME_STRING);
+
+            new Bug6335238();
+        } catch (Exception e) {
+            System.err.println(e);
+            err = true;
+        } finally {
+            TimeZone.setDefault(savedTimeZone);
+            Locale.setDefault(savedLocale);
+
+            if (err) {
+                throw new RuntimeException("Failed: Multiple DateFormat instances didn't work correctly.");
+            } else {
+                System.out.println("Passed.");
+            }
+        }
+    }
+
+    public Bug6335238() {
+        stopped = false;
+
+        DateParseThread d1 = new DateParseThread();
+        DateFormatThread d2 = new DateFormatThread();
+        DateParseThread d3 = new DateParseThread();
+        DateFormatThread d4 = new DateFormatThread();
+
+        d1.start();
+        d2.start();
+        d3.start();
+        d4.start();
+
+        try {
+            Thread.sleep(duration * 1000);
+        }
+        catch (Exception e) {
+            System.err.println(e);
+            err = true;
+        }
+
+        stopped = true;
+    }
+
+    class DateFormatThread extends Thread {
+
+        public void run() {
+            int i = 0;
+
+            while (!stopped) {
+                SimpleDateFormat sdf;
+                synchronized (masterSdf) {
+                    sdf = (SimpleDateFormat)masterSdf.clone();
+                }
+
+                i++;
+                String s = sdf.format(new Date(UTC_LONG));
+
+                if (!s.equals(TIME_STRING)) {
+                    stopped = true;
+                    err = true;
+
+                    throw new RuntimeException("Formatting Date Error: counter=" +
+                        i + ", Got<" + s + "> != Expected<" + TIME_STRING + ">");
+                }
+            }
+        }
+    }
+
+    class DateParseThread extends Thread {
+
+        public void run() {
+            int i = 0;
+
+            while (!stopped) {
+                SimpleDateFormat sdf;
+                synchronized (masterSdf) {
+                    sdf = (SimpleDateFormat)masterSdf.clone();
+                }
+
+                i++;
+                Date date;
+                try {
+                    date = sdf.parse(TIME_STRING);
+                    long t = date.getTime();
+
+                    if (t != UTC_LONG) {
+                        stopped = true;
+                        err = true;
+
+                        throw new RuntimeException("Parsing Date Error: counter=" +
+                            i + " Got:" + t + "<" + sdf.format(date) +
+                            "> != " + UTC_LONG);
+                    }
+                }
+                catch (ParseException e) {
+                    stopped = true;
+                    err = true;
+
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug6530336.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * 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
+ * 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 6530336 6537997 8008577
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336
+ */
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class Bug6530336 {
+
+    public static void main(String[] args) throws Exception {
+        Locale defaultLocale = Locale.getDefault();
+        TimeZone defaultTimeZone = TimeZone.getDefault();
+
+        boolean err = false;
+
+        try {
+            Locale locales[] = Locale.getAvailableLocales();
+            Locale locale_Japan = new Locale("ja", "JP", "JP");
+            TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles");
+            TimeZone.setDefault(timezone_LA);
+
+            TimeZone timezones[] = {
+                TimeZone.getTimeZone("America/New_York"),
+                TimeZone.getTimeZone("America/Denver"),
+            };
+
+            String[] expected = {
+                "Sun Jul 15 12:00:00 PDT 2007",
+                "Sun Jul 15 14:00:00 PDT 2007",
+            };
+
+            Date[] dates = new Date[2];
+
+            for (int i = 0; i < locales.length; i++) {
+                if (locales[i].getLanguage().equals("th") ||
+                    locales[i].equals(locale_Japan)) {
+                    continue;
+                }
+
+                Locale.setDefault(locales[i]);
+
+                for (int j = 0; j < timezones.length; j++) {
+                    Calendar cal = Calendar.getInstance(timezones[j]);
+                    cal.set(2007, 6, 15, 15, 0, 0);
+                    dates[j] = cal.getTime();
+                }
+
+                SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
+
+                for (int j = 0; j < timezones.length; j++) {
+                    sdf.setTimeZone(timezones[j]);
+                    String date = sdf.format(dates[j]);
+                    sdf.setTimeZone(timezone_LA);
+                    String date_LA = sdf.parse(date).toString();
+
+                    if (!expected[j].equals(date_LA)) {
+                        System.err.println("Got wrong Pacific time (" +
+                            date_LA + ") for (" + date + ") in " + locales[i] +
+                            " in " + timezones[j] +
+                            ".\nExpected=" + expected[j]);
+                        err = true;
+                    }
+                }
+            }
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+            err = true;
+        }
+        finally {
+            Locale.setDefault(defaultLocale);
+            TimeZone.setDefault(defaultTimeZone);
+
+            if (err) {
+                throw new RuntimeException("Failed.");
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/DateFormatRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1098 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.text.*;
+import java.util.*;
+import java.io.*;
+
+/**
+ * @test
+ * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003
+ * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407
+ * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209
+ * 4213086 4250359 4253490 4266432 4406615 4413980 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression
+ */
+public class DateFormatRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new DateFormatRegression().run(args);
+    }
+
+    public void Test4029195() {
+
+        Date today = new Date();
+
+        logln("today: " + today);
+
+        SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance();
+        logln("pattern: " + sdf.toPattern());
+        logln("today: " + sdf.format(today));
+
+        sdf.applyPattern("G yyyy DDD");
+        String todayS = sdf.format(today);
+        logln("today: " + todayS);
+        try {
+            today = sdf.parse(todayS);
+            logln("today date: " + today);
+        } catch(Exception e) {
+            logln("Error reparsing date: " + e.getMessage());
+        }
+
+        try {
+            String rt = sdf.format(sdf.parse(todayS));
+            logln("round trip: " + rt);
+            if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt);
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public void Test4052408() {
+
+        DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+                                                        DateFormat.SHORT, Locale.US);
+        Date date = new Date(97, Calendar.MAY, 3, 8, 55);
+        String str;
+        logln(str = fmt.format(date));
+
+        if (!str.equals("5/3/97 8:55 AM"))
+            errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str);
+        Hashtable expected = new Hashtable();
+        expected.put(new Integer(DateFormat.MONTH_FIELD), "5");
+        expected.put(new Integer(DateFormat.DATE_FIELD), "3");
+        expected.put(new Integer(DateFormat.YEAR_FIELD), "97");
+        expected.put(new Integer(DateFormat.HOUR1_FIELD), "8");
+        expected.put(new Integer(DateFormat.MINUTE_FIELD), "55");
+        expected.put(new Integer(DateFormat.AM_PM_FIELD), "AM");
+
+        StringBuffer buf = new StringBuffer();
+        String fieldNames[] = {
+            "ERA_FIELD",
+            "YEAR_FIELD",
+            "MONTH_FIELD",
+            "DATE_FIELD",
+            "HOUR_OF_DAY1_FIELD",
+            "HOUR_OF_DAY0_FIELD",
+            "MINUTE_FIELD",
+            "SECOND_FIELD",
+            "MILLISECOND_FIELD",
+            "DAY_OF_WEEK_FIELD",
+            "DAY_OF_YEAR_FIELD",
+            "DAY_OF_WEEK_IN_MONTH_FIELD",
+            "WEEK_OF_YEAR_FIELD",
+            "WEEK_OF_MONTH_FIELD",
+            "AM_PM_FIELD",
+            "HOUR1_FIELD",
+            "HOUR0_FIELD",
+            "TIMEZONE_FIELD",
+        };
+        boolean pass = true;
+        for (int i=0; i<=17; ++i) {
+            FieldPosition pos = new FieldPosition(i);
+            fmt.format(date, buf, pos);
+            char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()];
+            buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0);
+            str = new String(dst);
+            log(i + ": " + fieldNames[i] +
+                             ", \"" + str + "\", " +
+                             pos.getBeginIndex() + ", " +
+                             pos.getEndIndex());
+            String exp = (String) expected.get(new Integer(i));
+            if ((exp == null && str.length() == 0) ||
+                str.equals(exp))
+                logln(" ok");
+            else {
+                logln(" expected " + exp);
+                pass = false;
+            }
+        }
+        if (!pass) errln("Fail: FieldPosition not set right by DateFormat");
+    }
+
+    /**
+     * Verify the function of the [s|g]et2DigitYearStart() API.
+     */
+    public void Test4056591() {
+        try {
+            SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US);
+            Date start = new Date(1809-1900, Calendar.DECEMBER, 25);
+            fmt.set2DigitYearStart(start);
+            if (!fmt.get2DigitYearStart().equals(start))
+                errln("get2DigitYearStart broken");
+            Object[] DATA = {
+                "091225", new Date(1809-1900, Calendar.DECEMBER, 25),
+                "091224", new Date(1909-1900, Calendar.DECEMBER, 24),
+                "091226", new Date(1809-1900, Calendar.DECEMBER, 26),
+                "611225", new Date(1861-1900, Calendar.DECEMBER, 25),
+            };
+            for (int i=0; i<DATA.length; i+=2) {
+                String s = (String) DATA[i];
+                Date exp = (Date) DATA[i+1];
+                Date got = fmt.parse(s);
+                logln(s + " -> " + got + "; exp " + exp);
+                if (!got.equals(exp)) errln("set2DigitYearStart broken");
+            }
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public void Test4059917() {
+        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+            return;
+        }
+
+        SimpleDateFormat fmt;
+        String myDate;
+
+        fmt = new SimpleDateFormat( "yyyy/MM/dd" );
+        myDate = "1997/01/01";
+        aux917( fmt, myDate );
+
+        fmt = new SimpleDateFormat( "yyyyMMdd" );
+        myDate = "19970101";
+        aux917( fmt, myDate );
+    }
+
+    void aux917( SimpleDateFormat fmt, String str ) {
+        try {
+            logln( "==================" );
+            logln( "testIt: pattern=" + fmt.toPattern() +
+                   " string=" + str );
+
+            Object o;
+            o = fmt.parseObject( str );
+            logln( "Parsed object: " + o );
+
+            String formatted = fmt.format( o );
+            logln( "Formatted string: " + formatted );
+            if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted);
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public void Test4060212() {
+      Locale savedLocale = Locale.getDefault();
+      Locale.setDefault(Locale.US);
+      try {
+        String dateString = "1995-040.05:01:29";
+
+        logln( "dateString= " + dateString );
+        logln("Using yyyy-DDD.hh:mm:ss");
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss");
+        ParsePosition pos = new ParsePosition(0);
+        Date myDate = formatter.parse( dateString, pos );
+        String myString = DateFormat.getDateTimeInstance( DateFormat.FULL,
+                                                          DateFormat.LONG).format( myDate );
+        logln( myString );
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(myDate);
+        if (cal.get(Calendar.DAY_OF_YEAR) != 40)
+            errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) +
+                                " Want 40");
+
+        logln("Using yyyy-ddd.hh:mm:ss");
+        formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss");
+        pos = new ParsePosition(0);
+        myDate = formatter.parse( dateString, pos );
+        myString = DateFormat.getDateTimeInstance( DateFormat.FULL,
+                                                   DateFormat.LONG).format( myDate );
+        logln( myString );
+        cal.setTime(myDate);
+        if (cal.get(Calendar.DAY_OF_YEAR) != 40)
+            errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) +
+                                " Want 40");
+      }
+      finally {
+         Locale.setDefault(savedLocale);
+      }
+    }
+
+    public void Test4061287() {
+        SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
+        try {
+            logln(df.parse("35/01/1971").toString());
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        df.setLenient(false);
+        boolean ok = false;
+        try {
+            logln(df.parse("35/01/1971").toString());
+        } catch (ParseException e) {ok=true;}
+        if (!ok) errln("Fail: Lenient not working");
+    }
+
+    public void Test4065240() {
+        Date curDate;
+        DateFormat shortdate, fulldate;
+        String strShortDate, strFullDate;
+        Locale saveLocale = Locale.getDefault();
+        TimeZone saveZone = TimeZone.getDefault();
+        try {
+            Locale curLocale = new Locale("de","DE");
+            Locale.setDefault(curLocale);
+            TimeZone.setDefault(TimeZone.getTimeZone("EST"));
+            curDate = new Date(98, 0, 1);
+            shortdate = DateFormat.getDateInstance(DateFormat.SHORT);
+            fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG
+                                                      );
+            strShortDate = new String("The current date (short form) is " + shortdate.
+                                      format(curDate));
+            strFullDate = new String("The current date (long form) is " + fulldate.format(curDate));
+
+            logln(strShortDate);
+            logln(strFullDate);
+
+            // UPDATE THIS AS ZONE NAME RESOURCE FOR <EST> in de_DE is updated
+            if (!strFullDate.endsWith("EST")
+                    && !strFullDate.endsWith("GMT-05:00")) {
+                errln("Fail: Want GMT-05:00");
+            }
+        }
+        finally {
+            Locale.setDefault(saveLocale);
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    /*
+      DateFormat.equals is too narrowly defined.  As a result, MessageFormat
+      does not work correctly.  DateFormat.equals needs to be written so
+      that the Calendar sub-object is not compared using Calendar.equals,
+      but rather compared for equivalency.  This may necessitate adding a
+      (package private) method to Calendar to test for equivalency.
+
+      Currently this bug breaks MessageFormat.toPattern
+      */
+    public void Test4071441() {
+        DateFormat fmtA = DateFormat.getInstance();
+        DateFormat fmtB = DateFormat.getInstance();
+        Calendar calA = fmtA.getCalendar();
+        Calendar calB = fmtB.getCalendar();
+        Date epoch = new Date(0);
+        Date xmas = new Date(61, Calendar.DECEMBER, 25);
+        calA.setTime(epoch);
+        calB.setTime(epoch);
+        if (!calA.equals(calB))
+            errln("Fail: Can't complete test; Calendar instances unequal");
+        if (!fmtA.equals(fmtB))
+            errln("Fail: DateFormat unequal when Calendars equal");
+        calB.setTime(xmas);
+        if (calA.equals(calB))
+            errln("Fail: Can't complete test; Calendar instances equal");
+        if (!fmtA.equals(fmtB))
+            errln("Fail: DateFormat unequal when Calendars equivalent");
+        logln("DateFormat.equals ok");
+    }
+
+    /* The java.text.DateFormat.parse(String) method expects for the
+      US locale a string formatted according to mm/dd/yy and parses it
+      correctly.
+
+      When given a string mm/dd/yyyy it only parses up to the first
+      two y's, typically resulting in a date in the year 1919.
+
+      Please extend the parsing method(s) to handle strings with
+      four-digit year values (probably also applicable to various
+      other locales.  */
+    public void Test4073003() {
+        try {
+            DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
+            String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" };
+            for (int i=0; i<tests.length; i+=2) {
+                Date d = fmt.parse(tests[i]);
+                Date dd = fmt.parse(tests[i+1]);
+                String s = fmt.format(d);
+                String ss = fmt.format(dd);
+                if (!d.equals(dd))
+                    errln("Fail: " + d + " != " + dd);
+                if (!s.equals(ss))
+                    errln("Fail: " + s + " != " + ss);
+                logln("Ok: " + s + " " + d);
+            }
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public void Test4089106() {
+        TimeZone def = TimeZone.getDefault();
+        try {
+            TimeZone z = new SimpleTimeZone((int)(1.25 * 3600000), "FAKEZONE");
+            TimeZone.setDefault(z);
+            SimpleDateFormat f = new SimpleDateFormat();
+            if (!f.getTimeZone().equals(z))
+                errln("Fail: SimpleTimeZone should use TimeZone.getDefault()");
+        }
+        finally {
+            TimeZone.setDefault(def);
+        }
+    }
+
+    public void Test4100302() {
+        Locale[] locales = new Locale[] {
+            Locale.CANADA,
+            Locale.CANADA_FRENCH,
+            Locale.CHINA,
+            Locale.CHINESE,
+            Locale.ENGLISH,
+            Locale.FRANCE,
+            Locale.FRENCH,
+            Locale.GERMAN,
+            Locale.GERMANY,
+            Locale.ITALIAN,
+            Locale.ITALY,
+            Locale.JAPAN,
+            Locale.JAPANESE,
+            Locale.KOREA,
+            Locale.KOREAN,
+            Locale.PRC,
+            Locale.SIMPLIFIED_CHINESE,
+            Locale.TAIWAN,
+            Locale.TRADITIONAL_CHINESE,
+            Locale.UK,
+            Locale.US
+            };
+        try {
+            boolean pass = true;
+            for(int i = 0; i < locales.length; i++) {
+
+                Format format = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                               DateFormat.FULL, locales[i]);
+                byte[] bytes;
+
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+                oos.writeObject(format);
+                oos.flush();
+
+                baos.close();
+                bytes = baos.toByteArray();
+
+                ObjectInputStream ois =
+                    new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+                if (!format.equals(ois.readObject())) {
+                    pass = false;
+                    logln("DateFormat instance for locale " +
+                          locales[i] + " is incorrectly serialized/deserialized.");
+                } else {
+                    logln("DateFormat instance for locale " +
+                          locales[i] + " is OKAY.");
+                }
+            }
+            if (!pass) errln("Fail: DateFormat serialization/equality bug");
+        }
+        catch (IOException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        catch (ClassNotFoundException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Test whether DataFormat can be serialized/deserialized correctly
+     * even if invalid/customized TimeZone is used.
+     */
+    public void Test4413980() {
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        try {
+            boolean pass = true;
+            String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",
+                                         "GMT+3:00", "GMT-01:30"};
+            for (int i = 0; i < IDs.length; i++) {
+                TimeZone tz = TimeZone.getTimeZone(IDs[i]);
+                TimeZone.setDefault(tz);
+
+                Format format = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                               DateFormat.FULL);
+                byte[] bytes;
+
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+                oos.writeObject(format);
+                oos.flush();
+
+                baos.close();
+                bytes = baos.toByteArray();
+
+                ObjectInputStream ois =
+                    new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+                if (!format.equals(ois.readObject())) {
+                    pass = false;
+                    logln("DateFormat instance which uses TimeZone <" +
+                          IDs[i] + "> is incorrectly serialized/deserialized.");
+                } else {
+                    logln("DateFormat instance which uses TimeZone <" +
+                          IDs[i] + "> is correctly serialized/deserialized.");
+                }
+            }
+            if (!pass) {
+                errln("Fail: DateFormat serialization/equality bug");
+            }
+        }
+        catch (IOException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        catch (ClassNotFoundException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        finally {
+            TimeZone.setDefault(savedTimeZone);
+        }
+    }
+
+    public void Test4101483() {
+        SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US);
+        FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD);
+        Date d= new Date(9234567890L);
+        StringBuffer buf = new StringBuffer("");
+        logln(sdf.format(d, buf, fp).toString());
+        logln(d + " => " + buf);
+        logln("beginIndex = " + fp.getBeginIndex());
+        logln("endIndex = " + fp.getEndIndex());
+        if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field");
+    }
+
+    /**
+     * Bug 4103340
+     * Bug 4138203
+     * This bug really only works in Locale.US, since that's what the locale
+     * used for Date.toString() is.  Bug 4138203 reports that it fails on Korean
+     * NT; it would actually have failed on any non-US locale.  Now it should
+     * work on all locales.
+     */
+    public void Test4103340() {
+        // choose a date that is the FIRST of some month
+        // and some arbitrary time
+        Date d=new Date(97, 3, 1, 1, 1, 1);
+        SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US);
+
+        String s = d.toString();
+        String s2 = df.format(d);
+        logln("Date="+s);
+        logln("DF="+s2);
+        if (s.indexOf(s2.substring(0,2)) == -1)
+            errln("Months should match");
+    }
+
+    public void Test4103341() {
+        TimeZone saveZone  =TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("CST"));
+            SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm");
+            if (!simple.getTimeZone().equals(TimeZone.getDefault()))
+                errln("Fail: SimpleDateFormat not using default zone");
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    public void Test4104136() {
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        String pattern = "'time' hh:mm";
+        sdf.applyPattern(pattern);
+        logln("pattern: \"" + pattern + "\"");
+
+        Object[] DATA = {
+            "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30),
+            "time 10:x", new ParsePosition(0), null,
+            "time 10x", new ParsePosition(0), null,
+        };
+        for (int i=0; i<DATA.length; i+=3) {
+            String text = (String) DATA[i];
+            ParsePosition finish = (ParsePosition) DATA[i+1];
+            Date exp = (Date) DATA[i+2];
+
+            ParsePosition pos = new ParsePosition(0);
+            Date d = sdf.parse(text, pos);
+            logln(" text: \"" + text + "\"");
+            logln(" index: " + pos.getIndex());
+            logln(" result: " + d);
+            if (pos.getIndex() != finish.getIndex())
+                errln("Fail: Expected pos " + finish.getIndex());
+            if (!((d == null && exp == null) ||
+                  d.equals(exp)))
+                errln("Fail: Expected result " + exp);
+        }
+    }
+
+    /**
+     * CANNOT REPRODUCE
+     * According to the bug report, this test should throw a
+     * StringIndexOutOfBoundsException during the second parse.  However,
+     * this is not seen.
+     */
+    public void Test4104522() {
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        String pattern = "'time' hh:mm";
+        sdf.applyPattern(pattern);
+        logln("pattern: \"" + pattern + "\"");
+
+        // works correctly
+        ParsePosition pp = new ParsePosition(0);
+        String text = "time ";
+        Date date = sdf.parse(text, pp);
+        logln(" text: \"" + text + "\"" +
+              " date: " + date);
+
+        // works wrong
+        pp = new ParsePosition(0);
+        text = "time";
+        date = sdf.parse(text, pp);
+        logln(" text: \"" + text + "\"" +
+              " date: " + date);
+    }
+
+    public void Test4106807() {
+        Date date;
+        DateFormat df = DateFormat.getDateTimeInstance();
+        Object[] data = {
+            new SimpleDateFormat("yyyyMMddHHmmss"),       "19980211140000",
+            new SimpleDateFormat("yyyyMMddHHmmss'Z'"),    "19980211140000",
+            new SimpleDateFormat("yyyyMMddHHmmss''"),     "19980211140000",
+            new SimpleDateFormat("yyyyMMddHHmmss'a''a'"), "19980211140000a",
+            new SimpleDateFormat("yyyyMMddHHmmss %"),     "19980211140000 ",
+        };
+        GregorianCalendar gc = new GregorianCalendar();
+        TimeZone timeZone = TimeZone.getDefault();
+
+        TimeZone gmt = (TimeZone)timeZone.clone();
+
+        gmt.setRawOffset(0);
+
+        for (int i=0; i<data.length; i+=2) {
+            SimpleDateFormat format = (SimpleDateFormat) data[i];
+            String dateString = (String) data[i+1];
+            try {
+                format.setTimeZone(gmt);
+                date = format.parse(dateString);
+                logln(df.format(date));
+                gc.setTime(date);
+                logln("" + gc.get(Calendar.ZONE_OFFSET));
+                logln(format.format(date));
+            }
+            catch (ParseException e) {
+                logln("No way Jose");
+            }
+        }
+    }
+
+    /*
+      Synopsis: Chinese time zone CTT is not recogonized correctly.
+      Description: Platform Chinese Windows 95 - ** Time zone set to CST **
+      */
+    public void Test4108407() {
+
+        long l = System.currentTimeMillis();
+        logln("user.timezone = " + System.getProperty("user.timezone", "?"));
+        logln("Time Zone :" +
+                           DateFormat.getDateInstance().getTimeZone().getID());
+        logln("Default format :" +
+                           DateFormat.getDateInstance().format(new Date(l)));
+        logln("Full format :" +
+                           DateFormat.getDateInstance(DateFormat.FULL).format(new
+                                                                              Date(l)));
+        logln("*** Set host TZ to CST ***");
+        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
+    }
+
+    /**
+     * SimpleDateFormat won't parse "GMT"
+     */
+    public void Test4134203() {
+        String dateFormat = "MM/dd/yy HH:mm:ss zzz";
+        SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
+        ParsePosition p0 = new ParsePosition(0);
+        Date d = fmt.parse("01/22/92 04:52:00 GMT", p0);
+        logln(d.toString());
+        // In the failure case an exception is thrown by parse();
+        // if no exception is thrown, the test passes.
+    }
+
+    /**
+     * Another format for GMT string parse
+     */
+    public void Test4266432() {
+        String dateFormat = "MM/dd HH:mm:ss zzz yyyy";
+        SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
+        ParsePosition p0 = new ParsePosition(0);
+        Date d = fmt.parse("01/22 04:52:00 GMT 1992", p0);
+        logln(d.toString());
+        // In the failure case an exception is thrown by parse();
+        // if no exception is thrown, the test passes.
+    }
+
+    /**
+     * Millisecond field is limited to 3 digits; also test general millisecond
+     * handling.
+     *
+     * NOTE: Updated for fixed semantics as of Kestrel.  See
+     * 4253490
+     */
+    public void Test4148168() throws ParseException {
+        SimpleDateFormat fmt = new SimpleDateFormat("", Locale.US);
+        int ms = 456;
+        String[] PAT = { "S", "SS", "SSS", "SSSS", "SSSSS",
+                         "SSSSSSSSSSSSSSSSSSSS" };
+        String[] OUT = { "456", "456", "456", "0456", "00456",
+                         "00000000000000000456" };
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(Calendar.MILLISECOND, ms);
+        Date d = cal.getTime();
+        for (int i=0; i<OUT.length; ++i) {
+            fmt.applyPattern(PAT[i]);
+            String str = fmt.format(d);
+            if (!str.equals(OUT[i])) {
+                errln("FAIL: " + ms + " ms x \"" + PAT[i] + "\" -> \"" +
+                      str + "\", exp \"" + OUT[i] + '"');
+            }
+        }
+
+        // Test parsing
+        fmt.applyPattern("s.S");
+        String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456",
+                        "1.4567", "1.45678" };
+        int[] MS = { 4, 4, 4, 45, 456, 567, 678 };
+        for (int i=0; i<IN.length; ++i) {
+            d = fmt.parse(IN[i]);
+            cal.setTime(d);
+            ms = cal.get(Calendar.MILLISECOND);
+            if (ms != MS[i]) {
+                errln("FAIL: parse(\"" + IN[i] + "\" x \"s.S\") -> " +
+                      ms + " ms, exp " + MS[i] + " ms");
+            }
+        }
+    }
+
+    /**
+     * SimpleDateFormat incorrect handling of 2 single quotes in format()
+     */
+    public void Test4151631() {
+        String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'";
+        logln("pattern=" + pattern);
+        SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
+        String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0));
+        if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) {
+            errln("Fail: result=" + result);
+        }
+        else {
+            logln("Pass: result=" + result);
+        }
+    }
+
+    /**
+     * 'z' at end of date format throws index exception in SimpleDateFormat
+     * CANNOT REPRODUCE THIS BUG ON 1.2FCS
+     */
+    public void Test4151706() {
+        SimpleDateFormat fmt =
+            new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US);
+        try {
+            Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT");
+            if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0))
+                errln("Incorrect value: " + d);
+        } catch (Exception e) {
+            errln("Fail: " + e);
+        }
+    }
+
+    /**
+     * SimpleDateFormat fails to parse redundant data.
+     * This is actually a bug down in GregorianCalendar, but it was reported
+     * as follows...
+     */
+    public void Test4153860() throws ParseException {
+      Locale savedLocale = Locale.getDefault();
+      Locale.setDefault(Locale.US);
+      try {
+        SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance();
+        // Set the pattern
+        sf.applyPattern("yyyy.MM-dd");
+        // Try to create a Date for February 4th
+        Date d1 = sf.parse("1998.02-04");
+        // Set the pattern, this time to use the W value
+        sf.applyPattern("yyyy.MM-dd W");
+        // Try to create a Date for February 4th
+        Date d2 = sf.parse("1998.02-04 1");
+        if (!d1.equals(d2)) {
+            errln("Parse failed, got " + d2 +
+                  ", expected " + d1);
+        }
+      }
+      finally {
+        Locale.setDefault(savedLocale);
+      }
+    }
+
+    /**
+     * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US
+     * as "EST" or "CST", not Australian "EST" and "CST".
+     */
+    public void Test4406615() {
+      Locale savedLocale = Locale.getDefault();
+      TimeZone savedTimeZone = TimeZone.getDefault();
+      Locale.setDefault(Locale.US);
+      TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+      Date d1, d2;
+      String dt = "Mon, 1 Jan 2001 00:00:00";
+      SimpleDateFormat sdf =
+        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
+
+      try {
+        d1 = sdf.parse(dt+" EST");
+        d2 = sdf.parse(dt+" CST");
+
+        if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 ||
+            d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 ||
+            d2.getYear() != (2000-1900) || d2.getMonth() != 11 ||
+            d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) {
+            errln("Parse failed, d1 = " + d1 + ", d2 = " + d2);
+        } else {
+            logln("Parse passed");
+        }
+      }
+      catch (Exception e) {
+            errln("Parse failed, got Exception " + e);
+      }
+      finally {
+        Locale.setDefault(savedLocale);
+        TimeZone.setDefault(savedTimeZone);
+      }
+    }
+
+    /**
+     * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate
+     * of some other bug that has been fixed.
+     */
+    public void Test4162071() {
+        String dateString = "Thu, 30-Jul-1999 11:51:14 GMT";
+        String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123
+        SimpleDateFormat df = new
+            SimpleDateFormat(format, Locale.US);
+
+        try {
+            Date x = df.parse(dateString);
+            logln("Parse format \"" + format + "\" ok");
+            logln(dateString + " -> " + df.format(x));
+        } catch (Exception e) {
+            errln("Parse format \"" + format + "\" failed.");
+        }
+    }
+
+    /**
+     * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999).
+     */
+    public void Test4182066() {
+      Locale savedLocale = Locale.getDefault();
+      Locale.setDefault(Locale.US);
+      try {
+        SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy",
+                                                    DateFormatSymbols.getInstance(Locale.US));
+        SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG",
+                                                        DateFormatSymbols.getInstance(Locale.US));
+        /* We expect 2-digit year formats to put 2-digit years in the right
+         * window.  Out of range years, that is, anything less than "00" or
+         * greater than "99", are treated as literal years.  So "1/2/3456"
+         * becomes 3456 AD.  Likewise, "1/2/-3" becomes -3 AD == 2 BC.
+         */
+        Object[] DATA = {
+            "02/29/00",   new Date(2000-1900, Calendar.FEBRUARY, 29),
+            "01/23/01",   new Date(2001-1900, Calendar.JANUARY,  23),
+            "04/05/-1",   new Date(  -1-1900, Calendar.APRIL,     5),
+            "01/23/-9",   new Date(  -9-1900, Calendar.JANUARY,  23),
+            "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12),
+            "10/31/1",    new Date(   1-1900, Calendar.OCTOBER,  31),
+            "09/12/+1",   null, // "+1" isn't recognized by US NumberFormat
+            "09/12/001",  new Date(   1-1900, Calendar.SEPTEMBER,12),
+        };
+        StringBuffer out = new StringBuffer();
+        boolean pass = true;
+        for (int i=0; i<DATA.length; i+=2) {
+            String str = (String) DATA[i];
+            Date expected = (Date) DATA[i+1];
+            Date actual;
+            try {
+                actual = fmt.parse(str);
+            } catch (ParseException e) {
+                actual = null;
+            }
+            String actStr = actual != null
+                ? dispFmt.format(actual) : String.valueOf(actual);
+            if (expected == actual
+                || (expected != null && expected.equals(actual))) {
+                out.append(str + " => " + actStr + "\n");
+            } else {
+                String expStr = expected != null
+                    ? dispFmt.format(expected) : String.valueOf(expected);
+                out.append("FAIL: " + str + " => " + actStr
+                           + ", expected " + expStr + "\n");
+                pass = false;
+            }
+        }
+        if (pass) {
+            log(out.toString());
+        } else {
+            err(out.toString());
+        }
+      }
+      finally {
+        Locale.setDefault(savedLocale);
+      }
+    }
+
+    /**
+     * Bug 4210209
+     * Bug 4209272
+     * DateFormat cannot parse Feb 29 2000 when setLenient(false)
+     */
+    public void Test4210209() {
+        String pattern = "MMM d, yyyy";
+        DateFormat fmt = new SimpleDateFormat(pattern,
+                                              DateFormatSymbols.getInstance(Locale.US));
+        fmt.getCalendar().setLenient(false);
+        Date d = new Date(2000-1900, Calendar.FEBRUARY, 29);
+        String s = fmt.format(d);
+        logln(d + " x " + pattern + " => " + s);
+        ParsePosition pos = new ParsePosition(0);
+        d = fmt.parse(s, pos);
+        logln(d + " <= " + pattern + " x " + s);
+        logln("Parse pos = " + pos);
+        if (pos.getErrorIndex() != -1) {
+            errln("FAIL");
+        }
+
+        // The underlying bug is in GregorianCalendar.  If the following lines
+        // succeed, the bug is fixed.  If the bug isn't fixed, they will throw
+        // an exception.
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.clear();
+        cal.setLenient(false);
+        cal.set(2000, Calendar.FEBRUARY, 29); // This should work!
+        logln(cal.getTime().toString());
+    }
+
+    /**
+     * DateFormat.getDateTimeInstance() allows illegal parameters.
+     */
+    public void Test4213086() {
+        int[] DATA = {
+            // Style value, 0/1 for illegal/legal
+            -99, 0,
+             -1, 0,
+              0, 1,
+              1, 1,
+              2, 1,
+              3, 1,
+              4, 0,
+             99, 0,
+        };
+        String[] DESC = {
+            "getDateTimeInstance(date)",
+            "getDateTimeInstance(time)",
+            "getDateInstance",
+            "getTimeInstance",
+        };
+        String[] GOT = {
+            "disallowed", "allowed", "<invalid>"
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            int got = 2;
+            for (int j=0; j<4; ++j) {
+                Exception e = null;
+                try {
+                    DateFormat df;
+                    switch (j) {
+                    case 0:
+                        df = DateFormat.getDateTimeInstance(DATA[i], 0);
+                        break;
+                    case 1:
+                        df = DateFormat.getDateTimeInstance(0, DATA[i]);
+                        break;
+                    case 2:
+                        df = DateFormat.getDateInstance(DATA[i]);
+                        break;
+                    case 3:
+                        df = DateFormat.getTimeInstance(DATA[i]);
+                        break;
+                    }
+                    got = 1;
+                } catch (IllegalArgumentException iae) {
+                    got = 0;
+                } catch (Exception ex) {
+                    e = ex;
+                }
+                if (got != DATA[i+1] || e != null) {
+                    errln("FAIL: DateFormat." + DESC[j] + " style " + DATA[i] + " " +
+                          (e != null ? e.toString() : GOT[got]));
+                }
+            }
+        }
+    }
+
+    public void Test4253490() throws ParseException {
+        SimpleDateFormat fmt = new SimpleDateFormat("S", Locale.US);
+
+        GregorianCalendar cal = new GregorianCalendar();
+
+        int      FORMAT_MS  = 12;
+        String[] FORMAT_PAT = {  "S", "SS", "SSS", "SSSS" };
+        String[] FORMAT_TO  = { "12", "12", "012", "0012" };
+
+        String   PARSE_PAT  = "S";
+        String[] PARSE_STR  = { "1", "12", "125", "1250" };
+        int[]    PARSE_TO   = {  1,   12,   125,   250   };
+        String   PARSE_LPAT  = "SSSSS";
+
+        // Test formatting.  We want to make sure all digits are output
+        // and that they are zero-padded on the left if necessary.
+        cal.setTime(new Date(0L));
+        cal.set(Calendar.MILLISECOND, FORMAT_MS);
+        Date d = cal.getTime();
+        for (int i=0; i<FORMAT_PAT.length; ++i) {
+            fmt.applyPattern(FORMAT_PAT[i]);
+            String s = fmt.format(d);
+            if (s.equals(FORMAT_TO[i])) {
+                logln(String.valueOf(FORMAT_MS) + " ms f* \"" +
+                      FORMAT_PAT[i] + "\" -> \"" + s + '"');
+            } else {
+                errln("FAIL: " + FORMAT_MS + " ms f* \"" +
+                      FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" +
+                      FORMAT_TO[i] + '"');
+            }
+        }
+
+        // Test parsing.  We want to make sure all digits are read.
+        fmt.applyPattern(PARSE_PAT);
+        for (int i=0; i<PARSE_STR.length; ++i) {
+            cal.setTime(fmt.parse(PARSE_STR[i]));
+            int ms = cal.get(Calendar.MILLISECOND);
+            if (ms == PARSE_TO[i]) {
+                logln("\"" + PARSE_STR[i] + "\" p* \"" +
+                      PARSE_PAT + "\" -> " + ms + " ms");
+            } else {
+                errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" +
+                      PARSE_PAT + "\" -> " + ms + " ms, expect " +
+                      PARSE_TO[i] + " ms");
+            }
+        }
+
+        // Test LONG parsing.  We want to make sure all digits are read.
+        fmt.applyPattern(PARSE_LPAT);
+        for (int i=0; i<PARSE_STR.length; ++i) {
+            cal.setTime(fmt.parse(PARSE_STR[i]));
+            int ms = cal.get(Calendar.MILLISECOND);
+            if (ms == PARSE_TO[i]) {
+                logln("\"" + PARSE_STR[i] + "\" p* \"" +
+                      PARSE_LPAT + "\" -> " + ms + " ms");
+            } else {
+                errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" +
+                      PARSE_LPAT + "\" -> " + ms + " ms, expect " +
+                      PARSE_TO[i] + " ms");
+            }
+        }
+    }
+
+    /**
+     * Bug in handling of time instance; introduces in fix for 4213086.
+     */
+    public void Test4250359() {
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT,
+                                                   Locale.US);
+        Date d = new Date(1999-1900, Calendar.DECEMBER, 25,
+                          1, 2, 3);
+        String s = df.format(d);
+        // If the bug is present, we see "1:02 AM 1:02 AM".
+        // Look for more than one instance of "AM".
+        int i = s.indexOf("AM");
+        int j = s.indexOf("AM", i+1);
+        if (i < 0 || j >= 0) {
+            errln("FAIL: getTimeInstance().format(d) => \"" +
+                  s + "\"");
+        }
+    }
+
+    /**
+     * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse
+     * non-localized time zones.
+     */
+    public void Test4261506() {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        Locale.setDefault(Locale.JAPAN);
+
+        // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to
+        // pick up another time zone when L10N is done to that file.
+        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+        SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN);
+        String result = fmt.format(new Date(1999, 0, 1));
+        logln("format()=>" + result);
+        if (!result.endsWith("PST")) {
+            errln("FAIL: SimpleDataFormat.format() did not retrun PST");
+        }
+
+        Date d = null;
+        try {
+            d = fmt.parse("99/1/1 10:10 PST");
+        } catch (ParseException e) {
+            errln("FAIL: SimpleDataFormat.parse() could not parse PST");
+        }
+
+        result = fmt.format(d);
+        logln("roundtrip:" + result);
+        if (!result.equals("99/01/01 10:10 PST")) {
+            errln("FAIL: SimpleDataFomat timezone roundtrip failed");
+        }
+
+        Locale.setDefault(savedLocale);
+        TimeZone.setDefault(savedTimeZone);
+    }
+
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary test Date Format (Round Trip)
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class DateFormatRoundTripTest extends IntlTest {
+
+    static Random RANDOM = null;
+
+    static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value
+
+    // Useful for turning up subtle bugs: Use -infinite and run while at lunch.
+    boolean INFINITE = false; // Warning -- makes test run infinite loop!!!
+
+    boolean random = false;
+
+    // Options used to reproduce failures
+    Locale locale = null;
+    String pattern = null;
+    Date initialDate = null;
+
+    Locale[] avail;
+    TimeZone defaultZone;
+
+    // If SPARSENESS is > 0, we don't run each exhaustive possibility.
+    // There are 24 total possible tests per each locale.  A SPARSENESS
+    // of 12 means we run half of them.  A SPARSENESS of 23 means we run
+    // 1 of them.  SPARSENESS _must_ be in the range 0..23.
+    static final int SPARSENESS = 18;
+
+    static final int TRIALS = 4;
+
+    static final int DEPTH = 5;
+
+    static SimpleDateFormat refFormat =
+        new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
+
+    public DateFormatRoundTripTest(boolean rand, long seed, boolean infinite,
+                                   Date date, String pat, Locale loc) {
+        random = rand;
+        if (random) {
+            RANDOM = new Random(seed);
+        }
+        INFINITE = infinite;
+
+        initialDate = date;
+        locale = loc;
+        pattern = pat;
+    }
+
+    /**
+     * Parse a name like "fr_FR" into new Locale("fr", "FR", "");
+     */
+    static Locale createLocale(String name) {
+        String country = "",
+               variant = "";
+        int i;
+        if ((i = name.indexOf('_')) >= 0) {
+            country = name.substring(i+1);
+            name = name.substring(0, i);
+        }
+        if ((i = country.indexOf('_')) >= 0) {
+            variant = country.substring(i+1);
+            country = country.substring(0, i);
+        }
+        return new Locale(name, country, variant);
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Command-line parameters
+        Locale loc = null;
+        boolean infinite = false;
+        boolean random = false;
+        long seed = FIXED_SEED;
+        String pat = null;
+        Date date = null;
+
+        Vector newArgs = new Vector();
+        for (int i=0; i<args.length; ++i) {
+            if (args[i].equals("-locale")
+                && (i+1) < args.length) {
+                loc = createLocale(args[i+1]);
+                ++i;
+            } else if (args[i].equals("-date")
+                       && (i+1) < args.length) {
+                date = new Date(Long.parseLong(args[i+1]));
+                ++i;
+            } else if (args[i].equals("-pattern")
+                && (i+1) < args.length) {
+                pat = args[i+1];
+                ++i;
+            } else if (args[i].equals("-INFINITE")) {
+                infinite = true;
+            } else if (args[i].equals("-random")) {
+                random = true;
+            } else if (args[i].equals("-randomseed")) {
+                random = true;
+                seed = System.currentTimeMillis();
+            } else if (args[i].equals("-seed")
+                       && (i+1) < args.length) {
+                random = true;
+                seed = Long.parseLong(args[i+1]);
+                ++i;
+            } else {
+                newArgs.addElement(args[i]);
+            }
+        }
+
+        if (newArgs.size() != args.length) {
+            args = new String[newArgs.size()];
+            newArgs.copyInto(args);
+        }
+
+        new DateFormatRoundTripTest(random, seed, infinite, date, pat, loc).run(args);
+    }
+
+    /**
+     * Print a usage message for this test class.
+     */
+    void usage() {
+        System.out.println(getClass().getName() +
+                           ": [-pattern <pattern>] [-locale <locale>] [-date <ms>] [-INFINITE]");
+        System.out.println(" [-random | -randomseed | -seed <seed>]");
+        System.out.println("* Warning: Some patterns will fail with some locales.");
+        System.out.println("* Do not use -pattern unless you know what you are doing!");
+        System.out.println("When specifying a locale, use a format such as fr_FR.");
+        System.out.println("Use -pattern, -locale, and -date to reproduce a failure.");
+        System.out.println("-random     Random with fixed seed (same data every run).");
+        System.out.println("-randomseed Random with a random seed.");
+        System.out.println("-seed <s>   Random using <s> as seed.");
+        super.usage();
+    }
+
+    static private class TestCase {
+        private int[] date;
+        TimeZone zone;
+        FormatFactory ff;
+        boolean timeOnly;
+        private Date _date;
+
+        TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) {
+            date = d;
+            zone = z;
+            ff  = f;
+            this.timeOnly = timeOnly;
+        }
+
+        TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) {
+            date = null;
+            _date = d;
+            zone = z;
+            ff  = f;
+            this.timeOnly = timeOnly;
+        }
+
+        /**
+         * Create a format for testing.
+         */
+        DateFormat createFormat() {
+            return ff.createFormat();
+        }
+
+        /**
+         * Return the Date of this test case; must be called with the default
+         * zone set to this TestCase's zone.
+         */
+        Date getDate() {
+            if (_date == null) {
+                // Date constructor will work right iff we are in the target zone
+                int h = 0;
+                int m = 0;
+                int s = 0;
+                if (date.length >= 4) {
+                    h = date[3];
+                    if (date.length >= 5) {
+                        m = date[4];
+                        if (date.length >= 6) {
+                            s = date[5];
+                        }
+                    }
+                }
+                _date = new Date(date[0] - 1900, date[1] - 1, date[2],
+                                 h, m, s);
+            }
+            return _date;
+        }
+
+        public String toString() {
+            return String.valueOf(getDate().getTime()) + " " +
+                refFormat.format(getDate()) + " : " + ff.createFormat().format(getDate());
+        }
+    };
+
+    private interface FormatFactory {
+        DateFormat createFormat();
+    }
+
+    TestCase[] TESTS = {
+        // Feb 29 2004 -- ordinary leap day
+        new TestCase(new int[] {2004, 2, 29}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // Feb 29 2000 -- century leap day
+        new TestCase(new int[] {2000, 2, 29}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // 0:00:00 Jan 1 1999 -- first second of normal year
+        new TestCase(new int[] {1999, 1, 1}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance();
+                     }}, false),
+
+        // 23:59:59 Dec 31 1999 -- last second of normal year
+        new TestCase(new int[] {1999, 12, 31, 23, 59, 59}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance();
+                     }}, false),
+
+        // 0:00:00 Jan 1 2004 -- first second of leap year
+        new TestCase(new int[] {2004, 1, 1}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance();
+                     }}, false),
+
+        // 23:59:59 Dec 31 2004 -- last second of leap year
+        new TestCase(new int[] {2004, 12, 31, 23, 59, 59}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance();
+                     }}, false),
+
+        // October 25, 1998 1:59:59 AM PDT -- just before DST cessation
+        new TestCase(new Date(909305999000L), TimeZone.getTimeZone("PST"),
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // October 25, 1998 1:00:00 AM PST -- just after DST cessation
+        new TestCase(new Date(909306000000L), TimeZone.getTimeZone("PST"),
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // April 4, 1999 1:59:59 AM PST -- just before DST onset
+        new TestCase(new int[] {1999, 4, 4, 1, 59, 59},
+                     TimeZone.getTimeZone("PST"),
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // April 4, 1999 3:00:00 AM PDT -- just after DST onset
+        new TestCase(new Date(923220000000L), TimeZone.getTimeZone("PST"),
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change
+        new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+
+        // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change
+        new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null,
+                     new FormatFactory() { public DateFormat createFormat() {
+                         return DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                               DateFormat.LONG);
+                     }}, false),
+    };
+
+    public void TestDateFormatRoundTrip() {
+        avail = DateFormat.getAvailableLocales();
+        logln("DateFormat available locales: " + avail.length);
+        logln("Default TimeZone: " +
+              (defaultZone = TimeZone.getDefault()).getID());
+
+        if (random || initialDate != null) {
+            if (RANDOM == null) {
+                // Need this for sparse coverage to reduce combinatorial explosion,
+                // even for non-random looped testing (i.e., with explicit date but
+                // not pattern or locale).
+                RANDOM = new Random(FIXED_SEED);
+            }
+            loopedTest();
+        } else {
+            for (int i=0; i<TESTS.length; ++i) {
+                doTest(TESTS[i]);
+            }
+        }
+    }
+
+    /**
+     * TimeZone must be set to tc.zone before this method is called.
+     */
+    private void doTestInZone(TestCase tc) {
+        logln(escape(tc.toString()));
+        Locale save = Locale.getDefault();
+        try {
+            if (locale != null) {
+                Locale.setDefault(locale);
+                doTest(locale, tc.createFormat(), tc.timeOnly, tc.getDate());
+            } else {
+                for (int i=0; i<avail.length; ++i) {
+                    Locale.setDefault(avail[i]);
+                    doTest(avail[i], tc.createFormat(), tc.timeOnly, tc.getDate());
+                }
+            }
+        } finally {
+            Locale.setDefault(save);
+        }
+    }
+
+    private void doTest(TestCase tc) {
+        if (tc.zone == null) {
+            // Just run in the default zone
+            doTestInZone(tc);
+        } else {
+            try {
+                TimeZone.setDefault(tc.zone);
+                doTestInZone(tc);
+            } finally {
+                TimeZone.setDefault(defaultZone);
+            }
+        }
+    }
+
+    private void loopedTest() {
+        if (INFINITE) {
+            // Special infinite loop test mode for finding hard to reproduce errors
+            if (locale != null) {
+                logln("ENTERING INFINITE TEST LOOP, LOCALE " + locale.getDisplayName());
+                for (;;) doTest(locale);
+            } else {
+                logln("ENTERING INFINITE TEST LOOP, ALL LOCALES");
+                for (;;) {
+                    for (int i=0; i<avail.length; ++i) {
+                        doTest(avail[i]);
+                    }
+                }
+            }
+        }
+        else {
+            if (locale != null) {
+                doTest(locale);
+            } else {
+                doTest(Locale.getDefault());
+
+                for (int i=0; i<avail.length; ++i) {
+                    doTest(avail[i]);
+                }
+            }
+        }
+    }
+
+    void doTest(Locale loc) {
+        if (!INFINITE) logln("Locale: " + loc.getDisplayName());
+
+        if (pattern != null) {
+            doTest(loc, new SimpleDateFormat(pattern, loc));
+            return;
+        }
+
+        // Total possibilities = 24
+        //  4 date
+        //  4 time
+        //  16 date-time
+        boolean[] TEST_TABLE = new boolean[24];
+        for (int i=0; i<24; ++i) TEST_TABLE[i] = true;
+
+        // If we have some sparseness, implement it here.  Sparseness decreases
+        // test time by eliminating some tests, up to 23.
+        if (!INFINITE) {
+            for (int i=0; i<SPARSENESS; ) {
+                int random = (int)(java.lang.Math.random() * 24);
+                if (random >= 0 && random < 24 && TEST_TABLE[i]) {
+                    TEST_TABLE[i] = false;
+                    ++i;
+                }
+            }
+        }
+
+        int itable = 0;
+        for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) {
+            if (TEST_TABLE[itable++])
+                doTest(loc, DateFormat.getDateInstance(style, loc));
+        }
+
+        for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) {
+            if (TEST_TABLE[itable++])
+                doTest(loc, DateFormat.getTimeInstance(style, loc), true);
+        }
+
+        for (int dstyle=DateFormat.FULL; dstyle<=DateFormat.SHORT; ++dstyle) {
+            for (int tstyle=DateFormat.FULL; tstyle<=DateFormat.SHORT; ++tstyle) {
+                if (TEST_TABLE[itable++])
+                    doTest(loc, DateFormat.getDateTimeInstance(dstyle, tstyle, loc));
+            }
+        }
+    }
+
+    void doTest(Locale loc, DateFormat fmt) { doTest(loc, fmt, false); }
+
+    void doTest(Locale loc, DateFormat fmt, boolean timeOnly) {
+        doTest(loc, fmt, timeOnly, initialDate != null ? initialDate : generateDate());
+    }
+
+    void doTest(Locale loc, DateFormat fmt, boolean timeOnly, Date date) {
+        // Skip testing with the JapaneseImperialCalendar which
+        // doesn't support the Gregorian year semantices with 'y'.
+        if (fmt.getCalendar().getClass().getName().equals("java.util.JapaneseImperialCalendar")) {
+            return;
+        }
+
+        String pat = ((SimpleDateFormat)fmt).toPattern();
+        String deqPat = dequotePattern(pat); // Remove quoted elements
+
+        boolean hasEra = (deqPat.indexOf("G") != -1);
+        boolean hasZone = (deqPat.indexOf("z") != -1);
+
+        Calendar cal = fmt.getCalendar();
+
+        // Because patterns contain incomplete data representing the Date,
+        // we must be careful of how we do the roundtrip.  We start with
+        // a randomly generated Date because they're easier to generate.
+        // From this we get a string.  The string is our real starting point,
+        // because this string should parse the same way all the time.  Note
+        // that it will not necessarily parse back to the original date because
+        // of incompleteness in patterns.  For example, a time-only pattern won't
+        // parse back to the same date.
+
+        try {
+            for (int i=0; i<TRIALS; ++i) {
+                Date[] d = new Date[DEPTH];
+                String[] s = new String[DEPTH];
+                String error = null;
+
+                d[0] = date;
+
+                // We go through this loop until we achieve a match or until
+                // the maximum loop count is reached.  We record the points at
+                // which the date and the string starts to match.  Once matching
+                // starts, it should continue.
+                int loop;
+                int dmatch = 0; // d[dmatch].getTime() == d[dmatch-1].getTime()
+                int smatch = 0; // s[smatch].equals(s[smatch-1])
+                for (loop=0; loop<DEPTH; ++loop) {
+                    if (loop > 0) d[loop] = fmt.parse(s[loop-1]);
+                    s[loop] = fmt.format(d[loop]);
+
+                    if (loop > 0) {
+                        if (smatch == 0) {
+                            boolean match = s[loop].equals(s[loop-1]);
+                            if (smatch == 0) {
+                                if (match) smatch = loop;
+                            }
+                            else if (!match) {
+                                // This should never happen; if it does, fail.
+                                smatch = -1;
+                                error = "FAIL: String mismatch after match";
+                            }
+                        }
+
+                        if (dmatch == 0) {
+                            boolean match = d[loop].getTime() == d[loop-1].getTime();
+                            if (dmatch == 0) {
+                                if (match) dmatch = loop;
+                            }
+                            else if (!match) {
+                                // This should never happen; if it does, fail.
+                                dmatch = -1;
+                                error = "FAIL: Date mismatch after match";
+                            }
+                        }
+
+                        if (smatch != 0 && dmatch != 0) break;
+                    }
+                }
+                // At this point loop == DEPTH if we've failed, otherwise loop is the
+                // max(smatch, dmatch), that is, the index at which we have string and
+                // date matching.
+
+                // Date usually matches in 2.  Exceptions handled below.
+                int maxDmatch = 2;
+                int maxSmatch = 1;
+                if (dmatch > maxDmatch) {
+                    // Time-only pattern with zone information and a starting date in PST.
+                    if (timeOnly && hasZone && fmt.getTimeZone().inDaylightTime(d[0])) {
+                        maxDmatch = 3;
+                        maxSmatch = 2;
+                    }
+                }
+
+                // String usually matches in 1.  Exceptions are checked for here.
+                if (smatch > maxSmatch) { // Don't compute unless necessary
+                    // Starts in BC, with no era in pattern
+                    if (!hasEra && getField(cal, d[0], Calendar.ERA) == GregorianCalendar.BC)
+                        maxSmatch = 2;
+                    // Starts in DST, no year in pattern
+                    else if (fmt.getTimeZone().inDaylightTime(d[0]) &&
+                             deqPat.indexOf("yyyy") == -1)
+                        maxSmatch = 2;
+                    // Two digit year with zone and year change and zone in pattern
+                    else if (hasZone &&
+                             fmt.getTimeZone().inDaylightTime(d[0]) !=
+                             fmt.getTimeZone().inDaylightTime(d[dmatch]) &&
+                             getField(cal, d[0], Calendar.YEAR) !=
+                             getField(cal, d[dmatch], Calendar.YEAR) &&
+                             deqPat.indexOf("y") != -1 &&
+                             deqPat.indexOf("yyyy") == -1)
+                        maxSmatch = 2;
+                    // Two digit year, year change, DST changeover hour.  Example:
+                    //    FAIL: Pattern: dd/MM/yy HH:mm:ss
+                    //     Date matched in 2, wanted 2
+                    //     String matched in 2, wanted 1
+                    //        Thu Apr 02 02:35:52.110 PST 1795 AD F> 02/04/95 02:35:52
+                    //     P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52
+                    //     P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 d== s==
+                    // The problem is that the initial time is not a DST onset day, but
+                    // then the year changes, and the resultant parsed time IS a DST
+                    // onset day.  The hour "2:XX" makes no sense if 2:00 is the DST
+                    // onset, so DateFormat interprets it as 1:XX (arbitrary -- could
+                    // also be 3:XX, same problem).  This results in an extra iteration
+                    // for String match convergence.
+                    else if (!justBeforeOnset(cal, d[0]) && justBeforeOnset(cal, d[dmatch]) &&
+                             getField(cal, d[0], Calendar.YEAR) !=
+                             getField(cal, d[dmatch], Calendar.YEAR) &&
+                             deqPat.indexOf("y") != -1 &&
+                             deqPat.indexOf("yyyy") == -1)
+                        maxSmatch = 2;
+                    // Another spurious failure:
+                    // FAIL: Pattern: dd MMMM yyyy hh:mm:ss
+                    //  Date matched in 2, wanted 2
+                    //  String matched in 2, wanted 1
+                    //     Sun Apr 05 14:28:38.410 PDT 3998 AD F> 05 April 3998 02:28:38
+                    //  P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38
+                    //  P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 d== s==
+                    // The problem here is that with an 'hh' pattern, hour from 1-12,
+                    // a lack of AM/PM -- that is, no 'a' in pattern, and an initial
+                    // time in the onset hour + 12:00.
+                    else if (deqPat.indexOf('h') >= 0
+                             && deqPat.indexOf('a') < 0
+                             && justBeforeOnset(cal, new Date(d[0].getTime() - 12*60*60*1000L))
+                             && justBeforeOnset(cal, d[1]))
+                        maxSmatch = 2;
+                }
+
+                if (dmatch > maxDmatch || smatch > maxSmatch
+                    || dmatch < 0 || smatch < 0) {
+                    StringBuffer out = new StringBuffer();
+                    if (error != null) {
+                        out.append(error + '\n');
+                    }
+                    out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n');
+                    out.append("      Initial date (ms): " + d[0].getTime() + '\n');
+                    out.append("     Date matched in " + dmatch
+                               + ", wanted " + maxDmatch + '\n');
+                    out.append("     String matched in " + smatch
+                               + ", wanted " + maxSmatch);
+
+                    for (int j=0; j<=loop && j<DEPTH; ++j) {
+                        out.append("\n    " +
+                                   (j>0?" P> ":"    ") + refFormat.format(d[j]) + " F> " +
+                                   escape(s[j]) +
+                                   (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") +
+                                   (j>0&&s[j].equals(s[j-1])?" s==":""));
+                    }
+                    errln(escape(out.toString()));
+                }
+            }
+        }
+        catch (ParseException e) {
+            errln(e.toString());
+        }
+    }
+
+    /**
+     * Return a field of the given date
+     */
+    static int getField(Calendar cal, Date d, int f) {
+        // Should be synchronized, but we're single threaded so it's ok
+        cal.setTime(d);
+        return cal.get(f);
+    }
+
+    /**
+     * Return true if the given Date is in the 1 hour window BEFORE the
+     * change from STD to DST for the given Calendar.
+     */
+    static final boolean justBeforeOnset(Calendar cal, Date d) {
+        return nearOnset(cal, d, false);
+    }
+
+    /**
+     * Return true if the given Date is in the 1 hour window AFTER the
+     * change from STD to DST for the given Calendar.
+     */
+    static final boolean justAfterOnset(Calendar cal, Date d) {
+        return nearOnset(cal, d, true);
+    }
+
+    /**
+     * Return true if the given Date is in the 1 hour (or whatever the
+     * DST savings is) window before or after the onset of DST.
+     */
+    static boolean nearOnset(Calendar cal, Date d, boolean after) {
+        cal.setTime(d);
+        if ((cal.get(Calendar.DST_OFFSET) == 0) == after) {
+            return false;
+        }
+        int delta;
+        try {
+            delta = ((SimpleTimeZone) cal.getTimeZone()).getDSTSavings();
+        } catch (ClassCastException e) {
+            delta = 60*60*1000; // One hour as ms
+        }
+        cal.setTime(new Date(d.getTime() + (after ? -delta : delta)));
+        return (cal.get(Calendar.DST_OFFSET) == 0) == after;
+    }
+
+    static String escape(String s) {
+        StringBuffer buf = new StringBuffer();
+        for (int i=0; i<s.length(); ++i) {
+            char c = s.charAt(i);
+            if (c < '\u0080') buf.append(c);
+            else {
+                buf.append("\\u");
+                if (c < '\u1000') {
+                    buf.append('0');
+                    if (c < '\u0100') {
+                        buf.append('0');
+                        if (c < '\u0010') {
+                            buf.append('0');
+                        }
+                    }
+                }
+                buf.append(Integer.toHexString(c));
+            }
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Remove quoted elements from a pattern.  E.g., change "hh:mm 'o''clock'"
+     * to "hh:mm ?".  All quoted elements are replaced by one or more '?'
+     * characters.
+     */
+    static String dequotePattern(String pat) {
+        StringBuffer out = new StringBuffer();
+        boolean inQuote = false;
+        for (int i=0; i<pat.length(); ++i) {
+            char ch = pat.charAt(i);
+            if (ch == '\'') {
+                if ((i+1)<pat.length()
+                    && pat.charAt(i+1) == '\'') {
+                    // Handle "''"
+                    out.append('?');
+                    ++i;
+                } else {
+                    inQuote = !inQuote;
+                    if (inQuote) {
+                        out.append('?');
+                    }
+                }
+            } else if (!inQuote) {
+                out.append(ch);
+            }
+        }
+        return out.toString();
+    }
+
+    static Date generateDate() {
+        double a = (RANDOM.nextLong() & 0x7FFFFFFFFFFFFFFFL ) /
+            ((double)0x7FFFFFFFFFFFFFFFL);
+
+        // Now 'a' ranges from 0..1; scale it to range from 0 to 8000 years
+        a *= 8000;
+
+        // Range from (4000-1970) BC to (8000-1970) AD
+        a -= 4000;
+
+        // Now scale up to ms
+        a *= 365.25 * 24 * 60 * 60 * 1000;
+
+        return new Date((long)a);
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/DateFormatSymbolsSerializationTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ *
+ * 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 4278402
+ * @library /java/text/testlib
+ * @build DateFormatSymbolsSerializationTest HexDumpReader
+ * @run main DateFormatSymbolsSerializationTest
+ * @summary Make sure DateFormatSymbols serialization
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class DateFormatSymbolsSerializationTest {
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            boolean err = false;
+            Locale.setDefault(Locale.ENGLISH);
+            SimpleDateFormat sdf =
+                    new SimpleDateFormat("yyyy.MM.dd E hh.mm.ss zzz",
+                                                        Locale.ENGLISH);
+            Calendar calendar =
+                    new GregorianCalendar(TimeZone.getTimeZone("GMT"),
+                                                      Locale.ENGLISH);
+            calendar.setTime(new Date(0L));
+            DecimalFormat df = new DecimalFormat("");
+            df.setDecimalSeparatorAlwaysShown(true);
+            df.setGroupingSize(3);
+            df.setMultiplier(1);
+            df.setNegativePrefix("-");
+            df.setNegativeSuffix("");
+            df.setPositivePrefix("");
+            df.setPositiveSuffix("");
+            df.setMaximumFractionDigits(3); //
+            df.setMinimumIntegerDigits(1);  // for compatibility 1.2 and 1.3
+            df.setMaximumIntegerDigits(40); //
+
+            sdf.setCalendar(calendar);
+            sdf.setNumberFormat(df);
+
+            SimpleDateFormat sdf1;
+
+            if (args.length > 0) {
+                try (FileOutputStream fos =
+                        new FileOutputStream("SDFserialized.ser")) {
+                    ObjectOutputStream oStream = new ObjectOutputStream(fos);
+                    oStream.writeObject(sdf);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            } else {
+                try (InputStream is =
+                     HexDumpReader.getStreamFromHexDump("SDFserialized.ser.txt")) {
+                    ObjectInputStream iStream = new ObjectInputStream(is);
+                    sdf1 = (SimpleDateFormat)iStream.readObject();
+                }
+
+                DateFormatSymbols dfs = sdf.getDateFormatSymbols();
+                DateFormatSymbols dfs1 = sdf1.getDateFormatSymbols();
+                System.out.println(sdf + "," + sdf.toPattern());
+                System.out.println(sdf1 + "," + sdf1.toPattern());
+
+                // time zone display names should not be a part of this
+                // compatibility test. See 4112924 and 4282899.
+                dfs.setZoneStrings(dfs1.getZoneStrings());
+                // localPatternChars should not be a part of this
+                // compatibility test. See 4322313.
+                dfs.setLocalPatternChars(dfs1.getLocalPatternChars());
+                sdf.setDateFormatSymbols(dfs);
+
+                // decimal format symbols should not be part of this
+                // compatibility test - old decimal format symbols get filled
+                // in with the root locale (4290801)
+                DecimalFormat df1 = (DecimalFormat) sdf1.getNumberFormat();
+                df1.setDecimalFormatSymbols(df.getDecimalFormatSymbols());
+
+                if (!dfs.equals(dfs1)) {
+                    err = true;
+                    System.err.println(
+                        "Error: serialized DateFormatSymbols is different");
+                }
+                if (!sdf.equals(sdf1)) {
+                    err = true;
+                    System.err.println(
+                        "Error: serialized SimpleDateFormat is different");
+                }
+                if (err) {
+                    throw new Exception("Serialization failed.");
+                }
+            }
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/DateFormatTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1207 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571
+ * @summary test DateFormat and SimpleDateFormat.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest
+ */
+
+import java.util.*;
+import java.text.*;
+import static java.util.GregorianCalendar.*;
+
+public class DateFormatTest extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            new DateFormatTest().run(args);
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    // Test 4 digit year parsing with pattern "yy"
+    @SuppressWarnings("deprecation")
+    public void TestYearParsing()
+    {
+        String str = "7/Sep/2001";
+        Date exp = new Date(2001-1900, SEPTEMBER, 7);
+        String pat = "d/MMM/yy";
+        SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US);
+        try {
+            Date d = sdf.parse(str);
+            logln(str + " parses with " + pat + " to " + d);
+            if (d.getTime() != exp.getTime()) {
+                errln("FAIL: Expected " + exp);
+            }
+        }
+        catch (ParseException e) {
+            errln(str + " parse fails with " + pat);
+        }
+    }
+
+    // Test written by Wally Wedel and emailed to me.
+    public void TestWallyWedel()
+    {
+        /*
+         * Instantiate a TimeZone so we can get the ids.
+         */
+        TimeZone tz = new SimpleTimeZone(7,"");
+        /*
+         * Computational variables.
+         */
+        int offset, hours, minutes;
+        /*
+         * Instantiate a SimpleDateFormat set up to produce a full time
+         zone name.
+         */
+        SimpleDateFormat sdf = new SimpleDateFormat("zzzz");
+        /*
+         * A String array for the time zone ids.
+         */
+        String[] ids = TimeZone.getAvailableIDs();
+        /*
+         * How many ids do we have?
+         */
+        logln("Time Zone IDs size: " + ids.length);
+        /*
+         * Column headings (sort of)
+         */
+        logln("Ordinal ID offset(h:m) name");
+        /*
+         * Loop through the tzs.
+         */
+        Date today = new Date();
+        Calendar cal = Calendar.getInstance();
+        for (int i = 0; i < ids.length; i++) {
+            // logln(i + " " + ids[i]);
+            TimeZone ttz = TimeZone.getTimeZone(ids[i]);
+            // offset = ttz.getRawOffset();
+            cal.setTimeZone(ttz);
+            cal.setTime(today);
+            offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
+            // logln(i + " " + ids[i] + " offset " + offset);
+            char sign = '+';
+            if (offset < 0) { sign = '-'; offset = -offset; }
+            hours = offset/3600000;
+            minutes = (offset%3600000)/60000;
+            String dstOffset = "" + sign + (hours < 10 ? "0" : "") +
+                hours + ':' + (minutes < 10 ? "0" : "") + minutes;
+            /*
+             * Instantiate a date so we can display the time zone name.
+             */
+            sdf.setTimeZone(ttz);
+            /*
+             * Format the output.
+             */
+            StringBuffer tzS = new StringBuffer();
+            sdf.format(today,tzS, new FieldPosition(0));
+            String fmtOffset = tzS.toString();
+            String fmtDstOffset = null;
+            if (fmtOffset.startsWith("GMT"))
+            {
+                fmtDstOffset = fmtOffset.substring(3);
+            }
+            /*
+             * Show our result.
+             */
+            boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset);
+            if (ok)
+            {
+                logln(i + " " + ids[i] + " " + dstOffset +
+                      " " + fmtOffset +
+                      (fmtDstOffset != null ? " ok" : " ?"));
+            }
+            else
+            {
+                errln(i + " " + ids[i] + " " + dstOffset +
+                      " " + fmtOffset + " *** FAIL ***");
+            }
+        }
+    }
+
+    // Test equals
+    public void TestEquals()
+    {
+        DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
+
+        DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
+
+        if (!fmtA.equals(fmtB)) {
+            errln("FAIL");
+        }
+    }
+
+    // Check out some specific parsing problem
+    @SuppressWarnings("deprecation")
+    public void TestTwoDigitYearDSTParse()
+    {
+        SimpleDateFormat fullFmt =
+            new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
+
+        //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL,
+        //                                                Locale.ENGLISH);
+        SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z",
+                                                    Locale.ENGLISH);
+        //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47);
+        //logln(fmt.format(date)); // This shows what the current locale format is
+        //logln(((SimpleDateFormat)fmt).toPattern());
+        TimeZone save = TimeZone.getDefault();
+        TimeZone PST  = TimeZone.getTimeZone("PST");
+        String s = "03-Apr-04 2:20:47 o'clock AM PST";
+        int hour = 2;
+        try {
+            TimeZone.setDefault(PST);
+            Date d = fmt.parse(s);
+            logln(s + " P> " + fullFmt.format(d));
+            if (d.getHours() != hour) {
+                errln("FAIL: Should parse to hour " + hour);
+            }
+        }
+        catch (ParseException e) { errln("FAIL: " + e.getMessage()); }
+        finally {
+            TimeZone.setDefault(save);
+        }
+    }
+
+    static String escape(String s)
+    {
+        StringBuilder buf = new StringBuilder();
+        for (int i=0; i<s.length(); ++i)
+        {
+            char c = s.charAt(i);
+            if (c <= (char)0x7F) {
+                buf.append(c);
+            } else {
+                buf.append("\\u");
+                buf.append(Integer.toHexString((c & 0xF000) >> 12));
+                buf.append(Integer.toHexString((c & 0x0F00) >> 8));
+                buf.append(Integer.toHexString((c & 0x00F0) >> 4));
+                buf.append(Integer.toHexString(c & 0x000F));
+            }
+        }
+        return buf.toString();
+    }
+
+    // Test field position return values
+    static String fieldNames[] = {
+        "ERA_FIELD", "YEAR_FIELD", "MONTH_FIELD",
+        "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD",
+        "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD",
+        "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD",
+        "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD",
+        "MINUTE_FIELD", "SECOND_FIELD",
+        "MILLISECOND_FIELD", "TIMEZONE_FIELD",
+    };
+    static int fieldIDs[] = {
+        DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
+        DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD,
+        DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD,
+        DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD,
+        DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
+        DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD,
+        DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD,
+    };
+
+    /**
+     * Bug 4089987
+     */
+    public void TestFieldPosition()
+    {
+        DateFormat[] dateFormats = {
+            DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,
+                                           Locale.US),
+
+            DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE),
+            new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
+            new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
+            new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " +
+                                  "SSSS, EEEE, DDDD, " +
+                                  "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz")
+        };
+        String[] expected =
+        {
+            "", "1997", "August", "", "", "13", "", "Wednesday", "",
+            "PM", "", "2", "", "", "34", "12", "", "PDT",
+
+            "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "",
+            "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/,
+
+            "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM",
+            "2", "2", "14", "14", "34", "12", "513", "PDT",
+
+            "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM",
+            "2", "2", "14", "14", "34", "12", "513", "PDT",
+
+            "AD", "1997", "August", "0033", "0003", "0013", "0225",
+            "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014",
+            "0034", "0012", "0513", "Pacific Daylight Time",
+        };
+        Date someDate = new Date(871508052513L);
+        TimeZone PST = TimeZone.getTimeZone("PST");
+        for (int j = 0, exp = 0; j < dateFormats.length; ++j) {
+            DateFormat df = dateFormats[j];
+            if (!(df instanceof SimpleDateFormat)) {
+                continue;
+            }
+            df.setTimeZone(PST);
+            logln(" Pattern = " + ((SimpleDateFormat)df).toPattern());
+            logln("  Result = " + df.format(someDate));
+            for (int i = 0; i < fieldIDs.length; ++i)
+            {
+                String field = getFieldText(df, fieldIDs[i], someDate);
+                if (!field.equals(expected[exp])) {
+                    errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" +
+                            escape(field) + "\", expected \"" + escape(expected[exp]) + "\"");
+                }
+                ++exp;
+            }
+        }
+    }
+    // get the string value for the given field for the given date
+    static String getFieldText(DateFormat df, int field, Date date)
+    {
+        StringBuffer buffer = new StringBuffer();
+        FieldPosition pos = new FieldPosition(field);
+        df.format(date, buffer, pos);
+        return buffer.toString().substring(pos.getBeginIndex(),
+                                           pos.getEndIndex());
+    }
+
+    // Test parsing of partial strings
+    @SuppressWarnings("deprecation")
+    public void TestPartialParse994()
+    {
+        SimpleDateFormat f = new SimpleDateFormat();
+        Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1);
+        f.set2DigitYearStart(cal.getTime());
+        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42));
+        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
+        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
+        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
+        tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
+    }
+
+    void tryPat994(SimpleDateFormat format, String pat, String str, Date expected)
+    {
+        logln("Pattern \"" + pat + "\"   String \"" + str + "\"");
+        try {
+            format.applyPattern(pat);
+            Date date = format.parse(str);
+            String f = format.format(date);
+            logln(" parse(" + str + ") -> " + date.toString());
+            logln(" format -> " + f);
+            if (expected == null ||
+                !date.equals(expected)) {
+                errln("FAIL: Expected " + expected);
+            }
+            if (!f.equals(str)) {
+                errln("FAIL: Expected " + str);
+            }
+        }
+        catch(ParseException e) {
+            logln("ParseException: " + e.getMessage());
+            if (expected != null) {
+                errln("FAIL: Expected " + expected);
+            }
+        }
+        catch(Exception e) {
+            errln("*** Exception:");
+            e.printStackTrace();
+        }
+    }
+
+    // Test pattern with runs things together
+    public void TestRunTogetherPattern985()
+    {
+        String format = "yyyyMMddHHmmssSSS";
+        String now, then;
+
+        SimpleDateFormat formatter = new SimpleDateFormat(format);
+
+        Date date1 = new Date();
+        now = formatter.format(date1);
+
+        logln(now);
+
+        ParsePosition pos = new ParsePosition(0);
+
+        Date date2 = formatter.parse(now, pos);
+        if (date2 == null) {
+            then = "Parse stopped at " + pos.getIndex();
+        } else {
+            then = formatter.format(date2);
+        }
+
+        logln(then);
+
+        if (!date2.equals(date1)) {
+            errln("FAIL");
+        }
+    }
+
+    // Test patterns which run numbers together
+    @SuppressWarnings("deprecation")
+    public void TestRunTogetherPattern917()
+    {
+        SimpleDateFormat fmt;
+        String myDate;
+
+        fmt = new SimpleDateFormat( "yyyy/MM/dd" );
+        myDate = "1997/02/03";
+        _testIt917( fmt, myDate, new Date(97, 2-1, 3) );
+
+        fmt = new SimpleDateFormat( "yyyyMMdd" );
+        myDate = "19970304";
+        _testIt917( fmt, myDate, new Date(97, 3-1, 4) );
+
+    }
+    void _testIt917( SimpleDateFormat fmt, String str, Date expected )
+    {
+        logln( "pattern=" + fmt.toPattern() + "   string=" + str );
+
+        Object o;
+        try {
+            o = fmt.parseObject( str );
+        } catch( ParseException e ) {
+            e.printStackTrace();
+            return;
+        }
+        logln( "Parsed object: " + o );
+        if (!o.equals(expected)) {
+            errln("FAIL: Expected " + expected);
+        }
+
+        String formatted = fmt.format( o );
+        logln( "Formatted string: " + formatted );
+        if (!formatted.equals(str)) {
+            errln("FAIL: Expected " + str);
+        }
+    }
+
+    // Test Czech month formatting -- this can cause a problem because the June and
+    // July month names share a common prefix.
+    @SuppressWarnings("deprecation")
+    public void TestCzechMonths459()
+    {
+        // Use Czech, which has month names with shared prefixes for June and July
+        DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", ""));
+        //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy");
+        logln("Pattern " + ((SimpleDateFormat)fmt).toPattern());
+
+        Date june = new Date(97, Calendar.JUNE, 15);
+        Date july = new Date(97, Calendar.JULY, 15);
+
+        String juneStr = fmt.format(june);
+        String julyStr = fmt.format(july);
+
+        try {
+            logln("format(June 15 1997) = " + juneStr);
+            Date d = fmt.parse(juneStr);
+            String s = fmt.format(d);
+            int month = d.getMonth();
+            logln("  -> parse -> " + s + " (month = " + month + ")");
+            if (month != JUNE) {
+                errln("FAIL: Month should be June");
+            }
+
+            logln("format(July 15 1997) = " + julyStr);
+            d = fmt.parse(julyStr);
+            s = fmt.format(d);
+            month = d.getMonth();
+            logln("  -> parse -> " + s + " (month = " + month + ")");
+            if (month != JULY) {
+                errln("FAIL: Month should be July");
+            }
+        }
+        catch (ParseException e) {
+            errln("Exception: " + e);
+        }
+    }
+
+    // Test big D (day of year) versus little d (day of month)
+    @SuppressWarnings("deprecation")
+    public void TestLetterDPattern212()
+    {
+        String dateString = "1995-040.05:01:29";
+        String bigD = "yyyy-DDD.hh:mm:ss";
+        String littleD = "yyyy-ddd.hh:mm:ss";
+        Date expLittleD = new Date(95, 0, 1, 5, 1, 29);
+        Date expBigD =  new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days
+        expLittleD = expBigD; // Expect the same, with default lenient parsing
+        logln( "dateString= " + dateString );
+        SimpleDateFormat formatter = new SimpleDateFormat(bigD);
+        ParsePosition pos = new ParsePosition(0);
+        Date myDate = formatter.parse( dateString, pos );
+        logln("Using " + bigD + " -> " + myDate);
+        if (myDate.getTime() != expBigD.getTime()) {
+            errln("FAIL: Expected " + expBigD + " got " + myDate);
+        }
+
+        formatter = new SimpleDateFormat(littleD);
+        pos = new ParsePosition(0);
+        myDate = formatter.parse( dateString, pos );
+        logln("Using " + littleD + " -> " + myDate);
+        if (myDate.getTime() != expLittleD.getTime()) {
+            errln("FAIL: Expected " + expLittleD + " got " + myDate);
+        }
+    }
+
+    // Test the 'G' day of year pattern
+    @SuppressWarnings("deprecation")
+    public void TestDayOfYearPattern195()
+    {
+        Date today = new Date();
+        Date expected = new Date(today.getYear(), today.getMonth(), today.getDate());
+
+        logln("Test Date: " + today);
+
+        SimpleDateFormat sdf =
+            (SimpleDateFormat)SimpleDateFormat.getDateInstance();
+
+        tryPattern(sdf, today, null, expected);
+        tryPattern(sdf, today, "G yyyy DDD", expected);
+    }
+
+    void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected)
+    {
+        if (pattern != null) {
+            sdf.applyPattern(pattern);
+        }
+        logln("pattern: " + sdf.toPattern());
+
+        String formatResult = sdf.format(d);
+        logln(" format -> " + formatResult);
+        try {
+            Date d2 = sdf.parse(formatResult);
+            logln(" parse(" + formatResult +  ") -> " + d2);
+            if (d2.getTime() != expected.getTime()) {
+                errln("FAIL: Expected " + expected);
+            }
+            String format2 = sdf.format(d2);
+            logln(" format -> " + format2);
+            if (!formatResult.equals(format2)) {
+                errln("FAIL: Round trip drift");
+            }
+        }
+        catch(Exception e) {
+            errln("Error: " + e.getMessage());
+        }
+    }
+
+    // Test a pattern with single quotes
+    @SuppressWarnings("deprecation")
+    public void TestQuotePattern161()
+    {
+        // This pattern used to end in " zzz" but that makes this test zone-dependent
+        SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz");
+        Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28);
+        String dateString = formatter.format(currentTime_1);
+        String exp = "08/13/1997 at 10:42:28 AM ";
+        logln("format(" + currentTime_1 + ") = " + dateString);
+        if (!dateString.regionMatches(0, exp, 0, exp.length())) {
+            errln("FAIL: Expected " + exp);
+        }
+    }
+
+    // Test the parsing of bad input strings
+    /** Demonstrates a number of bugs in DateFormat.parse(String) where
+     *  either StringIndexOutOfBoundsException is thrown or null is
+     *  returned instead of ParseException. To reproduce, run this program
+     *  and notice all the "SHOULD NOT HAPPEN" errors.  Note also that the
+     *  1 line that should be correct is off by 100 years.  (In this day
+     *  and age, no one would assume that 1/1/00 is Jan 1 1900.)
+     **/
+    public void TestBadInput135()
+    {
+        int        looks[] = { DateFormat.SHORT, DateFormat.MEDIUM,
+                               DateFormat.LONG,  DateFormat.FULL };
+        String     strings[] = { "Mar 15", "Mar 15 1997", "asdf",
+                                 "3/1/97 1:23:", "3/1/00 1:23:45 AM" };
+        DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG,
+                                                         DateFormat.LONG);
+        String expected = "March 1, 2000 1:23:45 AM ";
+        for ( int i = 0;  i < strings.length;  ++i ){
+            String text = strings[i];
+            for ( int j = 0;  j < looks.length;  ++j ){
+                int dateLook = looks[j];
+                for ( int k = 0;  k < looks.length;  ++k ){
+                    int timeLook = looks[k];
+                    DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook);
+                    String prefix = text + ", " + dateLook + "/" + timeLook + ": ";
+                    try {
+                        Date when = df.parse(text);
+                        if ( when == null ){
+                            errln(prefix +
+                                  "SHOULD NOT HAPPEN: parse returned null.");
+                            continue;
+                        }
+                        String format = full.format(when);
+                        logln(prefix + "OK: " + format);
+                        // Only match the start -- not the zone, which could vary
+                        if (!format.regionMatches(0, expected, 0, expected.length())) {
+                            errln("FAIL: Expected " + expected);
+                        }
+                    }
+                    catch ( ParseException e ){
+                        //errln(prefix + e); // This is expected.
+                    }
+                    catch ( StringIndexOutOfBoundsException e ){
+                        errln(prefix + "SHOULD NOT HAPPEN: " + e);
+                    }
+                }
+            }
+        }
+    }
+
+    final private static String parseFormats[] =
+    {
+        "MMMM d, yyyy",  // january 1, 1970 or jan 1, 1970
+        "MMMM d yyyy",   // january 1 1970 or jan 1 1970
+        "M/d/yy",        // 1/1/70
+        "d MMMM, yyyy",  // 1 january, 1970 or 1 jan, 1970
+        "d MMMM yyyy",   // 1 january 1970 or 1 jan 1970
+        "d MMMM",        // 1 january or 1 jan
+        "MMMM d",        // january 1 or jan 1
+        "yyyy",          // 1970
+        "h:mm a MMMM d, yyyy" // Date and Time
+    };
+    final private static String inputStrings[] =
+    {
+        "bogus string",         null, null, null, null, null, null, null, null, null,
+        "April 1, 1997",        "April 1, 1997", null, null, null, null, null, "April 1", null, null,
+        "Jan 1, 1970",          "January 1, 1970", null, null, null, null, null, "January 1", null, null,
+        "Jan 1 2037",           null, "January 1 2037", null, null, null, null, "January 1", null, null,
+        "1/1/70",               null, null, "1/1/70", null, null, null, null, "0001", null,
+        "5 May 1997",           null, null, null, null, "5 May 1997", "5 May", null, "0005", null,
+        "16 May",               null, null, null, null, null, "16 May", null, "0016", null,
+        "April 30",             null, null, null, null, null, null, "April 30", null, null,
+        "1998",                 null, null, null, null, null, null, null, "1998", null,
+        "1",                    null, null, null, null, null, null, null, "0001", null, // Bug620
+        "3:00 pm Jan 1, 1997",  null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997",
+    };
+    // More testing of the parsing of bad input
+    @SuppressWarnings("UnusedAssignment")
+    public void TestBadInput135a()
+    {
+        SimpleDateFormat dateParse = new SimpleDateFormat();
+        String s;
+        Date date;
+        int PFLENGTH = parseFormats.length;
+
+        dateParse.applyPattern("d MMMM, yyyy");
+        dateParse.setTimeZone(TimeZone.getDefault());
+        s = "not parseable";
+        logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
+        try {
+            date = dateParse.parse(s);
+            errln("FAIL: Expected exception during parse");
+        } catch (Exception ex) {
+            logln("Exception during parse: " + ex); // This is expected
+        }
+
+        for (int i=0; i<inputStrings.length; i += (PFLENGTH+1))
+        {
+            ParsePosition parsePosition = new ParsePosition(0);
+            s = inputStrings[i];
+
+            for (int index=0; index<PFLENGTH; ++index)
+            {
+                String expected = inputStrings[i + 1 + index];
+                dateParse.applyPattern(parseFormats[index]);
+                dateParse.setTimeZone(TimeZone.getDefault());
+                // logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
+                try {
+                    parsePosition.setIndex(0);
+                    date = dateParse.parse(s, parsePosition);
+                    if (parsePosition.getIndex() != 0) {
+                        if (date == null) {
+                            errln("ERROR: null result with pos " +
+                                    parsePosition.getIndex() + " " +
+                                    s.substring(0, parsePosition.getIndex()) + "|" +
+                                    s.substring(parsePosition.getIndex()));
+                        } else {
+                            String result = dateParse.format(date);
+                            logln("Parsed \"" + s + "\" using \"" + dateParse.toPattern() +
+                                  "\" to: " + result);
+                            if (expected == null) {
+                                errln("FAIL: Expected parse failure");
+                            } else if (!expected.equals(result)) {
+                                errln("FAIL: Expected " + expected);
+                            }
+                        }
+                    } else {
+                        // logln("Not parsed.");
+                        if (expected != null) {
+                            errln("FAIL: Expected " + expected);
+                        }
+                    }
+                } catch (Exception ex) {
+                    errln("An exception was thrown during parse: " + ex);
+                }
+            }
+        }
+    }
+
+    // Test the handling of 2-digit dates
+    public void TestTwoDigitYear() {
+        SimpleDateFormat fmt = new SimpleDateFormat("M/d/yy");
+
+        // find out the expected 2-digit year values for "6/5/17" and "6/4/34"
+        long start = fmt.get2DigitYearStart().getTime();
+        Calendar cal = new Calendar.Builder().setInstant(start).build();
+        int startYear = cal.get(YEAR);
+        cal.add(YEAR, 100);
+        long end = cal.getTimeInMillis();
+        int endYear = cal.get(YEAR);
+        int xx17 = 0, xx34 = 0;
+        for (int year = startYear; year <= endYear; year++) {
+            int yy = year % 100;
+            if (yy == 17 && xx17 == 0) {
+                xx17 = yearValue(start, end, year, JUNE, 5);
+            } else if (yy == 34 && xx34 == 0) {
+                xx34 = yearValue(start, end, year, JUNE, 4);
+            }
+            if (xx17 != 0 && xx34 != 0) {
+                break;
+            }
+        }
+        if (xx17 == 0 || xx34 == 0) {
+            errln("Failed: producing expected values: 2DigitYearStart: " + new Date(start)
+                  + ", xx17 = " + xx17 + ", xx34 = " + xx34);
+        }
+        logln("2DigitYearStart: " + new Date(start) + ", xx17 = " + xx17 + ", xx34 = " + xx34);
+
+        parse2DigitYear(fmt, "6/5/17", new GregorianCalendar(xx17, JUNE, 5).getTime());
+        parse2DigitYear(fmt, "6/4/34", new GregorianCalendar(xx34, JUNE, 4).getTime());
+    }
+
+    private int yearValue(long start, long end, int year, int month, int dayOfMonth) {
+        Calendar cal = new GregorianCalendar(year, month, dayOfMonth);
+        long time = cal.getTimeInMillis();
+        return (start <= time && time < end) ? year : 0;
+    }
+
+    private void parse2DigitYear(SimpleDateFormat fmt, String str, Date expected) {
+        try {
+            Date d = fmt.parse(str);
+            logln("Parsing \"" + str + "\" with " +
+                  fmt.toPattern() +
+                  "  => " + d.toString());
+            if (d.getTime() != expected.getTime()) {
+                errln("FAIL: Expected " + expected);
+            }
+        } catch (ParseException e) {
+            errln("FAIL: Got exception");
+        }
+    }
+
+    // Test behavior of DateFormat with applied time zone
+    public void TestDateFormatZone061()
+    {
+        Date date;
+        DateFormat formatter;
+
+        // 25-Mar-97 00:00:00 GMT
+        date = new Date( 859248000000L );
+        logln( "Date 1997/3/25 00:00 GMT: " + date );
+        formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK);
+        formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
+
+        String temp = formatter.format( date );
+        logln( "Formatted in GMT to: " + temp );
+
+        /* Parse date string */
+        try {
+            Date tempDate = formatter.parse( temp );
+            logln( "Parsed to: " + tempDate );
+            if (tempDate.getTime() != date.getTime()) {
+                errln("FAIL: Expected " + date);
+            }
+        }
+        catch( Throwable t ) {
+            errln( "Date Formatter throws: " +
+                   t.toString() );
+        }
+    }
+
+    // Make sure DateFormat uses the correct zone.
+    public void TestDateFormatZone146()
+    {
+        TimeZone saveDefault = TimeZone.getDefault();
+
+        try {
+            TimeZone thedefault = TimeZone.getTimeZone("GMT");
+            TimeZone.setDefault(thedefault);
+            // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
+
+            // check to be sure... its GMT all right
+            TimeZone testdefault = TimeZone.getDefault();
+            String testtimezone = testdefault.getID();
+            if (testtimezone.equals("GMT")) {
+                logln("Test timezone = " + testtimezone);
+            } else {
+                errln("Test timezone should be GMT, not " + testtimezone);
+            }
+
+            // now try to use the default GMT time zone
+            GregorianCalendar greenwichcalendar =
+                new GregorianCalendar(1997, 3, 4, 23, 0);
+            //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
+            //greenwichcalendar.set(1997, 3, 4, 23, 0);
+            // try anything to set hour to 23:00 !!!
+            greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23);
+            // get time
+            Date greenwichdate = greenwichcalendar.getTime();
+            // format every way
+            String[] DATA = {
+                "simple format:  ", "04/04/97 23:00 GMT",
+                    "MM/dd/yy HH:mm z",
+                "full format:    ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT",
+                    "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z",
+                "long format:    ", "April 4, 1997 11:00:00 PM GMT",
+                    "MMMM d, yyyy h:mm:ss a z",
+                "default format: ", "04-Apr-97 11:00:00 PM",
+                    "dd-MMM-yy h:mm:ss a",
+                "short format:   ", "4/4/97 11:00 PM",
+                    "M/d/yy h:mm a",
+            };
+
+            for (int i=0; i<DATA.length; i+=3) {
+                DateFormat fmt = new SimpleDateFormat(DATA[i+2], Locale.ENGLISH);
+                fmt.setCalendar(greenwichcalendar);
+                String result = fmt.format(greenwichdate);
+                logln(DATA[i] + result);
+                if (!result.equals(DATA[i+1])) {
+                    errln("FAIL: Expected " + DATA[i+1]
+                            + ", got " + result);
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveDefault);
+        }
+    }
+
+/* HS : Commented out for now, need to be changed not to use hardcoded results.
+    public void TestLocaleDateFormat() // Bug 495
+    {
+        Date testDate = new Date (97, Calendar.SEPTEMBER, 15);
+        DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                             DateFormat.FULL, Locale.FRENCH);
+        DateFormat dfUS = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                         DateFormat.FULL, Locale.US);
+        String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 GMT-07:00";
+        String expectedUS = "Monday, September 15, 1997 12:00:00 o'clock AM PDT";
+        logln("Date set to : " + testDate);
+        String out = dfFrench.format(testDate);
+        logln("Date Formated with French Locale " + out);
+        if (!out.equals(expectedFRENCH)) errln("FAIL: Expected " + expectedFRENCH);
+        out = dfUS.format(testDate);
+        logln("Date Formated with US Locale " + out);
+        if (!out.equals(expectedUS)) errln("FAIL: Expected " + expectedUS);
+    }
+*/
+    /**
+     * Bug 4056591
+     */
+/*
+test commented out pending API-change approval
+    public void Test2YearStartDate() throws ParseException
+    {
+        // create a SimpleDateFormat to test with; dump out if it's not a SimpleDateFormat
+        DateFormat test = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
+
+        if (!(test instanceof SimpleDateFormat)) {
+            errln("DateFormat.getInstance() didn't return an instance of SimpleDateFormat!");
+            return;
+        }
+
+        SimpleDateFormat sdf = (SimpleDateFormat)test;
+        String testString1 = "3/10/67";
+        String testString2 = "3/16/43";
+        String testString3 = "7/21/43";
+
+        // set 2-digit start date to 1/1/1900
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(1900, 0, 1);
+        sdf.set2DigitStartDate(cal.getTime());
+
+        // check to make sure get2DigitStartDate() returns the value we passed to
+        // set2DigitStartDate()
+        Date date = sdf.get2DigitStartDate();
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1900 || cal.get(Calendar.MONTH) != 0 ||
+                        cal.get(Calendar.DATE) != 1)
+            errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
+                        + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
+                        " instead of 1/1/1900.");
+
+        // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1900
+        date = sdf.parse(testString1);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1967)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1967.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/10.");
+        date = sdf.parse(testString2);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1943)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1943.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/16.");
+
+        // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/2000
+        cal.set(2000, 0, 1);
+        sdf.set2DigitStartDate(cal.getTime());
+        date = sdf.parse(testString1);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 2067)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 2067.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/10.");
+        date = sdf.parse(testString2);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 2043)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1943.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/16.");
+
+        // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1950
+        cal.set(1950, 0, 1);
+        sdf.set2DigitStartDate(cal.getTime());
+        date = sdf.parse(testString1);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1967)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1967.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+            errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/10.");
+        date = sdf.parse(testString2);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 2043)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1943.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/16.");
+
+        // try parsing "3/16/43" and "7/21/43" with the 2-digit start date set to 6/1/1943
+        cal.set(1943, 5, 1);
+        sdf.set2DigitStartDate(cal.getTime());
+        date = sdf.parse(testString2);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 2043)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 2043.");
+        if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+            errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 3/16.");
+        date = sdf.parse(testString3);
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1943)
+            errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
+                            + cal.get(Calendar.YEAR) + " instead of 1943.");
+        if (cal.get(Calendar.MONTH) != 6 || cal.get(Calendar.DATE) != 21)
+            errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 failed: got " +
+                            (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+                            " instead of 7/21.");
+
+        // and finally, check one more time to make sure get2DigitStartDate() returns the last
+        // value we passed to set2DigitStartDate()
+        date = sdf.get2DigitStartDate();
+        cal.setTime(date);
+        if (cal.get(Calendar.YEAR) != 1943 || cal.get(Calendar.MONTH) != 5 ||
+                        cal.get(Calendar.DATE) != 1)
+            errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
+                        + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
+                        " instead of 6/1/1943.");
+    }
+*/
+
+    /**
+     * ParsePosition.errorIndex tests.
+     */
+    @SuppressWarnings("deprecation")
+    public void Test4052223()
+    {
+        String str = "7/SOS/2001";
+        Date exp = new Date(101, Calendar.SEPTEMBER, 7);
+        String pat = "d/MMM/yy";
+        SimpleDateFormat sdf = new SimpleDateFormat(pat);
+        ParsePosition pos = new ParsePosition(0);
+        Date d = sdf.parse(str, pos);
+        logln(str + " parses with " + pat + " to " + d);
+        if (d == null && pos.getErrorIndex() == 2) {
+            logln("Expected null returned, failed at : " + pos.getErrorIndex());
+        } else {
+            errln("Failed, parse " + str + " got : " + d + ", index=" + pos.getErrorIndex());
+        }
+    }
+
+    /**
+     * Bug4469904 -- th_TH date format doesn't use Thai B.E.
+     */
+    public void TestBuddhistEraBugId4469904() {
+        String era = "\u0e1e.\u0e28.";
+        Locale loc = new Locale("th", "TH");
+        Calendar cal = Calendar.getInstance(Locale.US);
+        cal.set(2001, 7, 23);
+        Date date = cal.getTime();
+        DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, loc);
+        String output = df.format(date);
+        int index = output.indexOf(era);
+        if (index == -1) {
+            errln("Test4469904: Failed. Buddhist Era abbrev not present.");
+        }
+    }
+
+    /**
+     * 4326988: API: SimpleDateFormat throws NullPointerException when parsing with null pattern
+     */
+    @SuppressWarnings("UnusedAssignment")
+    public void Test4326988() {
+        String[] wrongPatterns = {
+            "hh o''clock",
+            "hh 'o''clock",     // unterminated quote
+            "''''''''''''oclock",
+            "efgxyz",
+        };
+        String[] goodPatterns = {
+            "hh 'o''clock'",
+            "'''''''''''''o'",
+            "'efgxyz'",
+            ":;,.-",
+        };
+
+        // Check NullPointerException
+        try {
+            SimpleDateFormat fmt = new SimpleDateFormat(null);
+            errln("SimpleDateFormat() doesn't throw NPE with null pattern");
+        } catch (NullPointerException e) {
+            // Okay
+        }
+        try {
+            Locale loc = null;
+            SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", loc);
+            errln("SimpleDateFormat() doesn't throw NPE with null locale");
+        } catch (NullPointerException e) {
+            // Okay
+        }
+        try {
+            DateFormatSymbols symbols = null;
+            SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", symbols);
+            errln("SimpleDateFormat() doesn't throw NPE with null DateFormatSymbols");
+        } catch (NullPointerException e) {
+            // Okay
+        }
+        try {
+            SimpleDateFormat fmt = new SimpleDateFormat();
+            fmt.applyPattern(null);
+            errln("applyPattern() doesn't throw NPE with null pattern");
+        } catch (NullPointerException e) {
+            // Okay
+        }
+
+        // Check IllegalParameterException
+        for (int i = 0; i < wrongPatterns.length; i++) {
+            try {
+                SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i]);
+                errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\")" +
+                      " doesn't throw an IllegalArgumentException");
+            } catch (IllegalArgumentException e) {
+                // Okay
+            }
+            try {
+                SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
+                                                            DateFormatSymbols.getInstance());
+                errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\", DateFormatSymbols) doesn't " +
+                      "throw an IllegalArgumentException");
+            } catch (IllegalArgumentException e) {
+                // Okay
+            }
+            try {
+                SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
+                                                            Locale.US);
+                errln("SimpleDateFormat(\"" + wrongPatterns[i] +
+                      "\", Locale) doesn't throw an IllegalArgumentException");
+            } catch (IllegalArgumentException e) {
+                // Okay
+            }
+            try {
+                SimpleDateFormat fmt = new SimpleDateFormat();
+                fmt.applyPattern(wrongPatterns[i]);
+                errln("SimpleDateFormat.applyPattern(\"" + wrongPatterns[i] +
+                      "\") doesn't throw an IllegalArgumentException");
+            } catch (IllegalArgumentException e) {
+                // Okay
+            }
+        }
+
+        for (int i = 0; i < goodPatterns.length; i++) {
+            SimpleDateFormat fmt;
+            fmt = new SimpleDateFormat(goodPatterns[i]);
+            fmt = new SimpleDateFormat(goodPatterns[i],
+                                       DateFormatSymbols.getInstance());
+            fmt = new SimpleDateFormat(goodPatterns[i],
+                                       Locale.US);
+            fmt = new SimpleDateFormat();
+            fmt.applyPattern(goodPatterns[i]);
+        }
+    }
+
+    /**
+     * 4486735: RFE: SimpleDateFormat performance improvement
+     *
+     * Another round trip test
+     */
+    @SuppressWarnings("deprecation")
+    public void Test4486735() throws Exception {
+        TimeZone initialTimeZone = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+        Locale[] locales = Locale.getAvailableLocales();
+        String[] zones = { "GMT", "America/Los_Angeles", "Europe/London", "Asia/Tokyo" };
+
+        // Round to minutes. Some FULL formats don't have seconds.
+        long time = System.currentTimeMillis()/60000 * 60000;
+        Date date = new Date(time);
+        logln("the test date: " + date);
+
+        try {
+            for (int z = 0; z < zones.length; z++) {
+                TimeZone.setDefault(TimeZone.getTimeZone(zones[z]));
+                for (int i = 0; i < locales.length; i++) {
+                    Locale loc = locales[i];
+                    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                                   DateFormat.FULL,
+                                                                   loc);
+                    String s = df.format(date);
+                    logln(s);
+                    Date parsedDate = df.parse(s);
+                    long parsedTime = parsedDate.getTime();
+                    if (time != parsedTime) {
+                        // See if the time is in daylight-standard time transition. (JDK-8140571)
+                        // Date-time formats in some locales don't have time zone information.
+                        TimeZone tz = TimeZone.getDefault();
+                        if (tz.inDaylightTime(date) && !tz.inDaylightTime(parsedDate)) {
+                            if (time == parsedTime - tz.getDSTSavings()) {
+                                // OK (in "fall-back")
+                                continue;
+                            }
+                        }
+                        errln("round trip conversion failed: timezone="+zones[z]+
+                              ", locale=" + loc +
+                              ", expected=" + time + ", got=" + parsedTime);
+                    }
+                }
+            }
+
+            // Long format test
+            String pat =
+               "'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 100
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 200
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 300
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 400
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 500
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593':'" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +  // 100
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +  // 200
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +  // 300
+                "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\u5e74";
+
+            // Note that >4 y's produces just "2001" until 1.3.1. This
+            // was fixed in 1.4.
+            String expected =
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+                "00000000000000000000000000000000000000000000000000" +
+                "00000000000000000000000000000000000000000000000000" +
+                "00000000000000000000000000000000000000000000000000" +
+                "00000000000000000000000000000000000000000000000000" +
+                "00000000000000000000000000000000000000000000000000" +
+                "00000000000000000000000000000000000000000000002001\u5e74";
+            SimpleDateFormat sdf = new SimpleDateFormat(pat);
+            String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1));
+            if (!expected.equals(s)) {
+                errln("wrong format result: expected="+expected+", got="+s);
+            }
+            Date longday = sdf.parse(s);
+            GregorianCalendar cal = new GregorianCalendar();
+            cal.setTime(longday);
+            if (cal.get(YEAR) != 2001) {
+                errln("wrong parse result: expected=2001, got=" + cal.get(YEAR));
+            }
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            // Restore the initial time zone
+            TimeZone.setDefault(initialTimeZone);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormat.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary test International Date Format
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat
+ * @key randomness
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormat extends IntlTest {
+    // Values in milliseconds (== Date)
+    private static final long ONESECOND = 1000;
+    private static final long ONEMINUTE = 60 * ONESECOND;
+    private static final long ONEHOUR = 60 * ONEMINUTE;
+    private static final long ONEDAY = 24 * ONEHOUR;
+    private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate
+
+    // EModes
+    private static final byte GENERIC = 0;
+    private static final byte TIME = GENERIC + 1;
+    private static final byte DATE = TIME + 1;
+    private static final byte DATE_TIME = DATE + 1;
+
+    private DateFormat fFormat = DateFormat.getInstance();
+    private String fTestName = new String("getInstance");
+    private int fLimit = 3; // How many iterations it should take to reach convergence
+
+    public static void main(String[] args) throws Exception {
+        new IntlTestDateFormat().run(args);
+    }
+
+    public void TestLocale() {
+        localeTest(Locale.getDefault(), "Default Locale");
+    }
+
+    // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat.
+    public void localeTest(final Locale locale, final String localeName) {
+        int timeStyle, dateStyle;
+
+        // For patterns including only time information and a timezone, it may take
+        // up to three iterations, since the timezone may shift as the year number
+        // is determined.  For other patterns, 2 iterations should suffice.
+        fLimit = 3;
+
+        for(timeStyle = 0; timeStyle < 4; timeStyle++) {
+            fTestName = new String("Time test " + timeStyle + " (" + localeName + ")");
+            try {
+                fFormat = DateFormat.getTimeInstance(timeStyle, locale);
+            }
+            catch(StringIndexOutOfBoundsException e) {
+                errln("FAIL: localeTest time getTimeInstance exception");
+                throw e;
+            }
+            TestFormat();
+        }
+
+        fLimit = 2;
+
+        for(dateStyle = 0; dateStyle < 4; dateStyle++) {
+            fTestName = new String("Date test " + dateStyle + " (" + localeName + ")");
+            try {
+                fFormat = DateFormat.getDateInstance(dateStyle, locale);
+            }
+            catch(StringIndexOutOfBoundsException e) {
+                errln("FAIL: localeTest date getTimeInstance exception");
+                throw e;
+            }
+            TestFormat();
+        }
+
+        for(dateStyle = 0; dateStyle < 4; dateStyle++) {
+            for(timeStyle = 0; timeStyle < 4; timeStyle++) {
+                fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")");
+                try {
+                    fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
+                }
+                catch(StringIndexOutOfBoundsException e) {
+                    errln("FAIL: localeTest date/time getDateTimeInstance exception");
+                    throw e;
+                }
+                TestFormat();
+            }
+        }
+    }
+
+    public void TestFormat() {
+        if (fFormat == null) {
+            errln("FAIL: DateFormat creation failed");
+            return;
+        }
+        //        logln("TestFormat: " + fTestName);
+        Date now = new Date();
+        tryDate(new Date(0));
+        tryDate(new Date((long) 1278161801778.0));
+        tryDate(now);
+        // Shift 6 months into the future, AT THE SAME TIME OF DAY.
+        // This will test the DST handling.
+        tryDate(new Date(now.getTime() + 6*30*ONEDAY));
+
+        Date limit = new Date(now.getTime() * 10); // Arbitrary limit
+        for (int i=0; i<2; ++i)
+            //            tryDate(new Date(floor(randDouble() * limit)));
+            tryDate(new Date((long) (randDouble() * limit.getTime())));
+    }
+
+    private void describeTest() {
+        if (fFormat == null) {
+            errln("FAIL: no DateFormat");
+            return;
+        }
+
+        // Assume it's a SimpleDateFormat and get some info
+        SimpleDateFormat s = (SimpleDateFormat) fFormat;
+        logln(fTestName + " Pattern " + s.toPattern());
+    }
+
+    private void tryDate(Date theDate) {
+        final int DEPTH = 10;
+        Date[] date = new Date[DEPTH];
+        StringBuffer[] string = new StringBuffer[DEPTH];
+
+        int dateMatch = 0;
+        int stringMatch = 0;
+        boolean dump = false;
+        int i;
+        for (i=0; i<DEPTH; ++i) string[i] = new StringBuffer();
+        for (i=0; i<DEPTH; ++i) {
+            if (i == 0) date[i] = theDate;
+            else {
+                try {
+                    date[i] = fFormat.parse(string[i-1].toString());
+                }
+                catch (ParseException e) {
+                    describeTest();
+                    errln("********** FAIL: Parse of " + string[i-1] + " failed.");
+                    dump = true;
+                    break;
+                }
+            }
+            FieldPosition position = new FieldPosition(0);
+            fFormat.format(date[i], string[i], position);
+            if (i > 0) {
+                if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i;
+                else if (dateMatch > 0 && date[i] != date[i-1]) {
+                    describeTest();
+                    errln("********** FAIL: Date mismatch after match.");
+                    dump = true;
+                    break;
+                }
+                if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
+                else if (stringMatch > 0 && string[i] != string[i-1]) {
+                    describeTest();
+                    errln("********** FAIL: String mismatch after match.");
+                    dump = true;
+                    break;
+                }
+            }
+            if (dateMatch > 0 && stringMatch > 0) break;
+        }
+        if (i == DEPTH) --i;
+
+        if (stringMatch > fLimit || dateMatch > fLimit) {
+            describeTest();
+            errln("********** FAIL: No string and/or date match within " + fLimit + " iterations.");
+            dump = true;
+        }
+
+        if (dump) {
+            for (int k=0; k<=i; ++k) {
+                logln("" + k + ": " + date[k] + " F> " + string[k] + " P> ");
+            }
+        }
+    }
+
+    // Return a random double from 0.01 to 1, inclusive
+    private double randDouble() {
+        // Assume 8-bit (or larger) rand values.  Also assume
+        // that the system rand() function is very poor, which it always is.
+        //        double d;
+        //        int i;
+        //        do {
+        //            for (i=0; i < sizeof(double); ++i)
+        //            {
+        //                char poke = (char*)&d;
+        //                poke[i] = (rand() & 0xFF);
+        //            }
+        //        } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d));
+
+        //        if (d < 0.0) d = -d;
+        //        if (d > 0.0)
+        //        {
+        //            double e = floor(log10(d));
+        //            if (e < -2.0) d *= pow(10.0, -e-2);
+        //            else if (e > -1.0) d /= pow(10.0, e+1);
+        //        }
+        //        return d;
+        Random rand = new Random();
+        return rand.nextDouble();
+    }
+
+    public void TestAvailableLocales() {
+        final Locale[] locales = DateFormat.getAvailableLocales();
+        long count = locales.length;
+        logln("" + count + " available locales");
+        if (locales != null  &&  count != 0) {
+            StringBuffer all = new StringBuffer();
+            for (int i=0; i<count; ++i) {
+                if (i!=0) all.append(", ");
+                all.append(locales[i].getDisplayName());
+            }
+            logln(all.toString());
+        }
+        else errln("********** FAIL: Zero available locales or null array pointer");
+    }
+
+    /* This test is too slow; we disable it for now
+    public void TestMonster() {
+        final Locale[] locales = DateFormat.getAvailableLocales();
+        long count = locales.length;
+        if (locales != null  &&  count != 0) {
+            for (int i=0; i<count; ++i) {
+                String name = locales[i].getDisplayName();
+                logln("Testing " + name + "...");
+                try {
+                    localeTest(locales[i], name);
+                }
+                catch(Exception e) {
+                    errln("FAIL: TestMonster localeTest exception" + e);
+                }
+            }
+        }
+    }
+    */
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormatAPI.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary test International Date Format API
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormatAPI
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormatAPI extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            new IntlTestDateFormatAPI().run(args);
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    // Test that the equals method works correctly.
+    public void TestEquals()
+    {
+        // Create two objects at different system times
+        DateFormat a = DateFormat.getInstance();
+        Date start = Calendar.getInstance().getTime();
+        while (start.equals(Calendar.getInstance().getTime())) ; // Wait for time to change
+        DateFormat b = DateFormat.getInstance();
+
+        if (!(a.equals(b)))
+            errln("FAIL: DateFormat objects created at different times are unequal.");
+
+        if (b instanceof SimpleDateFormat)
+        {
+            double ONE_YEAR = 365*24*60*60*1000.0;
+            try {
+//                ((SimpleDateFormat)b).setTwoDigitStartDate(start.getTime() + 50*ONE_YEAR);
+//                if (a.equals(b))
+//                    errln("FAIL: DateFormat objects with different two digit start dates are equal.");
+            }
+            catch (Exception e) {
+                errln("FAIL: setTwoDigitStartDate failed.");
+            }
+        }
+    }
+
+    // This test checks various generic API methods in DateFormat to achieve 100% API coverage.
+    public void TestAPI()
+    {
+        logln("DateFormat API test---"); logln("");
+        Locale.setDefault(Locale.ENGLISH);
+
+
+        // ======= Test constructors
+
+        logln("Testing DateFormat constructors");
+
+        DateFormat def = DateFormat.getInstance();
+        DateFormat fr = DateFormat.getTimeInstance(DateFormat.FULL, Locale.FRENCH);
+        DateFormat it = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.ITALIAN);
+        DateFormat de = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.GERMAN);
+
+        // ======= Test equality
+
+        logln("Testing equality operator");
+
+        if( fr.equals(it) ) {
+            errln("ERROR: equals failed");
+        }
+
+        // ======= Test various format() methods
+
+        logln("Testing various format() methods");
+
+        Date d = new Date((long)837039928046.0);
+
+        StringBuffer res1 = new StringBuffer();
+        StringBuffer res2 = new StringBuffer();
+        String res3 = new String();
+        FieldPosition pos1 = new FieldPosition(0);
+        FieldPosition pos2 = new FieldPosition(0);
+
+        res1 = fr.format(d, res1, pos1);
+        logln("" + d.getTime() + " formatted to " + res1);
+
+        res2 = it.format(d, res2, pos2);
+        logln("" + d.getTime() + " formatted to " + res2);
+
+        res3 = de.format(d);
+        logln("" + d.getTime() + " formatted to " + res3);
+
+        // ======= Test parse()
+
+        logln("Testing parse()");
+
+        String text = new String("02/03/76 2:50 AM, CST");
+        Object result1 = new Date();
+        Date result2 = new Date();
+        Date result3 = new Date();
+        ParsePosition pos = new ParsePosition(0);
+        ParsePosition pos01 = new ParsePosition(0);
+
+        result1 = def.parseObject(text, pos);
+        if (result1 == null) {
+            errln("ERROR: parseObject() failed for " + text);
+        }
+        logln(text + " parsed into " + ((Date)result1).getTime());
+
+        try {
+            result2 = def.parse(text);
+        }
+        catch (ParseException e) {
+            errln("ERROR: parse() failed");
+        }
+        logln(text + " parsed into " + result2.getTime());
+
+        result3 = def.parse(text, pos01);
+        if (result3 == null) {
+            errln("ERROR: parse() failed for " + text);
+        }
+        logln(text + " parsed into " + result3.getTime());
+
+
+        // ======= Test getters and setters
+
+        logln("Testing getters and setters");
+
+        final Locale[] locales = DateFormat.getAvailableLocales();
+        long count = locales.length;
+        logln("Got " + count + " locales" );
+        for(int i = 0; i < count; i++) {
+            String name;
+            name = locales[i].getDisplayName();
+            logln(name);
+        }
+
+        fr.setLenient(it.isLenient());
+        if(fr.isLenient() != it.isLenient()) {
+            errln("ERROR: setLenient() failed");
+        }
+
+        final Calendar cal = def.getCalendar();
+        Calendar newCal = (Calendar) cal.clone();
+        de.setCalendar(newCal);
+        it.setCalendar(newCal);
+        if( ! de.getCalendar().equals(it.getCalendar())) {
+            errln("ERROR: set Calendar() failed");
+        }
+
+        final NumberFormat nf = def.getNumberFormat();
+        NumberFormat newNf = (NumberFormat) nf.clone();
+        de.setNumberFormat(newNf);
+        it.setNumberFormat(newNf);
+        if( ! de.getNumberFormat().equals(it.getNumberFormat())) {
+            errln("ERROR: set NumberFormat() failed");
+        }
+
+        final TimeZone tz = def.getTimeZone();
+        TimeZone newTz = (TimeZone) tz.clone();
+        de.setTimeZone(newTz);
+        it.setTimeZone(newTz);
+        if( ! de.getTimeZone().equals(it.getTimeZone())) {
+            errln("ERROR: set TimeZone() failed");
+        }
+
+        // ======= Test getStaticClassID()
+
+//        logln("Testing instanceof()");
+
+//        try {
+//            DateFormat test = new SimpleDateFormat();
+
+//            if (! (test instanceof SimpleDateFormat)) {
+//                errln("ERROR: instanceof failed");
+//            }
+//        }
+//        catch (Exception e) {
+//            errln("ERROR: Couldn't create a DateFormat");
+//        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/IntlTestDateFormatSymbols.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test International Date Format Symbols
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormatSymbols extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        new IntlTestDateFormatSymbols().run(args);
+    }
+
+    // Test getMonths
+    public void TestGetMonths()
+    {
+        final String[] month;
+        DateFormatSymbols symbol;
+
+        symbol=new DateFormatSymbols(Locale.getDefault());
+
+        month=symbol.getMonths();
+        int cnt = month.length;
+
+        logln("size = " + cnt);
+
+        for (int i=0; i<cnt; ++i)
+        {
+            logln(month[i]);
+        }
+    }
+
+    // Test the API of DateFormatSymbols; primarily a simple get/set set.
+    public void TestSymbols()
+    {
+        DateFormatSymbols fr = new DateFormatSymbols(Locale.FRENCH);
+
+        DateFormatSymbols en = new DateFormatSymbols(Locale.ENGLISH);
+
+        if(en.equals(fr)) {
+            errln("ERROR: English DateFormatSymbols equal to French");
+        }
+
+        // just do some VERY basic tests to make sure that get/set work
+
+        long count;
+        final String[] eras = en.getEras();
+        fr.setEras(eras);
+        final String[] eras1 = fr.getEras();
+        count = eras.length;
+        if( count != eras1.length) {
+            errln("ERROR: setEras() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! eras[i].equals(eras1[i])) {
+                    errln("ERROR: setEras() failed (different string values)");
+                }
+            }
+        }
+
+
+        final String[] months = en.getMonths();
+        fr.setMonths(months);
+        final String[] months1 = fr.getMonths();
+        count = months.length;
+        if( count != months1.length) {
+            errln("ERROR: setMonths() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! months[i].equals(months1[i])) {
+                    errln("ERROR: setMonths() failed (different string values)");
+                }
+            }
+        }
+
+        final String[] shortMonths = en.getShortMonths();
+        fr.setShortMonths(shortMonths);
+        final String[] shortMonths1 = fr.getShortMonths();
+        count = shortMonths.length;
+        if( count != shortMonths1.length) {
+            errln("ERROR: setShortMonths() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! shortMonths[i].equals(shortMonths1[i])) {
+                    errln("ERROR: setShortMonths() failed (different string values)");
+                }
+            }
+        }
+
+        final String[] weekdays = en.getWeekdays();
+        fr.setWeekdays(weekdays);
+        final String[] weekdays1 = fr.getWeekdays();
+        count = weekdays.length;
+        if( count != weekdays1.length) {
+            errln("ERROR: setWeekdays() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! weekdays[i].equals(weekdays1[i])) {
+                    errln("ERROR: setWeekdays() failed (different string values)");
+                }
+            }
+        }
+
+        final String[] shortWeekdays = en.getShortWeekdays();
+        fr.setShortWeekdays(shortWeekdays);
+        final String[] shortWeekdays1 = fr.getShortWeekdays();
+        count = shortWeekdays.length;
+        if( count != shortWeekdays1.length) {
+            errln("ERROR: setShortWeekdays() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! shortWeekdays[i].equals(shortWeekdays1[i])) {
+                    errln("ERROR: setShortWeekdays() failed (different string values)");
+                }
+            }
+        }
+
+        final String[] ampms = en.getAmPmStrings();
+        fr.setAmPmStrings(ampms);
+        final String[] ampms1 = fr.getAmPmStrings();
+        count = ampms.length;
+        if( count != ampms1.length) {
+            errln("ERROR: setAmPmStrings() failed (different size array)");
+        }
+        else {
+            for(int i = 0; i < count; i++) {
+                if(! ampms[i].equals(ampms1[i])) {
+                    errln("ERROR: setAmPmStrings() failed (different string values)");
+                }
+            }
+        }
+
+        long rowCount = 0, columnCount = 0;
+        final String[][] strings = en.getZoneStrings();
+        fr.setZoneStrings(strings);
+        final String[][] strings1 = fr.getZoneStrings();
+        rowCount = strings.length;
+        for(int i = 0; i < rowCount; i++) {
+            columnCount = strings[i].length;
+            for(int j = 0; j < columnCount; j++) {
+                if( strings[i][j] != strings1[i][j] ) {
+                    errln("ERROR: setZoneStrings() failed");
+                }
+            }
+        }
+
+//        final String pattern = DateFormatSymbols.getPatternChars();
+
+        String localPattern, pat1, pat2;
+        localPattern = en.getLocalPatternChars();
+        fr.setLocalPatternChars(localPattern);
+        if(! en.getLocalPatternChars().equals(fr.getLocalPatternChars())) {
+            errln("ERROR: setLocalPatternChars() failed");
+        }
+
+
+        DateFormatSymbols foo = new DateFormatSymbols();
+
+        en = (DateFormatSymbols) fr.clone();
+
+        if(! en.equals(fr)) {
+            errln("ERROR: Clone failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/IntlTestSimpleDateFormatAPI.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary test International Simple Date Format API
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestSimpleDateFormatAPI
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestSimpleDateFormatAPI extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            new IntlTestSimpleDateFormatAPI().run(args);
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+    public void TestAPI()
+    {
+        logln("SimpleDateFormat API test---"); logln("");
+
+        Locale.setDefault(Locale.ENGLISH);
+
+        // ======= Test constructors
+
+        logln("Testing SimpleDateFormat constructors");
+
+        SimpleDateFormat def = new SimpleDateFormat();
+
+        final String pattern = new String("yyyy.MM.dd G 'at' hh:mm:ss z");
+        SimpleDateFormat pat = new SimpleDateFormat(pattern);
+
+        SimpleDateFormat pat_fr = new SimpleDateFormat(pattern, Locale.FRENCH);
+
+        DateFormatSymbols symbols = new DateFormatSymbols(Locale.FRENCH);
+
+        SimpleDateFormat cust1 = new SimpleDateFormat(pattern, symbols);
+
+        // ======= Test clone() and equality
+
+        logln("Testing clone(), assignment and equality operators");
+
+        Format clone = (Format) def.clone();
+        if( ! clone.equals(def) ) {
+            errln("ERROR: Format clone or equals failed");
+        }
+
+        // ======= Test various format() methods
+
+        logln("Testing various format() methods");
+
+        Date d = new Date((long)837039928046.0);
+
+        StringBuffer res1 = new StringBuffer();
+        StringBuffer res2 = new StringBuffer();
+        FieldPosition pos1 = new FieldPosition(0);
+        FieldPosition pos2 = new FieldPosition(0);
+
+        res1 = def.format(d, res1, pos1);
+        logln( "" + d.getTime() + " formatted to " + res1);
+
+        res2 = cust1.format(d, res2, pos2);
+        logln("" + d.getTime() + " formatted to " + res2);
+
+        // ======= Test parse()
+
+        logln("Testing parse()");
+
+        String text = new String("02/03/76 2:50 AM, CST");
+        Date result1 = new Date();
+        Date result2 = new Date();
+        ParsePosition pos= new ParsePosition(0);
+        result1 = def.parse(text, pos);
+        logln(text + " parsed into " + result1);
+
+        try {
+            result2 = def.parse(text);
+        }
+        catch (ParseException e) {
+            errln("ERROR: parse() failed");
+        }
+        logln(text + " parsed into " + result2);
+
+        // ======= Test getters and setters
+
+        logln("Testing getters and setters");
+
+        final DateFormatSymbols syms = pat.getDateFormatSymbols();
+        def.setDateFormatSymbols(syms);
+        pat_fr.setDateFormatSymbols(syms);
+        if( ! pat.getDateFormatSymbols().equals(def.getDateFormatSymbols()) ) {
+            errln("ERROR: set DateFormatSymbols() failed");
+        }
+
+        Date startDate = null;
+        try {
+//            startDate = pat.getTwoDigitStartDate();
+        }
+        catch (Exception e) {
+            errln("ERROR: getTwoDigitStartDate() failed");
+        }
+
+        try {
+//            pat_fr.setTwoDigitStartDate(startDate);
+        }
+        catch (Exception e) {
+            errln("ERROR: setTwoDigitStartDate() failed");
+        }
+
+        // ======= Test applyPattern()
+
+        logln("Testing applyPattern()");
+
+        String p1 = new String("yyyy.MM.dd G 'at' hh:mm:ss z");
+        logln("Applying pattern " + p1);
+        pat.applyPattern(p1);
+
+        String s2 = pat.toPattern();
+        logln("Extracted pattern is " + s2);
+        if( ! s2.equals(p1) ) {
+            errln("ERROR: toPattern() result did not match pattern applied");
+        }
+
+        logln("Applying pattern " + p1);
+        pat.applyLocalizedPattern(p1);
+        String s3 = pat.toLocalizedPattern();
+        logln("Extracted pattern is " + s3);
+        if( ! s3.equals(p1) ) {
+            errln("ERROR: toLocalizedPattern() result did not match pattern applied");
+        }
+
+        // ======= Test getStaticClassID()
+
+//        logln("Testing instanceof");
+
+//        try {
+//            DateFormat test = new SimpleDateFormat();
+
+//            if (! (test instanceof SimpleDateFormat)) {
+//                errln("ERROR: instanceof failed");
+//            }
+//        }
+//        catch (Exception e) {
+//            errln("ERROR: Couldn't create a SimpleDateFormat");
+//        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/NonGregorianFormatTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4833268 6253991 8008577
+ * @summary Test formatting and parsing with non-Gregorian calendars
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NonGregorianFormatTest
+ */
+
+import java.util.*;
+import java.text.*;
+import static java.util.Calendar.*;
+
+public class NonGregorianFormatTest {
+    static int errors;
+
+    static final Object[][] JAPANESE_EN = {
+        { "GGGG yyyy MMMM d", "Showa 1 December 31", new Date(1926-1900, DECEMBER, 31) },
+        { "GGGG yyyy MMMM d", "Showa 64 January 6", new Date(1989-1900, JANUARY, 6) },
+        { "GGGG yyyy MMMM d", "Heisei 1 August 9", new Date(1989-1900, AUGUST, 9) },
+        { "GGGG yyyy MMMM d", "Heisei 17 June 10", new Date(2005-1900, JUNE, 10) },
+        { "Gy.MM.dd", "S1.12.31", new Date(1926-1900, DECEMBER, 31) },
+        { "Gy.MM.dd", "S64.01.06", new Date(1989-1900, JANUARY, 6) },
+        { "Gyy.MM.dd", "H01.08.09", new Date(1989-1900, AUGUST, 9) },
+        { "Gy.M.d", "H1.8.9", new Date(1989-1900, AUGUST, 9) },
+        { "Gy.MM.dd", "H17.06.10", new Date(2005-1900, JUNE, 10) },
+    };
+
+    // Invalid dates for parse exception tests
+    static final Object[][] EXCEPTION_JAPANESE_EN = {
+        { "GGGG yyyy MMMM d", "Showa 1 December 10" },
+        { "GGGG yyyy MMMM d", "Showa 64 January 16" },
+        { "GGGG yyyy MMMM d", "Heisei 1 January 1" },
+        { "Gy.MM.dd", "S1.12.10" },
+        { "Gy.MM.dd", "S64.01.16" },
+        { "Gyy.MM.dd", "H01.01.01" },
+    };
+
+    static final Object[][] BUDDHIST_EN = {
+        { "GGGG yyyy MMMM d", "B.E. 2469 December 31", new Date(1926-1900, DECEMBER, 31) },
+        { "GGGG yyyy MMMM d", "B.E. 2532 January 6", new Date(1989-1900, JANUARY, 6) },
+        { "GGGG yyyy MMMM d", "B.E. 2532 August 8", new Date(1989-1900, AUGUST, 8) },
+        { "GGGG yyyy MMMM d", "B.E. 2548 June 10", new Date(2005-1900, JUNE, 10) },
+        { "Gyyyy/MM/dd", "B.E.2469/12/31", new Date(1926-1900, DECEMBER, 31) },
+        { "Gyyyy/MM/dd", "B.E.2532/01/06", new Date(1989-1900, JANUARY, 6) },
+        { "Gyyyy/MM/dd", "B.E.2532/08/09", new Date(1989-1900, AUGUST, 9) },
+        { "Gyyyy/MM/dd", "B.E.2548/06/10", new Date(2005-1900, JUNE, 10) },
+    };
+
+    static final String FULL_DATE_FORMAT_JA = "GGGGyyyy'\u5e74'M'\u6708'd'\u65e5'";
+
+    static final Object[][] JAPANESE_JA = {
+        { FULL_DATE_FORMAT_JA, "\u662d\u548c\u5143\u5e7412\u670831\u65e5", new Date(1926-1900, DECEMBER, 31) },
+        { FULL_DATE_FORMAT_JA, "\u662d\u548c64\u5e741\u67086\u65e5", new Date(1989-1900, JANUARY, 6) },
+        { FULL_DATE_FORMAT_JA, "\u5e73\u6210\u5143\u5e748\u67089\u65e5", new Date(1989-1900, AUGUST, 9) },
+        { FULL_DATE_FORMAT_JA, "\u5e73\u621017\u5e746\u670810\u65e5", new Date(2005-1900, JUNE, 10) },
+        { "Gyy.MM.dd", "S01.12.31", new Date(1926-1900, DECEMBER, 31) },
+        { "Gyy.MM.dd", "S64.01.06", new Date(1989-1900, JANUARY, 6) },
+        { "Gyy.MM.dd", "H01.08.09", new Date(1989-1900, AUGUST, 9) },
+        { "Gy.M.d", "H1.8.9", new Date(1989-1900, AUGUST, 9) },
+        { "Gyy.MM.dd", "H17.06.10", new Date(2005-1900, JUNE, 10) },
+    };
+
+    // Invalid dates for parse exception tests
+    static final Object[][] EXCEPTION_JAPANESE_JA = {
+        { FULL_DATE_FORMAT_JA, "\u662d\u548c\u5143\u5e7412\u670810\u65e5" },
+        { FULL_DATE_FORMAT_JA, "\u662d\u548c64\u5e741\u670816\u65e5" },
+        { FULL_DATE_FORMAT_JA, "\u5e73\u6210\u5143\u5e741\u67081\u65e5" },
+        { "Gyy.MM.dd", "S01.12.10" },
+        { "Gyy.MM.dd", "S64.01.16" },
+        { "Gyy.MM.dd", "H01.01.01" },
+    };
+
+    static final Object[][] BUDDHIST_JA = {
+        { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62469\u5e7412\u670831\u65e5", new Date(1926-1900, DECEMBER, 31) },
+        { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62532\u5e741\u67086\u65e5", new Date(1989-1900, JANUARY, 6) },
+        { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62532\u5e748\u67089\u65e5", new Date(1989-1900, AUGUST, 9) },
+        { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62548\u5e746\u670810\u65e5", new Date(2005-1900, JUNE, 10) },
+        { "Gyyyy/MM/dd", "B.E.2469/12/31", new Date(1926-1900, DECEMBER, 31) },
+        { "Gyyyy/MM/dd", "B.E.2532/01/06", new Date(1989-1900, JANUARY, 6) },
+        { "Gyyyy/MM/dd", "B.E.2532/08/09", new Date(1989-1900, AUGUST, 9) },
+        { "Gyyyy/MM/dd", "B.E.2548/06/10", new Date(2005-1900, JUNE, 10) },
+    };
+
+    public static void main(String[] args) throws ParseException {
+        Locale defaultLocale = Locale.getDefault();
+        Locale[] locales = { Locale.ENGLISH, Locale.JAPAN };
+        try {
+            for (Locale locale : locales) {
+                test(locale);
+            }
+        } finally {
+            Locale.setDefault(defaultLocale);
+        }
+        if (errors > 0) {
+            throw new RuntimeException("FAILED: " + errors + " error(s)");
+        }
+    }
+
+    private static void test(Locale locale) {
+        Locale.setDefault(locale);
+
+        // Tests with the Japanese imperial calendar
+        Locale calendarLocale = new Locale("ja", "JP", "JP");
+        testRoundTrip(calendarLocale);
+        testRoundTripSimple(calendarLocale,
+                            locale == Locale.ENGLISH ? JAPANESE_EN : JAPANESE_JA);
+        testParseExceptions(calendarLocale,
+                            locale == Locale.ENGLISH ? EXCEPTION_JAPANESE_EN : EXCEPTION_JAPANESE_JA);
+
+        // Tests with the Thai Buddhist calendar
+        calendarLocale = new Locale("th", "TH");
+        testRoundTrip(calendarLocale);
+        testRoundTripSimple(calendarLocale,
+                            locale == Locale.ENGLISH ? BUDDHIST_EN : BUDDHIST_JA);
+    }
+
+    private static void testRoundTrip(Locale calendarLocale) {
+        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
+                                                       DateFormat.FULL,
+                                                       calendarLocale);
+
+        long t = System.currentTimeMillis();
+        t = (t / 1000) * 1000; // discard milliseconds
+        testRoundTrip(df, new Date(t));
+
+        // H1.8.9
+        testRoundTrip(df, new Date(1989-1900, AUGUST, 9));
+
+        // H17.6.13
+        testRoundTrip(df, new Date(2005-1900, JUNE, 13));
+    }
+
+    private static void testRoundTrip(DateFormat df, Date orig) {
+        try {
+            String s = df.format(orig);
+            Date parsed = df.parse(s);
+            if (!orig.equals(parsed)) {
+                error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed);
+            }
+        } catch (Exception e) {
+            error("Unexpected exception: %s%n", e);
+        }
+    }
+
+    private static void testRoundTripSimple(Locale calendarLocale, Object[][] data) {
+        try {
+            for (Object[] item : data) {
+                String pattern = (String) item[0];
+                String str = (String) item[1];
+                Date date = (Date) item[2];
+                SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+                Calendar cal = Calendar.getInstance(calendarLocale);
+                sdf.setCalendar(cal);
+                String s = sdf.format(date);
+                if (!s.equals(str)) {
+                    error("testRoundTripSimple: Got '%s', expected '%s'%n", s, str);
+                }
+                Date d = sdf.parse(str);
+                if (!d.equals(date)) {
+                    error("testRoundTripSimple: Got '%s', expected '%s'%n", d, date);
+                }
+            }
+        } catch (Exception e) {
+            error("Unexpected exception: %s%n", e);
+        }
+    }
+
+    private static void testParseExceptions(Locale calendarLocale, Object[][] data) {
+        for (Object[] item : data) {
+            String pattern = (String) item[0];
+            String str = (String) item[1];
+            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+            Calendar cal = Calendar.getInstance(calendarLocale);
+            sdf.setCalendar(cal);
+            sdf.setLenient(false);
+            try {
+                Date d = sdf.parse(str);
+                error("testParseExceptions: parsing '%s' doesn't throw a ParseException.%n", str);
+            } catch (ParseException e) {
+                // OK
+            }
+        }
+    }
+
+    private static void error(String msg) {
+        System.out.println(msg);
+        errors++;
+    }
+
+    private static void error(String fmt, Object... args) {
+        System.out.printf(fmt, args);
+        errors++;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/SDFserialized.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,173 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a serialized DateFormatSymbols for
+# DateFormatSymbolsSerializationTest.
+
+aced00057372001a6a6176612e746578742e53696d706c6544617465466f726d
+61744243c9da9394359002000449001573657269616c56657273696f6e4f6e53
+747265616d4c001364656661756c7443656e7475727953746172747400104c6a
+6176612f7574696c2f446174653b4c000a666f726d61744461746174001d4c6a
+6176612f746578742f44617465466f726d617453796d626f6c733b4c00077061
+747465726e7400124c6a6176612f6c616e672f537472696e673b787200146a61
+76612e746578742e44617465466f726d6174642ca1e4c22615fc0200024c0008
+63616c656e6461727400144c6a6176612f7574696c2f43616c656e6461723b4c
+000c6e756d626572466f726d61747400184c6a6176612f746578742f4e756d62
+6572466f726d61743b787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f184302000078707372001b6a6176612e7574696c2e477265676f726961
+6e43616c656e6461728f3dd7d6e5b0d0c10200014a0010677265676f7269616e
+4375746f766572787200126a6176612e7574696c2e43616c656e646172e6ea4d
+1ec8dc5b8e03000b5a000c6172654669656c647353657449000e666972737444
+61794f665765656b5a0009697354696d655365745a00076c656e69656e744900
+166d696e696d616c44617973496e46697273745765656b4900096e6578745374
+616d7049001573657269616c56657273696f6e4f6e53747265616d4a00047469
+6d655b00066669656c64737400025b495b000569735365747400025b5a4c0004
+7a6f6e657400144c6a6176612f7574696c2f54696d655a6f6e653b7870010000
+000101010000000100000002000000010000000000000000757200025b494dba
+602676eab2a502000078700000001100000001000007b2000000000000000100
+0000010000000100000001000000050000000100000000000000000000000000
+00000000000000000000000000000000000000757200025b5a578f203914b85d
+e20200007870000000110101010101010101010101010101010101737200186a
+6176612e7574696c2e53696d706c6554696d655a6f6e65fa675d60d15ef5a603
+001049000a647374536176696e6773490006656e6444617949000c656e644461
+794f665765656b490007656e644d6f6465490008656e644d6f6e746849000765
+6e6454696d654900097261774f666673657449001573657269616c5665727369
+6f6e4f6e53747265616d490008737461727444617949000e7374617274446179
+4f665765656b49000973746172744d6f646549000a73746172744d6f6e746849
+0009737461727454696d654900097374617274596561725a000b757365446179
+6c696768745b000b6d6f6e74684c656e6774687400025b42787200126a617661
+2e7574696c2e54696d655a6f6e6531b3e9f57744aca10200014c000249447100
+7e00037870740003474d540036ee800000000000000000000000000000000000
+0000000000000000000001000000000000000000000000000000000000000000
+00000000757200025b42acf317f8060854e002000078700000000c1f1c1f1e1f
+1e1f1f1e1f1e1f770800000004000000007878fffff4e2f964ac00737200176a
+6176612e746578742e446563696d616c466f726d61740bff0362d872303a0200
+0b5a001b646563696d616c536570617261746f72416c7761797353686f776e42
+000c67726f7570696e6753697a654200116d696e4578706f6e656e7444696769
+747349000a6d756c7469706c69657249001573657269616c56657273696f6e4f
+6e53747265616d5a00167573654578706f6e656e7469616c4e6f746174696f6e
+4c000e6e6567617469766550726566697871007e00034c000e6e656761746976
+6553756666697871007e00034c000e706f73697469766550726566697871007e
+00034c000e706f73697469766553756666697871007e00034c000773796d626f
+6c737400204c6a6176612f746578742f446563696d616c466f726d617453796d
+626f6c733b787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000701032800000003000000
+2800010000000000000001000000000178010300000000010000000100740001
+2d74000071007e001f71007e001f7372001e6a6176612e746578742e44656369
+6d616c466f726d617453796d626f6c73501d17990868939c02000f4300106465
+63696d616c536570617261746f72430005646967697443000b6578706f6e656e
+7469616c43001167726f7570696e67536570617261746f724300096d696e7573
+5369676e4300116d6f6e6574617279536570617261746f724300107061747465
+726e536570617261746f724300077065724d696c6c43000770657263656e7449
+001573657269616c56657273696f6e4f6e53747265616d4300097a65726f4469
+6769744c00034e614e71007e00034c000e63757272656e637953796d626f6c71
+007e00034c0008696e66696e69747971007e00034c0012696e746c4375727265
+6e637953796d626f6c71007e00037870002e00230045002c002d002e003b2030
+0025000000010030740003efbfbd740002c2a4740003e2889e74000358585800
+0000017372000e6a6176612e7574696c2e44617465686a81014b597419030000
+78707708fffffe8f24e5cdd7787372001b6a6176612e746578742e4461746546
+6f726d617453796d626f6c73ace671c9351717c20200085b0005616d706d7374
+00135b4c6a6176612f6c616e672f537472696e673b5b00046572617371007e00
+294c00116c6f63616c5061747465726e436861727371007e00035b00066d6f6e
+74687371007e00295b000b73686f72744d6f6e74687371007e00295b000d7368
+6f72745765656b6461797371007e00295b00087765656b6461797371007e0029
+5b000b7a6f6e65537472696e67737400145b5b4c6a6176612f6c616e672f5374
+72696e673b7870757200135b4c6a6176612e6c616e672e537472696e673badd2
+56e7e91d7b47020000787000000002740002414d740002504d7571007e002c00
+0000027400024243740002414474001247794d646b486d735345444677576168
+4b7a7571007e002c0000000d7400074a616e7561727974000846656272756172
+797400054d61726368740005417072696c7400034d61797400044a756e657400
+044a756c7974000641756775737474000953657074656d6265727400074f6374
+6f6265727400084e6f76656d626572740008446563656d62657271007e001f75
+71007e002c0000000d7400034a616e7400034665627400034d61727400034170
+7271007e00397400034a756e7400034a756c7400034175677400035365707400
+034f63747400034e6f7674000344656371007e001f7571007e002c0000000871
+007e001f74000353756e7400034d6f6e74000354756574000357656474000354
+68757400034672697400035361747571007e002c0000000871007e001f740006
+53756e6461797400064d6f6e646179740007547565736461797400095765646e
+6573646179740008546875727364617974000646726964617974000853617475
+72646179757200145b5b4c6a6176612e6c616e672e537472696e673b324d09ad
+8432e45702000078700000001d7571007e002c00000005740003505354740015
+50616369666963205374616e646172642054696d6571007e0060740015506163
+69666963204461796c696768742054696d657400035044547571007e002c0000
+0005740013416d65726963612f4c6f735f416e67656c657371007e006171007e
+006071007e006271007e00637571007e002c000000057400034d53547400164d
+6f756e7461696e205374616e646172642054696d6571007e00677400164d6f75
+6e7461696e204461796c696768742054696d657400034d44547571007e002c00
+00000574000e416d65726963612f44656e76657271007e006871007e00677100
+7e006971007e006a7571007e002c00000005740003504e5471007e006871007e
+006771007e006871007e00677571007e002c0000000574000f416d6572696361
+2f50686f656e697871007e006871007e006771007e006871007e00677571007e
+002c0000000574000343535474001543656e7472616c205374616e6461726420
+54696d6571007e007274001543656e7472616c204461796c696768742054696d
+657400034344547571007e002c0000000574000f416d65726963612f43686963
+61676f71007e007371007e007271007e007471007e00757571007e002c000000
+057400034553547400154561737465726e205374616e646172642054696d6571
+007e00797400154561737465726e204461796c696768742054696d6574000345
+44547571007e002c00000005740010416d65726963612f4e65775f596f726b71
+007e007a71007e007971007e007b71007e007c7571007e002c00000005740003
+49455471007e007a71007e007971007e007a71007e00797571007e002c000000
+05740014416d65726963612f496e6469616e61706f6c697371007e007a71007e
+007971007e007a71007e00797571007e002c0000000574000348535474001448
+6177616969205374616e646172642054696d6571007e008471007e008571007e
+00847571007e002c00000005740010506163696669632f486f6e6f6c756c7571
+007e008571007e008471007e008571007e00847571007e002c00000005740003
+415354740014416c61736b61205374616e646172642054696d65740004414b53
+54740014416c61736b61204461796c696768742054696d65740004414b445475
+71007e002c00000005740011416d65726963612f416e63686f7261676571007e
+008a71007e008b71007e008c71007e008d7571007e002c0000000574000f416d
+65726963612f48616c6966617874001641746c616e746963205374616e646172
+642054696d6571007e008974001641746c616e746963204461796c6967687420
+54696d657400034144547571007e002c00000005740003434e5474001a4e6577
+666f756e646c616e64205374616e646172642054696d657400034e535474001a
+4e6577666f756e646c616e64204461796c696768742054696d657400034e4454
+7571007e002c00000005740010416d65726963612f53745f4a6f686e7371007e
+009771007e009871007e009971007e009a7571007e002c000000057400034543
+5474001e43656e7472616c204575726f7065616e205374616e64617264205469
+6d6574000343455474001e43656e7472616c204575726f7065616e204461796c
+696768742054696d65740004434553547571007e002c0000000574000c457572
+6f70652f506172697371007e009f71007e00a071007e00a171007e00a2757100
+7e002c0000000571007e0017740013477265656e77696368204d65616e205469
+6d6571007e001771007e00a671007e00177571007e002c000000057400114166
+726963612f43617361626c616e636171007e00a671007e001771007e00a67100
+7e00177571007e002c0000000574000e417369612f4a65727573616c656d7400
+1449737261656c205374616e646172642054696d657400034953547400144973
+7261656c204461796c696768742054696d657400034944547571007e002c0000
+00057400034a53547400134a6170616e205374616e646172642054696d657100
+7e00b071007e00b171007e00b07571007e002c0000000574000a417369612f54
+6f6b796f71007e00b171007e00b071007e00b171007e00b07571007e002c0000
+00057400104575726f70652f42756368617265737474001e4561737465726e20
+4575726f7065616e205374616e646172642054696d6574000345455474001e45
+61737465726e204575726f7065616e204461796c696768742054696d65740004
+454553547571007e002c000000057400034354547400134368696e6120537461
+6e646172642054696d6571007e007271007e00bc71007e00757571007e002c00
+00000574000d417369612f5368616e6768616971007e00bc71007e007271007e
+00bc71007e0075740019797979792e4d4d2e646420452068682e6d6d2e737320
+7a7a7a0a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/TimeZoneNameTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4348864 4112924 4425386 4495052 4836940 4851113 8008577
+ * @summary test time zone display names in en_US locale
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneNameTest
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class TimeZoneNameTest extends IntlTest
+{
+    static final String[] data = {
+        // Added to verify the fix for 4836940
+        "N", "Antarctica/Rothera", "ROTT", "Rothera Time", "ROTT", "Rothera Time",
+        "N", "Asia/Tehran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time",
+        "N", "Iran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time",
+
+        // Added to verify the fix for 4851113
+        "N", "America/Rankin_Inlet", "CST", "Central Standard Time", "CDT", "Central Daylight Time",
+        "N", "Asia/Samarkand", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time",
+        "N", "Asia/Tashkent", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time",
+        "N", "Atlantic/Jan_Mayen", "CET", "Central European Time", "CEST", "Central European Summer Time",
+        "N", "Europe/Oslo", "CET", "Central European Time", "CEST", "Central European Summer Time",
+
+        "N", "Pacific/Honolulu", "HST", "Hawaii Standard Time", "HST", "Hawaii Standard Time",
+        "N", "America/Los_Angeles", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time",
+        "N", "US/Pacific", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time",
+        "N", "America/Phoenix", "MST", "Mountain Standard Time", "MST", "Mountain Standard Time",
+        "N", "America/Denver", "MST", "Mountain Standard Time", "MDT", "Mountain Daylight Time",
+        "N", "America/Chicago", "CST", "Central Standard Time", "CDT", "Central Daylight Time",
+        "N", "America/Indianapolis", "EST", "Eastern Standard Time", "EST", "Eastern Standard Time",
+        "N", "America/Montreal", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+        "N", "America/Toronto", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+        "N", "America/New_York", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+        "S", "America/Manaus", "AMT", "Amazon Time", "AMT", "Amazon Time",
+        "S", "America/Campo_Grande", "AMT", "Amazon Time", "AMST", "Amazon Summer Time",
+        "S", "America/Bahia", "BRT", "Brasilia Time", "BRST", "Brasilia Summer Time",
+        "N", "America/Halifax", "AST", "Atlantic Standard Time", "ADT", "Atlantic Daylight Time",
+        "N", "GMT", "GMT", "Greenwich Mean Time", "GMT", "Greenwich Mean Time",
+        "N", "Europe/London", "GMT", "Greenwich Mean Time", "BST", "British Summer Time",
+        "N", "Europe/Paris", "CET", "Central European Time", "CEST", "Central European Summer Time",
+        "N", "WET", "WET", "Western European Time", "WEST", "Western European Summer Time",
+        "N", "Europe/Berlin", "CET", "Central European Time", "CEST", "Central European Summer Time",
+        "N", "Asia/Jerusalem", "IST", "Israel Standard Time", "IDT", "Israel Daylight Time",
+        "N", "Europe/Helsinki", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time",
+        "N", "Africa/Cairo", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time",
+        "N", "Europe/Moscow", "MSK", "Moscow Standard Time", "MSD", "Moscow Daylight Time",
+        "N", "Asia/Omsk", "OMST", "Omsk Time", "OMSST", "Omsk Summer Time",
+        "N", "Asia/Shanghai", "CST", "China Standard Time", "CST", "China Standard Time",
+        "N", "Asia/Tokyo", "JST", "Japan Standard Time", "JST", "Japan Standard Time",
+        "N", "Japan", "JST", "Japan Standard Time", "JST", "Japan Standard Time",
+        "N", "Asia/Seoul", "KST", "Korea Standard Time", "KST", "Korea Standard Time",
+        "N", "ROK", "KST", "Korea Standard Time", "KST", "Korea Standard Time",
+        "S", "Australia/Darwin", "ACST", "Australian Central Standard Time (Northern Territory)",
+                                 "ACST", "Australian Central Standard Time (Northern Territory)",
+        "S", "Australia/Adelaide", "ACST", "Australian Central Standard Time (South Australia)",
+                                   "ACDT", "Australian Central Daylight Time (South Australia)",
+        "S", "Australia/Broken_Hill", "ACST", "Australian Central Standard Time (South Australia/New South Wales)",
+                                      "ACDT", "Australian Central Daylight Time (South Australia/New South Wales)",
+        "S", "Australia/Hobart", "AEST", "Australian Eastern Standard Time (Tasmania)",
+                                 "AEDT", "Australian Eastern Daylight Time (Tasmania)",
+        "S", "Australia/Brisbane", "AEST", "Australian Eastern Standard Time (Queensland)",
+                                   "AEST", "Australian Eastern Standard Time (Queensland)",
+        "S", "Australia/Sydney", "AEST", "Australian Eastern Standard Time (New South Wales)",
+                                 "AEDT", "Australian Eastern Daylight Time (New South Wales)",
+        "N", "Pacific/Guam", "ChST", "Chamorro Standard Time",
+                             "ChST", "Chamorro Standard Time",
+        "N", "Pacific/Saipan", "ChST", "Chamorro Standard Time",
+                               "ChST", "Chamorro Standard Time",
+    };
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            new TimeZoneNameTest().run(args);
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    public void Test4112924() {
+        SimpleDateFormat lfmt = new SimpleDateFormat("zzzz");
+        SimpleDateFormat sfmt = new SimpleDateFormat("z");
+
+        GregorianCalendar june = new GregorianCalendar(2000, Calendar.JUNE, 21);
+        GregorianCalendar december = new GregorianCalendar(2000, Calendar.DECEMBER, 21);
+
+        int count = data.length;
+        for (int i = 0; i < count; i++) {
+            GregorianCalendar sol1, sol2;
+
+            // check hemisphere
+            if ("N".equals(data[i++])) {
+                sol1 = december;
+                sol2 = june;
+            } else {
+                sol1 = june;
+                sol2 = december;
+            }
+
+            TimeZone tz = TimeZone.getTimeZone(data[i++]);
+            lfmt.setTimeZone(tz);
+            sfmt.setTimeZone(tz);
+
+            logln(tz.getID() + ": " + sfmt.format(sol1.getTime()) + ", " + lfmt.format(sol1.getTime()));
+            logln(tz.getID() + ": " + sfmt.format(sol2.getTime()) + ", " + lfmt.format(sol2.getTime()));
+            String s = sfmt.format(sol1.getTime());
+            if (!data[i].equals(s)) {
+                errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")");
+            }
+            s = lfmt.format(sol1.getTime());
+            if (!data[++i].equals(s)) {
+                errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")");
+            }
+            s = sfmt.format(sol2.getTime());
+            if (!data[++i].equals(s)) {
+                errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")");
+            }
+            s = lfmt.format(sol2.getTime());
+            if (!data[++i].equals(s)) {
+                errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug4097450.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4097450
+ */
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+public class bug4097450
+{
+    public static void main(String args[])
+    {
+        //
+        // Date parse requiring 4 digit year.
+        //
+        String[]  dstring = {"97","1997",  "97","1997","01","2001",  "01","2001"
+                             ,  "1",
+                             "1","11",  "11","111", "111"};
+        String[]  dformat = {"yy",  "yy","yyyy","yyyy","yy",  "yy","yyyy","yyyy"
+                             ,
+                             "yy","yyyy","yy","yyyy", "yy","yyyy"};
+        boolean[] dresult = {true, false, false,  true,true, false, false,  true
+                             ,false,
+                             false,true, false,false, false};
+        SimpleDateFormat formatter;
+        SimpleDateFormat resultFormatter = new SimpleDateFormat("yyyy");
+
+        System.out.println("Format\tSource\tResult");
+        System.out.println("-------\t-------\t-------");
+        for (int i = 0; i < dstring.length; i++)
+        {
+            System.out.print(dformat[i] + "\t" + dstring[i] + "\t");
+            formatter = new SimpleDateFormat(dformat[i]);
+            try {
+                System.out.print(resultFormatter.format(formatter.parse(dstring[
+                                                                                i])));
+                //if ( !dresult[i] ) System.out.print("   <-- error!");
+            }
+            catch (ParseException exception) {
+                //if ( dresult[i] ) System.out.print("   <-- error!");
+                System.out.print("exception --> " + exception);
+            }
+            System.out.println();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug4099975.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4099975
+ */
+
+import java.text.*;
+import java.util.Date;
+public class bug4099975 {
+    public static void main (String args[]){
+        DateFormatSymbols symbols = new DateFormatSymbols();
+        SimpleDateFormat df = new SimpleDateFormat("E hh:mm", symbols);
+        System.out.println(df.toLocalizedPattern());
+        symbols.setLocalPatternChars("abcdefghijklmonpqr"); // change value of field
+        System.out.println(df.toLocalizedPattern());
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug4117335.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4117335 4432617
+ */
+
+import java.text.DateFormatSymbols ;
+import java.util.Locale;
+
+public class bug4117335 {
+
+    public static void main(String[] args) throws Exception
+    {
+        DateFormatSymbols symbols = new DateFormatSymbols(Locale.JAPAN);
+        String[] eras = symbols.getEras();
+        System.out.println("BC = " + eras[0]);
+        if (!eras[0].equals(bc)) {
+            System.out.println("*** Should have been " + bc);
+            throw new Exception("Error in BC");
+        }
+        System.out.println("AD = " + eras[1]);
+        if (!eras[1].equals(ad)) {
+            System.out.println("*** Should have been " + ad);
+            throw new Exception("Error in AD");
+        }
+        String[][] zones = symbols.getZoneStrings();
+        for (int i = 0; i < zones.length; i++) {
+            if (!"Asia/Tokyo".equals(zones[i][0])) {
+                continue;
+            }
+            System.out.println("Long zone name = " + zones[i][1]);
+            if (!zones[i][1].equals(jstLong)) {
+                System.out.println("*** Should have been " + jstLong);
+                throw new Exception("Error in long TZ name");
+            }
+            System.out.println("Short zone name = " + zones[i][2]);
+            if (!zones[i][2].equals(jstShort)) {
+                System.out.println("*** Should have been " + jstShort);
+                throw new Exception("Error in short TZ name");
+            }
+            System.out.println("Long zone name = " + zones[i][3]);
+            if (!zones[i][3].equals(jdtLong)) {
+                System.out.println("*** Should have been " + jdtLong);
+                throw new Exception("Error in long TZ name");
+            }
+            System.out.println("SHORT zone name = " + zones[i][4]);
+            if (!zones[i][4].equals(jdtShort)) {
+                System.out.println("*** Should have been " + jdtShort);
+                throw new Exception("Error in short TZ name");
+            }
+        }
+    }
+
+    static final String bc = "\u7d00\u5143\u524d";
+    static final String ad = "\u897f\u66a6";
+    static final String jstLong = "\u65e5\u672c\u6a19\u6e96\u6642";
+    static final String jstShort = "JST";
+    static final String jdtLong = "\u65e5\u672c\u590f\u6642\u9593";
+    static final String jdtShort = "JDT";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug4358730.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.util.*;
+import java.text.*;
+
+/**
+ * @test
+ * @bug 4358730
+ * @library /java/text/testlib
+ * @summary test that confirms Zero-Padding on year.
+ */
+
+public class bug4358730 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new bug4358730().run(args);
+    }
+
+    String[] patterns = {"y",    "yy", "yyy",  "yyyy", "yyyyy"};
+    String[][] data = {
+        /* 2 A.D. */    {"2",    "02", "002",  "0002", "00002"},
+        /* 20 A.D. */   {"20",   "20", "020",  "0020", "00020"},
+        /* 200 A.D. */  {"200",  "00", "200",  "0200", "00200"},
+        /* 2000 A.D. */ {"2000", "00", "2000", "2000", "02000"},
+    };
+    int[] year = {2, 20, 200, 2000};
+
+    SimpleDateFormat sdf = new SimpleDateFormat();
+    int datasize = data.length;
+    int nPatterns = data[0].length;
+
+    public void Test4358730() {
+        Locale locale = Locale.getDefault();
+        if (locale.equals(new Locale("th", "TH")) ||
+            locale.equals(new Locale("hi", "IN"))) {
+            return;
+        }
+
+        TimeZone saveZone = TimeZone.getDefault();
+        Locale saveLocale = Locale.getDefault();
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+            Locale.setDefault(new Locale("en", "US"));
+
+            for (int i = 0; i < datasize; i++) {
+                Date d = new Date(year[i]-1900, 10, 15);
+                for (int j = 0; j < nPatterns; j++) {
+                    sdf.applyPattern(patterns[j]);
+                    if (!data[i][j].equals(sdf.format(d))) {
+                        errln("Invalid format : " + sdf.format(d) +
+                            ", expected : " + data[i][j]);
+                    }
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+            Locale.setDefault(saveLocale);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug6271375.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6271375 7059546
+ * @summary Make sure DateFormatSymbols serialization works
+ *    correctly for 'zoneStrings' field
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class bug6271375 {
+
+    public static void main(String[] args) throws Exception {
+        DateFormatSymbols dfsSrc = DateFormatSymbols.getInstance();
+
+        try (FileOutputStream fos = new FileOutputStream("dfs.ser");
+             ObjectOutputStream oStream = new ObjectOutputStream(fos)) {
+            oStream.writeObject(dfsSrc);
+        } catch (Exception e) {
+            throw new RuntimeException("An exception is thrown.", e);
+        }
+
+        try (FileInputStream fis = new FileInputStream("dfs.ser");
+             ObjectInputStream iStream = new ObjectInputStream(fis)) {
+            DateFormatSymbols dfsDest = (DateFormatSymbols)iStream.readObject();
+
+            String[][] zoneStringsSrc = dfsSrc.getZoneStrings();
+            String[][] zoneStringsDest = dfsDest.getZoneStrings();
+
+            if (!Arrays.deepEquals(zoneStringsSrc, zoneStringsDest)) {
+                throw new RuntimeException("src and dest zone strings are not equal");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("An exception is thrown.", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug6317072.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6317072
+ * @summary Make sure NPE is thrown with "null" argumemnts in the
+ *    SimpleDateFormat constructors.
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class bug6317072 {
+
+    public static void main(String[] args) {
+
+        try {
+            new SimpleDateFormat("yy", (Locale)null);
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            new SimpleDateFormat((String)null, Locale.getDefault());
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            new SimpleDateFormat("yy", (DateFormatSymbols)null);
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            new SimpleDateFormat((String)null, DateFormatSymbols.getInstance());
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            DateFormat.getTimeInstance(DateFormat.FULL, null);
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            DateFormat.getDateInstance(DateFormat.FULL, null);
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+
+        try {
+            DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, null);
+            throw new RuntimeException("should thrown a NullPointerException");
+        } catch (NullPointerException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/bug6412896.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006, 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 6412896
+ * @summary Make sure that an IllegalArgumentException is thrown
+ *    if the length of any row in zoneStrings array is less than 5
+ */
+
+import java.text.*;
+
+public class bug6412896 {
+
+    static final String[][] zoneOK = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}};
+    static final String[][] zoneNG = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time"}};
+
+    public static void main(String[] args) {
+
+        DateFormatSymbols dfs = DateFormatSymbols.getInstance();
+
+        dfs.setZoneStrings(zoneOK);
+
+        try {
+            dfs.setZoneStrings(zoneNG);
+            throw new RuntimeException("should throw an IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a serialized MessageFormat for Bug4185816Test.
+
+aced0005737200176a6176612e746578742e4d657373616765466f726d617459
+ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e
+744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661
+2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75
+74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174
+7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176
+612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572
+00025b494dba602676eab2a502000078700000000a0000000100000000000000
+0000000000000000000000000000000000000000000000000000000000757200
+135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078
+700000000a70737200166a6176612e746578742e43686f696365466f726d6174
+18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c
+6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473
+7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000
+2800010000000000000001000000000178757200135b4c6a6176612e6c616e67
+2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066
+696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c
+6573757200025b443ea68c14ab635a1e02000078700000000300000000000000
+003ff000000000000040000000000000007070707070707070737200106a6176
+612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863
+6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e
+00044c000776617269616e7471007e00047870ffffffff740002555374000265
+6e740000787571007e00070000000a0000000a00000015000000000000000000
+0000000000000000000000000000000000000000000000740016546865206469
+736b20222220636f6e7461696e73202e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a corrupted serialized MessageFormat for Bug4185732Test.
+
+aced0005737200176a6176612e746578742e4d657373616765466f726d617459
+ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e
+744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661
+2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75
+74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174
+7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176
+612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572
+00025b494dba602676eab2a502000078700000000a0000000100000000000000
+0000000000000000000000000000000000000000000000000000000000757200
+135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078
+700000000a70737200166a6176612e746578742e43686f696365466f726d6174
+18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c
+6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473
+7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000
+2800010000000000000001000000000178757200135b4c6a6176612e6c616e67
+2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066
+696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c
+6573757200025b443ea68c14ab635a1e02000078700000000300000000000000
+003ff000000000000040000000000000007070707070707070737200106a6176
+612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863
+6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e
+00044c000776617269616e7471007e00047870ffffffff740002555374000265
+6e740000787571007e00070000000a0000000a00000015000000000000000000
+0000000000000000000000000000000000000000000000740010546865206469
+736b20222220636f6e74
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/Bug4185816Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * 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 4185816
+ * @library /java/text/testlib
+ * @build Bug4185816Test IntlTest HexDumpReader
+ * @run main Bug4185816Test
+ * @summary test that MessageFormat invariants are preserved across serialization
+ */
+/*
+ *
+ *
+ * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * 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.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.ChoiceFormat;
+import java.text.MessageFormat;
+
+/**
+ *  A Locale can never contains language codes of he, yi or id.
+ */
+public class Bug4185816Test extends IntlTest {
+    private static final String FILE_NAME = "Bug4185816.ser";
+    private static final String CORRUPT_FILE_NAME = "Bug4185816Corrupt.ser";
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 1 && args[0].equals("prepTest")) {
+            prepTest();
+        } else {
+            new Bug4185816Test().run(args);
+        }
+    }
+
+    public void testIt() throws Exception {
+        Exception e = checkStreaming(FILE_NAME);
+        if (e != null) {
+            errln("MessageFormat did not stream in valid stream: "+e);
+            e.printStackTrace();
+        }
+        e = checkStreaming(CORRUPT_FILE_NAME);
+        if (!(e instanceof InvalidObjectException)) {
+            errln("MessageFormat did NOT detect corrupt stream: "+e);
+            e.printStackTrace();
+        }
+    }
+
+    public Exception checkStreaming(final String fileName) {
+        try {
+            final InputStream is = HexDumpReader.getStreamFromHexDump(fileName + ".txt");
+            final ObjectInputStream in = new ObjectInputStream(is);
+            final MessageFormat form = (MessageFormat)in.readObject();
+            final Object[] testArgs = {new Long(12373), "MyDisk"};
+            final String result = form.format(testArgs);
+            in.close();
+        } catch (Exception e) {
+            return e;
+        }
+        return null;
+    }
+
+    /**
+     * Create a data file for this test.  The data file must be corrupted by hand.
+     */
+    private static void prepTest() {
+        writeFormatToFile(FILE_NAME);
+        writeFormatToFile(CORRUPT_FILE_NAME);
+    }
+
+    private static void writeFormatToFile(final String name) {
+        try {
+            ObjectOutputStream out = new ObjectOutputStream(
+                    new FileOutputStream(name));
+
+            MessageFormat fmt = new MessageFormat("The disk \"{1}\" contains {0}.");
+            double[] filelimits = {0,1,2};
+            String[] filepart = {"no files","one file","{0,number} files"};
+            ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
+            fmt.setFormat(1,fileform); // NOT zero, see below
+
+            out.writeObject(fmt);
+            out.close();
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/Bug6481179.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @summary Confirm that a bug in an error message has been fixed.
+ * @bug 6481179
+ */
+
+import java.text.MessageFormat;
+import java.text.ParseException;
+
+public class Bug6481179 {
+
+    public static void main(String[] args) {
+        boolean err = false;
+
+        try {
+            MessageFormat.format("Testdata {1,invalid_format_type}",
+                                 new Object[] { "val0", "val1" });
+
+            System.err.println("Error: IllegalArgumentException should be thrown.");
+            err = true;
+        }
+        catch (IllegalArgumentException e) {
+            String expected = "unknown format type: invalid_format_type";
+            String got = e.getMessage();
+
+            if (!expected.equals(got)) {
+                System.err.println("Error: Unexpected error message: " + got);
+                err = true;
+            }
+        }
+        catch (Exception e) {
+            System.err.println("Error: Unexpected exception was thrown: " + e);
+            err = true;
+        }
+
+        if (err) {
+            throw new RuntimeException("Failed.");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/LargeMessageFormat.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4112090 8008577
+ * @summary verify that MessageFormat can handle large numbers of arguments
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI LargeMessageFormat
+ */
+
+import java.text.MessageFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class LargeMessageFormat {
+
+    public static void main(String[] args) throws ParseException {
+        Locale reservedLocale = Locale.getDefault();
+        TimeZone reservedTimeZone = TimeZone.getDefault();
+        try {
+            Locale.setDefault(Locale.GERMANY);
+            TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
+            testFormat();
+            testParse();
+        } finally {
+            // restore the reserved locale and time zone
+            Locale.setDefault(reservedLocale);
+            TimeZone.setDefault(reservedTimeZone);
+        }
+    }
+
+    private static final int REPEATS = 89;
+
+    private static void testFormat() {
+        // construct large argument array
+        Object[] sample = {
+                new Integer(0), // replace with running count below
+                "hello",
+                new Date(89, 10, 9),
+                new Integer(567890),
+                new Double(1234.50)
+        };
+        int samples = sample.length;
+        Object[] arguments = new Object[REPEATS * (samples + 1)];
+        for (int i = 0; i < REPEATS; i++) {
+            System.arraycopy(sample, 0, arguments, i * samples, samples);
+            arguments[i * samples] = new Integer(i);
+        }
+
+        // construct large template
+        StringBuffer template = new StringBuffer();
+        for (int i = 0; i < REPEATS; i++) {
+            template.append("section {" + (i * samples) + ", number} - ");
+            template.append("string: {" + (i * samples + 1) + "}; ");
+            template.append("date: {" + (i * samples + 2) + ", date}; ");
+            template.append("integer: {" + (i * samples + 3) + ", number}; ");
+            template.append("currency: {" + (i * samples + 4) + ", number, currency};\n");
+        }
+
+        // construct expected result string
+        StringBuffer expected = new StringBuffer();
+        for (int i = 0; i < REPEATS; i++) {
+            expected.append("section " + i + " - ");
+            expected.append("string: hello; ");
+            expected.append("date: 09.11.1989; ");
+            expected.append("integer: 567.890; ");
+            expected.append("currency: 1.234,50 \u20AC;\n");
+        }
+
+        // create message format
+        MessageFormat format = new MessageFormat(template.toString());
+        String result = format.format(arguments);
+        if (!result.equals(expected.toString())) {
+           System.out.println("Template:");
+           System.out.println(template);
+           System.out.println("Expected result: ");
+           System.out.println(expected);
+           System.out.println("Actual result: ");
+           System.out.println(result);
+           throw new RuntimeException();
+       }
+    }
+
+    private static void testParse() throws ParseException {
+        StringBuffer parseTemplate = new StringBuffer();
+        StringBuffer parseInput = new StringBuffer();
+        for (int i = 0; i < REPEATS; i++) {
+            parseTemplate.append("{" + i + ", number} ");
+            parseInput.append(i + " ");
+        }
+        MessageFormat parseFormat = new MessageFormat(parseTemplate.toString());
+        Object[] parseResult = parseFormat.parse(parseInput.toString());
+        for (int i = 0; i < REPEATS; i++) {
+            if (((Number) parseResult[i]).intValue() != i) {
+                throw new RuntimeException("got wrong parse result");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4105380
+ * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex
+ */
+
+import java.text.ChoiceFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+
+public class MessageFormatsByArgumentIndex {
+
+    private static String choicePattern = "0.0#are no files|1.0#is one file|1.0<are {0,number,integer} files";
+
+    public static void main(String[] args) {
+        Format[] subformats;
+
+        MessageFormat format = new MessageFormat("{3, choice," + choicePattern + "}, {2}, {0}");
+
+        subformats = format.getFormatsByArgumentIndex();
+        checkSubformatLength(subformats, 4);
+        checkSubformat(subformats, 0, null);
+        checkSubformat(subformats, 1, null);
+        checkSubformat(subformats, 2, null);
+        checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+        subformats = format.getFormats();
+        checkSubformatLength(subformats, 3);
+        checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+        checkSubformat(subformats, 1, null);
+        checkSubformat(subformats, 2, null);
+
+        format.setFormatByArgumentIndex(0, NumberFormat.getInstance());
+
+        checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2}, {0,number}");
+
+        subformats = format.getFormatsByArgumentIndex();
+        checkSubformatLength(subformats, 4);
+        checkSubformat(subformats, 0, NumberFormat.getInstance());
+        checkSubformat(subformats, 1, null);
+        checkSubformat(subformats, 2, null);
+        checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+        subformats = format.getFormats();
+        checkSubformatLength(subformats, 3);
+        checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+        checkSubformat(subformats, 1, null);
+        checkSubformat(subformats, 2, NumberFormat.getInstance());
+
+        format.setFormatsByArgumentIndex(subformats);
+
+        checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2,number}, {0,choice," + choicePattern + "}");
+
+        subformats = format.getFormatsByArgumentIndex();
+        checkSubformatLength(subformats, 4);
+        checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+        checkSubformat(subformats, 1, null);
+        checkSubformat(subformats, 2, NumberFormat.getInstance());
+        checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+        subformats = format.getFormats();
+        checkSubformatLength(subformats, 3);
+        checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+        checkSubformat(subformats, 1, NumberFormat.getInstance());
+        checkSubformat(subformats, 2, new ChoiceFormat(choicePattern));
+
+    }
+
+    private static void checkPattern(String actual, String expected) {
+        if (!expected.equals(actual)) {
+              throw new RuntimeException("unexpected pattern:\n expected: " + expected + "\n   actual: " + actual);
+        }
+    }
+
+    private static void checkSubformatLength(Format[] subformats, int expected) {
+        if (subformats.length != expected) {
+            throw new RuntimeException("unexpected subformat length:\n expected: " + expected + "\n   actual: " + subformats.length);
+        }
+    }
+
+    private static void checkSubformat(Format[] subformats, int index, Format expected) {
+        Format subformat = subformats[index];
+        if (subformat == expected) {
+            return;
+        }
+        if ((subformat != null) && subformat.equals(expected)) {
+            return;
+        }
+        throw new RuntimeException("found unexpected subformat for argument " + index + ":\n expected: " + expected + "\n   actual: " + subformat);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/MessageRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 4106661
+ * 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 4120552
+ * 4142938 4169959 4232154 4293229
+ * @summary Regression tests for MessageFormat and associated classes
+ * @library /java/text/testlib
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public class MessageRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new MessageRegression().run(args);
+    }
+
+    /* @bug 4074764
+     * Null exception when formatting pattern with MessageFormat
+     * with no parameters.
+     */
+    public void Test4074764() {
+        String[] pattern = {"Message without param",
+        "Message with param:{0}",
+        "Longer Message with param {0}"};
+        //difference between the two param strings are that
+        //in the first one, the param position is within the
+        //length of the string without param while it is not so
+        //in the other case.
+
+        MessageFormat messageFormatter = new MessageFormat("");
+
+        try {
+            //Apply pattern with param and print the result
+            messageFormatter.applyPattern(pattern[1]);
+            Object[] params = {new String("BUG"), new Date()};
+            String tempBuffer = messageFormatter.format(params);
+            if (!tempBuffer.equals("Message with param:BUG"))
+                errln("MessageFormat with one param test failed.");
+            logln("Formatted with one extra param : " + tempBuffer);
+
+            //Apply pattern without param and print the result
+            messageFormatter.applyPattern(pattern[0]);
+            tempBuffer = messageFormatter.format(null);
+            if (!tempBuffer.equals("Message without param"))
+                errln("MessageFormat with no param test failed.");
+            logln("Formatted with no params : " + tempBuffer);
+
+             tempBuffer = messageFormatter.format(params);
+             if (!tempBuffer.equals("Message without param"))
+                errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString());
+             logln("Formatted with extra params : " + tempBuffer);
+            //This statement gives an exception while formatting...
+            //If we use pattern[1] for the message with param,
+            //we get an NullPointerException in MessageFormat.java(617)
+            //If we use pattern[2] for the message with param,
+            //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614)
+            //Both are due to maxOffset not being reset to -1
+            //in applyPattern() when the pattern does not
+            //contain any param.
+        } catch (Exception foo) {
+            errln("Exception when formatting with no params.");
+        }
+    }
+
+    /* @bug 4058973
+     * MessageFormat.toPattern has weird rounding behavior.
+     */
+    public void Test4058973() {
+
+        MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");
+        String pat = fmt.toPattern();
+        if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) {
+            errln("MessageFormat.toPattern failed");
+        }
+    }
+    /* @bug 4031438
+     * More robust message formats.
+     */
+    public void Test4031438() {
+        String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}.";
+        String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.";
+
+        // If the current locale is hi_IN, skip this test case.
+        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+            return;
+        }
+
+        MessageFormat messageFormatter = new MessageFormat("");
+
+        try {
+            logln("Apply with pattern : " + pattern1);
+            messageFormatter.applyPattern(pattern1);
+            Object[] params = {new Integer(7)};
+            String tempBuffer = messageFormatter.format(params);
+            if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}."))
+                errln("Tests arguments < substitution failed. Formatted text=" +
+                      "<" + tempBuffer + ">");
+            logln("Formatted with 7 : " + tempBuffer);
+            ParsePosition status = new ParsePosition(0);
+            Object[] objs = messageFormatter.parse(tempBuffer, status);
+            if (objs[params.length] != null)
+                errln("Parse failed with more than expected arguments");
+            for (int i = 0; i < objs.length; i++) {
+                if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) {
+                    errln("Parse failed on object " + objs[i] + " at index : " + i);
+                }
+            }
+            tempBuffer = messageFormatter.format(null);
+            if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}."))
+                errln("Tests with no arguments failed");
+            logln("Formatted with null : " + tempBuffer);
+            logln("Apply with pattern : " + pattern2);
+            messageFormatter.applyPattern(pattern2);
+            tempBuffer = messageFormatter.format(params);
+            if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff."))
+                errln("quote format test (w/ params) failed.");
+            logln("Formatted with params : " + tempBuffer);
+            tempBuffer = messageFormatter.format(null);
+            if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff."))
+                errln("quote format test (w/ null) failed.");
+            logln("Formatted with null : " + tempBuffer);
+            logln("toPattern : " + messageFormatter.toPattern());
+        } catch (Exception foo) {
+            errln("Exception when formatting in bug 4031438. "+foo.getMessage());
+        }
+    }
+    public void Test4052223()
+    {
+        ParsePosition pos = new ParsePosition(0);
+        if (pos.getErrorIndex() != -1) {
+            errln("ParsePosition.getErrorIndex initialization failed.");
+        }
+        MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree.");
+        String str = new String("There is one apple growing on the peach tree.");
+        Object[] objs = fmt.parse(str, pos);
+        logln("unparsable string , should fail at " + pos.getErrorIndex());
+        if (pos.getErrorIndex() == -1)
+            errln("Bug 4052223 failed : parsing string " + str);
+        pos.setErrorIndex(4);
+        if (pos.getErrorIndex() != 4)
+            errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4");
+        ChoiceFormat f = new ChoiceFormat(
+            "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2.");
+        pos.setIndex(0); pos.setErrorIndex(-1);
+        Number obj = f.parse("are negative", pos);
+        if (pos.getErrorIndex() != -1 && obj.doubleValue() == -1.0)
+            errln("Parse with \"are negative\" failed, at " + pos.getErrorIndex());
+        pos.setIndex(0); pos.setErrorIndex(-1);
+        obj = f.parse("are no or fraction ", pos);
+        if (pos.getErrorIndex() != -1 && obj.doubleValue() == 0.0)
+            errln("Parse with \"are no or fraction\" failed, at " + pos.getErrorIndex());
+        pos.setIndex(0); pos.setErrorIndex(-1);
+        obj = f.parse("go postal", pos);
+        if (pos.getErrorIndex() == -1 && !Double.isNaN(obj.doubleValue()))
+            errln("Parse with \"go postal\" failed, at " + pos.getErrorIndex());
+    }
+    /* @bug 4104976
+     * ChoiceFormat.equals(null) throws NullPointerException
+     */
+    public void Test4104976()
+    {
+        double[] limits = {1, 20};
+        String[] formats = {"xyz", "abc"};
+        ChoiceFormat cf = new ChoiceFormat(limits, formats);
+        try {
+            log("Compares to null is always false, returned : ");
+            logln(cf.equals(null) ? "TRUE" : "FALSE");
+        } catch (Exception foo) {
+            errln("ChoiceFormat.equals(null) throws exception.");
+        }
+    }
+    /* @bug 4106659
+     * ChoiceFormat.ctor(double[], String[]) doesn't check
+     * whether lengths of input arrays are equal.
+     */
+    public void Test4106659()
+    {
+        double[] limits = {1, 2, 3};
+        String[] formats = {"one", "two"};
+        ChoiceFormat cf = null;
+        try {
+            cf = new ChoiceFormat(limits, formats);
+        } catch (Exception foo) {
+            logln("ChoiceFormat constructor should check for the array lengths");
+            cf = null;
+        }
+        if (cf != null) errln(cf.format(5));
+    }
+
+    /* @bug 4106660
+     * ChoiceFormat.ctor(double[], String[]) allows unordered double array.
+     * This is not a bug, added javadoc to emphasize the use of limit
+     * array must be in ascending order.
+     */
+    public void Test4106660()
+    {
+        double[] limits = {3, 1, 2};
+        String[] formats = {"Three", "One", "Two"};
+        ChoiceFormat cf = new ChoiceFormat(limits, formats);
+        double d = 5.0;
+        String str = cf.format(d);
+        if (!str.equals("Two"))
+            errln("format(" + d + ") = " + cf.format(d));
+    }
+
+    /* @bug 4111739
+     * MessageFormat is incorrectly serialized/deserialized.
+     */
+    public void Test4111739()
+    {
+        MessageFormat format1 = null;
+        MessageFormat format2 = null;
+        ObjectOutputStream ostream = null;
+        ByteArrayOutputStream baos = null;
+        ObjectInputStream istream = null;
+
+        try {
+            baos = new ByteArrayOutputStream();
+            ostream = new ObjectOutputStream(baos);
+        } catch(IOException e) {
+            errln("Unexpected exception : " + e.getMessage());
+            return;
+        }
+
+        try {
+            format1 = new MessageFormat("pattern{0}");
+            ostream.writeObject(format1);
+            ostream.flush();
+
+            byte bytes[] = baos.toByteArray();
+
+            istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
+            format2 = (MessageFormat)istream.readObject();
+        } catch(Exception e) {
+            errln("Unexpected exception : " + e.getMessage());
+        }
+
+        if (!format1.equals(format2)) {
+            errln("MessageFormats before and after serialization are not" +
+                " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " +
+                format2 + "(" + format2.toPattern() + ")");
+        } else {
+            logln("Serialization for MessageFormat is OK.");
+        }
+    }
+    /* @bug 4114743
+     * MessageFormat.applyPattern allows illegal patterns.
+     */
+    public void Test4114743()
+    {
+        String originalPattern = "initial pattern";
+        MessageFormat mf = new MessageFormat(originalPattern);
+        try {
+            String illegalPattern = "ab { '}' de";
+            mf.applyPattern(illegalPattern);
+            errln("illegal pattern: \"" + illegalPattern + "\"");
+        } catch (IllegalArgumentException foo) {
+            if (!originalPattern.equals(mf.toPattern()))
+                errln("pattern after: \"" + mf.toPattern() + "\"");
+        }
+    }
+
+    /* @bug 4116444
+     * MessageFormat.parse has different behavior in case of null.
+     */
+    public void Test4116444()
+    {
+        String[] patterns = {"", "one", "{0,date,short}"};
+        MessageFormat mf = new MessageFormat("");
+
+        for (int i = 0; i < patterns.length; i++) {
+            String pattern = patterns[i];
+            mf.applyPattern(pattern);
+            try {
+                Object[] array = mf.parse(null, new ParsePosition(0));
+                logln("pattern: \"" + pattern + "\"");
+                log(" parsedObjects: ");
+                if (array != null) {
+                    log("{");
+                    for (int j = 0; j < array.length; j++) {
+                        if (array[j] != null)
+                            err("\"" + array[j].toString() + "\"");
+                        else
+                            log("null");
+                        if (j < array.length - 1) log(",");
+                    }
+                    log("}") ;
+                } else {
+                    log("null");
+                }
+                logln("");
+            } catch (Exception e) {
+                errln("pattern: \"" + pattern + "\"");
+                errln("  Exception: " + e.getMessage());
+            }
+        }
+
+    }
+    /* @bug 4114739 (FIX and add javadoc)
+     * MessageFormat.format has undocumented behavior about empty format objects.
+     */
+    public void Test4114739()
+    {
+
+        MessageFormat mf = new MessageFormat("<{0}>");
+        Object[] objs1 = null;
+        Object[] objs2 = {};
+        Object[] objs3 = {null};
+        try {
+            logln("pattern: \"" + mf.toPattern() + "\"");
+            log("format(null) : ");
+            logln("\"" + mf.format(objs1) + "\"");
+            log("format({})   : ");
+            logln("\"" + mf.format(objs2) + "\"");
+            log("format({null}) :");
+            logln("\"" + mf.format(objs3) + "\"");
+        } catch (Exception e) {
+            errln("Exception thrown for null argument tests.");
+        }
+    }
+
+    /* @bug 4113018
+     * MessageFormat.applyPattern works wrong with illegal patterns.
+     */
+    public void Test4113018()
+    {
+        String originalPattern = "initial pattern";
+        MessageFormat mf = new MessageFormat(originalPattern);
+        String illegalPattern = "format: {0, xxxYYY}";
+        logln("pattern before: \"" + mf.toPattern() + "\"");
+        logln("illegal pattern: \"" + illegalPattern + "\"");
+        try {
+            mf.applyPattern(illegalPattern);
+            errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern);
+        } catch (IllegalArgumentException e) {
+            if (!originalPattern.equals(mf.toPattern()))
+                errln("pattern after: \"" + mf.toPattern() + "\"");
+        }
+    }
+    /* @bug 4106661
+     * ChoiceFormat is silent about the pattern usage in javadoc.
+     */
+    public void Test4106661()
+    {
+        ChoiceFormat fmt = new ChoiceFormat(
+          "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2.");
+        logln("Formatter Pattern : " + fmt.toPattern());
+
+        logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
+        logln("Format with -1.0 : " + fmt.format(-1.0));
+        logln("Format with 0 : " + fmt.format(0));
+        logln("Format with 0.9 : " + fmt.format(0.9));
+        logln("Format with 1.0 : " + fmt.format(1));
+        logln("Format with 1.5 : " + fmt.format(1.5));
+        logln("Format with 2 : " + fmt.format(2));
+        logln("Format with 2.1 : " + fmt.format(2.1));
+        logln("Format with NaN : " + fmt.format(Double.NaN));
+        logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
+    }
+    /* @bug 4094906
+     * ChoiceFormat should accept \u221E as eq. to INF.
+     */
+    public void Test4094906()
+    {
+        ChoiceFormat fmt = new ChoiceFormat(
+          "-\u221E<are negative|0<are no or fraction|1#is one|1.0<is 1+|\u221E<are many.");
+        if (!fmt.toPattern().startsWith("-\u221E<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|\u221E<are many."))
+            errln("Formatter Pattern : " + fmt.toPattern());
+        logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
+        logln("Format with -1.0 : " + fmt.format(-1.0));
+        logln("Format with 0 : " + fmt.format(0));
+        logln("Format with 0.9 : " + fmt.format(0.9));
+        logln("Format with 1.0 : " + fmt.format(1));
+        logln("Format with 1.5 : " + fmt.format(1.5));
+        logln("Format with 2 : " + fmt.format(2));
+        logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
+    }
+
+    /* @bug 4118592
+     * MessageFormat.parse fails with ChoiceFormat.
+     */
+    public void Test4118592()
+    {
+        MessageFormat mf = new MessageFormat("");
+        String pattern = "{0,choice,1#YES|2#NO}";
+        String prefix = "";
+        for (int i = 0; i < 5; i++) {
+            String formatted = prefix + "YES";
+            mf.applyPattern(prefix + pattern);
+            prefix += "x";
+            Object[] objs = mf.parse(formatted, new ParsePosition(0));
+            logln(i + ". pattern :\"" + mf.toPattern() + "\"");
+            log(" \"" + formatted + "\" parsed as ");
+            if (objs == null) logln("  null");
+            else logln("  " + objs[0]);
+        }
+    }
+    /* @bug 4118594
+     * MessageFormat.parse fails for some patterns.
+     */
+    public void Test4118594()
+    {
+        MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
+        String forParsing = "x, y, z";
+        Object[] objs = mf.parse(forParsing, new ParsePosition(0));
+        logln("pattern: \"" + mf.toPattern() + "\"");
+        logln("text for parsing: \"" + forParsing + "\"");
+        if (!objs[0].toString().equals("z"))
+            errln("argument0: \"" + objs[0] + "\"");
+        mf.setLocale(Locale.US);
+        mf.applyPattern("{0,number,#.##}, {0,number,#.#}");
+        Object[] oldobjs = {new Double(3.1415)};
+        String result = mf.format( oldobjs );
+        logln("pattern: \"" + mf.toPattern() + "\"");
+        logln("text for parsing: \"" + result + "\"");
+        // result now equals "3.14, 3.1"
+        if (!result.equals("3.14, 3.1"))
+            errln("result = " + result);
+        Object[] newobjs = mf.parse(result, new ParsePosition(0));
+        // newobjs now equals {new Double(3.1)}
+        if (((Double)newobjs[0]).doubleValue() != 3.1)
+            errln( "newobjs[0] = " + newobjs[0]);
+    }
+    /* @bug 4105380
+     * When using ChoiceFormat, MessageFormat is not good for I18n.
+     */
+    public void Test4105380()
+    {
+        String patternText1 = "The disk \"{1}\" contains {0}.";
+        String patternText2 = "There are {0} on the disk \"{1}\"";
+        MessageFormat form1 = new MessageFormat(patternText1);
+        MessageFormat form2 = new MessageFormat(patternText2);
+        double[] filelimits = {0,1,2};
+        String[] filepart = {"no files","one file","{0,number} files"};
+        ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
+        form1.setFormat(1, fileform);
+        form2.setFormat(0, fileform);
+        Object[] testArgs = {new Long(12373), "MyDisk"};
+        logln(form1.format(testArgs));
+        logln(form2.format(testArgs));
+    }
+    /* @bug 4120552
+     * MessageFormat.parse incorrectly sets errorIndex.
+     */
+    public void Test4120552()
+    {
+        MessageFormat mf = new MessageFormat("pattern");
+        String texts[] = {"pattern", "pat", "1234"};
+        logln("pattern: \"" + mf.toPattern() + "\"");
+        for (int i = 0; i < texts.length; i++) {
+            ParsePosition pp = new ParsePosition(0);
+            Object[] objs = mf.parse(texts[i], pp);
+            log("  text for parsing: \"" + texts[i] + "\"");
+            if (objs == null) {
+                logln("  (incorrectly formatted string)");
+                if (pp.getErrorIndex() == -1)
+                    errln("Incorrect error index: " + pp.getErrorIndex());
+            } else {
+                logln("  (correctly formatted string)");
+            }
+        }
+    }
+
+    /**
+     * @bug 4142938
+     * MessageFormat handles single quotes in pattern wrong.
+     * This is actually a problem in ChoiceFormat; it doesn't
+     * understand single quotes.
+     */
+    public void Test4142938() {
+        String pat = "''Vous'' {0,choice,0#n''|1#}avez s\u00E9lectionne\u00E9 " +
+            "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " +
+            "personnel{0,choice,0#s|1#|2#s}.";
+        MessageFormat mf = new MessageFormat(pat);
+
+        String[] PREFIX = {
+            "'Vous' n'avez s\u00E9lectionne\u00E9 aucun clients personnels.",
+            "'Vous' avez s\u00E9lectionne\u00E9 ",
+            "'Vous' avez s\u00E9lectionne\u00E9 "
+        };
+        String[] SUFFIX = {
+            null,
+            " client personnel.",
+            " clients personnels."
+        };
+
+        for (int i=0; i<3; i++) {
+            String out = mf.format(new Object[]{new Integer(i)});
+            if (SUFFIX[i] == null) {
+                if (!out.equals(PREFIX[i]))
+                    errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"");
+            }
+            else {
+                if (!out.startsWith(PREFIX[i]) ||
+                    !out.endsWith(SUFFIX[i]))
+                    errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" +
+                          SUFFIX[i] + "\"");
+            }
+        }
+    }
+
+    /**
+     * @bug 4142938
+     * Test the applyPattern and toPattern handling of single quotes
+     * by ChoiceFormat.  (This is in here because this was a bug reported
+     * against MessageFormat.)  The single quote is used to quote the
+     * pattern characters '|', '#', '<', and '\u2264'.  Two quotes in a row
+     * is a quote literal.
+     */
+    public void TestChoicePatternQuote() {
+        String[] DATA = {
+            // Pattern                  0 value           1 value
+            "0#can''t|1#can",           "can't",          "can",
+            "0#'pound(#)=''#'''|1#xyz", "pound(#)='#'",   "xyz",
+            "0#'1<2 | 1\u22641'|1#''",  "1<2 | 1\u22641", "'",
+        };
+        for (int i=0; i<DATA.length; i+=3) {
+            try {
+                ChoiceFormat cf = new ChoiceFormat(DATA[i]);
+                for (int j=0; j<=1; ++j) {
+                    String out = cf.format(j);
+                    if (!out.equals(DATA[i+1+j]))
+                        errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " +
+                              out + "; want \"" + DATA[i+1+j] + '"');
+                }
+                String pat = cf.toPattern();
+                String pat2 = new ChoiceFormat(pat).toPattern();
+                if (!pat.equals(pat2))
+                    errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
+                else
+                    logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
+            }
+            catch (IllegalArgumentException e) {
+                errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e);
+            }
+        }
+    }
+
+    /**
+     * @bug 4112104
+     * MessageFormat.equals(null) throws a NullPointerException.  The JLS states
+     * that it should return false.
+     */
+    public void Test4112104() {
+        MessageFormat format = new MessageFormat("");
+        try {
+            // This should NOT throw an exception
+            if (format.equals(null)) {
+                // It also should return false
+                errln("MessageFormat.equals(null) returns false");
+            }
+        }
+        catch (NullPointerException e) {
+            errln("MessageFormat.equals(null) throws " + e);
+        }
+    }
+
+    /**
+     * @bug 4169959
+     * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG.
+     */
+    public void Test4169959() {
+        // This works
+        logln(MessageFormat.format( "This will {0}",
+                                    new String[]{"work"} ) );
+
+        // This fails
+        logln(MessageFormat.format( "This will {0}",
+                                    new Object[]{ null } ) );
+    }
+
+    public void test4232154() {
+        boolean gotException = false;
+        try {
+            MessageFormat format = new MessageFormat("The date is {0:date}");
+        } catch (Exception e) {
+            gotException = true;
+            if (!(e instanceof IllegalArgumentException)) {
+                throw new RuntimeException("got wrong exception type");
+            }
+            if ("argument number too large at ".equals(e.getMessage())) {
+                throw new RuntimeException("got wrong exception message");
+            }
+        }
+        if (!gotException) {
+            throw new RuntimeException("didn't get exception for invalid input");
+        }
+    }
+
+    public void test4293229() {
+        MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''");
+        Object[] args = { null };
+        String expected = "'{0}' '{0}'";
+        String result = format.format(args);
+        if (!result.equals(expected)) {
+            throw new RuntimeException("wrong format result - expected \"" +
+                    expected + "\", got \"" + result + "\"");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/MessageTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test MessageFormat
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+
+import java.util.*;
+import java.io.*;
+import java.text.*;
+
+public class MessageTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new MessageTest().run(args);
+    }
+
+
+   public void TestMSGPatternTest() {
+        Object[] testArgs = {
+            new Double (1), new Double(3456),
+            "Disk", new Date(10000000000L)};
+
+        String[] testCases = {
+           "Quotes '', '{', 'a' {0} '{0}'",
+           "Quotes '', '{', 'a' {0,number} '{0}'",
+           "'{'1,number,'#',##} {1,number,'#',##}",
+           "There are {1} files on {2} at {3}",
+           "On {2}, there are {1} files, with {0,number,currency}.",
+           "'{1,number,percent}', {1,number,percent}, ",
+           "'{1,date,full}', {1,date,full}, ",
+           "'{3,date,full}', {3,date,full}, ",
+           "'{1,number,#,##}' {1,number,#,##}",
+        };
+
+        for (int i = 0; i < testCases.length; ++i) {
+            Locale save = Locale.getDefault();
+            try {
+                Locale.setDefault(Locale.US);
+                logln("");
+                logln( i + " Pat in:  " + testCases[i]);
+                MessageFormat form = new MessageFormat(testCases[i]);
+                logln( i + " Pat out: " + form.toPattern());
+                String result = form.format(testArgs);
+                logln( i + " Result:  " + result);
+                Object[] values = form.parse(result);
+                for (int j = 0; j < testArgs.length; ++j) {
+                    Object testArg = testArgs[j];
+                    Object value = null;
+                    if (j < values.length) {
+                        value = values[j];
+                    }
+                    if ((testArg == null && value != null)
+                        || (testArg != null && !testArg.equals(value))) {
+                       logln( i + " " + j + " old: " + testArg);
+                       logln( i + " " + j + " new: " + value);
+                    }
+                }
+            }
+            catch(java.text.ParseException pe ) {
+                throw new RuntimeException("Error: MessageFormat.parse throws ParseException");
+            }
+            finally{
+                Locale.setDefault(save);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/MessageFormat/bug4492719.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ *
+ * @bug 4492719
+ * @library /java/text/testlib
+ * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException.
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class bug4492719 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        MessageFormat mf;
+        boolean err =false;
+
+        String[] formats = {
+            "short", "medium", "long", "full"
+        };
+        String[] timezones = {
+            "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00",
+            "GMT+123", "GMT-1234", "GMT+2", "GMT-13"
+        };
+        String text;
+
+        Locale.setDefault(Locale.US);
+
+        try {
+            for (int i = 0; i < timezones.length; i++) {
+                TimeZone.setDefault(TimeZone.getTimeZone(timezones[i]));
+
+                for (int j = 0; j < formats.length; j++) {
+                    mf = new MessageFormat("{0,time," + formats[j] + "} - time");
+                    text = MessageFormat.format("{0,time," + formats[j] + "} - time",
+                                      new Object [] { new Date(123456789012L)});
+                    Object[] objs = mf.parse(text);
+                }
+            }
+        } catch (ParseException e) {
+            err = true;
+            System.err.println("Invalid ParseException occurred : " +
+                               e.getMessage());
+            System.err.println("    TimeZone=" + TimeZone.getDefault());
+        }
+        finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+            if (err) {
+                throw new Exception("MessageFormat.parse(\"GMT format\") failed.");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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
+ * 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 4018937
+ * @summary Confirm that DecimalFormat.parse() parses BigDecimal and BigInteger as expected.
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalCompatibilityTest {
+
+    static boolean err = false;
+
+    static final String[] input_data = {
+        "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+        "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+    };
+    static final String[] exponents = {
+        "E-100", "E100", "E-900", "E900", ""
+    };
+    static final int[] multipliers = {
+        -1, 1, -100, 100, -9999, 9999
+    };
+
+    public static void main(String[] args) throws Exception {
+        Locale loc = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+
+        testBigDecimal();
+        testBigInteger();
+
+        Locale.setDefault(loc);
+
+        if (err) {
+            throw new RuntimeException("Error: Unexpected value");
+        }
+    }
+
+    static private void testBigDecimal() {
+        DecimalFormat df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+        df.setMaximumFractionDigits(Integer.MAX_VALUE);
+
+        for (int i = 0; i < input_data.length; i++) {
+            for (int j = 0; j < input_data.length; j++) {
+                for (int k = 0; k < input_data.length; k++) {
+                    for (int l = 0; l < input_data.length; l++) {
+                        for (int m = 0; m < exponents.length; m++) {
+                            String s = input_data[i] + input_data[j] + '.' +
+                                       input_data[k] + input_data[l] +
+                                       exponents[m];
+                            for (int n = 0; n < multipliers.length; n++) {
+                                test(df, s, multipliers[n]);
+                                test(df, '-'+s, multipliers[n]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static private void testBigInteger() {
+        DecimalFormat df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+        df.setMaximumFractionDigits(Integer.MAX_VALUE);
+
+        for (int i = 0; i < input_data.length; i++) {
+            for (int j = 0; j < input_data.length; j++) {
+                String s = input_data[i] + input_data[j];
+                for (int k = 0; k < multipliers.length; k++) {
+                    test(df, s, multipliers[k]);
+                    test(df, '-'+s, multipliers[k]);
+                }
+            }
+        }
+    }
+
+    static void test(DecimalFormat df, String s, int multiplier) {
+        df.setMultiplier(multiplier);
+
+        Number num = null;
+        try {
+            num = df.parse(s);
+        }
+        catch (ParseException e) {
+            err = true;
+            System.err.println("Failed: Exception occurred: " + e.getMessage());
+            return;
+        }
+
+        BigDecimal bd = new BigDecimal(s);
+        try {
+           bd = bd.divide(new BigDecimal(multiplier));
+        }
+        catch (ArithmeticException e) {
+           bd = bd.divide(new BigDecimal(multiplier), BigDecimal.ROUND_HALF_EVEN);
+        }
+        check(num, bd, multiplier);
+    }
+
+    static void check(Number got, BigDecimal expected, int multiplier) {
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("Failed: got:" + got +
+                               ", expected: " + expected +
+                               ", multiplier=" + multiplier);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalFormat.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1044 @@
+/*
+ * 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
+ * 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 4018937 8008577
+ * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalFormat extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new BigDecimalFormat().run(args);
+    }
+
+    static final String nonsep_int =
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890";
+
+    static final String sep_int =
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890";
+
+    static final String nonsep_zero =
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000";
+
+    static final String sep_zero =
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000";
+
+    static final String fra =
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789";
+
+
+    StringBuffer formatted = new StringBuffer(1000);
+    FieldPosition fp;
+
+    /**
+     * Test for normal big numbers which have the fraction part
+     */
+    void test_Format_in_NumberFormat_BigDecimal() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+        // From: 0.000...789
+        // To:   0.000...789 (same as From)
+        formatted.setLength(0);
+        from = "0." + nonsep_zero + "123456789";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -0.000...789
+        // To:   -0.000...789 (same as From)
+        //       ~ : FieldPosition(SIGN)
+        fp = new FieldPosition(NumberFormat.Field.SIGN);
+        formatted.setLength(0);
+        from = "-0." + nonsep_zero + "123456789";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 0, 1);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1234...7890.012...789
+        // To:   123,4...7,890.012...789
+        //       ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD)
+        fp = new FieldPosition(DecimalFormat.INTEGER_FIELD);
+        formatted.setLength(0);
+        from = nonsep_int + "." + fra;
+        to   = sep_int    + "." + fra;
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 0, 479);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...7890.012...789
+        // To:   -123,4...7,890.012...789
+        //                    ~~~~~~~~~ : FieldPosition(FRACTION_FIELD)
+        fp = new FieldPosition(DecimalFormat.FRACTION_FIELD);
+        formatted.setLength(0);
+        from = "-" + nonsep_int + "." + fra;
+        to   = "-" + sep_int    + "." + fra;
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 481, 841);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1234...78900000...0000.000...789
+        // To:   123,4...7,890,000,0...0,000.000...789
+        formatted.setLength(0);
+        from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra;
+        to   = sep_int + "," + sep_zero + "." + nonsep_zero + fra;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...78900000...0000.000...789
+        // To:   -123,4...7,890,000,0...0,000.000...789
+        formatted.setLength(0);
+        from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra;
+        to   = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1234...78900000...0000
+        // To:   123,4...7,890,000,0...0,000
+        formatted.setLength(0);
+        from = nonsep_int + nonsep_zero;
+        to   = sep_int + "," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...78900000...0000
+        // To:   -123,4...7,890,000,0...0,000
+        formatted.setLength(0);
+        from = "-" + nonsep_int + nonsep_zero;
+        to   = "-" + sep_int + "," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1234...78900000...0000.0...0
+        // To:   1,234...7,890,000,0...0,000
+        formatted.setLength(0);
+        from = nonsep_int + nonsep_zero + "." + nonsep_zero;
+        to   = sep_int + "," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...78900000...0000.0...0
+        // To:   -1,234...7,890,000,0...0,000
+        formatted.setLength(0);
+        from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero;
+        to   = "-" + sep_int + "," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 000...0000
+        // To:   0
+        formatted.setLength(0);
+        from = nonsep_zero;
+        to   = "0";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -000...0000
+        // To:   0
+        formatted.setLength(0);
+        from = "-" + nonsep_zero;
+        to   = "0";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 000...00001234
+        // To:   1,234
+        formatted.setLength(0);
+        from = nonsep_zero + "1234";
+        to   = "1,234";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -000...00001234
+        // To:   -1,234
+        //       ~ : FieldPosition(GROUPING_SEPARATOR)
+        fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
+        formatted.setLength(0);
+        from = "-" + nonsep_zero + "1234";
+        to   = "-1,234";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 2, 3);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 000...0000.0...0
+        // To:   0
+        formatted.setLength(0);
+        from = nonsep_zero + "." + nonsep_zero;
+        to   = "0";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.0");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1);
+
+        // From: -000...0000.0...0
+        // To:   0.0
+        formatted.setLength(0);
+        from = "-" + nonsep_zero + "." + nonsep_zero;
+        to   = "0.0";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1234...7890.012...7890...0
+        // To:   1,234...7,890.0123...789
+        formatted.setLength(0);
+        from = nonsep_int + "." + fra + nonsep_zero;
+        to   = sep_int    + "." + fra;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...7890.012...7890...0
+        // To:   -1,234...7,890.0123...789
+        formatted.setLength(0);
+        from = "-" + nonsep_int + "." + fra + nonsep_zero;
+        to   = "-" + sep_int    + "." + fra;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+        // From: 1123...890.012...789
+        // To  : 1.123...8900123...789E360
+        //                           ~~~ : FieldPosition(EXPONENT)
+        fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+        formatted.setLength(0);
+        from = "1"  + nonsep_int + "." + fra;
+        to   = "1." + nonsep_int       + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 723, 726);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1123...890.012...789
+        // To  : -1.123...8900123...789E360
+        formatted.setLength(0);
+        from = "-1"  + nonsep_int + "." + fra;
+        to   = "-1." + nonsep_int       + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+        // From: 0.000...0001123...890.012...789
+        // To  : 1.123...8900123...789E-360
+        formatted.setLength(0);
+        from = "0." + nonsep_zero + "1" + fra;
+        to   = "1."                  + fra + "E-361";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -0.000...0001123...890.012...789
+        // To  : -1.123...8900123...789E-360
+        formatted.setLength(0);
+        from = "-0." + nonsep_zero + "1"  + fra;
+        to   = "-1."                  + fra + "E-361";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 1123...890.012...789000...000
+        // To  : 1.123...8900123...789E360
+        formatted.setLength(0);
+        from = "1"  + nonsep_int + "." + fra + nonsep_zero;
+        to   = "1." + nonsep_int       + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1123...890.012...789000...000
+        // To  : -1.123...8900123...789E360
+        //                           ~ : FieldPosition(EXPONENT_SYMBOL)
+        fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL);
+        formatted.setLength(0);
+        from = "-1"  + nonsep_int + "." + fra + nonsep_zero;
+        to   = "-1." + nonsep_int       + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 723, 724);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 0.000...0001123...890.012...789000...000
+        // To  : 1.123...8900123...789E-360
+        //                           ~ : FieldPosition(EXPONENT_SIGN)
+        fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN);
+        formatted.setLength(0);
+        from = "0." + nonsep_zero + "1" + fra + nonsep_zero;
+        to   = "1."                  + fra + "E-361";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 363, 364);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -0.000...0001123...890.012...789000...000
+        // To  : -1.123...8900123...789E-360
+        formatted.setLength(0);
+        from = "-0." + nonsep_zero + "1"  + fra + nonsep_zero;
+        to   = "-1."                  + fra + "E-361";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: ABC1123...890.012...789
+        // To  : ABC1.123...890.0123...789
+        formatted = new StringBuffer("ABC");
+        from = "1"     + nonsep_int + "."  + fra;
+        to   = "ABC1." + nonsep_int     + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: ABC-1123...890.012...789
+        // To  : ABC-1.123...890.0123...789
+        //          ~ : FieldPosition(DECIMAL_SEPARATOR)
+        fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
+        formatted = new StringBuffer("ABC");
+        from = "-1"     + nonsep_int + "."  + fra;
+        to   = "ABC-1." + nonsep_int    + fra + "E360";
+        nf.format(new BigDecimal(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 5, 6);
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, 726, 0);
+
+        // From: 0.000...000012...7890123456789
+        // To:   0.000...000012...789012346 (Shorter than From)
+        formatted.setLength(0);
+        from = "0." + nonsep_zero + fra + fra;
+        to   = "0." + nonsep_zero + fra + "012346";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, 723, 0);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -0.000...000012...7890123456789
+        // To:   -0.000...000012...789012 (Shorter than From)
+        formatted.setLength(0);
+        from = "-0." + nonsep_zero + fra + fra;
+        to   = "-0." + nonsep_zero + fra + "012";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("00000.###E0");
+        setDigits(nf, 5, 5, 370, 0);
+
+        // From: 1234567890.012...78901234567890
+        // To:   12345.67890012...789012346E5
+        formatted.setLength(0);
+        from = "1234567890." + fra + "0123456789";
+        to   = "12345.67890" + fra + "01235E5";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, 364, 0);
+
+        // From: -0.000...0001012...7890123456789
+        // To:   -1.012...789012E-361
+        formatted.setLength(0);
+        from = "-0." + nonsep_zero + "1" + fra + "0123456789";
+        to   = "-1."                 + fra + "0123E-361";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, 366, 0);
+
+        // From: 1012...78901234567890
+        // To:   1.012...789012346E370
+        formatted.setLength(0);
+        from = "1"  + fra + "0123456789";
+        to   = "1." + fra + "012346E370";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, 363, 0);
+
+        // From: -1012...7890123456789
+        // To:   -1.012...789012E370
+        formatted.setLength(0);
+        from = "-1"  + fra + "0123456789";
+        to   = "-1." + fra + "012E370";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720);
+
+        // From: 1234...78900000...0000.0...0
+        // To:   1,234...7,890,000,0...0,000.0...0
+        formatted.setLength(0);
+        from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero;
+        to   = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...78900000...0000.0...0
+        // To:   -1,234...7,890,000,0...0,000.0...0
+        formatted.setLength(0);
+        from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero;
+        to   = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+    }
+
+    /**
+     * Test for normal big numbers which have the fraction part with multiplier
+     */
+    void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+        ((DecimalFormat)nf).setMultiplier(250000000);
+        ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true);
+
+        // From: 1000...0000.000...000
+        // To:   250,0...0,000.
+        formatted.setLength(0);
+        from = "1"          + nonsep_zero + "." + nonsep_zero;
+        to   = "250,000,000," + sep_zero    + ".";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false);
+
+        // From: -1000...0000.000...000
+        // To:   -250,0...0,000
+        formatted.setLength(0);
+        from = "-1"         + nonsep_zero + "." + nonsep_zero;
+        to   = "-250,000,000," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+        ((DecimalFormat)nf).setMultiplier(-250000000);
+        ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true);
+
+        // From: 1000...0000.000...000
+        // To:   -250,0...0,000.
+        formatted.setLength(0);
+        from = "1"          + nonsep_zero + "." + nonsep_zero;
+        to   = "-250,000,000," + sep_zero    + ".";
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false);
+
+        // From: -1000...0000.000...000
+        // To:   250,0...0,000
+        formatted.setLength(0);
+        from = "-1"         + nonsep_zero + "." + nonsep_zero;
+        to   = "250,000,000," + sep_zero;
+        nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+    }
+
+    /**
+     * Test for normal big numbers which don't have the fraction part
+     */
+    void test_Format_in_NumberFormat_BigInteger() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        if (!(nf instanceof DecimalFormat)) {
+            throw new RuntimeException("Couldn't get DecimalFormat instance.");
+        }
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+        // From: 1234...7890
+        // To:   123,4...7,890
+        formatted.setLength(0);
+        from = nonsep_int;
+        to   = sep_int;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1234...7890
+        // To:   -123,4...7,890
+        //      ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD)
+        fp = new FieldPosition(DecimalFormat.INTEGER_FIELD);
+        formatted.setLength(0);
+        from = "-" + nonsep_int;
+        to   = "-" + sep_int;
+        nf.format(new BigInteger(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 1, 480);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 000...0001234...7890
+        // To:   123,4...7,890
+        formatted.setLength(0);
+        from = nonsep_zero + nonsep_int;
+        to   = sep_int;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -000...0001234...7890
+        // To:   -123,4...7,890
+        //       ~ : FieldPosition(SIGN)
+        fp = new FieldPosition(NumberFormat.Field.SIGN);
+        formatted.setLength(0);
+        from = "-" + nonsep_zero + nonsep_int;
+        to   = "-" + sep_int;
+        nf.format(new BigInteger(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 0, 1);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: 000...0000
+        // To:   0
+        formatted.setLength(0);
+        from = nonsep_zero;
+        to   = "0";
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.0");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1);
+
+        // From: -000...0000
+        // To:   0.0
+        fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
+        formatted.setLength(0);
+        from = "-" + nonsep_zero;
+        to   = "0.0";
+        nf.format(new BigInteger(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 1, 2);
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+        // From: 10123...789
+        // To  : 1.0123...789E360
+        //                  ~~~ : FieldPosition(EXPONENT)
+        fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+        formatted.setLength(0);
+        from = "1"  + fra;
+        to   = "1." + fra + "E360";
+        nf.format(new BigInteger(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 363, 366);
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1012...789
+        // To  : -1.012...789E360
+        formatted.setLength(0);
+        from = "-1"  + fra;
+        to   = "-1." + fra + "E360";
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("00000.###E0");
+        setDigits(nf, 5, 5, Integer.MAX_VALUE, 720);
+
+        // From: 12345012...789000...000
+        // To  : 12345.012...789000...000E720
+        //                              ~~~ : FieldPosition(EXPONENT)
+        fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+        formatted.setLength(0);
+        from = "12345"  + fra + nonsep_zero;
+        to   = "12345." + fra + nonsep_zero + "E720";
+        nf.format(new BigInteger(from), formatted, fp);
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        checkFieldPosition(from, fp, 727, 730);
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("00000.###E0");
+        setDigits(nf, 5, 5, Integer.MAX_VALUE, 365);
+
+        // From: -1234567890012...789000...000
+        // To  : -12345.67890012...789E365
+        formatted.setLength(0);
+        from = "-1234567890"  + fra;
+        to   = "-12345.67890" + fra + "E365";
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+    }
+
+    /**
+     * Test for normal big numbers which don't have the fraction part with
+     * multiplier
+     */
+    void test_Format_in_NumberFormat_BigInteger_usingMultiplier() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        ((DecimalFormat)nf).setMultiplier(250000000);
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+        // From: 1000...0000
+        // To:   250,0...0,000
+        formatted.setLength(0);
+        from = "1" + nonsep_zero;
+        to   = "250,000,000," + sep_zero;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1000...0000
+        // To:   -250,0...0,000
+        formatted.setLength(0);
+        from = "-1" + nonsep_zero;
+        to   = "-250,000,000," + sep_zero;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        ((DecimalFormat)nf).setMultiplier(-250000000);
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+        // From: 1000...0000
+        // To:   -250,0...0,000
+        formatted.setLength(0);
+        from = "1" + nonsep_zero;
+        to   = "-250,000,000," + sep_zero;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        // From: -1000...0000
+        // To:   250,0...0,000
+        formatted.setLength(0);
+        from = "-1" + nonsep_zero;
+        to   = "250,000,000," + sep_zero;
+        nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+    }
+
+    /**
+     * Test for normal Long numbers when maximum and minimum digits are
+     * specified
+     */
+    void test_Format_in_NumberFormat_Long_checkDigits() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        if (!(nf instanceof DecimalFormat)) {
+            throw new RuntimeException("Couldn't get DecimalFormat instance.");
+        }
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0);
+
+        // From: 1234567890
+        // To:   000,0...0,000,123,456,789
+        //       -------------
+        //       300 zeros
+        formatted.setLength(0);
+        from = "123456789";
+        to   = sep_zero.substring(0, 399) + ",123,456,789";
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("##0.###");
+        ((DecimalFormat)nf).setMultiplier(-1);
+        setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+        // From: 1234567890
+        // To:   -0000...0000123456789.000...000
+        //      -------------
+        //        300 zeros
+        formatted.setLength(0);
+        from = "123456789";
+        to   = "-" + nonsep_zero.substring(0, 300) + "123456789." +
+               nonsep_zero.substring(0, 340);
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE);
+        setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0);
+
+        // From: Long.MAX_VALUE
+        // To:   000,0...0,000,019,807,040,619,342,712,359,383,728,129
+        //       ---------------
+        //       280 zeros
+        formatted.setLength(0);
+        from = Long.toString(Long.MAX_VALUE);
+        to   = sep_zero.substring(0, 373) +
+               "19,807,040,619,342,712,359,383,728,129";
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("0.###E0");
+        ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE);
+        setDigits(nf, 1, 1, Integer.MAX_VALUE, 360);
+
+        // From: Long.MAX_VALUE
+        // To:   -1.9807040628566084396238503936000...000E28
+        //                                      ---------
+        //                                      312 zeros
+        formatted.setLength(0);
+        from = Long.toString(Long.MAX_VALUE);
+        to   = "-1.9807040628566084396238503936" +
+               nonsep_zero.substring(0, 312) + "E28";
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("##0.###E0");
+        ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE);
+        setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+        // From: Long.MIN_VALUE
+        // To:   -198070406193427123615312117760000...0000.000...000E-280
+        //                                     ----------- ---------
+        //                                      280 zeros  340 zeros
+        formatted.setLength(0);
+        from = Long.toString(Long.MIN_VALUE);
+        to   = "-19807040619342712361531211776" +
+               nonsep_zero.substring(0, 280) + "." +
+               nonsep_zero.substring(0, 340) + "E-280";
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+        /* ------------------------------------------------------------------ */
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE);
+        setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+        // From: Long.MIN_VALUE
+        // To:   000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000
+        //       ---------------                                       ---------
+        //          280 zeros                                          340 zeros
+        formatted.setLength(0);
+        from = Long.toString(Long.MIN_VALUE);
+        to   = sep_zero.substring(0, 373) +
+               "19,807,040,628,566,084,398,385,987,584." +
+               nonsep_zero.substring(0, 340);
+        nf.format(new Long(from), formatted, new FieldPosition(0));
+        checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+    }
+
+    /**
+     * Test for special numbers
+     *    Double.NaN
+     *    Double.POSITIVE_INFINITY
+     *    Double.NEGATIVE_INFINITY
+     */
+    void test_Format_in_NumberFormat_SpecialNumber() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        if (!(nf instanceof DecimalFormat)) {
+            throw new RuntimeException("Couldn't get DecimalFormat instance.");
+        }
+
+        ((DecimalFormat)nf).applyPattern("#,##0.###");
+        setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+        double[] numbers = {
+            -0.0, 0.0, Double.NaN,
+            Double.POSITIVE_INFINITY, 5.1, 5.0,
+            Double.NEGATIVE_INFINITY, -5.1, -5.0,
+        };
+        int multipliers[] = {0, 5, -5};
+        String[][] expected = {
+            {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"},
+            {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5",
+             "-25"},
+            {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5",
+             "25"},
+        };
+
+        for (int i = 0; i < multipliers.length; i++) {
+            ((DecimalFormat)nf).setMultiplier(multipliers[i]);
+            for (int j = 0; j < numbers.length; j++) {
+                formatted.setLength(0);
+                from = String.valueOf(numbers[j]);
+                nf.format(numbers[j], formatted, new FieldPosition(0));
+                checkFormat(from, formatted, expected[i][j],
+                            ((DecimalFormat)nf).getMultiplier());
+            }
+        }
+    }
+
+    /**
+     * Test for Long.MIN_VALUE
+     *   (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong
+     *    number.)
+     */
+    void test_Format_in_NumberFormat_Other() {
+        String from, to;
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        if (!(nf instanceof DecimalFormat)) {
+            throw new RuntimeException("Couldn't get DecimalFormat instance.");
+        }
+
+        long[] numbers = {
+            Long.MIN_VALUE,
+        };
+        int multipliers[] = {1, -1};
+        String[][] expected = {
+            {"-9,223,372,036,854,775,808"},     // Long.MIN_VALUE
+            {"9,223,372,036,854,775,808"},      // Long.MIN_VALUE * (-1)
+        };
+
+        for (int i = 0; i < multipliers.length; i++) {
+            ((DecimalFormat)nf).setMultiplier(multipliers[i]);
+            for (int j = 0; j < numbers.length; j++) {
+                formatted.setLength(0);
+                from = String.valueOf(numbers[j]);
+                nf.format(numbers[j], formatted, new FieldPosition(0));
+                checkFormat(from, formatted, expected[i][j],
+                            ((DecimalFormat)nf).getMultiplier());
+            }
+        }
+    }
+
+    /**
+     * Test for MessageFormat
+     */
+    void test_Format_in_MessageFormat() {
+        MessageFormat mf = new MessageFormat(
+            "  {0, number}\n" +
+            "  {0, number, integer}\n" +
+            "  {0, number, currency}\n" +
+            "  {0, number, percent}\n" +
+            "  {0, number,0.###########E0}\n" +
+
+            "  {1, number}\n" +
+            "  {1, number, integer}\n" +
+            "  {1, number, currency}\n" +
+            "  {1, number, percent}\n" +
+            "  {1, number,0.#######E0}\n",
+            Locale.US
+        );
+        Object[] testArgs = {
+            new BigInteger("9876543210987654321098765432109876543210"),
+            new BigDecimal("-12345678901234567890.98765432109876543210987654321"),
+        };
+        String expected =
+            "  9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" +
+            "  9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" +
+            "  $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" +
+            "  987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" +
+            "  9.87654321099E39\n" +
+
+            "  -12,345,678,901,234,567,890.988\n" +
+            "  -12,345,678,901,234,567,891\n" +
+            "  ($12,345,678,901,234,567,890.99)\n" +
+            "  -1,234,567,890,123,456,789,099%\n" +
+            "  -1.2345679E19\n"
+        ;
+
+        if (!expected.equals(mf.format(testArgs))) {
+            errln("Wrong format.\n      got:\n" + mf.format(testArgs) +
+                  "     expected:\n" + expected);
+        }
+    }
+
+    private void setDigits(NumberFormat nf,
+                           int i_max, int i_min, int f_max, int f_min) {
+        nf.setMaximumIntegerDigits(i_max);
+        nf.setMinimumIntegerDigits(i_min);
+        nf.setMaximumFractionDigits(f_max);
+        nf.setMinimumFractionDigits(f_min);
+    }
+
+    private void checkFormat(String orig, StringBuffer got, String expected,
+                             int multiplier) {
+        if (!expected.equals(new String(got))) {
+            errln("Formatting... failed." +
+                  "\n   original:   " + orig +
+                  "\n   multiplier: " + multiplier +
+                  "\n   formatted:  " + got +
+                  "\n   expected:   " + expected + "\n");
+        }
+    }
+
+    private void checkFieldPosition(String orig, FieldPosition fp, int begin,
+                                    int end) {
+        int position;
+
+        if ((position = fp.getBeginIndex()) != begin) {
+            errln("Formatting... wrong Begin index returned for " +
+                  fp.getFieldAttribute() + "." +
+                  "\n   original: " + orig +
+                  "\n   got:      " + position +
+                  "\n   expected: " + begin + "\n");
+        }
+        if ((position = fp.getEndIndex()) != end) {
+            errln("Formatting... wrong End index returned for " +
+                  fp.getFieldAttribute() + "." +
+                  "\n   original: " + orig +
+                  "\n   got:      " + position +
+                  "\n   expected: " + end + "\n");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/BigDecimalParse.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,709 @@
+/*
+ * 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
+ * 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 4018937 8008577
+ * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse
+ */
+
+import java.math.BigDecimal;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalParse extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        Locale loc = Locale.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            new BigDecimalParse().run(args);
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(loc);
+        }
+    }
+
+    static final String nonsep_int =
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890" +
+        "123456789012345678901234567890123456789012345678901234567890";
+
+    static final String sep_int =
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890," +
+        "123,456,789,012,345,678,901,234,567,890";
+
+    static final String nonsep_zero =
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000" +
+        "000000000000000000000000000000000000000000000000000000000000";
+
+    static final String sep_zero =
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000," +
+        "000,000,000,000,000,000,000,000,000,000";
+
+    static final String fra =
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789" +
+        "012345678901234567890123456789012345678901234567890123456789";
+
+
+    Number parsed = null;
+    ParsePosition pp;
+    boolean exceptionOccurred;
+    String msg;
+    DecimalFormat df;
+
+    /**
+     * Test for normal big numbers which have the fraction part
+     */
+    void test_Parse_in_DecimalFormat_BigDecimal() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        // From: 1234...7890.012...789
+        // To:   BigDecimal 1234...7890.012...789
+        check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra));
+
+        // From: -1,234...7,890.012...789
+        // To:   BigDecimal -1234...7890.012...789
+        check("-" + sep_int    + "." + fra,
+              new BigDecimal("-" + nonsep_int + "." + fra));
+
+        // From: 000...0000.0...0
+        // To:   BigDecimal 0E-360
+        check(nonsep_zero + "." + nonsep_zero,
+              new BigDecimal(nonsep_zero + "." + nonsep_zero));
+
+        // From: 0.000...0000123...789E370
+        // To:   BigDecimal 0.0123...789
+        check("0.0000000000" + nonsep_zero + fra + "E370",
+              new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370"));
+
+        // From: 0.1123...890E-360
+        // To:   BigDecimal 1.123...890E-361
+        check("0.1" + nonsep_int + "E-360",
+              new BigDecimal("0.1" + nonsep_int + "E-360"));
+
+        // From: 000...0000.0...0123...7890
+        // To:   BigDecimal 1.234...890E-361
+        check(nonsep_zero + "." + nonsep_zero + nonsep_int,
+              new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int));
+
+        // From: 0.123...890E360
+        // To:   BigDecimal 123...890
+        check("0." + nonsep_int + "E360",
+              new BigDecimal("0." + nonsep_int + "E360"));
+    }
+
+    /**
+     * Test for normal big numbers which have the fraction part with multiplier
+     */
+    void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        // From: 250,0...0,000.000...000
+        // To:   1000...0000.000...000
+        df.setMultiplier(250000000);
+        check("250,000,000," + sep_zero + "." + nonsep_zero,
+              new BigDecimal("1" + nonsep_zero + "." + nonsep_zero));
+
+        // From: -250,0...0,000.000...000
+        // To:   -1000...0000.000...000
+        check("-250,000,000," + sep_zero + "." + nonsep_zero,
+              new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+        // From: 250,0...0,000.000...000
+        // To:   -1000...0000.000...000
+        df.setMultiplier(-250000000);
+        check("250,000,000," + sep_zero + "." + nonsep_zero,
+              new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+        // From: -250,0...0,000.000...000
+        // To:   1000...0000.000...000
+        check("-250,000,000," + sep_zero + "." + nonsep_zero,
+              new BigDecimal("1" + nonsep_zero + "." + nonsep_zero));
+
+        // Confirm that ArithmeticException is handled properly
+        // From: 1000.000
+        // To:   333.333
+        df.setMultiplier(3);
+        check("1000.000", new BigDecimal("333.333"));
+
+        // Confirm that ArithmeticException is handled properly
+        // From: 10000.0000
+        // To:   303.0303
+        df.setMultiplier(33);
+        check("10000.0000", new BigDecimal("303.0303"));
+    }
+
+    /**
+     * Test for division by zero (BigDecimal)
+     */
+    void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+        df.setMultiplier(0);
+
+        // From: 1000.000
+        // To:   Double.POSITIVE_INFINITY
+        check("1000.000", new Double(Double.POSITIVE_INFINITY));
+
+        // From: -1000
+        // To:   Double.NEGATIVE_INFINITY
+        check("-1000", new Double(Double.NEGATIVE_INFINITY));
+
+        // From: -0.00
+        // To:   Double.NaN
+        check("-0.00", new Double(Double.NaN));
+    }
+
+    /**
+     * Test for division by zero (Double)
+     */
+    void test_Parse_in_DecimalFormat_Double_DivisionByZero() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(false);
+        df.setMultiplier(0);
+
+        // From: 1000.000
+        // To:   Double.POSITIVE_INFINITY
+        check("1000.000", new Double(Double.POSITIVE_INFINITY));
+
+        // From: -1000.000
+        // To:   Double.NEGATIVE_INFINITY
+        check("-1000.000", new Double(Double.NEGATIVE_INFINITY));
+
+        // From: 0.0
+        // To:   Double.NaN
+        check("0.0", new Double(Double.NaN));
+
+        // From: -0.0 (Double)
+        // To:   Double.NaN
+        check("-0.0", new Double(Double.NaN));
+
+        // From: Double.NaN
+        // To:   Double.NaN
+        check("\ufffd", new Double(Double.NaN));
+
+        // From: Double.POSITIVE_INFINITY
+        // To:   Double.NaN
+        check("\u221e", new Double(Double.POSITIVE_INFINITY));
+
+        // From: Double.NEGATIVE_INFINITY
+        // To:   Double.NaN
+        check("-\u221e", new Double(Double.NEGATIVE_INFINITY));
+    }
+
+    /**
+     * Test for division by zero (Long)
+     */
+    void test_Parse_in_DecimalFormat_Long_DivisionByZero() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(false);
+        df.setMultiplier(0);
+
+        // From: 1000
+        // To:   Double.POSITIVE_INFINITY
+        check("1000", new Double(Double.POSITIVE_INFINITY));
+
+        // From: -1000
+        // To:   Double.NEGATIVE_INFINITY
+        check("-1000", new Double(Double.NEGATIVE_INFINITY));
+
+        // From: -000 (Long)
+        // To:   Double.NaN
+        check("-000", new Double(Double.NaN));
+    }
+
+    /**
+     * Test for normal big numbers which don't have the fraction part
+     */
+    void test_Parse_in_DecimalFormat_BigInteger() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        // From: 123...890
+        // To:   BigDecimal 123...890
+        check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int));
+
+        // From: 123,4...7,890
+        // To:   BigDecimal 1234...7890
+        check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int));
+
+        // From: -000...000123...890
+        // To:   BigDecimal -123...890
+        check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int));
+
+        // From: -000,0...0,000,123,4...7,890
+        // To:   BigDecimal -123...890
+        check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int));
+    }
+
+    /**
+     * Test for normal big numbers which don't have the fraction part with
+     * multiplier
+     */
+    void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        // From: 250,0...0,000
+        // To:   1000...0000
+        df.setMultiplier(250000000);
+        check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero));
+
+        // From: -250,0...0,000
+        // To:   -1000...0000
+        check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero));
+
+        // From: 250,0...0,000
+        // To:   -1000...0000
+        df.setMultiplier(-250000000);
+        check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero));
+
+        // From: -250,0...0,000
+        // To:   1000...0000
+        check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero));
+
+        // From: 250,0...0,000E-360
+        // To:   -1000...0000.000...000
+        check("250,000,000," + sep_zero + "," + sep_zero + "E-360",
+              new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+        // Confirm that a division which results in a irrational number is done
+        // properly
+        // From: 1000
+        // To:   333
+        df.setMultiplier(3);
+        check("1000", new BigDecimal("333"));
+    }
+
+    /**
+     * Test for special numbers
+     *    Double.NaN
+     *    Double.POSITIVE_INFINITY
+     *    Double.NEGATIVE_INFINITY
+     */
+    void test_Parse_in_DecimalFormat_SpecialNumber() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        String[] numbers = {
+            "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd",
+            "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e",
+        };
+        int multipliers[] = {5, -5};
+        Number[][] expected = {
+            {
+                new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"),
+                new BigDecimal("5.0"), new BigDecimal("5.1"),
+                new Double(Double.POSITIVE_INFINITY), new Double(Double.NaN),
+                new BigDecimal("0"), new BigDecimal("0.0"),
+                new BigDecimal("-5"), new BigDecimal("-5.0"),
+                new BigDecimal("-5.1"),
+                new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN),
+            },
+            {
+                new BigDecimal("0"), new BigDecimal("0.0"),
+                new BigDecimal("-5"), new BigDecimal("-5.0"),
+                new BigDecimal("-5.1"),
+                new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN),
+                new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"),
+                new BigDecimal("5.0"), new BigDecimal("5.1"),
+                new Double(Double.POSITIVE_INFINITY),
+            },
+        };
+
+        for (int i = 0; i < multipliers.length; i++) {
+            df.setMultiplier(multipliers[i]);
+            for (int j = 0; j < numbers.length; j++) {
+                check(String.valueOf(numbers[j]), expected[i][j]);
+            }
+        }
+    }
+
+    /**
+     * Test for special numbers
+     */
+    void test_Parse_in_DecimalFormat_Other() {
+        df = new DecimalFormat();
+        df.setParseBigDecimal(true);
+
+        String[] numbers = {
+            "-9223372036854775808",     // Long.MIN_VALUE
+        };
+        int multipliers[] = {1, -1};
+        String[][] expected = {
+            {"-9223372036854775808"},   // Long.MIN_VALUE
+            {"9223372036854775808"},    // Long.MAX_VALUE+1 = abs(MIN_VALUE)
+        };
+
+        for (int i = 0; i < multipliers.length; i++) {
+            df.setMultiplier(multipliers[i]);
+            for (int j = 0; j < numbers.length; j++) {
+                check(String.valueOf(numbers[j]),
+                      new BigDecimal(expected[i][j]));
+            }
+        }
+    }
+
+    static final String[] patterns = {
+        "  {0, number}  ",
+        "  {0, number}  ",
+        "  {0, number, currency}  ",
+        "  {0, number, currency}  ",
+        "  {0, number, percent}  ",
+        "  {0, number, percent}  ",
+        "  {0, number,#,##0.###E0}  ",
+        "  {0, number,#,##0.###E0}  ",
+
+        "  {0, number}  ",
+        "  {0, number}  ",
+        "  {0, number, integer}  ",
+        "  {0, number, integer}  ",
+        "  {0, number, currency}  ",
+        "  {0, number, currency}  ",
+        "  {0, number, percent}  ",
+        "  {0, number, percent}  ",
+        "  {0, number,#,##0.###E0}  ",
+        "  {0, number,#,##0.###E0}  ",
+    };
+    static final String[] from = {
+        "  12,345,678,901,234,567,890.98765432109876543210987654321  ",
+        "  -12,345,678,901,234,567,890.98765432109876543210987654321  ",
+        "  $12,345,678,901,234,567,890.98765432109876543210987654321  ",
+        "  ($12,345,678,901,234,567,890.98765432109876543210987654321)  ",
+        "  1,234,567,890,123,456,789,098.76543210987654321098765432100%  ",
+        "  -1,234,567,890,123,456,789,098.76543210987654321098765432100%  ",
+        "  12,345,678,901,234,567,890.98765432109876543210987654321E-20  ",
+        "  -12,345,678,901,234,567,890.98765432109876543210987654321E-20  ",
+
+        "  9,876,543,210,987,654,321,098,765,432,109,876,543,210  ",
+        "  -9,876,543,210,987,654,321,098,765,432,109,876,543,210  ",
+        "  9,876,543,210,987,654,321,098,765,432,109,876,543,210E5  ",
+        "  -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5  ",
+        "  $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00  ",
+        "  ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00)  ",
+        "  987,654,321,098,765,432,109,876,543,210,987,654,321,012%  ",
+        "  -987,654,321,098,765,432,109,876,543,210,987,654,321,012%  ",
+        "  98,765,432,109,876,543,210.98765432109876543210E20  ",
+        "  -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20  ",
+    };
+
+    static final String[] expected1 = { // isParseIntegerOnly() == false
+        "12345678901234567890.98765432109876543210987654321",
+        "-12345678901234567890.98765432109876543210987654321",
+        "12345678901234567890.98765432109876543210987654321",
+        "-12345678901234567890.98765432109876543210987654321",
+        "12345678901234567890.98765432109876543210987654321",
+        "-12345678901234567890.98765432109876543210987654321",
+        "0.1234567890123456789098765432109876543210987654321",
+        "-0.1234567890123456789098765432109876543210987654321",
+
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210",
+        "9.876543210987654321098765432109876543210E44",
+        "-98765432109876543210987654321098765.43210",
+        "9876543210987654321098765432109876543210.00",
+        "-9876543210987654321098765432109876543210.00",
+        "9876543210987654321098765432109876543210.12",
+        "-9876543210987654321098765432109876543210.12",
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210.00000000000000000000",
+    };
+    static final int[] parsePosition1 = {
+        60, 61, 61, 63, 64, 65, 64, 65,
+        57, 58, 59, 61, 61, 63, 60, 61, 54, 88,
+    };
+
+    /**
+     * Test for MessageFormat: setParseIntegerOnly(false)
+     */
+    void test_Parse_in_MessageFormat_NotParseIntegerOnly() {
+        for (int i=0; i < patterns.length; i++) {
+            pp = new ParsePosition(0);
+            Object[] parsed = null;
+
+            try {
+                MessageFormat mf = new MessageFormat(patterns[i]);
+                Format[] formats = mf.getFormats();
+                for (int j=0; j < formats.length; j++) {
+                    ((DecimalFormat)formats[j]).setParseBigDecimal(true);
+                }
+
+                parsed = mf.parse(from[i], pp);
+
+                if (pp.getErrorIndex() != -1) {
+                    errln("Case" + (i+1) +
+                          ": getErrorIndex() returns wrong value. expected:-1, got:"+
+                          pp.getErrorIndex() + " for " + from[i]);
+                }
+                if (pp.getIndex() != parsePosition1[i]) {
+                    errln("Case" + (i+1) +
+                          ": getIndex() returns wrong value. expected:" +
+                          parsePosition1[i] + ", got:"+ pp.getIndex() +
+                          " for " + from[i]);
+                }
+            }
+            catch(Exception e) {
+                errln("Unexpected exception: " + e.getMessage());
+            }
+
+            checkType(from[i], getType(new BigDecimal(expected1[i])),
+                      getType((Number)parsed[0]));
+            checkParse(from[i], new BigDecimal(expected1[i]),
+                       (Number)parsed[0]);
+        }
+    }
+
+    static final String[] expected2 = { // isParseIntegerOnly() == true
+        "12345678901234567890",
+        "-12345678901234567890",
+        "12345678901234567890",
+        "-12345678901234567890",
+        "12345678901234567890",
+        "-12345678901234567890",
+        "0",
+        "0",
+
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210",
+        "9.876543210987654321098765432109876543210E44",
+        "-98765432109876543210987654321098765.43210",
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210",
+        "9876543210987654321098765432109876543210.12",
+        "-9876543210987654321098765432109876543210.12",
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210.00000000000000000000",
+    };
+    static final int[][] parsePosition2 = {     // {errorIndex, index}
+        /*
+         * Should keep in mind that the expected result is different from
+         * DecimalFormat.parse() for some cases.
+         */
+        {28, 0},        // parsing stopped at '.'
+        {29, 0},        // parsing stopped at '.'
+        {29, 0},        // parsing stopped at '.'
+        {2, 0},         // parsing stopped at '(' because cannot find ')'
+        {2, 0},         // parsing stopped at the first numeric
+                        // because cannot find '%'
+        {2, 0},         // parsing stopped at the first numeric
+                        // because cannot find '%'
+        {28, 0},        // parsing stopped at '.'
+        {29, 0},        // parsing stopped at '.'
+
+        {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61},
+        {56, 0},        // parsing stopped at '.'
+                        // because cannot find '%'
+        {2, 0},         // parsing stopped at '(' because cannot find ')'
+        {-1, 60}, {-1, 61},
+        {28, 0},        // parsing stopped at '.'
+        {-1, 88},
+    };
+
+    /**
+     * Test for MessageFormat: setParseIntegerOnly(true)
+     */
+    void test_Parse_in_MessageFormat_ParseIntegerOnly() {
+        for (int i=0; i < patterns.length; i++) {
+            pp = new ParsePosition(0);
+            Object[] parsed = null;
+
+            try {
+                MessageFormat mf = new MessageFormat(patterns[i]);
+                Format[] formats = mf.getFormats();
+                for (int j=0; j < formats.length; j++) {
+                    ((DecimalFormat)formats[j]).setParseBigDecimal(true);
+                    ((DecimalFormat)formats[j]).setParseIntegerOnly(true);
+                }
+
+                parsed = mf.parse(from[i], pp);
+
+                if (pp.getErrorIndex() != parsePosition2[i][0]) {
+                    errln("Case" + (i+1) +
+                          ": getErrorIndex() returns wrong value. expected:" +
+                          parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() +
+                          " for " + from[i]);
+                }
+                if (pp.getIndex() != parsePosition2[i][1]) {
+                    errln("Case" + (i+1) +
+                          ": getIndex() returns wrong value. expected:" +
+                          parsePosition2[i][1] + ", got:"+ pp.getIndex() +
+                          " for " + from[i]);
+                }
+            }
+            catch(Exception e) {
+                errln("Unexpected exception: " + e.getMessage());
+            }
+
+            if (parsePosition2[i][0] == -1) {
+                checkType(from[i], getType(new BigDecimal(expected2[i])),
+                          getType((Number)parsed[0]));
+                checkParse(from[i], new BigDecimal(expected2[i]),
+                           (Number)parsed[0]);
+            }
+        }
+    }
+
+    static final String[] from3 = {
+        "12,345,678,901,234,567,890.98765432109876543210987654321",
+        "-12,345,678,901,234,567,890.98765432109876543210987654321",
+        "9,876,543,210,987,654,321,098,765,432,109,876,543,210",
+        "-9,876,543,210,987,654,321,098,765,432,109,876,543,210",
+        "1234556790000E-8",
+    };
+    static final String[] expected3 = {
+        "12345678901234567890",
+        "-12345678901234567890",
+        "9876543210987654321098765432109876543210",
+        "-9876543210987654321098765432109876543210",
+        "12345.56790000",
+    };
+    static final int[][] parsePosition3 = {     // {errorIndex, index}
+        {-1, 26},
+        {-1, 27},
+        {-1, 53},
+        {-1, 54},
+        {-1, 16},
+    };
+
+    /**
+     * Test for DecimalFormat: setParseIntegerOnly(true)
+     */
+    void test_Parse_in_DecimalFormat_ParseIntegerOnly() {
+        DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance();
+        df.setParseBigDecimal(true);
+
+        for (int i=0; i < from3.length; i++) {
+            pp = new ParsePosition(0);
+            Number parsed = null;
+
+            try {
+                parsed = df.parse(from3[i], pp);
+
+                if (pp.getErrorIndex() != parsePosition3[i][0]) {
+                    errln("Case" + (i+1) +
+                          ": getErrorIndex() returns wrong value. expected:" +
+                          parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() +
+                          " for " + from3[i]);
+                }
+                if (pp.getIndex() != parsePosition3[i][1]) {
+                    errln("Case" + (i+1) +
+                          ": getIndex() returns wrong value. expected:" +
+                          parsePosition3[i][1] + ", got:"+ pp.getIndex() +
+                          " for " + from3[i]);
+                }
+            }
+            catch(Exception e) {
+                errln("Unexpected exception: " + e.getMessage());
+            }
+
+            if (parsePosition3[i][0] == -1) {
+                checkType(from3[i], getType(new BigDecimal(expected3[i])),
+                          getType(parsed));
+                checkParse(from3[i], new BigDecimal(expected3[i]), parsed);
+            }
+        }
+    }
+
+    protected void check(String from, Number to) {
+        pp = new ParsePosition(0);
+        try {
+            parsed = df.parse(from, pp);
+        }
+        catch(Exception e) {
+            exceptionOccurred = true;
+            errln(e.getMessage());
+        }
+        if (!exceptionOccurred) {
+            checkParse(from, to, parsed);
+            checkType(from, getType(to), getType(parsed));
+            checkParsePosition(from, from.length(), pp.getIndex());
+        }
+    }
+
+    private void checkParse(String orig, Number expected, Number got) {
+        if (!expected.equals(got)) {
+            errln("Parsing... failed." +
+                  "\n   original: " + orig +
+                  "\n   parsed:   " + got +
+                  "\n   expected: " + expected + "\n");
+        }
+    }
+
+    private void checkType(String orig, String expected, String got) {
+        if (!expected.equals(got)) {
+            errln("Parsing... unexpected Class returned." +
+                  "\n   original: " + orig +
+                  "\n   got:      " + got +
+                  "\n   expected: " + expected + "\n");
+        }
+    }
+
+    private void checkParsePosition(String orig, int expected, int got) {
+        if (expected != got) {
+            errln("Parsing... wrong ParsePosition returned." +
+                  "\n   original: " + orig +
+                  "\n   got:      " + got +
+                  "\n   expected: " + expected + "\n");
+        }
+    }
+
+    private String getType(Number number) {
+        return number.getClass().getName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug4208135.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * 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
+ * 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
+ * @summary Confirm that the decimal separator is shown when explicitly requested.
+ * @bug 4208135
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4208135 {
+
+    static DecimalFormat df;
+
+    static boolean err = false;
+
+    static public void main(String[] args){
+
+        Locale defaultLoc = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+
+        df = new DecimalFormat();
+
+        df.applyPattern("0.#E0");
+
+        df.setDecimalSeparatorAlwaysShown(true);
+        checkFormat(new Double(0.0), "0.E0");
+        checkFormat(new Double(10.0), "1.E1");
+        checkFormat(new Double(1000.0), "1.E3");
+        checkFormat(new Long(0), "0.E0");
+        checkFormat(new Long(10), "1.E1");
+        checkFormat(new Long(1000), "1.E3");
+        checkFormat(new BigDecimal("0.0"), "0.E0");
+        checkFormat(new BigDecimal("10.0"), "1.E1");
+        checkFormat(new BigDecimal("1000.0"), "1.E3");
+        checkFormat(new BigInteger("00"), "0.E0");
+        checkFormat(new BigInteger("10"), "1.E1");
+        checkFormat(new BigInteger("1000"), "1.E3");
+
+        df.setDecimalSeparatorAlwaysShown(false);
+        checkFormat(new Double(0.0), "0E0");
+        checkFormat(new Double(10.0), "1E1");
+        checkFormat(new Double(1000.0), "1E3");
+        checkFormat(new Long(0), "0E0");
+        checkFormat(new Long(10), "1E1");
+        checkFormat(new Long(1000), "1E3");
+        checkFormat(new BigDecimal("0.0"), "0E0");
+        checkFormat(new BigDecimal("10.0"), "1E1");
+        checkFormat(new BigDecimal("1000.0"), "1E3");
+        checkFormat(new BigInteger("0"), "0E0");
+        checkFormat(new BigInteger("10"), "1E1");
+        checkFormat(new BigInteger("1000"), "1E3");
+
+        df.applyPattern("0.###");
+
+        df.setDecimalSeparatorAlwaysShown(true);
+        checkFormat(new Double(0.0), "0.");
+        checkFormat(new Double(10.0), "10.");
+        checkFormat(new Double(1000.0), "1000.");
+        checkFormat(new Long(0), "0.");
+        checkFormat(new Long(10), "10.");
+        checkFormat(new Long(1000), "1000.");
+        checkFormat(new BigDecimal("0.0"), "0.");
+        checkFormat(new BigDecimal("10.0"), "10.");
+        checkFormat(new BigDecimal("1000.0"), "1000.");
+        checkFormat(new BigInteger("0"), "0.");
+        checkFormat(new BigInteger("10"), "10.");
+        checkFormat(new BigInteger("1000"), "1000.");
+
+        df.setDecimalSeparatorAlwaysShown(false);
+        checkFormat(new Double(0.0), "0");
+        checkFormat(new Double(10.0), "10");
+        checkFormat(new Double(1000.0), "1000");
+        checkFormat(new Long(0), "0");
+        checkFormat(new Long(10), "10");
+        checkFormat(new Long(1000), "1000");
+        checkFormat(new BigDecimal("0.0"), "0");
+        checkFormat(new BigDecimal("10.0"), "10");
+        checkFormat(new BigDecimal("1000.0"), "1000");
+        checkFormat(new BigInteger("0"), "0");
+        checkFormat(new BigInteger("10"), "10");
+        checkFormat(new BigInteger("1000"), "1000");
+
+        Locale.setDefault(defaultLoc);
+
+        if (err) {
+            throw new RuntimeException("Wrong format/parse with DecimalFormat");
+        }
+    }
+
+    static void checkFormat(Number num, String expected) {
+        String got = df.format(num);
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("    DecimalFormat format(" +
+                               num.getClass().getName() +
+                               ") error:" +
+                               "\n\tnumber:           " + num +
+                               "\n\tSeparatorShown? : " + df.isDecimalSeparatorAlwaysShown() +
+                               "\n\tgot:              " + got +
+                               "\n\texpected:         " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug4833877.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,464 @@
+/*
+ * 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
+ * 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
+ * @summary Confirm that the negative multiplier works as expected.
+ * @bug 4833877
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4833877 {
+
+    static DecimalFormat df;
+
+    static boolean err = false;
+
+    public static void main(String[] args) throws Exception {
+
+        Locale defaultLoc = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+
+        /* ================================================================ */
+
+        df = new DecimalFormat();
+        df.setMaximumFractionDigits(50);
+        df.setMultiplier(4);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(252.5252525252525), "1,010.10101010101");
+        checkParse("-1,010.10101010101", new Double(-252.5252525252525));
+
+        checkFormat(new Double(-2222.2222), "-8,888.8888");
+        checkParse("8888.8888", new Double(2222.2222));
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(1000), "4,000");
+        checkParse("-4,000", new Long(-1000));
+
+        checkFormat(new Long(-250), "-1,000");
+        checkParse("1000", new Long(250));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+        checkFormat(new BigDecimal("22222.222222222222222222222"),
+                    "88,888.888888888888888888888");
+        checkParse("-88,888.888888888888888888888",
+                    new BigDecimal("-22222.222222222222222222222"));
+
+        checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+                    "-4,444,444,444,444,444,444.444444444444444444");
+        checkParse("4444444444444444444.444444444444444444",
+                    new BigDecimal("1111111111111111111.111111111111111111"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("22222222222222222222222222"),
+                    "88,888,888,888,888,888,888,888,888");
+        checkParse("-88,888,888,888,888,888,888,888,888",
+                    new BigDecimal("-22222222222222222222222222"));
+
+        checkFormat(new BigInteger("-1111111111111111111111111"),
+                    "-4,444,444,444,444,444,444,444,444");
+        checkParse("4444444444444444444444444",
+                    new BigDecimal("1111111111111111111111111"));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(false);
+        df.setMultiplier(-4);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(252.5252525252525), "-1,010.10101010101");
+        checkParse("-1,010.10101010101", new Double(252.5252525252525));
+
+        checkFormat(new Double(-2222.2222), "8,888.8888");
+        checkParse("8888.8888", new Double(-2222.2222));
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(1000), "-4,000");
+        checkParse("-4,000", new Long(1000));
+
+        checkFormat(new Long(-250), "1,000");
+        checkParse("1000", new Long(-250));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+        checkFormat(new BigDecimal("22222.222222222222222222222"),
+                    "-88,888.888888888888888888888");
+        checkParse("-88,888.888888888888888888888",
+                    new BigDecimal("22222.222222222222222222222"));
+
+        checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+                   "4,444,444,444,444,444,444.444444444444444444");
+        checkParse("4444444444444444444.444444444444444444",
+                    new BigDecimal("-1111111111111111111.111111111111111111"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("22222222222222222222222222"),
+                    "-88,888,888,888,888,888,888,888,888");
+        checkParse("-88,888,888,888,888,888,888,888,888",
+                    new BigDecimal("22222222222222222222222222"));
+
+        checkFormat(new BigInteger("-1111111111111111111111111"),
+                   "4,444,444,444,444,444,444,444,444");
+        checkParse("4444444444444444444444444",
+                    new BigDecimal("-1111111111111111111111111"));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(false);
+        df.setMultiplier(-3);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(3333.3333333), "-9,999.9999999");
+        checkParse("-10,000.00000000000", new Double(3333.3333333333335));// rounding error
+
+        df.setParseIntegerOnly(true);
+        checkFormat(new Double(-3333.3333333), "9,999.9999999");
+        checkParse("10,000.00000000000", new Long(-3333));
+        df.setParseIntegerOnly(false);
+        checkFormat(new Double(-3333.3333333), "9,999.9999999");
+        checkParse("10,000.00000000000", new Double(-3333.3333333333335));// rounding error
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(3333), "-9,999");
+        df.setParseIntegerOnly(true);
+        checkParse("-10,000", new Long(3333));
+        df.setParseIntegerOnly(false);
+        checkParse("-10000", new Double(3333.3333333333335));// rounding error
+
+        checkFormat(new Long(-3333), "9,999");
+        df.setParseIntegerOnly(true);
+        checkParse("10,000", new Long(-3333));
+        df.setParseIntegerOnly(false);
+        checkParse("10000", new Double(-3333.3333333333335));// rounding error
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+        checkFormat(new BigDecimal("33333.333333333333333333333"),
+                    "-99,999.999999999999999999999");
+        checkParse("-100,000.000000000000000000000",
+                    new BigDecimal("33333.333333333333333333333"));
+
+        checkFormat(new BigDecimal("-33333.333333333333333333333"),
+                    "99,999.999999999999999999999");
+        checkParse("100,000.000000000000000000000",
+                    new BigDecimal("-33333.333333333333333333333"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("33333333333333333333333333"),
+                    "-99,999,999,999,999,999,999,999,999");
+        checkParse("-100,000,000,000,000,000,000,000,000",
+                    new BigDecimal("33333333333333333333333333"));
+
+        checkFormat(new BigInteger("-33333333333333333333333333"),
+                    "99,999,999,999,999,999,999,999,999");
+        df.setParseIntegerOnly(true);
+        checkParse("100,000,000,000,000,000,000,000,000.000",
+                    new BigDecimal("-33333333333333333333333333"));
+        df.setParseIntegerOnly(false);
+        checkParse("100,000,000,000,000,000,000,000,000.000",
+                    new BigDecimal("-33333333333333333333333333.333"));
+
+        /* ================================================================ */
+
+        df = new DecimalFormat("0.#E0;-0.#E0");
+        df.setMaximumFractionDigits(50);
+        df.setMultiplier(4);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(252.5252525252525), "1.01010101010101E3");
+        checkParse("-1.01010101010101E3", new Double(-2.525252525252525E2));
+
+        checkFormat(new Double(-2222.2222), "-8.8888888E3");
+        checkParse("8888.8888", new Double(2.2222222E3));
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(1000), "4E3");
+        checkParse("-4E3", new Long(-1000));
+
+        checkFormat(new Long(-250), "-1E3");
+        checkParse("1000", new Long(250));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+
+        checkFormat(new BigDecimal("22222.222222222222222222222"),
+                    "8.8888888888888888888888888E4");
+        checkParse("-8.8888888888888888888888888E4",
+                    new BigDecimal("-2.2222222222222222222222222E4"));
+
+        checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+                    "-4.444444444444444444444444444444444444E18");
+        checkParse("4444444444444444444.444444444444444444",
+                    new BigDecimal("1111111111111111111.111111111111111111"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("22222222222222222222222222"),
+                    "8.8888888888888888888888888E25");
+        checkParse("-8.8888888888888888888888888E25",
+                    new BigDecimal("-22222222222222222222222222"));
+
+        checkFormat(new BigInteger("-1111111111111111111111111"),
+                    "-4.444444444444444444444444E24");
+        checkParse("4444444444444444444444444",
+                    new BigDecimal("1111111111111111111111111"));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(false);
+        df.setMultiplier(-4);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(252.5252525252525), "-1.01010101010101E3");
+        checkParse("-1.01010101010101E3", new Double(2.525252525252525E2));
+
+        checkFormat(new Double(-2222.2222), "8.8888888E3");
+        checkParse("8888.8888", new Double(-2.2222222E3));
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(1000), "-4E3");
+        checkParse("-4E3", new Long(1000));
+
+        checkFormat(new Long(-250), "1E3");
+        checkParse("1000", new Long(-250));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+
+        checkFormat(new BigDecimal("22222.222222222222222222222"),
+                   "-8.8888888888888888888888888E4");
+        checkParse("-8.8888888888888888888888888E4",
+                    new BigDecimal("2.2222222222222222222222222E4"));
+
+        checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+                    "4.444444444444444444444444444444444444E18");
+        checkParse("4444444444444444444.444444444444444444",
+                    new BigDecimal("-1111111111111111111.111111111111111111"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("22222222222222222222222222"),
+                   "-8.8888888888888888888888888E25");
+        checkParse("-8.8888888888888888888888888E25",
+                    new BigDecimal("22222222222222222222222222"));
+
+        checkFormat(new BigInteger("-1111111111111111111111111"),
+                    "4.444444444444444444444444E24");
+        checkParse("4444444444444444444444444",
+                   new BigDecimal("-1111111111111111111111111"));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(false);
+        df.setMultiplier(-3);
+
+        /*
+         * Test for double/Double
+         */
+        checkFormat(new Double(3333.3333333), "-9.9999999999E3");
+        checkParse("-1.00000000000000E3", new Double(3.33333333333333333E2));
+
+        df.setParseIntegerOnly(true);
+        checkFormat(new Double(-3333.3333333), "9.9999999999E3");
+        checkParse("10.00000000000000E3", new Long(-3));
+        df.setParseIntegerOnly(false);
+        checkFormat(new Double(-3333.3333333), "9.9999999999E3");
+        checkParse("10.00000000000000E3", new Double(-3.33333333333333333E3));
+
+        /*
+         * Test for long/Long
+         */
+        checkFormat(new Long(3333), "-9.999E3");
+        df.setParseIntegerOnly(true);
+        checkParse("-1.0E4", new Long(0));
+        df.setParseIntegerOnly(false);
+        checkParse("-1.0E4", new Double(3333.3333333333335));
+
+        checkFormat(new Long(-3333), "9.999E3");
+        df.setParseIntegerOnly(true);
+        checkParse("10.0E4", new Long(-3));
+        df.setParseIntegerOnly(false);
+        checkParse("10.0E4", new Double(-33333.3333333333336));
+
+        /* ---------------------------------------------------------------- */
+
+        df.setParseBigDecimal(true);
+
+        /*
+         * Test for BigDecimal
+         */
+
+        checkFormat(new BigDecimal("333.333333333333333333333333"),
+                   "-9.99999999999999999999999999E2");
+        checkParse("-1.0000000000000000000000000E3",
+                    new BigDecimal("3.333333333333333333333333E2"));
+
+        df.setParseIntegerOnly(true);
+        checkFormat(new BigDecimal("-333.333333333333333333333333"),
+                   "9.99999999999999999999999999E2");
+        checkParse("10.0000000000000000000000000E3",
+                    new BigDecimal("-3"));
+        df.setParseIntegerOnly(false);
+        checkFormat(new BigDecimal("-333.333333333333333333333333"),
+                   "9.99999999999999999999999999E2");
+        checkParse("1.0000000000000000000000000E3",
+                    new BigDecimal("-3.333333333333333333333333E2"));
+
+        /*
+         * Test for BigInteger
+         */
+        checkFormat(new BigInteger("33333333333333333333333333"),
+                    "-9.9999999999999999999999999E25");
+        checkParse("-100000000000000000000000000",
+                    new BigDecimal("33333333333333333333333333"));
+
+        checkFormat(new BigInteger("-33333333333333333333333333"),
+                    "9.9999999999999999999999999E25");
+        df.setParseIntegerOnly(true);
+        checkParse("100000000000000000000000000000",
+                    new BigDecimal("-33333333333333333333333333333"));
+        df.setParseIntegerOnly(false);
+        checkParse("100000000000000000000000000.000",
+                    new BigDecimal("-33333333333333333333333333.333"));
+
+        /* ================================================================ */
+
+        Locale.setDefault(defaultLoc);
+
+        if (err) {
+            throw new RuntimeException("Wrong format/parse with DecimalFormat");
+        }
+    }
+
+    static void checkFormat(Number num, String expected) {
+        String got = df.format(num);
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("    DecimalFormat format(" +
+                               num.getClass().getName() +
+                               ") error:" +
+                               "\n\tnumber:     " + num +
+                               "\n\tpattern:    " + df.toPattern() +
+                               "\n\tmultiplier: " + df.getMultiplier() +
+                               "\n\tgot:        " + got +
+                               "\n\texpected:   " + expected);
+        }
+    }
+
+    static void checkParse(String text, Double expected) {
+        Double got = (Double)df.parse(text, new ParsePosition(0));
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("    DecimalFormat parse(double) error:" +
+                               "\n\ttext:       " + text +
+                               "\n\tpattern:    " + df.toPattern() +
+                               "\n\tmultiplier: " + df.getMultiplier() +
+                               "\n\tgot:        " + got +
+                               "\n\texpected:   " + expected);
+        }
+    }
+
+    static void checkParse(String text, Long expected) {
+        Long got = (Long)df.parse(text, new ParsePosition(0));
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("    DecimalFormat parse(long) error:" +
+                               "\n\ttext:       " + text +
+                               "\n\tpattern:    " + df.toPattern() +
+                               "\n\tmultiplier: " + df.getMultiplier() +
+                               "\n\tgot:        " + got +
+                               "\n\texpected:   " + expected);
+        }
+    }
+
+    static void checkParse(String text, BigDecimal expected) {
+        BigDecimal got = (BigDecimal)df.parse(text, new ParsePosition(0));
+        if (!got.equals(expected)) {
+            err = true;
+            System.err.println("    DecimalFormat parse(BigDecimal) error:" +
+                               "\n\ttext:       " + text +
+                               "\n\tpattern:    " + df.toPattern() +
+                               "\n\tmultiplier: " + df.getMultiplier() +
+                               "\n\tgot:        " + got +
+                               "\n\texpected:   " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug4838107.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,248 @@
+/*
+ * 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
+ * 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 4838107 8008577
+ * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107
+ */
+
+import java.math.*;
+import java.util.*;
+import java.text.*;
+
+public class Bug4838107 extends IntlTest {
+
+    static DecimalFormat df;
+    static DecimalFormatSymbols dfs;
+    static boolean err = false;
+
+    static public void main(String[] args) {
+        Locale defaultLoc = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+
+        /**
+         * This bug is about exponential formatting. But I added test cases for:
+         *   - Double and BigDecimal numbers which don't have exponent parts.
+         *   - Long and BigInteger numbers which don't support exponential
+         *     notation.
+         * because there are few test cases for suffix and prefix.
+         * And also, I added test cases to guarantee further formatting and
+         * parsing using the same DecimalFormat instance will not change the
+         * Number's value anymore.
+         */
+
+        test_double();
+        test_long();
+        test_BigDecimal();
+        test_BigInteger();
+
+        Locale.setDefault(defaultLoc);
+
+        if (err) {
+            throw new RuntimeException("Wrong format with DecimalFormat");
+        }
+    }
+
+    static void test_double() {
+        df = new DecimalFormat();
+        dfs = df.getDecimalFormatSymbols();
+
+        /* Test with default pattern */
+        test(new Double(1234),    "1,234");
+        test(new Double(0.1234),  "0.123");     // rounded
+        test(new Double(-1234),   "-1,234");
+        test(new Double(-0.1234), "-0.123");    // rounded
+
+        test(new Double(Double.POSITIVE_INFINITY), "\u221e");
+        test(new Double(Double.NEGATIVE_INFINITY), "-\u221e");
+        test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
+        test(new Double(0.0),  "0");
+        test(new Double(-0.0), "-0");   // with the minus sign
+
+        /* Specify a pattern and the minus sign. */
+        prepareFormatter("<P>#.###E00<S>", 'm');
+        test(new Double(1234),    "<P>1.234E03<S>");
+        test(new Double(0.1234),  "<P>1.234Em01<S>");
+        test(new Double(-1234),   "m<P>1.234E03<S>");
+        test(new Double(-0.1234), "m<P>1.234Em01<S>");
+
+        prepareFormatter("<P>#.###E00<S>;#.###E00", 'm');
+        test(new Double(1234),    "<P>1.234E03<S>");
+        test(new Double(0.1234),  "<P>1.234Em01<S>");
+        test(new Double(-1234),   "1.234E03");
+        test(new Double(-0.1234), "1.234Em01");
+
+        prepareFormatter("#.###E00;<P>#.###E00<S>", 'm');
+        test(new Double(1234),    "1.234E03");
+        test(new Double(0.1234),  "1.234Em01");
+        test(new Double(-1234),   "<P>1.234E03<S>");
+        test(new Double(-0.1234), "<P>1.234Em01<S>");
+
+        prepareFormatter("<P>#.###E00<S>;<p>-#.###E00<s>", 'm');
+        test(new Double(1234),    "<P>1.234E03<S>");
+        test(new Double(0.1234),  "<P>1.234Em01<S>");
+        test(new Double(-1234),   "<p>m1.234E03<s>");
+        test(new Double(-0.1234), "<p>m1.234Em01<s>");
+
+        test(new Double(Double.POSITIVE_INFINITY), "<P>\u221e<S>");
+        test(new Double(Double.NEGATIVE_INFINITY), "<p>m\u221e<s>");
+        test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
+        test(new Double(0.0),  "<P>0E00<S>");
+        test(new Double(-0.0), "<p>m0E00<s>");  // with the minus sign
+    }
+
+    static void test_BigDecimal() {
+        df = new DecimalFormat();
+        dfs = df.getDecimalFormatSymbols();
+
+        /* Test with default pattern */
+        test(new BigDecimal("123456789012345678901234567890"),
+             "123,456,789,012,345,678,901,234,567,890");
+        test(new BigDecimal("0.000000000123456789012345678901234567890"),
+             "0");
+        test(new BigDecimal("-123456789012345678901234567890"),
+             "-123,456,789,012,345,678,901,234,567,890");
+        test(new BigDecimal("-0.000000000123456789012345678901234567890"),
+              "-0");
+
+        test(new BigDecimal("0"), "0");
+        test(new BigDecimal("-0"), "0");
+
+        /* Specify a pattern and the minus sign. */
+        prepareFormatter("<P>#.####################E00<S>;<p>-#.####################E00<s>", 'm');
+        test(new BigDecimal("123456789012345678901234567890"),
+             "<P>1.23456789012345678901E29<S>");
+        test(new BigDecimal("0.000000000123456789012345678901234567890"),
+             "<P>1.23456789012345678901Em10<S>");
+        test(new BigDecimal("-123456789012345678901234567890"),
+             "<p>m1.23456789012345678901E29<s>");
+        test(new BigDecimal("-0.000000000123456789012345678901234567890"),
+              "<p>m1.23456789012345678901Em10<s>");
+
+        test(new BigDecimal("0"), "<P>0E00<S>");
+        test(new BigDecimal("-0"), "<P>0E00<S>");
+    }
+
+    static void test_long() {
+        df = new DecimalFormat();
+        dfs = df.getDecimalFormatSymbols();
+
+        /* Test with default pattern */
+        test(new Long(123456789),  "123,456,789");
+        test(new Long(-123456789), "-123,456,789");
+
+        test(new Long(0), "0");
+        test(new Long(-0), "0");
+
+        /* Specify a pattern and the minus sign. */
+        prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
+        test(new Long(123456789),  "<P>123,456,789<S>");
+        test(new Long(-123456789), "<p>m123,456,789<s>");
+
+        test(new Long(0), "<P>0<S>");
+        test(new Long(-0), "<P>0<S>");
+    }
+
+    static void test_BigInteger() {
+        df = new DecimalFormat();
+        dfs = df.getDecimalFormatSymbols();
+
+        /* Test with default pattern */
+        test(new BigInteger("123456789012345678901234567890"),
+             "123,456,789,012,345,678,901,234,567,890");
+        test(new BigInteger("-123456789012345678901234567890"),
+             "-123,456,789,012,345,678,901,234,567,890");
+
+        test(new BigInteger("0"), "0");
+        test(new BigInteger("-0"), "0");
+
+        /* Specify a pattern and the minus sign. */
+        prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
+        test(new BigInteger("123456789012345678901234567890"),
+             "<P>123,456,789,012,345,678,901,234,567,890<S>");
+        test(new BigInteger("-123456789012345678901234567890"),
+             "<p>m123,456,789,012,345,678,901,234,567,890<s>");
+
+        test(new BigInteger("0"), "<P>0<S>");
+        test(new BigInteger("-0"), "<P>0<S>");
+    }
+
+    static void prepareFormatter(String pattern, char minusSign) {
+        dfs = df.getDecimalFormatSymbols();
+        df.applyPattern(pattern);
+        dfs.setMinusSign(minusSign);
+        df.setDecimalFormatSymbols(dfs);
+    }
+
+    static void test(Number num, String str) {
+        String formatted = df.format(num);
+        if (!formatted.equals(str)) {
+            err = true;
+            System.err.println("    DecimalFormat format(" +
+                               num.getClass().getName() +
+                               ") error: \n\tnumber: " + num +
+                               "\n\tminus sign: " + dfs.getMinusSign() +
+                               "\n\tgot:        " + formatted +
+                               "\n\texpected:   " + str);
+            return;
+        }
+
+        if (num instanceof BigDecimal || num instanceof BigInteger) {
+            df.setParseBigDecimal(true);
+        }
+        Number parsed1 = null, parsed2 = null;
+        try {
+            parsed1 = df.parse(formatted);
+            formatted = df.format(parsed1);
+            parsed2 = df.parse(formatted);
+            if (!parsed1.equals(parsed2)) {
+                err = true;
+                System.err.println("    DecimalFormat roundtrip parse(" +
+                                   num.getClass().getName() +
+                                   ") error: \n\toriginal number:  " + str +
+                                   "\n\tparsed number:    " + parsed1 +
+                                   "  (" + parsed1.getClass().getName() + ")" +
+                                   "\n\tformatted number: " + formatted +
+                                   "\n\tre-parsed number: " + parsed2 +
+                                   "  (" + parsed2.getClass().getName() + ")" +
+                                   "\n\tminus sign: " + dfs.getMinusSign());
+            }
+        }
+        catch (Exception e) {
+            err = true;
+            System.err.println("    DecimalFormat parse(" +
+                               num.getClass().getName() +
+                               ") threw an Exception:  " + e.getMessage() +
+                               "\n\toriginal number:  " + str +
+                               "\n\tparsed number   : " + parsed1 +
+                               "  (" + parsed1.getClass().getName() + ")" +
+                               "\n\tformatted number: " + formatted +
+                               "\n\tre-parsed number: " + parsed2 +
+                               "  (" + parsed2.getClass().getName() + ")" +
+                               "\n\tminus sign: " + dfs.getMinusSign());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug4944439.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * 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 4944439
+ * @summary Confirm that numbers where all digits after the decimal separator are 0
+ * and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned as Long(not double).
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DecimalFormat;
+import java.util.Locale;
+
+public class Bug4944439 {
+
+    static boolean err = false;
+    static DecimalFormat df;
+
+    public static void main(String[] args) throws Exception {
+
+        Locale defaultLoc = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+
+        df = new DecimalFormat();
+        String s = "-9223372036854775809";      // Long.MIN_VALUE-1
+        check_Double(s);
+
+        test(Long.MIN_VALUE, Long.MIN_VALUE+10);
+        test(-10, 10);
+        test(Long.MAX_VALUE-10, Long.MAX_VALUE-1);
+
+        s = "9223372036854775807.00";   // Long.MAX_VALUE
+        check_Long(s);
+        s = "9223372036854775808";      // Long.MAX_VALUE+1
+        check_Double(s);
+
+        s = "-0.0";
+        check_Double(s);
+        s = "0.0";
+        check_Long(s);
+
+        Locale.setDefault(defaultLoc);
+
+        if (err) {
+            throw new RuntimeException("Wrong parsing with DecimalFormat");
+        }
+    }
+
+    private static void test(long from, long to) throws Exception {
+        for (long l = from; l <= to; l++) {
+            check_Long(Long.toString(l) + ".00");
+        }
+    }
+
+    private static void check_Long(String s) throws Exception {
+        Number number = df.parse(s);
+        if (!(number instanceof Long)) {
+            err = true;
+            System.err.println("Failed: DecimalFormat.parse(\"" + s +
+                "\") should return a Long, but returned a " +
+                number.getClass().getName());
+        }
+
+        int index = s.indexOf('.');
+        Long l = new Long(s.substring(0, index));
+        if (!l.equals(number)) {
+            err = true;
+            System.err.println("Failed: DecimalFormat.parse(" + s +
+                ") should return a Long(" + l + "), but returned " + number);
+        }
+    }
+
+    private static void check_Double(String s) throws Exception {
+        Number number = df.parse(s);
+        if (!(number instanceof Double)) {
+            err = true;
+            System.err.println("Failed: DecimalFormat.parse(\"" + s +
+                "\") should return a Double, but returned a " +
+                number.getClass().getName());
+        }
+
+        Double d = new Double(s);
+        if (!d.equals(number)) {
+            err = true;
+            System.err.println("Failed: DecimalFormat.parse(" + s +
+                ") should return a Double(" + d + "), but returned " + number);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug4990596.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * 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 4990596
+ * @summary Make sure that any subclass of Number can be formatted using DecimalFormat.format().
+ */
+
+import java.text.DecimalFormat;
+
+public class Bug4990596 {
+
+    public static void main(String[] args) {
+        new DecimalFormat().format(new MutableInteger(0));
+    }
+
+    public static class MutableInteger extends Number {
+        public int value;
+
+        public MutableInteger() {
+        }
+        public MutableInteger(int value) {
+            this.value = value;
+        }
+        public double doubleValue() {
+            return this.value;
+        }
+        public float floatValue() {
+            return this.value;
+        }
+        public int intValue() {
+            return this.value;
+        }
+        public long longValue() {
+            return this.value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/Bug6278616.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary Confirm that AtomicInteger and AtomicLong are formatted correctly.
+ * @bug 6278616
+ */
+
+import java.text.NumberFormat;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import java.util.Locale;
+
+public class Bug6278616 {
+
+    static final int[] ints = {
+        Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE
+    };
+
+    static final long[] longs = {
+        Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE
+    };
+
+    public static void main(String[] args) {
+        NumberFormat nf = NumberFormat.getInstance();
+
+        for (int j = 0; j < ints.length; j++) {
+            String s_i = nf.format(new Integer(ints[j]));
+            String s_ai = nf.format(new AtomicInteger(ints[j]));
+            if (!s_i.equals(s_ai)) {
+                throw new RuntimeException("format(AtomicInteger " + s_ai +
+                                           ") doesn't equal format(Integer " +
+                                           s_i + ")");
+            }
+        }
+
+        for (int j = 0; j < longs.length; j++) {
+            String s_l = nf.format(new Long(longs[j]));
+            String s_al = nf.format(new AtomicLong(longs[j]));
+            if (!s_l.equals(s_al)) {
+                throw new RuntimeException("format(AtomicLong " + s_al +
+                                           ") doesn't equal format(Long " +
+                                           s_l + ")");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/CurrencyFormat.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4290801 4942982 5102005 8008577 8021121
+ * @summary Basic tests for currency formatting.
+ * @run main/othervm -Djava.locale.providers=JRE,SPI CurrencyFormat
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+
+public class CurrencyFormat {
+
+    public static void main(String[] args) throws Exception {
+        testFormatting();
+        testSymbols();
+    }
+
+    static void testFormatting() {
+        boolean failed = false;
+        Locale[] locales = {
+            Locale.US,
+            Locale.JAPAN,
+            Locale.GERMANY,
+            Locale.ITALY,
+            new Locale("it", "IT", "EURO") };
+        Currency[] currencies = {
+            null,
+            Currency.getInstance("USD"),
+            Currency.getInstance("JPY"),
+            Currency.getInstance("DEM"),
+            Currency.getInstance("EUR"),
+        };
+        String[][] expecteds = {
+            {"$1,234.56", "$1,234.56", "JPY1,235", "DEM1,234.56", "EUR1,234.56"},
+            {"\uFFE51,235", "USD1,234.56", "\uFFE51,235", "DEM1,234.56", "EUR1,234.56"},
+            {"1.234,56 \u20AC", "1.234,56 USD", "1.235 JPY", "1.234,56 DM", "1.234,56 \u20AC"},
+            {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"},
+            {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"},
+        };
+
+        for (int i = 0; i < locales.length; i++) {
+            Locale locale = locales[i];
+            NumberFormat format = NumberFormat.getCurrencyInstance(locale);
+            for (int j = 0; j < currencies.length; j++) {
+                Currency currency = currencies[j];
+                String expected = expecteds[i][j];
+                if (currency != null) {
+                    format.setCurrency(currency);
+                    int digits = currency.getDefaultFractionDigits();
+                    format.setMinimumFractionDigits(digits);
+                    format.setMaximumFractionDigits(digits);
+                }
+                String result = format.format(1234.56);
+                if (!result.equals(expected)) {
+                    failed = true;
+                    System.out.println("FAIL: Locale " + locale
+                        + (currency == null ? ", default currency" : (", currency: " + currency))
+                        + ", expected: " + expected
+                        + ", actual: " + result);
+                }
+            }
+        }
+
+        if (failed) {
+            throw new RuntimeException();
+        }
+    }
+
+    static void testSymbols() throws Exception {
+        FileInputStream stream = new FileInputStream(new File(System.getProperty("test.src", "."), "CurrencySymbols.properties"));
+        Properties props = new Properties();
+        props.load(stream);
+        SimpleDateFormat format = null;
+
+        Locale[] locales = NumberFormat.getAvailableLocales();
+        for (int i = 0; i < locales.length; i++) {
+            Locale locale = locales[i];
+            DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
+            String result = symbols.getCurrencySymbol();
+            String expected = (String) props.get(locale.toString());
+
+            if (expected == null) {
+                System.out.println("Warning: No expected currency symbol defined for locale " + locale);
+            } else {
+                    if (expected.contains(";")) {
+                        StringTokenizer tokens = new StringTokenizer(expected, ";");
+                        int tokensCount = tokens.countTokens();
+
+                        if (tokensCount == 3) {
+                            expected = tokens.nextToken();
+                            if (format == null) {
+                                format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
+                                format.setTimeZone(TimeZone.getTimeZone("GMT"));
+                                format.setLenient(false);
+                            }
+
+                            if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) {
+                                expected = tokens.nextToken();
+                            }
+                        }
+                    }
+
+                    if (!expected.equals(result)) {
+                        throw new RuntimeException("Wrong currency symbol for locale " +
+                            locale + ", expected: " + expected + ", got: " + result);
+                    }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/CurrencySymbols.properties	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,134 @@
+ar=\u00A4
+ar_AE=\u062F.\u0625.\u200F
+ar_BH=\u062F.\u0628.\u200F
+ar_DZ=\u062F.\u062C.\u200F
+ar_EG=\u062C.\u0645.\u200F
+ar_IQ=\u062F.\u0639.\u200F
+ar_JO=\u062F.\u0623.\u200F
+ar_KW=\u062F.\u0643.\u200F
+ar_LB=\u0644.\u0644.\u200F
+ar_LY=\u062F.\u0644.\u200F
+ar_MA=\u062F.\u0645.\u200F
+ar_OM=\u0631.\u0639.\u200F
+ar_QA=\u0631.\u0642.\u200F
+ar_SA=\u0631.\u0633.\u200F
+# see bug 4412080
+# ar_SD=\u062C.\u0633.\u200F
+ar_SY=\u0644.\u0633.\u200F
+ar_TN=\u062F.\u062A.\u200F
+ar_YE=\u0631.\u064A.\u200F
+be=\u00A4
+# see bug 4412080
+# be_BY=\u0420\u0443\u0431
+bg=\u00A4
+# see bug 4412080
+# bg_BG=Lr
+ca=\u00A4
+ca_ES=\u20AC
+cs=\u00A4
+cs_CZ=K\u010D
+da=\u00A4
+da_DK=kr
+de=\u00A4
+de_AT=\u20AC
+de_CH=SFr.
+de_DE=\u20AC
+de_LU=\u20AC
+el=\u00A4
+el_GR=\u20AC
+en=\u00A4
+en_AU=$
+en_CA=$
+en_GB=\u00A3
+en_IE=\u20AC
+en_NZ=$
+en_US=$
+en_ZA=R
+es=\u00A4
+es_AR=$
+es_BO=B$
+es_CL=Ch$
+# 5102005
+es_CO=$
+es_CR=C
+es_CU=CU$
+es_DO=RD$
+# see bug 4412080
+# es_EC=S/
+es_ES=\u20AC
+es_GT=Q
+es_HN=L
+es_MX=$
+es_NI=$C
+es_PA=B
+es_PE=S/.
+es_PR=$
+es_PY=G
+es_SV=C
+es_UY=NU$
+es_VE=Bs.F.
+et=\u00A4
+et_EE=\u20AC
+fi=\u00A4
+fi_FI=\u20AC
+fr=\u00A4
+fr_BE=\u20AC
+fr_CA=$
+fr_CH=SFr.
+fr_FR=\u20AC
+fr_LU=\u20AC
+hi_IN=\u0930\u0942
+hr=\u00A4
+hr_HR=Kn
+hu=\u00A4
+hu_HU=Ft
+is=\u00A4
+is_IS=kr.
+it=\u00A4
+it_CH=SFr.
+it_IT=\u20AC
+iw=\u00A4
+iw_IL=\u05E9"\u05D7
+ja=\u00A4
+ja_JP=\uFFE5
+ko=\u00A4
+ko_KR=\uFFE6
+lt=\u00A4
+lt_LT=Lt;2014-12-31-22-00-00;\u20AC
+lv=\u00A4
+lv_LV=Ls;2013-12-31-22-00-00;\u20AC
+mk=\u00A4
+mk_MK=Den
+nl=\u00A4
+nl_BE=\u20AC
+nl_NL=\u20AC
+no=\u00A4
+no_NO=kr
+no_NO_NY=kr
+pl=\u00A4
+pl_PL=z\u0142
+pt=\u00A4
+pt_BR=R$
+pt_PT=\u20AC
+ro=\u00A4
+ro_RO=LEI
+ru=\u00A4
+ru_RU=\u0440\u0443\u0431.
+sk=\u00A4
+sk_SK=\u20AC
+sl=\u00A4
+sl_SI=\u20AC
+sq=\u00A4
+sq_AL=Lek
+sv=\u00A4
+sv_SE=kr
+th=\u00A4
+th_TH=\u0E3F
+tr=\u00A4
+tr_TR=TL
+uk=\u00A4
+uk_UA=\u0433\u0440\u043d.
+zh=\u00A4
+zh_CN=\uFFE5
+zh_HK=HK$
+zh_TW=NT$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DFSDeserialization142.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on older version JDK than 1.6 to test.
+ * It was tested using 1.4.2. The file object was created using JDK1.6.
+ */
+
+
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSDeserialization142{
+
+    public static void main(String[] args)
+    {
+        try {
+
+           File file = new File("DecimalFormatSymbols.current");
+           FileInputStream istream = new FileInputStream(file);
+           ObjectInputStream p = new ObjectInputStream(istream);
+           DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
+           if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+                System.out.println("Serialization/Deserialization Test Passed.");
+           }else{
+                throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol());
+           }
+           istream.close();
+       } catch (Exception e) {
+            e.printStackTrace();
+          }
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DFSExponential.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4068067
+ * @library /java/text/testlib
+ * @summary test NumberFormat with exponential separator symbols. It also tests the new
+ *          public methods in DecimalFormatSymbols, setExponentSeparator() and
+ *          getExponentSeparator()
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class DFSExponential extends IntlTest
+{
+
+    public static void main(String[] args) throws Exception {
+        new DFSExponential().run(args);
+    }
+
+
+   public void DFSExponenTest() throws Exception {
+        DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
+        String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]"  };
+        double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
+        long lval[] = { 0, -1, 1, 123456789 };
+        String valFormat[][] = {
+                {"1.234x10^-2", "1.2346x10^8", "1.23x10^300", "-3.1416x10^-271"},
+                {"12.340x10^-03", "12.346x10^07", "12.300x10^299", "-31.416x10^-272"},
+                {"12.34x10^-003", "123.4568x10^006", "1.23x10^300", "-314.1593x10^-273"},
+                {"1.234x10^-2", "1.235x10^8", "1.23x10^300", "[3.142x10^-271]"},
+        };
+
+
+        int ival = 0, ilval = 0;
+        logln("Default exponent separator: "+sym.getExponentSeparator());
+        try {
+            sym.setExponentSeparator("x10^");
+        } catch (NullPointerException e){
+            errln("null String was passed to set an exponent separator symbol");
+            throw new RuntimeException("Test Malfunction: null String was passed to set an exponent separator symbol" );
+        }
+        logln("Current exponent separator: "+sym.getExponentSeparator());
+
+        for (int p=0; p<pat.length; ++p){
+            DecimalFormat fmt = new DecimalFormat(pat[p], sym);
+            logln("     Pattern: " + fmt.toPattern());
+            String locPattern = fmt.toLocalizedPattern();
+            logln("     Localized pattern: "+locPattern);
+            //fmt.applyLocalizedPattern(locPattern);
+            //System.out.println("      fmt.applyLocalizedPattern(): "+fmt.toLocalizedPattern());
+
+            for (int v=0; v<val.length; ++v) {
+                String s = fmt.format(val[v]);
+                logln("         " + val[v]+" --> "+s);
+                if(valFormat[p][v].equals(s)){
+                    logln(": Passed");
+                }else{
+                   errln(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s);
+                   throw new RuntimeException(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s);
+                }
+           }
+         } //end of the first for loop
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4068067
+ * @library /java/text/testlib
+ * @build DFSSerialization IntlTest HexDumpReader
+ * @run main DFSSerialization
+ * @summary Three different tests are done. 1.read from the object created using jdk1.4.2  2.create a valid DecimalFormatSymbols object with current JDK, then read the object 3.Try to create an valid DecimalFormatSymbols object by passing null to set null for the exponent separator symbol. Expect the NullPointerException.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSSerialization extends IntlTest{
+    public static void main(String[] args) throws Exception {
+        new DFSSerialization().run(args);
+    }
+    public void TestDFSSerialization(){
+        /*
+         * 1. read from the object created using jdk1.4.2
+         */
+        File oldFile = new File(System.getProperty("test.src", "."), "DecimalFormatSymbols.142.txt");
+        DecimalFormatSymbols dfs142 = readTestObject(oldFile);
+        if (dfs142 != null){
+            if (dfs142.getExponentSeparator().equals("E") && dfs142.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+                System.out.println("\n  Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
+                logln(" Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
+            } else {
+                errln(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+                      +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
+                /*
+                 * logically should not throw this exception as errln throws exception
+                 * if not thrown yet - but in case errln got changed
+                 */
+                throw new RuntimeException(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+                                           +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
+            }
+        }
+        /*
+         * 2. create a valid DecimalFormatSymbols object with current JDK, then read the object
+         */
+        String validObject = "DecimalFormatSymbols.current";
+        File currentFile = createTestObject(validObject, "*SpecialExponentSeparator*");
+
+        DecimalFormatSymbols dfsValid = readTestObject(currentFile);
+        if (dfsValid != null){
+            if (dfsValid.getExponentSeparator().equals("*SpecialExponentSeparator*") &&
+                dfsValid.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+                System.out.println("  Deserialization of current JDK Object from the current JDK: Passed.");
+                logln(" Deserialization of current JDK Object from the current JDK: Passed.");
+            } else {
+                errln(" Deserialization of current JDK Object from the current JDK was Failed:"
+                      +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
+                /*
+                 * logically should not throw this exception as errln throws exception
+                 * if not thrown yet - but in case errln got changed
+                 */
+                throw new RuntimeException(" Deserialization of current Object from the current JDK was Failed:"
+                                           +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
+            }
+        }
+        /*
+         * 3. Try to create an valid DecimalFormatSymbols object by passing null
+         *    to set null for the exponent separator symbol. Expect the NullPointerException.
+         */
+        DecimalFormatSymbols symNPE = new DecimalFormatSymbols(Locale.US);
+        boolean npePassed = false;
+        try {
+            symNPE.setExponentSeparator(null);
+        } catch (NullPointerException npe){
+            npePassed = true;
+            System.out.println("  Trying to set exponent separator with null: Passed.");
+            logln(" Trying to set exponent separator with null: Passed.");
+        }
+        if (!npePassed){
+            System.out.println(" Trying to set exponent separator with null:Failed.");
+            errln("  Trying to set exponent separator with null:Failed.");
+            /*
+             * logically should not throw this exception as errln throws exception
+             * if not thrown yet - but in case errln got changed
+             */
+            throw new RuntimeException(" Trying to set exponent separator with null:Failed.");
+        }
+
+    }
+
+    private DecimalFormatSymbols readTestObject(File inputFile){
+        try (InputStream istream = inputFile.getName().endsWith(".txt") ?
+                                       HexDumpReader.getStreamFromHexDump(inputFile) :
+                                       new FileInputStream(inputFile)) {
+            ObjectInputStream p = new ObjectInputStream(istream);
+            DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
+            return dfs;
+        } catch (Exception e) {
+            errln("Test Malfunction in DFSSerialization: Exception while reading the object");
+            /*
+             * logically should not throw this exception as errln throws exception
+             * if not thrown yet - but in case errln got changed
+             */
+            throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
+        }
+    }
+
+    private File createTestObject(String objectName, String expString){
+        DecimalFormatSymbols dfs= new DecimalFormatSymbols();
+        dfs.setExponentSeparator(expString);
+        dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
+        logln(" The special exponent separator is set : "  + dfs.getExponentSeparator());
+        logln(" The special currency symbol is set : "  + dfs.getCurrencySymbol());
+
+        // 6345659: create a test object in the test.class dir where test user has a write permission.
+        File file = new File(System.getProperty("test.class", "."), objectName);
+        try (FileOutputStream ostream = new FileOutputStream(file)) {
+            ObjectOutputStream p = new ObjectOutputStream(ostream);
+            p.writeObject(dfs);
+            //System.out.println(" The special currency symbol is set : "  + dfs.getCurrencySymbol());
+            return file;
+        } catch (Exception e){
+            errln("Test Malfunction in DFSSerialization: Exception while creating an object");
+            /*
+             * logically should not throw this exception as errln throws exception
+             * if not thrown yet - but in case errln got changed
+             */
+            throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DFSSerialization142.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on JDK 1.4.2
+ * Instead, the resulting serialized file
+ * DecimalFormatSymbols.142 is archived.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSSerialization142 {
+
+    public static void main(String[] args)
+    {
+        try {
+
+            DecimalFormatSymbols dfs= new DecimalFormatSymbols();
+            System.out.println("Default currency symbol in the default locale : "  + dfs.getCurrencySymbol());
+            dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
+            System.out.println("The special currency symbol is set : "  + dfs.getCurrencySymbol());
+            FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142");
+            ObjectOutputStream p = new ObjectOutputStream(ostream);
+            p.writeObject(dfs);
+            ostream.close();
+            System.out.println("DecimalFormatSymbols saved ok.");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormat.114.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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.
+#
+
+# Hex dump of a serialized DecimalFormat for SerializationLoadTest.
+
+aced000573720012436865636b446563696d616c466f726d6174aa9218d3b530
+540a0200014c000a5f646563466f726d61747400194c6a6176612f746578742f
+446563696d616c466f726d61743b7870737200176a6176612e746578742e4465
+63696d616c466f726d61740bff0362d872303a0200085a001b646563696d616c
+536570617261746f72416c7761797353686f776e42000c67726f7570696e6753
+697a6549000a6d756c7469706c6965724c000e6e656761746976655072656669
+787400124c6a6176612f6c616e672f537472696e673b4c000e6e656761746976
+655375666669787400124c6a6176612f6c616e672f537472696e673b4c000e70
+6f7369746976655072656669787400124c6a6176612f6c616e672f537472696e
+673b4c000e706f7369746976655375666669787400124c6a6176612f6c616e67
+2f537472696e673b4c000773796d626f6c737400204c6a6176612f746578742f
+446563696d616c466f726d617453796d626f6c733b787200166a6176612e7465
+78742e4e756d626572466f726d6174dff6b3bf137d07e80200065a000c67726f
+7570696e67557365644200116d61784672616374696f6e446967697473420010
+6d6178496e74656765724469676974734200116d696e4672616374696f6e4469
+676974734200106d696e496e74656765724469676974735a0010706172736549
+6e74656765724f6e6c79787200106a6176612e746578742e466f726d6174fbd8
+bc12e90f1843020000787001037f0001000003000000017400012d7400007400
+007400007372001e6a6176612e746578742e446563696d616c466f726d617453
+796d626f6c73501d17990868939c02000c430010646563696d616c5365706172
+61746f72430005646967697443001167726f7570696e67536570617261746f72
+4300096d696e75735369676e4300107061747465726e536570617261746f7243
+00077065724d696c6c43000770657263656e744300097a65726f44696769744c
+00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e637572
+72656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e673b
+4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e673b
+4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c61
+6e672f537472696e673b7870002e0023002c002d003b203000250030740003ef
+bfbd74000124740003e2889e740003555344
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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.
+#
+
+# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest.
+
+aced000573720019436865636b446563696d616c466f726d617453796d626f6c
+737763237e1aa359bb0200014c00115f646563466f726d617453796d626f6c73
+7400204c6a6176612f746578742f446563696d616c466f726d617453796d626f
+6c733b78707372001e6a6176612e746578742e446563696d616c466f726d6174
+53796d626f6c73501d17990868939c02000c430010646563696d616c53657061
+7261746f72430005646967697443001167726f7570696e67536570617261746f
+724300096d696e75735369676e4300107061747465726e536570617261746f72
+4300077065724d696c6c43000770657263656e744300097a65726f4469676974
+4c00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e6375
+7272656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e67
+3b4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e67
+3b4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c
+616e672f537472696e673b7870002e0023002c002d003b203000250030740003
+efbfbd74000124740003e2889e740003555344
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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.
+#
+
+# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest.
+
+aced00057372001e6a6176612e746578742e446563696d616c466f726d617453
+796d626f6c73501d17990868939c020010430010646563696d616c5365706172
+61746f72430005646967697443000b6578706f6e656e7469616c43001167726f
+7570696e67536570617261746f724300096d696e75735369676e4300116d6f6e
+6574617279536570617261746f724300107061747465726e536570617261746f
+724300077065724d696c6c43000770657263656e7449001573657269616c5665
+7273696f6e4f6e53747265616d4300097a65726f44696769744c00034e614e74
+00124c6a6176612f6c616e672f537472696e673b4c000e63757272656e637953
+796d626f6c71007e00014c0008696e66696e69747971007e00014c0012696e74
+6c43757272656e637953796d626f6c71007e00014c00066c6f63616c65740012
+4c6a6176612f7574696c2f4c6f63616c653b7870002e00230045002c002d002e
+003b20300025000000020030740003efbfbd7400172a5370656369616c437572
+72656e637953796d626f6c2a740003e2889e740003434e59737200106a617661
+2e7574696c2e4c6f63616c657ef811609c30f9ec03000449000868617368636f
+64654c0007636f756e74727971007e00014c00086c616e677561676571007e00
+014c000776617269616e7471007e00017870ffffffff740002434e7400027a68
+74000078
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test International Decimal Format API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDecimalFormatAPI extends IntlTest
+{
+    public static void main(String[] args)  throws Exception {
+        new IntlTestDecimalFormatAPI().run(args);
+    }
+
+    // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+    public void TestAPI()
+    {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            logln("DecimalFormat API test---"); logln("");
+            Locale.setDefault(Locale.ENGLISH);
+
+            // ======= Test constructors
+
+            logln("Testing DecimalFormat constructors");
+
+            DecimalFormat def = new DecimalFormat();
+
+            final String pattern = new String("#,##0.# FF");
+            DecimalFormat pat = null;
+            try {
+                pat = new DecimalFormat(pattern);
+            }
+            catch (IllegalArgumentException e) {
+                errln("ERROR: Could not create DecimalFormat (pattern)");
+            }
+
+            DecimalFormatSymbols symbols =
+                    new DecimalFormatSymbols(Locale.FRENCH);
+
+            DecimalFormat cust1 = new DecimalFormat(pattern, symbols);
+
+            // ======= Test clone(), assignment, and equality
+
+            logln("Testing clone() and equality operators");
+
+            Format clone = (Format) def.clone();
+            if( ! def.equals(clone)) {
+                errln("ERROR: Clone() failed");
+            }
+
+            // ======= Test various format() methods
+
+            logln("Testing various format() methods");
+
+//          final double d = -10456.0037; // this appears as
+                                          // -10456.003700000001 on NT
+//          final double d = -1.04560037e-4; // this appears as
+                                             // -1.0456003700000002E-4 on NT
+            final double d = -10456.00370000000000; // this works!
+            final long l = 100000000;
+            logln("" + d + " is the double value");
+
+            StringBuffer res1 = new StringBuffer();
+            StringBuffer res2 = new StringBuffer();
+            StringBuffer res3 = new StringBuffer();
+            StringBuffer res4 = new StringBuffer();
+            FieldPosition pos1 = new FieldPosition(0);
+            FieldPosition pos2 = new FieldPosition(0);
+            FieldPosition pos3 = new FieldPosition(0);
+            FieldPosition pos4 = new FieldPosition(0);
+
+            res1 = def.format(d, res1, pos1);
+            logln("" + d + " formatted to " + res1);
+
+            res2 = pat.format(l, res2, pos2);
+            logln("" + l + " formatted to " + res2);
+
+            res3 = cust1.format(d, res3, pos3);
+            logln("" + d + " formatted to " + res3);
+
+            res4 = cust1.format(l, res4, pos4);
+            logln("" + l + " formatted to " + res4);
+
+            // ======= Test parse()
+
+            logln("Testing parse()");
+
+            String text = new String("-10,456.0037");
+            ParsePosition pos = new ParsePosition(0);
+            String patt = new String("#,##0.#");
+            pat.applyPattern(patt);
+            double d2 = pat.parse(text, pos).doubleValue();
+            if(d2 != d) {
+                errln("ERROR: Roundtrip failed (via parse(" +
+                    d2 + " != " + d + ")) for " + text);
+            }
+            logln(text + " parsed into " + (long) d2);
+
+            // ======= Test getters and setters
+
+            logln("Testing getters and setters");
+
+            final DecimalFormatSymbols syms = pat.getDecimalFormatSymbols();
+            def.setDecimalFormatSymbols(syms);
+            if(!pat.getDecimalFormatSymbols().equals(
+                    def.getDecimalFormatSymbols())) {
+                errln("ERROR: set DecimalFormatSymbols() failed");
+            }
+
+            String posPrefix;
+            pat.setPositivePrefix("+");
+            posPrefix = pat.getPositivePrefix();
+            logln("Positive prefix (should be +): " + posPrefix);
+            if(posPrefix != "+") {
+                errln("ERROR: setPositivePrefix() failed");
+            }
+
+            String negPrefix;
+            pat.setNegativePrefix("-");
+            negPrefix = pat.getNegativePrefix();
+            logln("Negative prefix (should be -): " + negPrefix);
+            if(negPrefix != "-") {
+                errln("ERROR: setNegativePrefix() failed");
+            }
+
+            String posSuffix;
+            pat.setPositiveSuffix("_");
+            posSuffix = pat.getPositiveSuffix();
+            logln("Positive suffix (should be _): " + posSuffix);
+            if(posSuffix != "_") {
+                errln("ERROR: setPositiveSuffix() failed");
+            }
+
+            String negSuffix;
+            pat.setNegativeSuffix("~");
+            negSuffix = pat.getNegativeSuffix();
+            logln("Negative suffix (should be ~): " + negSuffix);
+            if(negSuffix != "~") {
+                errln("ERROR: setNegativeSuffix() failed");
+            }
+
+            long multiplier = 0;
+            pat.setMultiplier(8);
+            multiplier = pat.getMultiplier();
+            logln("Multiplier (should be 8): " + multiplier);
+            if(multiplier != 8) {
+                errln("ERROR: setMultiplier() failed");
+            }
+
+            int groupingSize = 0;
+            pat.setGroupingSize(2);
+            groupingSize = pat.getGroupingSize();
+            logln("Grouping size (should be 2): " + (long) groupingSize);
+            if(groupingSize != 2) {
+                errln("ERROR: setGroupingSize() failed");
+            }
+
+            pat.setDecimalSeparatorAlwaysShown(true);
+            boolean tf = pat.isDecimalSeparatorAlwaysShown();
+            logln("DecimalSeparatorIsAlwaysShown (should be true) is " +
+                                                (tf ? "true" : "false"));
+            if(tf != true) {
+                errln("ERROR: setDecimalSeparatorAlwaysShown() failed");
+            }
+
+            String funkyPat;
+            funkyPat = pat.toPattern();
+            logln("Pattern is " + funkyPat);
+
+            String locPat;
+            locPat = pat.toLocalizedPattern();
+            logln("Localized pattern is " + locPat);
+
+            // ======= Test applyPattern()
+
+            logln("Testing applyPattern()");
+
+            String p1 = new String("#,##0.0#;(#,##0.0#)");
+            logln("Applying pattern " + p1);
+            pat.applyPattern(p1);
+            String s2;
+            s2 = pat.toPattern();
+            logln("Extracted pattern is " + s2);
+            if( ! s2.equals(p1) ) {
+                errln("ERROR: toPattern() result did not match " +
+                        "pattern applied");
+            }
+
+            String p2 = new String("#,##0.0# FF;(#,##0.0# FF)");
+            logln("Applying pattern " + p2);
+            pat.applyLocalizedPattern(p2);
+            String s3;
+            s3 = pat.toLocalizedPattern();
+            logln("Extracted pattern is " + s3);
+            if( ! s3.equals(p2) ) {
+                errln("ERROR: toLocalizedPattern() result did not match " +
+                        "pattern applied");
+            }
+
+            // ======= Test getStaticClassID()
+
+//          logln("Testing instanceof()");
+
+//          try {
+//             NumberFormat test = new DecimalFormat();
+
+//              if (! (test instanceof DecimalFormat)) {
+//                  errln("ERROR: instanceof failed");
+//              }
+//          }
+//          catch (Exception e) {
+//              errln("ERROR: Couldn't create a DecimalFormat");
+//          }
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test International Decimal Format Symbols
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDecimalFormatSymbols extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        new IntlTestDecimalFormatSymbols().run(args);
+    }
+
+    // Test the API of DecimalFormatSymbols; primarily a simple get/set set.
+    public void TestSymbols()
+    {
+        DecimalFormatSymbols fr = new DecimalFormatSymbols(Locale.FRENCH);
+
+        DecimalFormatSymbols en = new DecimalFormatSymbols(Locale.ENGLISH);
+
+        if(en.equals(fr)) {
+            errln("ERROR: English DecimalFormatSymbols equal to French");
+        }
+
+        // just do some VERY basic tests to make sure that get/set work
+
+        char zero = en.getZeroDigit();
+        fr.setZeroDigit(zero);
+        if(fr.getZeroDigit() != en.getZeroDigit()) {
+            errln("ERROR: get/set ZeroDigit failed");
+        }
+
+        char group = en.getGroupingSeparator();
+        fr.setGroupingSeparator(group);
+        if(fr.getGroupingSeparator() != en.getGroupingSeparator()) {
+            errln("ERROR: get/set GroupingSeparator failed");
+        }
+
+        char decimal = en.getDecimalSeparator();
+        fr.setDecimalSeparator(decimal);
+        if(fr.getDecimalSeparator() != en.getDecimalSeparator()) {
+            errln("ERROR: get/set DecimalSeparator failed");
+        }
+
+        char perMill = en.getPerMill();
+        fr.setPerMill(perMill);
+        if(fr.getPerMill() != en.getPerMill()) {
+            errln("ERROR: get/set PerMill failed");
+        }
+
+        char percent = en.getPercent();
+        fr.setPercent(percent);
+        if(fr.getPercent() != en.getPercent()) {
+            errln("ERROR: get/set Percent failed");
+        }
+
+        char digit = en.getDigit();
+        fr.setDigit(digit);
+        if(fr.getPercent() != en.getPercent()) {
+            errln("ERROR: get/set Percent failed");
+        }
+
+        char patternSeparator = en.getPatternSeparator();
+        fr.setPatternSeparator(patternSeparator);
+        if(fr.getPatternSeparator() != en.getPatternSeparator()) {
+            errln("ERROR: get/set PatternSeparator failed");
+        }
+
+        String infinity = en.getInfinity();
+        fr.setInfinity(infinity);
+        String infinity2 = fr.getInfinity();
+        if(! infinity.equals(infinity2)) {
+            errln("ERROR: get/set Infinity failed");
+        }
+
+        String nan = en.getNaN();
+        fr.setNaN(nan);
+        String nan2 = fr.getNaN();
+        if(! nan.equals(nan2)) {
+            errln("ERROR: get/set NaN failed");
+        }
+
+        char minusSign = en.getMinusSign();
+        fr.setMinusSign(minusSign);
+        if(fr.getMinusSign() != en.getMinusSign()) {
+            errln("ERROR: get/set MinusSign failed");
+        }
+
+//        char exponential = en.getExponentialSymbol();
+//        fr.setExponentialSymbol(exponential);
+//        if(fr.getExponentialSymbol() != en.getExponentialSymbol()) {
+//            errln("ERROR: get/set Exponential failed");
+//        }
+
+        DecimalFormatSymbols foo = new DecimalFormatSymbols();
+
+        en = (DecimalFormatSymbols) fr.clone();
+
+        if(! en.equals(fr)) {
+            errln("ERROR: Clone failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test International Number Format API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestNumberFormatAPI extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        new IntlTestNumberFormatAPI().run(args);
+    }
+
+    // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+    public void TestAPI()
+    {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            logln("NumberFormat API test---"); logln("");
+            Locale.setDefault(Locale.ENGLISH);
+
+            // ======= Test constructors
+
+            logln("Testing NumberFormat constructors");
+
+            NumberFormat def = NumberFormat.getInstance();
+
+            NumberFormat fr = NumberFormat.getInstance(Locale.FRENCH);
+
+            NumberFormat cur = NumberFormat.getCurrencyInstance();
+
+            NumberFormat cur_fr =
+                    NumberFormat.getCurrencyInstance(Locale.FRENCH);
+
+            NumberFormat per = NumberFormat.getPercentInstance();
+
+            NumberFormat per_fr =
+                    NumberFormat.getPercentInstance(Locale.FRENCH);
+
+            // ======= Test equality
+
+            logln("Testing equality operator");
+
+            if( per_fr.equals(cur_fr) ) {
+                errln("ERROR: == failed");
+            }
+
+            // ======= Test various format() methods
+
+            logln("Testing various format() methods");
+
+//          final double d = -10456.0037; // this appears as
+                                          // -10456.003700000001 on NT
+//          final double d = -1.04560037e-4; // this appears as
+                                             // -1.0456003700000002E-4 on NT
+            final double d = -10456.00370000000000; // this works!
+            final long l = 100000000;
+
+            String res1 = new String();
+            String res2 = new String();
+            StringBuffer res3 = new StringBuffer();
+            StringBuffer res4 = new StringBuffer();
+            StringBuffer res5 = new StringBuffer();
+            StringBuffer res6 = new StringBuffer();
+            FieldPosition pos1 = new FieldPosition(0);
+            FieldPosition pos2 = new FieldPosition(0);
+            FieldPosition pos3 = new FieldPosition(0);
+            FieldPosition pos4 = new FieldPosition(0);
+
+            res1 = cur_fr.format(d);
+            logln( "" + d + " formatted to " + res1);
+
+            res2 = cur_fr.format(l);
+            logln("" + l + " formatted to " + res2);
+
+            res3 = cur_fr.format(d, res3, pos1);
+            logln( "" + d + " formatted to " + res3);
+
+            res4 = cur_fr.format(l, res4, pos2);
+            logln("" + l + " formatted to " + res4);
+
+            res5 = cur_fr.format(d, res5, pos3);
+            logln("" + d + " formatted to " + res5);
+
+            res6 = cur_fr.format(l, res6, pos4);
+            logln("" + l + " formatted to " + res6);
+
+
+            // ======= Test parse()
+
+            logln("Testing parse()");
+
+//          String text = new String("-10,456.0037");
+            String text = new String("-10456,0037");
+            ParsePosition pos = new ParsePosition(0);
+            ParsePosition pos01 = new ParsePosition(0);
+            double d1 = ((Number)fr.parseObject(text, pos)).doubleValue();
+            if(d1 != d) {
+                errln("ERROR: Roundtrip failed (via parse()) for " + text);
+            }
+            logln(text + " parsed into " + d1);
+
+            double d2 = fr.parse(text, pos01).doubleValue();
+            if(d2 != d) {
+                errln("ERROR: Roundtrip failed (via parse()) for " + text);
+            }
+            logln(text + " parsed into " + d2);
+
+            double d3 = 0;
+            try {
+                d3 = fr.parse(text).doubleValue();
+            }
+            catch (ParseException e) {
+                errln("ERROR: parse() failed");
+            }
+            if(d3 != d) {
+                errln("ERROR: Roundtrip failed (via parse()) for " + text);
+            }
+            logln(text + " parsed into " + d3);
+
+
+            // ======= Test getters and setters
+
+            logln("Testing getters and setters");
+
+            final Locale[] locales = NumberFormat.getAvailableLocales();
+            long count = locales.length;
+            logln("Got " + count + " locales" );
+            for(int i = 0; i < count; i++) {
+                String name;
+                name = locales[i].getDisplayName();
+                logln(name);
+            }
+
+            fr.setParseIntegerOnly( def.isParseIntegerOnly() );
+            if(fr.isParseIntegerOnly() != def.isParseIntegerOnly() ) {
+                    errln("ERROR: setParseIntegerOnly() failed");
+            }
+
+            fr.setGroupingUsed( def.isGroupingUsed() );
+            if(fr.isGroupingUsed() != def.isGroupingUsed() ) {
+                    errln("ERROR: setGroupingUsed() failed");
+            }
+
+            fr.setMaximumIntegerDigits( def.getMaximumIntegerDigits() );
+            if(fr.getMaximumIntegerDigits() != def.getMaximumIntegerDigits() ) {
+                    errln("ERROR: setMaximumIntegerDigits() failed");
+            }
+
+            fr.setMinimumIntegerDigits( def.getMinimumIntegerDigits() );
+            if(fr.getMinimumIntegerDigits() != def.getMinimumIntegerDigits() ) {
+                    errln("ERROR: setMinimumIntegerDigits() failed");
+            }
+
+            fr.setMaximumFractionDigits( def.getMaximumFractionDigits() );
+            if(fr.getMaximumFractionDigits() != def.getMaximumFractionDigits() ) {
+                    errln("ERROR: setMaximumFractionDigits() failed");
+            }
+
+            fr.setMinimumFractionDigits( def.getMinimumFractionDigits() );
+            if(fr.getMinimumFractionDigits() != def.getMinimumFractionDigits() ) {
+                    errln("ERROR: setMinimumFractionDigits() failed");
+            }
+
+            // ======= Test getStaticClassID()
+
+//          logln("Testing instanceof()");
+
+//          try {
+//              NumberFormat test = new DecimalFormat();
+
+//              if (! (test instanceof DecimalFormat)) {
+//                  errln("ERROR: instanceof failed");
+//              }
+//          }
+//          catch (Exception e) {
+//              errln("ERROR: Couldn't create a DecimalFormat");
+//          }
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a serialized NumberFormat for NumberRegression.
+
+aced0005737200176a6176612e746578742e446563696d616c466f726d61740b
+ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77
+61797353686f776e42000c67726f7570696e6753697a654200116d696e457870
+6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961
+6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961
+6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61
+76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978
+71007e00014c000e706f73697469766550726566697871007e00014c000e706f
+73697469766553756666697871007e00014c000773796d626f6c737400204c6a
+6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872
+00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8
+03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e
+4469676974734200106d6178496e74656765724469676974734900156d617869
+6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567
+65724469676974734200116d696e4672616374696f6e4469676974734200106d
+696e496e74656765724469676974734900156d696e696d756d4672616374696f
+6e4469676974734900146d696e696d756d496e74656765724469676974735a00
+107061727365496e74656765724f6e6c7949001573657269616c56657273696f
+6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f18430200007870017f7f00000123000001217f7f000001240000012200
+00000001780003000000000100000001007400012d7400007400007400007372
+001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73
+501d17990868939c02000f430010646563696d616c536570617261746f724300
+05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753
+6570617261746f724300096d696e75735369676e4300116d6f6e657461727953
+6570617261746f724300107061747465726e536570617261746f724300077065
+724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f
+6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00
+0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971
+007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870
+002e00230045002c002d002e003b20300025000000010030740003efbfbd7400
+0124740003e2889e740003555344
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+# 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.
+#
+
+# Hex dump of a serialized NumberFormat for NumberRegression.
+
+aced0005737200176a6176612e746578742e446563696d616c466f726d61740b
+ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77
+61797353686f776e42000c67726f7570696e6753697a654200116d696e457870
+6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961
+6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961
+6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61
+76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978
+71007e00014c000e706f73697469766550726566697871007e00014c000e706f
+73697469766553756666697871007e00014c000773796d626f6c737400204c6a
+6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872
+00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8
+03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e
+4469676974734200106d6178496e74656765724469676974734900156d617869
+6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567
+65724469676974734200116d696e4672616374696f6e4469676974734200106d
+696e496e74656765724469676974734900156d696e696d756d4672616374696f
+6e4469676974734900146d696e696d756d496e74656765724469676974735a00
+107061727365496e74656765724f6e6c7949001573657269616c56657273696f
+6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f18430200007870017f7f00000314000003127f7f000003130000031100
+00000001780003000000000100000001007400012d7400007400007400007372
+001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73
+501d17990868939c02000f430010646563696d616c536570617261746f724300
+05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753
+6570617261746f724300096d696e75735369676e4300116d6f6e657461727953
+6570617261746f724300107061747465726e536570617261746f724300077065
+724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f
+6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00
+0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971
+007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870
+002e00230045002c002d002e003b20300025000000010030740003efbfbd7400
+0124740003e2889e740003555344
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberFormatRounding.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4092330 6246348
+ * @summary Tests for rounding mode in NumberFormat
+ */
+
+import java.math.*;
+import java.text.*;
+
+public class NumberFormatRounding {
+
+    static final String AE = "ArithmeticException";
+
+    static final double src[] = {5.5, 2.5, 1.6, 1.1, 1.0, -1.0, -1.1, -1.6, -2.5, -5.5,
+                                 5.501, -5.501, 5.500, -5.500, 1.001, -1.001, 4.501, -4.501, 4.500, -4.500};
+    static final String up[] = {"6", "3", "2", "2", "1", "-1", "-2", "-2", "-3", "-6",
+                                "6", "-6", "6", "-6", "2", "-2", "5", "-5", "5", "-5"};
+    static final String down[] = {"5", "2", "1", "1", "1", "-1", "-1", "-1", "-2", "-5",
+                                  "5", "-5", "5", "-5", "1", "-1", "4", "-4", "4", "-4"};
+    static final String ceiling[] = {"6", "3", "2", "2", "1", "-1", "-1", "-1", "-2", "-5",
+                                     "6", "-5", "6", "-5", "2", "-1", "5", "-4", "5", "-4"};
+    static final String floor[] = {"5", "2", "1", "1", "1", "-1", "-2", "-2", "-3", "-6",
+                                   "5", "-6", "5", "-6", "1", "-2", "4", "-5", "4", "-5"};
+    static final String half_up[] = {"6", "3", "2", "1", "1", "-1", "-1", "-2", "-3", "-6",
+                                     "6", "-6", "6", "-6", "1", "-1", "5", "-5", "5", "-5"};
+    static final String half_down[] = {"5", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-5",
+                                       "6", "-6", "5", "-5", "1", "-1", "5", "-5", "4", "-4"};
+    static final String half_even[] = {"6", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-6",
+                                       "6", "-6", "6", "-6", "1", "-1", "5", "-5", "4", "-4"};
+    static final String unnecessary[] = {AE, AE, AE, AE, "1", "-1", AE, AE, AE, AE,
+                                         AE, AE, AE, AE, AE, AE, AE, AE, AE, AE};
+
+    public static void main(String[] args) {
+        basicTest();
+
+        roundTest(RoundingMode.UP, up);
+        roundTest(RoundingMode.DOWN, down);
+        roundTest(RoundingMode.CEILING, ceiling);
+        roundTest(RoundingMode.FLOOR, floor);
+        roundTest(RoundingMode.HALF_UP, half_up);
+        roundTest(RoundingMode.HALF_DOWN, half_down);
+        roundTest(RoundingMode.HALF_EVEN, half_even);
+        roundTest(RoundingMode.UNNECESSARY, unnecessary);
+    }
+
+    static void basicTest() {
+        NumberFormat nf = NumberFormat.getIntegerInstance();
+
+        if (nf.getRoundingMode() != RoundingMode.HALF_EVEN) {
+            throw new RuntimeException("default rounding is not HALF_EVEN");
+        }
+
+        try {
+            nf.setRoundingMode(null);
+            throw new RuntimeException(
+                "NullPointerException is not thrown by calling setRoundingMode(null)");
+        } catch (NullPointerException npe) {
+            // continue testing
+        }
+
+        ChoiceFormat cf = new ChoiceFormat("");
+
+        try {
+            cf.setRoundingMode(RoundingMode.HALF_EVEN);
+            throw new RuntimeException(
+                "UnsupportedOperationException is not thrown by calling setRoundingMode()");
+        } catch (UnsupportedOperationException uoe) {
+            // continue testing
+        }
+
+        try {
+            cf.getRoundingMode();
+            throw new RuntimeException(
+                "UnsupportedOperationException is not thrown by calling getRoundingMode()");
+        } catch (UnsupportedOperationException uoe) {
+            // continue testing
+        }
+    }
+
+    static void roundTest(RoundingMode rm, String[] expected) {
+        NumberFormat nf = NumberFormat.getIntegerInstance();
+        nf.setRoundingMode(rm);
+
+        if (nf.getRoundingMode() != rm) {
+            throw new RuntimeException("set rounding mode is not returned by get method");
+        }
+
+        for (int i = 0; i < src.length; i ++) {
+            String result = null;
+            try {
+                result = nf.parse(nf.format(src[i])).toString();
+                if (!result.equals(expected[i])) {
+                    throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result);
+                }
+            } catch (ArithmeticException ae) {
+                if (expected[i].equals(AE)) {
+                    continue;
+                } else {
+                    result = AE;
+                    throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result);
+                }
+            } catch (ParseException pe) {
+                throw new RuntimeException("ParseException ocurred.", pe);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1824 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014
+ * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245
+ * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713
+ * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840
+ * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
+ * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
+ * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577
+ * @summary Regression tests for NumberFormat and associated classes
+ * @library /java/text/testlib
+ * @build IntlTest HexDumpReader
+ * @modules java.base/sun.util.resources
+ * @compile -XDignore.symbol.file NumberRegression.java
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression
+ */
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.text.*;
+import java.util.*;
+import java.math.BigDecimal;
+import java.io.*;
+import java.math.BigInteger;
+import sun.util.resources.LocaleData;
+
+public class NumberRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new NumberRegression().run(args);
+    }
+
+    /**
+     * NumberFormat.equals comparing with null should always return false.
+     */
+    public void Test4075713(){
+
+        try {
+            MyNumberFormatTest tmp = new MyNumberFormatTest();
+            if (!tmp.equals(null))
+                logln("NumberFormat.equals passed");
+        } catch (NullPointerException e) {
+            errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
+        }
+    }
+
+    /**
+     * NumberFormat.equals comparing two obj equal even the setGroupingUsed
+     * flag is different.
+     */
+    public void Test4074620() {
+
+        MyNumberFormatTest nf1 = new MyNumberFormatTest();
+        MyNumberFormatTest nf2 = new MyNumberFormatTest();
+
+        nf1.setGroupingUsed(false);
+        nf2.setGroupingUsed(true);
+
+        if (nf1.equals(nf2)) errln("Test for bug 4074620 failed");
+        else logln("Test for bug 4074620 passed.");
+        return;
+    }
+
+
+    /**
+     * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
+     */
+
+    public void Test4088161 (){
+        DecimalFormat df = new DecimalFormat();
+        double d = 100;
+        df.setMinimumFractionDigits(0);
+        df.setMaximumFractionDigits(16);
+        StringBuffer sBuf1 = new StringBuffer("");
+        FieldPosition fp1 = new FieldPosition(0);
+        logln("d = " + d);
+        logln("maxFractionDigits = " + df.getMaximumFractionDigits());
+        logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'");
+        df.setMaximumFractionDigits(17);
+        StringBuffer sBuf2 = new StringBuffer("");
+        FieldPosition fp2 = new FieldPosition(0);
+        logln("maxFractionDigits = " + df.getMaximumFractionDigits());
+        df.format(d, sBuf2, fp2);
+        String expected = Locale.getDefault().equals(new Locale("hi", "IN")) ?
+                              "\u0967\u0966\u0966" : "100";
+        if (!sBuf2.toString().equals(expected))
+            errln(" format(d) = '" + sBuf2 + "'");
+    }
+    /**
+     * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
+     * DecimalFormat(String, DecimalFormatSymbols).
+     */
+    public void Test4087245 (){
+        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
+        DecimalFormat df = new DecimalFormat("#,##0.0", symbols);
+        long n = 123;
+        StringBuffer buf1 = new StringBuffer();
+        StringBuffer buf2 = new StringBuffer();
+        logln("format(" + n + ") = " +
+        df.format(n, buf1, new FieldPosition(0)));
+        symbols.setDecimalSeparator('p'); // change value of field
+        logln("format(" + n + ") = " +
+        df.format(n, buf2, new FieldPosition(0)));
+        if (!buf1.toString().equals(buf2.toString()))
+            errln("Test for bug 4087245 failed");
+    }
+    /**
+     * DecimalFormat.format() incorrectly formats 0.0
+     */
+    public void Test4087535 ()
+    {
+        DecimalFormat df = new DecimalFormat();
+        df.setMinimumIntegerDigits(0);
+
+        double n = 0;
+        String buffer = new String();
+        buffer = df.format(n);
+        if (buffer.length() == 0)
+            errln(n + ": '" + buffer + "'");
+        n = 0.1;
+        buffer = df.format(n);
+        if (buffer.length() == 0)
+            errln(n + ": '" + buffer + "'");
+    }
+
+    /**
+     * DecimalFormat.format fails when groupingSize is set to 0.
+     */
+    public void Test4088503 (){
+        DecimalFormat df = new DecimalFormat();
+        df.setGroupingSize(0);
+        StringBuffer sBuf = new StringBuffer("");
+        FieldPosition fp = new FieldPosition(0);
+        try {
+            logln(df.format(123, sBuf, fp).toString());
+        } catch (Exception foo) {
+            errln("Test for bug 4088503 failed.");
+        }
+
+    }
+    /**
+     * NumberFormat.getCurrencyInstance is wrong.
+     */
+    public void Test4066646 () {
+        float returnfloat = 0.0f;
+        assignFloatValue(2.04f);
+        assignFloatValue(2.03f);
+        assignFloatValue(2.02f);
+        assignFloatValue(0.0f);
+    }
+
+    public float assignFloatValue(float returnfloat)
+    {
+        logln(" VALUE " + returnfloat);
+        NumberFormat nfcommon =  NumberFormat.getCurrencyInstance(Locale.US);
+        nfcommon.setGroupingUsed(false);
+
+        String stringValue = nfcommon.format(returnfloat).substring(1);
+        if (Float.valueOf(stringValue).floatValue() != returnfloat)
+            errln(" DISPLAYVALUE " + stringValue);
+        return returnfloat;
+    } // End Of assignFloatValue()
+
+    /**
+     * DecimalFormat throws exception when parsing "0"
+     */
+    public void Test4059870() {
+        DecimalFormat format = new DecimalFormat("00");
+        try {
+            logln(format.parse("0").toString());
+        } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); }
+    }
+    /**
+     * DecimalFormatSymbol.equals should always return false when
+     * comparing with null.
+     */
+
+    public void Test4083018 (){
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
+        try {
+            if (!dfs.equals(null))
+                logln("Test Passed!");
+        } catch (Exception foo) {
+            errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
+        }
+    }
+    /**
+     * DecimalFormat does not round up correctly.
+     */
+    public void Test4071492 (){
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        double x = 0.00159999;
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumFractionDigits(4);
+        String out = nf.format(x);
+        logln("0.00159999 formats with 4 fractional digits to " + out);
+        String expected = "0.0016";
+        if (!out.equals(expected))
+            errln("FAIL: Expected " + expected);
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * A space as a group separator for localized pattern causes
+     * wrong format.  WorkAround : use non-breaking space.
+     */
+    public void Test4086575() {
+
+        NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
+        logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern());
+        logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern());
+
+        // No group separator
+        logln("...applyLocalizedPattern ###,00;(###,00) ");
+        ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)");
+        logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
+        logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
+
+        logln("nf: " + nf.format(1234)); // 1234,00
+        logln("nf: " + nf.format(-1234)); // (1234,00)
+
+        // Space as group separator
+
+        logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
+        ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
+        logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
+        logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
+        String buffer = nf.format(1234);
+        if (!buffer.equals("1\u00a0234,00"))
+            errln("nf : " + buffer); // Expect 1 234,00
+        buffer = nf.format(-1234);
+        if (!buffer.equals("(1\u00a0234,00)"))
+            errln("nf : " + buffer); // Expect (1 234,00)
+
+        // Erroneously prints:
+        // 1234,00 ,
+        // (1234,00 ,)
+
+    }
+    /**
+     * DecimalFormat.parse returns wrong value
+     */
+    public void Test4068693()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        logln("----- Test Application -----");
+        ParsePosition pos;
+        DecimalFormat df = new DecimalFormat();
+        Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
+        if (!d.toString().equals("123.55456")) {
+            errln("Result -> " + d.doubleValue());
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /* bugs 4069754, 4067878
+     * null pointer thrown when accessing a deserialized DecimalFormat
+     * object.
+     */
+    public void Test4069754()
+    {
+        try {
+            myformat it = new myformat();
+            logln(it.Now());
+            FileOutputStream ostream = new FileOutputStream("t.tmp");
+            ObjectOutputStream p = new ObjectOutputStream(ostream);
+            p.writeObject(it);
+            ostream.close();
+            logln("Saved ok.");
+
+            FileInputStream istream = new FileInputStream("t.tmp");
+            ObjectInputStream p2 = new ObjectInputStream(istream);
+            myformat it2 = (myformat)p2.readObject();
+            logln(it2.Now());
+            istream.close();
+            logln("Loaded ok.");
+        } catch (Exception foo) {
+            errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
+        }
+    }
+
+    /**
+     * DecimalFormat.applyPattern(String) allows illegal patterns
+     */
+    public void Test4087251 (){
+        DecimalFormat df = new DecimalFormat();
+        try {
+            df.applyPattern("#.#.#");
+            logln("toPattern() returns \"" + df.toPattern() + "\"");
+            errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            logln("Caught Illegal Argument Error !");
+        }
+        // Second test; added 5/11/98 when reported to fail on 1.2b3
+        try {
+            df.applyPattern("#0.0#0#0");
+            logln("toPattern() returns \"" + df.toPattern() + "\"");
+            errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            logln("Ok - IllegalArgumentException for #0.0#0#0");
+        }
+    }
+
+    /**
+     * DecimalFormat.format() loses precision
+     */
+    public void Test4090489 (){
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat();
+        df.setMinimumFractionDigits(10);
+        df.setGroupingUsed(false);
+        double d = 1.000000000000001E7;
+        BigDecimal bd = new BigDecimal(d);
+        StringBuffer sb = new StringBuffer("");
+        FieldPosition fp = new FieldPosition(0);
+        logln("d = " + d);
+        logln("BigDecimal.toString():  " + bd.toString());
+        df.format(d, sb, fp);
+        if (!sb.toString().equals("10000000.0000000100")) {
+            errln("DecimalFormat.format(): " + sb.toString());
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * DecimalFormat.format() loses precision
+     */
+    public void Test4090504 ()
+    {
+        double d = 1;
+        logln("d = " + d);
+        DecimalFormat df = new DecimalFormat();
+        StringBuffer sb;
+        FieldPosition fp;
+        try {
+            for (int i = 17; i <= 20; i++) {
+                df.setMaximumFractionDigits(i);
+                sb = new StringBuffer("");
+                fp = new FieldPosition(0);
+                logln("  getMaximumFractionDigits() = " + i);
+                logln("  formated: " + df.format(d, sb, fp));
+            }
+        } catch (Exception foo) {
+            errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
+        }
+    }
+    /**
+     * DecimalFormat.parse(String str, ParsePosition pp) loses precision
+     */
+    public void Test4095713 ()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat();
+        String str = "0.1234";
+        Double d1 = new Double(str);
+        Double d2 = (Double) df.parse(str, new ParsePosition(0));
+        logln(d1.toString());
+        if (d2.doubleValue() != d1.doubleValue())
+            errln("Bug 4095713 test failed, new double value : " + d2.doubleValue());
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * DecimalFormat.parse() fails when multiplier is not set to 1
+     */
+    public void Test4092561 ()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat();
+
+        String str = Long.toString(Long.MIN_VALUE);
+        logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
+        df.setMultiplier(100);
+        Number num = df.parse(str, new ParsePosition(0));
+        if (num.doubleValue() != -9.223372036854776E16) {
+            errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue());
+        }
+
+        df.setMultiplier(-100);
+        num = df.parse(str, new ParsePosition(0));
+        if (num.doubleValue() != 9.223372036854776E16) {
+            errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue());
+        }
+
+        str = Long.toString(Long.MAX_VALUE);
+        logln("Long.MAX_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
+
+        df.setMultiplier(100);
+        num = df.parse(str, new ParsePosition(0));
+        if (num.doubleValue() != 9.223372036854776E16) {
+            errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue());
+        }
+
+        df.setMultiplier(-100);
+        num = df.parse(str, new ParsePosition(0));
+        if (num.doubleValue() != -9.223372036854776E16) {
+            errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue());
+        }
+
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * DecimalFormat: Negative format ignored.
+     */
+    public void Test4092480 ()
+    {
+        DecimalFormat dfFoo = new DecimalFormat("000");
+
+        try {
+            dfFoo.applyPattern("0000;-000");
+            if (!dfFoo.toPattern().equals("#0000"))
+                errln("dfFoo.toPattern : " + dfFoo.toPattern());
+            logln(dfFoo.format(42));
+            logln(dfFoo.format(-42));
+            dfFoo.applyPattern("000;-000");
+            if (!dfFoo.toPattern().equals("#000"))
+                errln("dfFoo.toPattern : " + dfFoo.toPattern());
+            logln(dfFoo.format(42));
+            logln(dfFoo.format(-42));
+
+            dfFoo.applyPattern("000;-0000");
+            if (!dfFoo.toPattern().equals("#000"))
+                errln("dfFoo.toPattern : " + dfFoo.toPattern());
+            logln(dfFoo.format(42));
+            logln(dfFoo.format(-42));
+
+            dfFoo.applyPattern("0000;-000");
+            if (!dfFoo.toPattern().equals("#0000"))
+                errln("dfFoo.toPattern : " + dfFoo.toPattern());
+            logln(dfFoo.format(42));
+            logln(dfFoo.format(-42));
+        } catch (Exception foo) {
+            errln("Message " + foo.getMessage());
+        }
+    }
+    /**
+     * NumberFormat.getCurrencyInstance() produces format that uses
+     * decimal separator instead of monetary decimal separator.
+     *
+     * Rewrote this test not to depend on the actual pattern.  Pattern should
+     * never contain the monetary separator!  Decimal separator in pattern is
+     * interpreted as monetary separator if currency symbol is seen!
+     */
+    public void Test4087244 () {
+        Locale de = new Locale("pt", "PT");
+        DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de);
+        DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
+        sym.setMonetaryDecimalSeparator('$');
+        df.setDecimalFormatSymbols(sym);
+        char decSep = sym.getDecimalSeparator();
+        char monSep = sym.getMonetaryDecimalSeparator();
+        char zero = sym.getZeroDigit();
+        if (decSep == monSep) {
+            errln("ERROR in test: want decimal sep != monetary sep");
+        } else {
+            df.setMinimumIntegerDigits(1);
+            df.setMinimumFractionDigits(2);
+            String str = df.format(1.23);
+            String monStr = "1" + monSep + "23";
+            String decStr = "1" + decSep + "23";
+            if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
+                logln("OK: 1.23 -> \"" + str + "\" contains \"" +
+                      monStr + "\" and not \"" + decStr + '"');
+            } else {
+                errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" +
+                      monStr +
+                      "\" and not \"" + decStr + '"');
+            }
+        }
+    }
+    /**
+     * Number format data rounding errors for locale FR
+     */
+    public void Test4070798 () {
+        NumberFormat formatter;
+        String tempString;
+        /* User error :
+        String expectedDefault = "-5\u00a0789,987";
+        String expectedCurrency = "5\u00a0789,98 F";
+        String expectedPercent = "-578\u00a0998%";
+        */
+        String expectedDefault = "-5\u00a0789,988";
+        String expectedCurrency = "5\u00a0789,99 \u20AC";
+        // changed for bug 6547501
+        String expectedPercent = "-578\u00a0999 %";
+
+        formatter = NumberFormat.getNumberInstance(Locale.FRANCE);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedDefault)) {
+            logln ("Bug 4070798 default test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedDefault +
+            " Received " + tempString );
+        }
+
+
+        formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE);
+        tempString = formatter.format( 5789.9876 );
+
+        if (tempString.equals(expectedCurrency) ) {
+            logln ("Bug 4070798 currency test assed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedCurrency +
+            " Received " + tempString );
+        }
+
+
+        formatter = NumberFormat.getPercentInstance(Locale.FRANCE);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedPercent) ) {
+            logln ("Bug 4070798 percentage test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedPercent +
+            " Received " + tempString );
+        }
+    }
+    /**
+     * Data rounding errors for French (Canada) locale
+     */
+    public void Test4071005 () {
+
+        NumberFormat formatter;
+        String tempString;
+    /* user error :
+        String expectedDefault = "-5 789,987";
+        String expectedCurrency = "5 789,98 $";
+        String expectedPercent = "-578 998%";
+    */
+        String expectedDefault = "-5\u00a0789,988";
+        String expectedCurrency = "5\u00a0789,99 $";
+        // changed for bug 6547501
+        String expectedPercent = "-578\u00a0999 %";
+
+        formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
+        tempString = formatter.format (-5789.9876);
+        if (tempString.equals(expectedDefault)) {
+            logln ("Bug 4071005 default test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedDefault +
+            " Received " + tempString );
+        }
+
+        formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
+        tempString = formatter.format( 5789.9876 ) ;
+
+        if (tempString.equals(expectedCurrency) ) {
+            logln ("Bug 4071005 currency test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedCurrency +
+            " Received " + tempString );
+        }
+        formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedPercent) ) {
+            logln ("Bug 4071005 percentage test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedPercent +
+            " Received " + tempString );
+        }
+    }
+
+    /**
+     * Data rounding errors for German (Germany) locale
+     */
+    public void Test4071014 () {
+        NumberFormat formatter;
+        String tempString;
+        /* user error :
+        String expectedDefault = "-5.789,987";
+        String expectedCurrency = "5.789,98 DM";
+        String expectedPercent = "-578.998%";
+        */
+        String expectedDefault = "-5.789,988";
+        String expectedCurrency = "5.789,99 \u20AC";
+        String expectedPercent = "-578.999%";
+
+        formatter = NumberFormat.getNumberInstance(Locale.GERMANY);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedDefault)) {
+            logln ("Bug 4071014 default test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedDefault +
+            " Received " + tempString );
+        }
+
+        formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY);
+        tempString = formatter.format( 5789.9876 ) ;
+
+        if (tempString.equals(expectedCurrency) ) {
+            logln ("Bug 4071014 currency test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedCurrency +
+            " Received " + tempString );
+        }
+
+        formatter = NumberFormat.getPercentInstance(Locale.GERMANY);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedPercent) ) {
+            logln ("Bug 4071014 percentage test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedPercent +
+            " Received " + tempString );
+        }
+
+    }
+    /**
+     * Data rounding errors for Italian locale number formats
+     */
+    public void Test4071859 () {
+        NumberFormat formatter;
+        String tempString;
+        /* user error :
+        String expectedDefault = "-5.789,987";
+        String expectedCurrency = "-L. 5.789,98";
+        String expectedPercent = "-578.998%";
+        */
+        String expectedDefault = "-5.789,988";
+        String expectedCurrency = "-\u20AC 5.789,99";
+        String expectedPercent = "-578.999%";
+
+        formatter = NumberFormat.getNumberInstance(Locale.ITALY);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedDefault)) {
+            logln ("Bug 4071859 default test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedDefault +
+            " Received " + tempString );
+        }
+
+        formatter = NumberFormat.getCurrencyInstance(Locale.ITALY);
+        tempString = formatter.format( -5789.9876 ) ;
+
+        if (tempString.equals(expectedCurrency) ) {
+            logln ("Bug 4071859 currency test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedCurrency +
+            " Received " + tempString );
+        }
+
+        formatter = NumberFormat.getPercentInstance(Locale.ITALY);
+        tempString = formatter.format (-5789.9876);
+
+        if (tempString.equals(expectedPercent) ) {
+            logln ("Bug 4071859 percentage test passed.");
+        } else {
+            errln("Failed:" +
+            " Expected " + expectedPercent +
+            " Received " + tempString );
+        }
+
+    }
+
+    /* bug 4071859
+     * Test rounding for nearest even.
+     */
+    public void Test4093610()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat("#0.#");
+
+        roundingTest(df, 12.15, "12.2"); // Rounding-up. Above tie (12.150..)
+        roundingTest(df, 12.25, "12.2"); // No round-up. Exact + half-even rule.
+        roundingTest(df, 12.45, "12.4"); // No round-up. Below tie (12.449..)
+        roundingTest(df, 12.450000001,"12.5"); // Rounding-up. Above tie.
+        roundingTest(df, 12.55, "12.6"); // Rounding-up. Above tie (12.550..)
+        roundingTest(df, 12.650000001,"12.7"); // Rounding-up. Above tie.
+        roundingTest(df, 12.75, "12.8"); // Rounding-up. Exact + half-even rule.
+        roundingTest(df, 12.750000001,"12.8"); // Rounding-up. Above tie.
+        roundingTest(df, 12.85, "12.8"); // No round-up. Below tie (12.849..)
+        roundingTest(df, 12.850000001,"12.9"); // Rounding-up. Above tie.
+        roundingTest(df, 12.950000001,"13");   // Rounding-up. Above tie.
+
+        Locale.setDefault(savedLocale);
+    }
+
+    void roundingTest(DecimalFormat df, double x, String expected)
+    {
+        String out = df.format(x);
+        logln("" + x + " formats with 1 fractional digits to " + out);
+        if (!out.equals(expected)) errln("FAIL: Expected " + expected);
+    }
+    /**
+     * Tests the setMaximumFractionDigits limit.
+     */
+    public void Test4098741()
+    {
+        try {
+            NumberFormat fmt = NumberFormat.getPercentInstance();
+            fmt.setMaximumFractionDigits(20);
+            logln(fmt.format(.001));
+        } catch (Exception foo) {
+            errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
+        }
+    }
+    /**
+     * Tests illegal pattern exception.
+     * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
+     * Part2 has been fixed.
+     */
+    public void Test4074454()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        try {
+            DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#");
+            logln("Inconsistent negative pattern is fine.");
+            DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces");
+            String tempString = newFmt.format(3456.78);
+            if (!tempString.equals("3,456.78 p'ieces"))
+                errln("Failed!  3,456.78 p'ieces expected, but got : " + tempString);
+        } catch (Exception foo) {
+            errln("An exception was thrown for any inconsistent negative pattern.");
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * Tests all different comments.
+     * Response to some comments :
+     * [1] DecimalFormat.parse API documentation is more than just one line.
+     * This is not a reproducable doc error in 116 source code.
+     * [2] See updated javadoc.
+     * [3] Fixed.
+     * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
+     * a null object will be returned.  The unchanged parse position also
+     * reflects an error.
+     * NumberFormat.parse(String) : If parsing fails, an ParseException
+     * will be thrown.
+     * See updated javadoc for more details.
+     * [5] See updated javadoc.
+     * [6] See updated javadoc.
+     * [7] This is a correct behavior if the DateFormat object is linient.
+     * Otherwise, an IllegalArgumentException will be thrown when formatting
+     * "January 35".  See GregorianCalendar class javadoc for more details.
+     */
+    public void Test4099404()
+    {
+        try {
+            DecimalFormat fmt = new DecimalFormat("000.0#0");
+            errln("Bug 4099404 failed applying illegal pattern \"000.0#0\"");
+        } catch (Exception foo) {
+            logln("Bug 4099404 pattern \"000.0#0\" passed");
+        }
+        try {
+            DecimalFormat fmt = new DecimalFormat("0#0.000");
+            errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
+        } catch (Exception foo) {
+            logln("Bug 4099404 pattern \"0#0.000\" passed");
+        }
+    }
+    /**
+     * DecimalFormat.applyPattern doesn't set minimum integer digits
+     */
+    public void Test4101481()
+    {
+        DecimalFormat sdf = new DecimalFormat("#,##0");
+        if (sdf.getMinimumIntegerDigits() != 1)
+            errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits());
+    }
+    /**
+     * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
+     */
+    public void Test4052223()
+    {
+        try {
+            DecimalFormat fmt = new DecimalFormat("#,#00.00");
+            Number num = fmt.parse("abc3");
+            errln("Bug 4052223 failed : can't parse string \"a\".  Got " + num);
+        } catch (ParseException foo) {
+            logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
+        }
+    }
+    /**
+     * API tests for API addition request A9.
+     */
+    public void Test4061302()
+    {
+        DecimalFormatSymbols fmt = DecimalFormatSymbols.getInstance();
+        String currency = fmt.getCurrencySymbol();
+        String intlCurrency = fmt.getInternationalCurrencySymbol();
+        char monDecSeparator = fmt.getMonetaryDecimalSeparator();
+        if (currency.equals("") ||
+            intlCurrency.equals("") ||
+            monDecSeparator == 0) {
+            errln("getCurrencySymbols failed, got empty string.");
+        }
+        logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
+        fmt.setCurrencySymbol("XYZ");
+        fmt.setInternationalCurrencySymbol("ABC");
+        fmt.setMonetaryDecimalSeparator('*');
+        currency = fmt.getCurrencySymbol();
+        intlCurrency = fmt.getInternationalCurrencySymbol();
+        monDecSeparator = fmt.getMonetaryDecimalSeparator();
+        if (!currency.equals("XYZ") ||
+            !intlCurrency.equals("ABC") ||
+            monDecSeparator != '*') {
+            errln("setCurrencySymbols failed.");
+        }
+        logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
+    }
+    /**
+     * API tests for API addition request A23. FieldPosition.getBeginIndex and
+     * FieldPosition.getEndIndex.
+     */
+    public void Test4062486()
+    {
+        DecimalFormat fmt = new DecimalFormat("#,##0.00");
+        StringBuffer formatted = new StringBuffer();
+        FieldPosition field = new FieldPosition(0);
+        Double num = new Double(1234.5);
+        fmt.format(num, formatted, field);
+        if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
+            errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
+        field.setBeginIndex(7);
+        field.setEndIndex(4);
+        if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
+            errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
+    }
+
+    /**
+     * DecimalFormat.parse incorrectly works with a group separator.
+     */
+    public void Test4108738()
+    {
+
+        DecimalFormat df = new DecimalFormat("#,##0.###",
+        DecimalFormatSymbols.getInstance(java.util.Locale.US));
+        String text = "1.222,111";
+        Number num = df.parse(text,new ParsePosition(0));
+        if (!num.toString().equals("1.222"))
+            errln("\"" + text + "\"  is parsed as " + num);
+        text = "1.222x111";
+        num = df.parse(text,new ParsePosition(0));
+        if (!num.toString().equals("1.222"))
+            errln("\"" + text + "\"  is parsed as " + num);
+    }
+
+    /**
+     * DecimalFormat.format() incorrectly formats negative doubles.
+     */
+    public void Test4106658()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706
+        double d1 = -0.0;
+        double d2 = -0.0001;
+        StringBuffer buffer = new StringBuffer();
+        logln("pattern: \"" + df.toPattern() + "\"");
+        df.format(d1, buffer, new FieldPosition(0));
+        if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+            errln(d1 + "      is formatted as " + buffer);
+        }
+        buffer.setLength(0);
+        df.format(d2, buffer, new FieldPosition(0));
+        if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+            errln(d2 + "      is formatted as " + buffer);
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * DecimalFormat.parse returns 0 if string parameter is incorrect.
+     */
+    public void Test4106662()
+    {
+        DecimalFormat df = new DecimalFormat();
+        String text = "x";
+        ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0);
+
+        logln("pattern: \"" + df.toPattern() + "\"");
+        Number num = df.parse(text, pos1);
+        if (num != null) {
+            errln("Test Failed: \"" + text + "\" is parsed as " + num);
+        }
+        df = null;
+        df = new DecimalFormat("$###.00");
+        num = df.parse("$", pos2);
+        if (num != null){
+            errln("Test Failed: \"$\" is parsed as " + num);
+        }
+    }
+
+    /**
+     * NumberFormat.parse doesn't return null
+     */
+    public void Test4114639()
+    {
+        NumberFormat format = NumberFormat.getInstance();
+        String text = "time 10:x";
+        ParsePosition pos = new ParsePosition(8);
+        Number result = format.parse(text, pos);
+        if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't
+    }
+
+    /**
+     * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
+     */
+    public void Test4106664()
+    {
+        DecimalFormat df = new DecimalFormat();
+        long n = 1234567890123456L;
+        int m = 12345678;
+        BigInteger bigN = BigInteger.valueOf(n);
+        bigN = bigN.multiply(BigInteger.valueOf(m));
+        df.setMultiplier(m);
+        df.setGroupingUsed(false);
+        logln("formated: " +
+            df.format(n, new StringBuffer(), new FieldPosition(0)));
+        logln("expected: " + bigN.toString());
+    }
+    /**
+     * DecimalFormat.format incorrectly formats -0.0.
+     */
+    public void Test4106667()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat();
+        df.setPositivePrefix("+");
+        double d = -0.0;
+        logln("pattern: \"" + df.toPattern() + "\"");
+        StringBuffer buffer = new StringBuffer();
+        df.format(d, buffer, new FieldPosition(0));
+        if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+            errln(d + "  is formatted as " + buffer);
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
+     */
+    public void Test4110936()
+    {
+        NumberFormat nf = NumberFormat.getInstance();
+        nf.setMaximumIntegerDigits(128);
+        logln("setMaximumIntegerDigits(128)");
+        if (nf.getMaximumIntegerDigits() != 128)
+            errln("getMaximumIntegerDigits() returns " +
+                nf.getMaximumIntegerDigits());
+    }
+
+    /**
+     * Locale data should use generic currency symbol
+     *
+     * 1) Make sure that all currency formats use the generic currency symbol.
+     * 2) Make sure we get the same results using the generic symbol or a
+     *    hard-coded one.
+     */
+    public void Test4122840()
+    {
+        Locale[] locales = NumberFormat.getAvailableLocales();
+
+        for (int i = 0; i < locales.length; i++) {
+            ResourceBundle rb = LocaleData.getBundle("sun.text.resources.FormatData",
+                                                     locales[i]);
+            //
+            // Get the currency pattern for this locale.  We have to fish it
+            // out of the ResourceBundle directly, since DecimalFormat.toPattern
+            // will return the localized symbol, not \00a4
+            //
+            String[] numPatterns = (String[])rb.getObject("NumberPatterns");
+            String pattern = numPatterns[1];
+
+            if (pattern.indexOf("\u00A4") == -1 ) {
+                errln("Currency format for " + locales[i] +
+                        " does not contain generic currency symbol:" +
+                        pattern );
+            }
+
+            // Create a DecimalFormat using the pattern we got and format a number
+            DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locales[i]);
+            DecimalFormat fmt1 = new DecimalFormat(pattern, symbols);
+
+            String result1 = fmt1.format(1.111);
+
+            //
+            // Now substitute in the locale's currency symbol and create another
+            // pattern.  Replace the decimal separator with the monetary separator.
+            //
+            char decSep = symbols.getDecimalSeparator();
+            char monSep = symbols.getMonetaryDecimalSeparator();
+            StringBuffer buf = new StringBuffer(pattern);
+            for (int j = 0; j < buf.length(); j++) {
+                if (buf.charAt(j) == '\u00a4') {
+                    String cur = "'" + symbols.getCurrencySymbol() + "'";
+                    buf.replace(j, j+1, cur);
+                    j += cur.length() - 1;
+                }
+            }
+            symbols.setDecimalSeparator(monSep);
+            DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols);
+
+            String result2 = fmt2.format(1.111);
+
+            if (!result1.equals(result2)) {
+                errln("Results for " + locales[i] + " differ: " +
+                      result1 + " vs " + result2);
+            }
+        }
+    }
+
+    /**
+     * DecimalFormat.format() delivers wrong string.
+     */
+    public void Test4125885()
+    {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        double rate = 12.34;
+        DecimalFormat formatDec = new DecimalFormat ("000.00");
+        logln("toPattern: " + formatDec.toPattern());
+        String rateString= formatDec.format(rate);
+        if (!rateString.equals("012.34"))
+            errln("result : " + rateString + " expected : 012.34");
+        rate = 0.1234;
+        formatDec = null;
+        formatDec = new DecimalFormat ("+000.00%;-000.00%");
+        logln("toPattern: " + formatDec.toPattern());
+        rateString= formatDec.format(rate);
+        if (!rateString.equals("+012.34%"))
+            errln("result : " + rateString + " expected : +012.34%");
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     **
+     * DecimalFormat produces extra zeros when formatting numbers.
+     */
+    public void Test4134034() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat nf = new DecimalFormat("##,###,###.00");
+
+        String f = nf.format(9.02);
+        if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02");
+
+        f = nf.format(0);
+        if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00");
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * CANNOT REPRODUCE - This bug could not be reproduced.  It may be
+     * a duplicate of 4134034.
+     *
+     * JDK 1.1.6 Bug, did NOT occur in 1.1.5
+     * Possibly related to bug 4125885.
+     *
+     * This class demonstrates a regression in version 1.1.6
+     * of DecimalFormat class.
+     *
+     * 1.1.6 Results
+     * Value 1.2 Format #.00 Result '01.20' !!!wrong
+     * Value 1.2 Format 0.00 Result '001.20' !!!wrong
+     * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
+     * Value 1.2 Format #0.0# Result '1.2'
+     * Value 1.2 Format #0.00 Result '001.20' !!!wrong
+     *
+     * 1.1.5 Results
+     * Value 1.2 Format #.00 Result '1.20'
+     * Value 1.2 Format 0.00 Result '1.20'
+     * Value 1.2 Format 00.00 Result '01.20'
+     * Value 1.2 Format #0.0# Result '1.2'
+     * Value 1.2 Format #0.00 Result '1.20'
+     */
+    public void Test4134300() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        String[] DATA = {
+         // Pattern      Expected string
+            "#.00",      "1.20",
+            "0.00",      "1.20",
+            "00.00",     "01.20",
+            "#0.0#",     "1.2",
+            "#0.00",     "1.20",
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            String result = new DecimalFormat(DATA[i]).format(1.2);
+            if (!result.equals(DATA[i+1])) {
+                errln("Fail: 1.2 x " + DATA[i] + " = " + result +
+                      "; want " + DATA[i+1]);
+            }
+            else {
+                logln("Ok: 1.2 x " + DATA[i] + " = " + result);
+            }
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * Empty pattern produces double negative prefix.
+     */
+    public void Test4140009() {
+        for (int i=0; i<2; ++i) {
+            DecimalFormat f = null;
+            switch (i) {
+            case 0:
+                f = new DecimalFormat("",
+                            DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+                break;
+            case 1:
+                f = new DecimalFormat("#.#",
+                            DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+                f.applyPattern("");
+                break;
+            }
+            String s = f.format(123.456);
+            if (!s.equals("123.456"))
+                errln("Fail: Format empty pattern x 123.456 => " + s);
+            s = f.format(-123.456);
+            if (!s.equals("-123.456"))
+                errln("Fail: Format empty pattern x -123.456 => " + s);
+        }
+    }
+
+    /**
+     * BigDecimal numbers get their fractions truncated by NumberFormat.
+     */
+    public void Test4141750() {
+        try {
+            String str = "12345.67";
+            BigDecimal bd = new BigDecimal(str);
+            NumberFormat nf = NumberFormat.getInstance(Locale.US);
+            String sd = nf.format(bd);
+            if (!sd.endsWith("67")) {
+                errln("Fail: " + str + " x format -> " + sd);
+            }
+        }
+        catch (Exception e) {
+            errln(e.toString());
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * DecimalFormat toPattern() doesn't quote special characters or handle
+     * single quotes.
+     */
+    public void Test4145457() {
+        try {
+            DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
+            DecimalFormatSymbols sym = nf.getDecimalFormatSymbols();
+            sym.setDecimalSeparator('\'');
+            nf.setDecimalFormatSymbols(sym);
+            double pi = 3.14159;
+
+            String[] PATS = { "#.00 'num''ber'", "''#.00''" };
+
+            for (int i=0; i<PATS.length; ++i) {
+                nf.applyPattern(PATS[i]);
+                String out = nf.format(pi);
+                String pat = nf.toPattern();
+                double val = nf.parse(out).doubleValue();
+
+                nf.applyPattern(pat);
+                String out2 = nf.format(pi);
+                String pat2 = nf.toPattern();
+                double val2 = nf.parse(out2).doubleValue();
+
+                if (!pat.equals(pat2))
+                    errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
+                          pat + "\" vs. \"" + pat2 + "\"");
+                else
+                    logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
+
+                if (val == val2 && out.equals(out2)) {
+                    logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" +
+                          out + "\" -> " + val + " -> \"" +
+                          out2 + "\" -> " + val2);
+                }
+                else {
+                    errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" +
+                          out + "\" -> " + val + " -> \"" +
+                          out2 + "\" -> " + val2);
+                }
+            }
+        }
+        catch (ParseException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
+     * CANNOT REPRODUCE
+     * This bug is a duplicate of 4139344, which is a duplicate of 4134300
+     */
+    public void Test4147295() {
+        DecimalFormat sdf = new DecimalFormat();
+        String pattern = "#,###";
+        logln("Applying pattern \"" + pattern + "\"");
+        sdf.applyPattern(pattern);
+        int minIntDig = sdf.getMinimumIntegerDigits();
+        if (minIntDig != 0) {
+            errln("Test failed");
+            errln(" Minimum integer digits : " + minIntDig);
+            errln(" new pattern: " + sdf.toPattern());
+        } else {
+            logln("Test passed");
+            logln(" Minimum integer digits : " + minIntDig);
+        }
+    }
+
+    /**
+     * DecimalFormat formats -0.0 as +0.0
+     * See also older related bug 4106658, 4106667
+     */
+    public void Test4147706() {
+        DecimalFormat df = new DecimalFormat("#,##0.0##");
+        df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+        double d1 = -0.0;
+        double d2 = -0.0001;
+        StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0));
+        StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0));
+        if (!f1.toString().equals("-0.0")) {
+            errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"');
+        }
+        if (!f2.toString().equals("-0.0")) {
+            errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"');
+        }
+    }
+
+    /**
+     * NumberFormat cannot format Double.MAX_VALUE
+     */
+    public void Test4162198() {
+        double dbl = Double.MAX_VALUE;
+        NumberFormat f = NumberFormat.getInstance();
+        f.setMaximumFractionDigits(Integer.MAX_VALUE);
+        f.setMaximumIntegerDigits(Integer.MAX_VALUE);
+        String s = f.format(dbl);
+        logln("The number " + dbl + " formatted to " + s);
+        Number n = null;
+        try {
+            n = f.parse(s);
+        } catch (java.text.ParseException e) {
+            errln("Caught a ParseException:");
+            e.printStackTrace();
+        }
+        logln("The string " + s + " parsed as " + n);
+        if (n.doubleValue() != dbl) {
+            errln("Round trip failure");
+        }
+    }
+
+    /**
+     * NumberFormat does not parse negative zero.
+     */
+    public void Test4162852() throws ParseException {
+        for (int i=0; i<2; ++i) {
+            NumberFormat f = (i == 0) ? NumberFormat.getInstance()
+                : NumberFormat.getPercentInstance();
+            double d = -0.0;
+            String s = f.format(d);
+            double e = f.parse(s).doubleValue();
+            logln("" +
+                  d + " -> " +
+                  '"' + s + '"' + " -> " +
+              e);
+            if (e != 0.0 || 1.0/e > 0.0) {
+                logln("Failed to parse negative zero");
+            }
+        }
+    }
+
+    /**
+     * NumberFormat truncates data
+     */
+    public void Test4167494() throws Exception {
+        NumberFormat fmt = NumberFormat.getInstance(Locale.US);
+
+        double a = Double.MAX_VALUE;
+        String s = fmt.format(a);
+        double b = fmt.parse(s).doubleValue();
+        boolean match = a == b;
+        if (match) {
+            logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
+        } else {
+            errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
+        }
+
+        // We don't test Double.MIN_VALUE because the locale data for the US
+        // currently doesn't specify enough digits to display Double.MIN_VALUE.
+        // This is correct for now; however, we leave this here as a reminder
+        // in case we want to address this later.
+        if (false) {
+            a = Double.MIN_VALUE;
+            s = fmt.format(a);
+            b = fmt.parse(s).doubleValue();
+            match = a == b;
+            if (match) {
+                logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
+            } else {
+                errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
+            }
+        }
+    }
+
+    /**
+     * DecimalFormat.parse() fails when ParseIntegerOnly set to true
+     */
+    public void Test4170798() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat df = new DecimalFormat();
+        df.setParseIntegerOnly(true);
+        Number n = df.parse("-0.0", new ParsePosition(0));
+        if (!(n instanceof Long || n instanceof Integer)
+            || n.intValue() != 0) {
+            errln("FAIL: parse(\"-0.0\") returns " +
+                  n + " (" + n.getClass().getName() + ')');
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * toPattern only puts the first grouping separator in.
+     */
+    public void Test4176114() {
+        String[] DATA = {
+            "00", "#00",
+            "000", "#000", // No grouping
+            "#000", "#000", // No grouping
+            "#,##0", "#,##0",
+            "#,000", "#,000",
+            "0,000", "#0,000",
+            "00,000", "#00,000",
+            "000,000", "#,000,000",
+            "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            DecimalFormat df = new DecimalFormat(DATA[i]);
+            String s = df.toPattern();
+            if (!s.equals(DATA[i+1])) {
+                errln("FAIL: " + DATA[i] + " -> " + s + ", want " + DATA[i+1]);
+            }
+        }
+    }
+
+    /**
+     * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
+     */
+    public void Test4179818() {
+        String DATA[] = {
+            // Input  Pattern  Expected output
+            "1.2511", "#.#",   "1.3",
+            "1.2501", "#.#",   "1.3",
+            "0.9999", "#",     "1",
+        };
+        DecimalFormat fmt = new DecimalFormat("#",
+                DecimalFormatSymbols.getInstance(Locale.US));
+        for (int i=0; i<DATA.length; i+=3) {
+            double in = Double.valueOf(DATA[i]).doubleValue();
+            String pat = DATA[i+1];
+            String exp = DATA[i+2];
+            fmt.applyPattern(pat);
+            String out = fmt.format(in);
+            if (out.equals(exp)) {
+                logln("Ok: " + in + " x " + pat + " = " + out);
+            } else {
+                errln("FAIL: " + in + " x  " + pat + " = " + out +
+                      ", expected " + exp);
+            }
+        }
+    }
+
+    public void Test4185761() throws IOException, ClassNotFoundException {
+        /* Code used to write out the initial files, which are
+         * then edited manually:
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        nf.setMinimumIntegerDigits(0x111); // Keep under 309
+        nf.setMaximumIntegerDigits(0x112); // Keep under 309
+        nf.setMinimumFractionDigits(0x113); // Keep under 340
+        nf.setMaximumFractionDigits(0x114); // Keep under 340
+        FileOutputStream ostream =
+            new FileOutputStream("NumberFormat4185761");
+        ObjectOutputStream p = new ObjectOutputStream(ostream);
+        p.writeObject(nf);
+        ostream.close();
+        */
+
+        // File                 minint maxint minfrac maxfrac
+        // NumberFormat4185761a  0x122  0x121   0x124   0x123
+        // NumberFormat4185761b  0x311  0x312   0x313   0x314
+        // File a is bad because the mins are smaller than the maxes.
+        // File b is bad because the values are too big for a DecimalFormat.
+        // These files have a sufix ".ser.txt".
+
+        InputStream istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761a.ser.txt");
+        ObjectInputStream p = new ObjectInputStream(istream);
+        try {
+            NumberFormat nf = (NumberFormat) p.readObject();
+            errln("FAIL: Deserialized bogus NumberFormat int:" +
+                  nf.getMinimumIntegerDigits() + ".." +
+                  nf.getMaximumIntegerDigits() + " frac:" +
+                  nf.getMinimumFractionDigits() + ".." +
+                  nf.getMaximumFractionDigits());
+        } catch (InvalidObjectException e) {
+            logln("Ok: " + e.getMessage());
+        }
+        istream.close();
+
+        istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761b.ser.txt");
+        p = new ObjectInputStream(istream);
+        try {
+            NumberFormat nf = (NumberFormat) p.readObject();
+            errln("FAIL: Deserialized bogus DecimalFormat int:" +
+                  nf.getMinimumIntegerDigits() + ".." +
+                  nf.getMaximumIntegerDigits() + " frac:" +
+                  nf.getMinimumFractionDigits() + ".." +
+                  nf.getMaximumFractionDigits());
+        } catch (InvalidObjectException e) {
+            logln("Ok: " + e.getMessage());
+        }
+        istream.close();
+    }
+
+
+    /**
+     * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
+     * This includes the minus sign, currency symbol, international currency
+     * symbol, percent, and permille.  This is filed as bugs 4212072 and
+     * 4212073.
+     */
+    public void Test4212072() throws IOException, ClassNotFoundException {
+        DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+        DecimalFormat fmt = new DecimalFormat("#", sym);
+
+        sym.setMinusSign('^');
+        fmt.setDecimalFormatSymbols(sym);
+        if (!fmt.format(-1).equals("^1")) {
+            errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) +
+                  ", exp ^1");
+        }
+        if (!fmt.getNegativePrefix().equals("^")) {
+            errln("FAIL: (minus=^).getNegativePrefix -> " +
+                  fmt.getNegativePrefix() + ", exp ^");
+        }
+        sym.setMinusSign('-');
+
+        fmt.applyPattern("#%");
+        sym.setPercent('^');
+        fmt.setDecimalFormatSymbols(sym);
+        if (!fmt.format(0.25).equals("25^")) {
+            errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) +
+                  ", exp 25^");
+        }
+        if (!fmt.getPositiveSuffix().equals("^")) {
+            errln("FAIL: (percent=^).getPositiveSuffix -> " +
+                  fmt.getPositiveSuffix() + ", exp ^");
+        }
+        sym.setPercent('%');
+
+        fmt.applyPattern("#\u2030");
+        sym.setPerMill('^');
+        fmt.setDecimalFormatSymbols(sym);
+        if (!fmt.format(0.25).equals("250^")) {
+            errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) +
+                  ", exp 250^");
+        }
+        if (!fmt.getPositiveSuffix().equals("^")) {
+            errln("FAIL: (permill=^).getPositiveSuffix -> " +
+                  fmt.getPositiveSuffix() + ", exp ^");
+        }
+        sym.setPerMill('\u2030');
+
+        fmt.applyPattern("\u00A4#.00");
+        sym.setCurrencySymbol("usd");
+        fmt.setDecimalFormatSymbols(sym);
+        if (!fmt.format(12.5).equals("usd12.50")) {
+            errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
+                  ", exp usd12.50");
+        }
+        if (!fmt.getPositivePrefix().equals("usd")) {
+            errln("FAIL: (currency=usd).getPositivePrefix -> " +
+                  fmt.getPositivePrefix() + ", exp usd");
+        }
+        sym.setCurrencySymbol("$");
+
+        fmt.applyPattern("\u00A4\u00A4#.00");
+        sym.setInternationalCurrencySymbol("DOL");
+        fmt.setDecimalFormatSymbols(sym);
+        if (!fmt.format(12.5).equals("DOL12.50")) {
+            errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
+                  ", exp DOL12.50");
+        }
+        if (!fmt.getPositivePrefix().equals("DOL")) {
+            errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
+                  fmt.getPositivePrefix() + ", exp DOL");
+        }
+        sym.setInternationalCurrencySymbol("USD");
+
+        // Since the pattern logic has changed, make sure that patterns round
+        // trip properly.  Test stream in/out integrity too.
+        Locale[] avail = NumberFormat.getAvailableLocales();
+        for (int i=0; i<avail.length; ++i) {
+            for (int j=0; j<3; ++j) {
+                NumberFormat nf;
+                switch (j) {
+                case 0:
+                    nf = NumberFormat.getInstance(avail[i]);
+                    break;
+                case 1:
+                    nf = NumberFormat.getCurrencyInstance(avail[i]);
+                    break;
+                default:
+                    nf = NumberFormat.getPercentInstance(avail[i]);
+                    break;
+                }
+                DecimalFormat df = (DecimalFormat) nf;
+
+                // Test toPattern/applyPattern round trip
+                String pat = df.toPattern();
+                DecimalFormatSymbols symb = DecimalFormatSymbols.getInstance(avail[i]);
+                DecimalFormat f2 = new DecimalFormat(pat, symb);
+                if (!df.equals(f2)) {
+                    errln("FAIL: " + avail[i] + " -> \"" + pat +
+                          "\" -> \"" + f2.toPattern() + '"');
+                }
+
+                // Test toLocalizedPattern/applyLocalizedPattern round trip
+                pat = df.toLocalizedPattern();
+                f2.applyLocalizedPattern(pat);
+                if (!df.equals(f2)) {
+                    errln("FAIL: " + avail[i] + " -> localized \"" + pat +
+                          "\" -> \"" + f2.toPattern() + '"');
+                }
+
+                // Test writeObject/readObject round trip
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                ObjectOutputStream oos = new ObjectOutputStream(baos);
+                oos.writeObject(df);
+                oos.flush();
+                baos.close();
+                byte[] bytes = baos.toByteArray();
+                ObjectInputStream ois =
+                    new ObjectInputStream(new ByteArrayInputStream(bytes));
+                f2 = (DecimalFormat) ois.readObject();
+                if (!df.equals(f2)) {
+                    errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat +
+                          "\" -> " +
+                          (f2 != null ? ("\""+f2.toPattern()+'"') : "null"));
+                }
+
+            }
+        }
+    }
+
+    /**
+     * DecimalFormat.parse() fails for mulipliers 2^n.
+     */
+    public void Test4216742() throws ParseException {
+        DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US);
+        long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L};
+        for (int i=0; i<DATA.length; ++i) {
+            String str = Long.toString(DATA[i]);
+            for (int m = 1; m <= 100; m++) {
+                fmt.setMultiplier(m);
+                long n = ((Number) fmt.parse(str)).longValue();
+                if (n > 0 != DATA[i] > 0) {
+                    errln("\"" + str + "\" parse(x " + fmt.getMultiplier() +
+                          ") => " + n);
+                }
+            }
+        }
+    }
+
+    /**
+     * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
+     * digits.
+     */
+    public void Test4217661() {
+        Object[] DATA = {
+            new Double(0.001), "0",
+            new Double(1.001), "1",
+            new Double(0.006), "0.01",
+            new Double(1.006), "1.01",
+        };
+        NumberFormat fmt = NumberFormat.getInstance(Locale.US);
+        fmt.setMaximumFractionDigits(2);
+        for (int i=0; i<DATA.length; i+=2) {
+            String s = fmt.format(((Double) DATA[i]).doubleValue());
+            if (!s.equals(DATA[i+1])) {
+                errln("FAIL: Got " + s + ", exp " + DATA[i+1]);
+            }
+        }
+    }
+
+    /**
+     * 4243011: Formatting .5 rounds to "1" instead of "0"
+     */
+    public void Test4243011() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        double DATA[] = {0.5, 1.5, 2.5, 3.5, 4.5};
+        String EXPECTED[] = {"0.", "2.", "2.", "4.", "4."};
+
+        DecimalFormat format = new DecimalFormat("0.");
+        for (int i = 0; i < DATA.length; i++) {
+            String result = format.format(DATA[i]);
+            if (result.equals(EXPECTED[i])) {
+                logln("OK: got " + result);
+            } else {
+                errln("FAIL: got " + result);
+            }
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * 4243108: format(0.0) gives "0.1" if preceded by parse("99.99")
+     */
+    public void Test4243108() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        DecimalFormat f = new DecimalFormat("#.#");
+        String result = f.format(0.0);
+        if (result.equals("0")) {
+            logln("OK: got " + result);
+        } else {
+            errln("FAIL: got " + result);
+        }
+        try {
+            double dResult = f.parse("99.99").doubleValue();
+            if (dResult == 99.99) {
+                logln("OK: got " + dResult);
+            } else {
+                errln("FAIL: got " + dResult);
+            }
+        } catch (ParseException e) {
+            errln("Caught a ParseException:");
+            e.printStackTrace();
+        }
+        result = f.format(0.0);
+        if (result.equals("0")) {
+            logln("OK: got " + result);
+        } else {
+            errln("FAIL: got " + result);
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * 4330377: DecimalFormat engineering notation gives incorrect results
+     */
+    public void test4330377() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        double[] input = {5000.0, 500.0, 50.0, 5.0, 0.5, 0.05, 0.005, 0.0005,
+               5050.0, 505.0, 50.5, 5.05, 0.505, 0.0505, 0.00505, 0.000505};
+        String[] pattern = {"000.#E0", "##0.#E0", "#00.#E0"};
+        String[][] expected = {
+            // it's questionable whether "#00.#E0" should result in post-decimal
+            // zeroes, i.e., whether "5.0E3", "5.0E0", "5.0E-3" are really good
+            {"500E1", "5E3", "5.0E3"},
+            {"500E0", "500E0", "500E0"},
+            {"500E-1", "50E0", "50E0"},
+            {"500E-2", "5E0", "5.0E0"},
+            {"500E-3", "500E-3", "500E-3"},
+            {"500E-4", "50E-3", "50E-3"},
+            {"500E-5", "5E-3", "5.0E-3"},
+            {"500E-6", "500E-6", "500E-6"},
+            {"505E1", "5.05E3", "5.05E3"},
+            {"505E0", "505E0", "505E0"},
+            {"505E-1", "50.5E0", "50.5E0"},
+            {"505E-2", "5.05E0", "5.05E0"},
+            {"505E-3", "505E-3", "505E-3"},
+            {"505E-4", "50.5E-3", "50.5E-3"},
+            {"505E-5", "5.05E-3", "5.05E-3"},
+            {"505E-6", "505E-6", "505E-6"}
+        };
+        for (int i = 0; i < input.length; i++) {
+            for (int j = 0; j < pattern.length; j++) {
+                DecimalFormat format = new DecimalFormat(pattern[j]);
+                String result = format.format(input[i]);
+                if (!result.equals(expected[i][j])) {
+                    errln("FAIL: input: " + input[i] +
+                            ", pattern: " + pattern[j] +
+                            ", expected: " + expected[i][j] +
+                            ", got: " + result);
+                }
+            }
+        }
+        Locale.setDefault(savedLocale);
+    }
+
+    /**
+     * 4233840: NumberFormat does not round correctly
+     */
+    public void test4233840() {
+        float f = 0.0099f;
+
+        NumberFormat nf = new DecimalFormat("0.##", DecimalFormatSymbols.getInstance(Locale.US));
+        nf.setMinimumFractionDigits(2);
+
+        String result = nf.format(f);
+
+        if (!result.equals("0.01")) {
+            errln("FAIL: input: " + f + ", expected: 0.01, got: " + result);
+        }
+    }
+
+    /**
+     * 4241880: Decimal format doesnt round a double properly when the number is less than 1
+     */
+    public void test4241880() {
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        double[] input = {
+                .019, .009, .015, .016, .014,
+                .004, .005, .006, .007, .008,
+                .5, 1.5, .25, .55, .045,
+                .035, .0005, .0015,
+        };
+        String[] pattern = {
+                "##0%", "##0%", "##0%", "##0%", "##0%",
+                "##0%", "##0%", "##0%", "##0%", "##0%",
+                "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
+                "#,##0.00", "#,##0.000", "#,##0.000",
+        };
+        String[] expected = {
+                "2%", "1%", "2%", "2%", "1%",
+                "0%", "0%", "1%", "1%", "1%",
+                "0", "2", "0.2", "0.6", "0.04",
+                "0.04", "0.000", "0.002",
+        };
+        for (int i = 0; i < input.length; i++) {
+            DecimalFormat format = new DecimalFormat(pattern[i]);
+            String result = format.format(input[i]);
+            if (!result.equals(expected[i])) {
+                errln("FAIL: input: " + input[i] +
+                        ", pattern: " + pattern[i] +
+                        ", expected: " + expected[i] +
+                        ", got: " + result);
+            }
+        }
+        Locale.setDefault(savedLocale);
+    }
+}
+
+class myformat implements Serializable
+{
+    DateFormat _dateFormat = DateFormat.getDateInstance();
+
+    public String Now()
+    {
+        GregorianCalendar calendar = new GregorianCalendar();
+        Date t = calendar.getTime();
+        String nowStr = _dateFormat.format(t);
+        return nowStr;
+    }
+}
+
+class MyNumberFormatTest extends NumberFormat {
+    public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+        return new StringBuffer("");
+    }
+    public StringBuffer format(long number,StringBuffer toAppendTo, FieldPosition pos) {
+        return new StringBuffer("");
+    }
+    public Number parse(String text, ParsePosition parsePosition) {
+        return new Integer(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberRoundTrip.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary round trip test NumberFormat
+ * @library /java/text/testlib
+ * @key randomness
+ */
+
+import java.text.*;
+import java.util.*;
+
+/**
+ * This class tests the round-trip behavior of NumberFormat, DecimalFormat, and DigitList.
+ * Round-trip behavior is tested by taking a numeric value and formatting it, then
+ * parsing the resulting string, and comparing this result with the original value.
+ * Two tests are applied:  String preservation, and numeric preservation.  String
+ * preservation is exact; numeric preservation is not.  However, numeric preservation
+ * should extend to the few least-significant bits.
+ * //bug472
+ */
+public class NumberRoundTrip extends IntlTest {
+    static final boolean STRING_COMPARE = true;
+    static final boolean EXACT_NUMERIC_COMPARE = false;
+    static final double MAX_ERROR = 1e-14;
+    static boolean DEBUG = false;
+    static double max_numeric_error = 0;
+    static double min_numeric_error = 1;
+
+    String localeName, formatName;
+
+    public static void main(String[] args) throws Exception {
+        if (args.length > 0 && args[0].equals("-debug")) {
+            DEBUG = true;
+            String[] newargs = new String[args.length - 1];
+            System.arraycopy(args, 1, newargs, 0, newargs.length);
+            args = newargs;
+        }
+        new NumberRoundTrip().run(args);
+    }
+
+    public void TestNumberFormatRoundTrip() {
+        logln("Default Locale");
+        localeName = "Default Locale";
+        formatName = "getInstance";
+        doTest(NumberFormat.getInstance());
+        formatName = "getNumberInstance";
+        doTest(NumberFormat.getNumberInstance());
+        formatName = "getCurrencyInstance";
+        doTest(NumberFormat.getCurrencyInstance());
+        formatName = "getPercentInstance";
+        doTest(NumberFormat.getPercentInstance());
+
+        Locale[] loc = NumberFormat.getAvailableLocales();
+        for (int i=0; i<loc.length; ++i) {
+            logln(loc[i].getDisplayName());
+            localeName = loc[i].toString();
+            formatName = "getInstance";
+            doTest(NumberFormat.getInstance(loc[i]));
+            formatName = "getNumberInstance";
+            doTest(NumberFormat.getNumberInstance(loc[i]));
+            formatName = "getCurrencyInstance";
+            doTest(NumberFormat.getCurrencyInstance(loc[i]));
+            formatName = "getPercentInstance";
+            doTest(NumberFormat.getPercentInstance(loc[i]));
+        }
+
+        logln("Numeric error " +
+              min_numeric_error + " to " +
+              max_numeric_error);
+    }
+
+    public void doTest(NumberFormat fmt) {
+        doTest(fmt, Double.NaN);
+        doTest(fmt, Double.POSITIVE_INFINITY);
+        doTest(fmt, Double.NEGATIVE_INFINITY);
+
+        doTest(fmt, 500);
+        doTest(fmt, 0);
+        doTest(fmt, 5555555555555555L);
+        doTest(fmt, 55555555555555555L);
+        doTest(fmt, 9223372036854775807L);
+        doTest(fmt, 9223372036854775808.0);
+        doTest(fmt, -9223372036854775808L);
+        doTest(fmt, -9223372036854775809.0);
+
+        for (int i=0; i<2; ++i) {
+            doTest(fmt, randomDouble(1));
+            doTest(fmt, randomDouble(10000));
+            doTest(fmt, Math.floor(randomDouble(10000)));
+            doTest(fmt, randomDouble(1e50));
+            doTest(fmt, randomDouble(1e-50));
+            doTest(fmt, randomDouble(1e100));
+            // The use of double d such that isInfinite(100d) causes the
+            // numeric test to fail with percent formats (bug 4266589).
+            // Largest double s.t. 100d < Inf: d=1.7976931348623156E306
+            doTest(fmt, randomDouble(1e306));
+            doTest(fmt, randomDouble(1e-323));
+            doTest(fmt, randomDouble(1e-100));
+        }
+    }
+
+    /**
+     * Return a random value from -range..+range.
+     */
+    public double randomDouble(double range) {
+        double a = Math.random();
+        return (2.0 * range * a) - range;
+    }
+
+    public void doTest(NumberFormat fmt, double value) {
+        doTest(fmt, new Double(value));
+    }
+
+    public void doTest(NumberFormat fmt, long value) {
+        doTest(fmt, new Long(value));
+    }
+
+    static double proportionalError(Number a, Number b) {
+        double aa = a.doubleValue(), bb = b.doubleValue();
+        double error = aa - bb;
+        if (aa != 0 && bb != 0) error /= aa;
+        return Math.abs(error);
+    }
+
+    public void doTest(NumberFormat fmt, Number value) {
+        fmt.setMaximumFractionDigits(Integer.MAX_VALUE);
+        String s = fmt.format(value), s2 = null;
+        Number n = null;
+        String err = "";
+        try {
+            if (DEBUG) logln("  " + value + " F> " + escape(s));
+            n = fmt.parse(s);
+            if (DEBUG) logln("  " + escape(s) + " P> " + n);
+            s2 = fmt.format(n);
+            if (DEBUG) logln("  " + n + " F> " + escape(s2));
+
+            if (STRING_COMPARE) {
+                if (!s.equals(s2)) {
+                    if (fmt instanceof DecimalFormat) {
+                        logln("Text mismatch: expected: " + s + ", got: " + s2 + " --- Try BigDecimal parsing.");
+                        ((DecimalFormat)fmt).setParseBigDecimal(true);
+                        n = fmt.parse(s);
+                        if (DEBUG) logln("  " + escape(s) + " P> " + n);
+                        s2 = fmt.format(n);
+                        if (DEBUG) logln("  " + n + " F> " + escape(s2));
+                        ((DecimalFormat)fmt).setParseBigDecimal(false);
+
+                        if (!s.equals(s2)) {
+                            err = "STRING ERROR(DecimalFormat): ";
+                        }
+                    } else {
+                        err = "STRING ERROR(NumberFormat): ";
+                    }
+                }
+            }
+
+            if (EXACT_NUMERIC_COMPARE) {
+                if (value.doubleValue() != n.doubleValue()) {
+                    err += "NUMERIC ERROR: ";
+                }
+            } else {
+                // Compute proportional error
+                double error = proportionalError(value, n);
+
+                if (error > MAX_ERROR) {
+                    err += "NUMERIC ERROR " + error + ": ";
+                }
+
+                if (error > max_numeric_error) max_numeric_error = error;
+                if (error < min_numeric_error) min_numeric_error = error;
+            }
+
+            String message = value + typeOf(value) + " F> " +
+                escape(s) + " P> " +
+                n + typeOf(n) + " F> " +
+                escape(s2);
+            if (err.length() > 0) {
+                errln("*** " + err + " with " +
+                      formatName + " in " + localeName +
+                      " " + message);
+            } else {
+                logln(message);
+            }
+        } catch (ParseException e) {
+            errln("*** " + e.toString() + " with " +
+                  formatName + " in " + localeName);
+        }
+    }
+
+    static String typeOf(Number n) {
+        if (n instanceof Long) return " Long";
+        if (n instanceof Double) return " Double";
+        return " Number";
+    }
+
+    static String escape(String s) {
+        StringBuffer buf = new StringBuffer();
+        for (int i=0; i<s.length(); ++i) {
+            char c = s.charAt(i);
+            if (c < (char)0xFF) {
+                buf.append(c);
+            } else {
+                buf.append("\\U");
+                buf.append(Integer.toHexString((c & 0xF000) >> 12));
+                buf.append(Integer.toHexString((c & 0x0F00) >> 8));
+                buf.append(Integer.toHexString((c & 0x00F0) >> 4));
+                buf.append(Integer.toHexString(c & 0x000F));
+            }
+        }
+        return buf.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/NumberTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4122840 4135202 4408066 4838107 8008577
+ * @summary test NumberFormat
+ * @library /java/text/testlib
+ * @modules java.base/sun.util.resources
+ * @compile -XDignore.symbol.file NumberTest.java
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberTest
+ */
+
+import java.util.*;
+import java.text.*;
+import sun.util.resources.LocaleData;
+
+public class NumberTest extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        new NumberTest().run(args);
+    }
+
+    // Test pattern handling
+    public void TestPatterns()
+    {
+    DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+    String pat[]    = { "#.#", "#.", ".#", "#" };
+    String newpat[] = { "#0.#", "#0.", "#.0", "#" };
+    String num[]    = { "0",   "0.", ".0", "0" };
+    for (int i=0; i<pat.length; ++i)
+    {
+        DecimalFormat fmt = new DecimalFormat(pat[i], sym);
+        String newp = fmt.toPattern();
+        if (!newp.equals(newpat[i]))
+        errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
+              "; " + newp + " seen instead");
+
+        String s = fmt.format(0);
+        if (!s.equals(num[i]))
+        {
+        errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
+              "; " + s + " seen instead");
+        logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
+        }
+    }
+    }
+
+    // Test exponential pattern
+    public void TestExponential() {
+        DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+        String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]"  };
+        double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
+        long lval[] = { 0, -1, 1, 123456789 };
+        String valFormat[] = {
+                "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
+                "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
+                "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
+                "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
+        };
+        String lvalFormat[] = {
+                "0E0", "-1E0", "1E0", "1.2346E8",
+                "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
+                "0E000", "-1E000", "1E000", "123.4568E006",
+                "0E0", "[1E0]", "1E0", "1.235E8"
+        };
+        double valParse[] = {
+                0.01234, 123460000, 1.23E300, -3.1416E-271,
+                0.01234, 123460000, 1.23E300, -3.1416E-271,
+                0.01234, 123456800, 1.23E300, -3.141593E-271,
+                0.01234, 123500000, 1.23E300, -3.142E-271,
+        };
+        long lvalParse[] = {
+                0, -1, 1, 123460000,
+                0, -1, 1, 123460000,
+                0, -1, 1, 123456800,
+                0, -1, 1, 123500000,
+        };
+        int ival = 0, ilval = 0;
+        for (int p=0; p<pat.length; ++p) {
+            DecimalFormat fmt = new DecimalFormat(pat[p], sym);
+            logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" +
+                  fmt.toPattern() + '"');
+
+            for (int v=0; v<val.length; ++v) {
+                String s = fmt.format(val[v]);
+                logln(" Format " + val[v] + " -> " + escape(s));
+                if (!s.equals(valFormat[v+ival])) {
+                    errln("FAIL: Expected " + valFormat[v+ival] +
+                          ", got " + s +
+                          ", pattern=" + fmt.toPattern());
+                }
+
+                ParsePosition pos = new ParsePosition(0);
+                Number a = fmt.parse(s, pos);
+                if (pos.getIndex() == s.length()) {
+                    logln(" Parse -> " + a);
+                    if (a.doubleValue() != valParse[v+ival]) {
+                        errln("FAIL: Expected " + valParse[v+ival] +
+                              ", got " + a.doubleValue() +
+                              ", pattern=" + fmt.toPattern());
+                    }
+                } else {
+                    errln(" FAIL: Partial parse (" + pos.getIndex() +
+                          " chars) -> " + a);
+                }
+            }
+            for (int v=0; v<lval.length; ++v) {
+                String s = fmt.format(lval[v]);
+                logln(" Format " + lval[v] + "L -> " + escape(s));
+                if (!s.equals(lvalFormat[v+ilval])) {
+                    errln("ERROR: Expected " + lvalFormat[v+ilval] +
+                          ", got " + s +
+                          ", pattern=" + fmt.toPattern());
+                }
+
+                ParsePosition pos = new ParsePosition(0);
+                Number a = fmt.parse(s, pos);
+                if (pos.getIndex() == s.length()) {
+                    logln(" Parse -> " + a);
+                    if (a.longValue() != lvalParse[v+ilval]) {
+                        errln("FAIL: Expected " + lvalParse[v+ilval] +
+                              ", got " + a +
+                              ", pattern=" + fmt.toPattern());
+                    }
+                } else {
+                    errln(" FAIL: Partial parse (" + pos.getIndex() +
+                          " chars) -> " + a);
+                }
+            }
+            ival += val.length;
+            ilval += lval.length;
+        }
+    }
+
+    // Test the handling of quotes
+    public void TestQuotes()
+    {
+    String pat;
+    DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+    DecimalFormat fmt = new DecimalFormat(pat = "a'fo''o'b#", sym);
+    String s = fmt.format(123);
+    logln("Pattern \"" + pat + "\"");
+    logln(" Format 123 -> " + escape(s));
+    if (!s.equals("afo'ob123")) errln("FAIL: Expected afo'ob123");
+
+    fmt = new DecimalFormat(pat = "a''b#", sym);
+    s = fmt.format(123);
+    logln("Pattern \"" + pat + "\"");
+    logln(" Format 123 -> " + escape(s));
+    if (!s.equals("a'b123")) errln("FAIL: Expected a'b123");
+    }
+
+    // Test the use of the currency sign
+    public void TestCurrencySign()
+    {
+    DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+    DecimalFormat fmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", sym);
+    // Can't test this properly until currency API goes public
+    // DecimalFormatSymbols sym = fmt.getDecimalFormatSymbols();
+
+    String s = fmt.format(1234.56);
+    logln("Pattern \"" + fmt.toPattern() + "\"");
+    logln(" Format " + 1234.56 + " -> " + escape(s));
+    if (!s.equals("$1,234.56")) errln("FAIL: Expected $1,234.56");
+    s = fmt.format(-1234.56);
+    logln(" Format " + -1234.56 + " -> " + escape(s));
+    if (!s.equals("-$1,234.56")) errln("FAIL: Expected -$1,234.56");
+
+    fmt = new DecimalFormat("\u00A4\u00A4 #,##0.00;\u00A4\u00A4 -#,##0.00", sym);
+    s = fmt.format(1234.56);
+    logln("Pattern \"" + fmt.toPattern() + "\"");
+    logln(" Format " + 1234.56 + " -> " + escape(s));
+    if (!s.equals("USD 1,234.56")) errln("FAIL: Expected USD 1,234.56");
+    s = fmt.format(-1234.56);
+    logln(" Format " + -1234.56 + " -> " + escape(s));
+    if (!s.equals("USD -1,234.56")) errln("FAIL: Expected USD -1,234.56");
+    }
+    static String escape(String s)
+    {
+    StringBuffer buf = new StringBuffer();
+    char HEX[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
+    for (int i=0; i<s.length(); ++i)
+    {
+        char c = s.charAt(i);
+        if (c <= (char)0x7F) buf.append(c);
+        else
+        {
+        buf.append("\\U");
+        buf.append(HEX[(c & 0xF000) >> 12]);
+        buf.append(HEX[(c & 0x0F00) >> 8]);
+        buf.append(HEX[(c & 0x00F0) >> 4]);
+        buf.append(HEX[c & 0x000F]);
+        }
+    }
+    return buf.toString();
+    }
+
+    // Test simple currency format
+    // Bug 4024941; this code used to throw a NumberFormat exception
+    public void TestCurrency() {
+        NumberFormat currencyFmt =
+                NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
+        String s = currencyFmt.format(1.50);
+        logln("Un pauvre ici a..........." + s);
+        if (!s.equals("1,50 $")) {
+            errln("FAIL: Expected 1,50 $; got " + s + "; "+ dumpFmt(currencyFmt));
+        }
+        currencyFmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
+        s = currencyFmt.format(1.50);
+        logln("Un pauvre en Allemagne a.." + s);
+        if (!s.equals("1,50 \u20AC")) {
+            errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));
+        }
+        currencyFmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
+        s = currencyFmt.format(1.50);
+        logln("Un pauvre en France a....." + s);
+        if (!s.equals("1,50 \u20AC")) {
+            errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));
+        }
+    }
+
+    String dumpFmt(NumberFormat numfmt) {
+        DecimalFormat fmt = (DecimalFormat)numfmt;
+        StringBuffer buf = new StringBuffer();
+        buf.append("pattern \"");
+        buf.append(fmt.toPattern());
+        buf.append("\", currency \"");
+        buf.append(fmt.getDecimalFormatSymbols().getCurrencySymbol());
+        buf.append("\"");
+        return buf.toString();
+    }
+
+    // Test numeric parsing
+    // Bug 4059870
+    public void TestParse()
+    {
+    String arg = "0";
+    java.text.DecimalFormat format = new java.text.DecimalFormat("00");
+    try {
+        Number n = format.parse(arg);
+        logln("parse(" + arg + ") = " + n);
+        if (n.doubleValue() != 0.0) errln("FAIL: Expected 0");
+    } catch (Exception e) { errln("Exception caught: " + e); }
+    }
+
+    // Test rounding
+    public void TestRounding487() {
+        NumberFormat nf = NumberFormat.getInstance(Locale.US);
+        roundingTest(nf, 0.00159999, 4, "0.0016");
+        roundingTest(nf, 0.00995,  4, "0.01");
+        roundingTest(nf, 12.7995,  3, "12.8");
+        roundingTest(nf, 12.4999,  0, "12");
+        roundingTest(nf, -19.5,  0, "-20");
+    }
+
+    void roundingTest(NumberFormat nf, double x, int maxFractionDigits, String expected) {
+        nf.setMaximumFractionDigits(maxFractionDigits);
+        String out = nf.format(x);
+        logln("" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
+        if (!out.equals(expected)) {
+            errln("FAIL: Expected " + expected + ", got " + out);
+        }
+    }
+
+    /**
+     * Bug 4135202
+     * DecimalFormat should recognize not only Latin digits 0-9 (\u0030-\u0039)
+     * but also various other ranges of Unicode digits, such as Arabic
+     * digits \u0660-\u0669 and Devanagari digits \u0966-\u096F, to name
+     * a couple.
+     * @see java.lang.Character#isDigit(char)
+     */
+    public void TestUnicodeDigits() {
+        char[] zeros = {
+            0x0030, // ISO-LATIN-1 digits ('0' through '9')
+            0x0660, // Arabic-Indic digits
+            0x06F0, // Extended Arabic-Indic digits
+            0x0966, // Devanagari digits
+            0x09E6, // Bengali digits
+            0x0A66, // Gurmukhi digits
+            0x0AE6, // Gujarati digits
+            0x0B66, // Oriya digits
+            0x0BE6, // Tamil digits
+            0x0C66, // Telugu digits
+            0x0CE6, // Kannada digits
+            0x0D66, // Malayalam digits
+            0x0E50, // Thai digits
+            0x0ED0, // Lao digits
+            0x0F20, // Tibetan digits
+            0xFF10, // Fullwidth digits
+        };
+        NumberFormat format = NumberFormat.getInstance();
+        for (int i=0; i<zeros.length; ++i) {
+            char zero = zeros[i];
+            StringBuffer buf = new StringBuffer();
+            buf.append((char)(zero+3));
+            buf.append((char)(zero+1));
+            buf.append((char)(zero+4));
+            int n = -1;
+            try {
+                n = format.parse(buf.toString()).intValue();
+            }
+            catch (ParseException e) { n = -2; }
+            if (n != 314)
+                errln("Can't parse Unicode " + Integer.toHexString(zero) + " as digit (" + n + ")");
+            else
+                logln("Parse digit " + Integer.toHexString(zero) + " ok");
+        }
+    }
+
+    /**
+     * Bug 4122840
+     * Make sure that the currency symbol is not hard-coded in any locale.
+     */
+    public void TestCurrencySubstitution() {
+        final String SYM = "<currency>";
+        final String INTL_SYM = "<intl.currency>";
+        Locale[] locales = NumberFormat.getAvailableLocales();
+        for (int i=0; i<locales.length; ++i) {
+            NumberFormat nf = NumberFormat.getCurrencyInstance(locales[i]);
+            if (nf instanceof DecimalFormat) {
+                DecimalFormat df = (DecimalFormat)nf;
+                String genericPos = df.format(1234.5678);
+                String genericNeg = df.format(-1234.5678);
+                DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
+                sym.setCurrencySymbol(SYM);
+                sym.setInternationalCurrencySymbol(INTL_SYM);
+                // We have to make a new DecimalFormat from scratch in order
+                // to make the new symbols 'take'.  This may be a bug or
+                // design flaw in DecimalFormat.
+                String[] patterns = LocaleData.getBundle("sun.text.resources.FormatData", locales[i])
+                                              .getStringArray("NumberPatterns");
+                df = new DecimalFormat(patterns[1 /*CURRENCYSTYLE*/], sym);
+                String customPos = df.format(1234.5678);
+                String customNeg = df.format(-1234.5678);
+                if (genericPos.equals(customPos) || genericNeg.equals(customNeg)) {
+                    errln("FAIL: " + locales[i] +
+                          " not using currency symbol substitution: " + genericPos);
+                }
+                else {
+                    if (customPos.indexOf(SYM) >= 0) {
+                        if (customNeg.indexOf(INTL_SYM) >= 0)
+                            errln("Fail: Positive and negative patterns use different symbols");
+                        else
+                            logln("Ok: " + locales[i] +
+                                  " uses currency symbol: " + genericPos +
+                                  ", " + customPos);
+                    }
+                    else if (customPos.indexOf(INTL_SYM) >= 0) {
+                        if (customNeg.indexOf(SYM) >= 0)
+                            errln("Fail: Positive and negative patterns use different symbols");
+                        else
+                            logln("Ok: " + locales[i] +
+                                  " uses intl. currency symbol: " + genericPos +
+                                  ", " + customPos);
+                    }
+                    else {
+                        errln("FAIL: " + locales[i] +
+                              " contains no currency symbol (impossible!)");
+                    }
+                }
+            }
+            else logln("Skipping " + locales[i] + "; not a DecimalFormat");
+        }
+    }
+
+    public void TestIntegerFormat() throws ParseException {
+        NumberFormat format = NumberFormat.getIntegerInstance(Locale.GERMANY);
+
+        float[] formatInput = { 12345.67f, -12345.67f, -0, 0 };
+        String[] formatExpected = { "12.346", "-12.346", "0", "0" };
+
+        for (int i = 0; i < formatInput.length; i++) {
+            String result = format.format(formatInput[i]);
+            if (!result.equals(formatExpected[i])) {
+                errln("FAIL: Expected " + formatExpected[i] + ", got " + result);
+            }
+        }
+
+        String[] parseInput = { "0", "-0", "12.345,67", "-12.345,67" };
+        float[] parseExpected = { 0, 0, 12345, -12345 };
+
+        for (int i = 0; i < parseInput.length; i++) {
+            float result = ((Number) format.parse(parseInput[i])).floatValue();
+            if (result != parseExpected[i]) {
+                errln("FAIL: Expected " + parseExpected[i] + ", got " + result);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/PositionTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4109023 4153060 4153061
+ * @library /java/text/testlib
+ * @summary test ParsePosition and FieldPosition
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - 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.
+*/
+
+import java.text.*;
+import java.io.*;
+
+public class PositionTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new PositionTest().run(args);
+    }
+
+    public void TestParsePosition() {
+        ParsePosition pp1 = new ParsePosition(0);
+        if (pp1.getIndex() == 0) {
+            logln("PP constructor() tested.");
+        }else{
+            errln("*** PP getIndex or constructor() result");
+        }
+
+        {
+            int to = 5;
+            ParsePosition pp2 = new ParsePosition ( to );
+            if (pp2.getIndex() == 5) {
+                logln("PP getIndex and constructor(TextOffset) tested.");
+            }else{
+                errln("*** PP getIndex or constructor(TextOffset) result");
+            }
+            pp2.setIndex( 3 );
+            if (pp2.getIndex() == 3) {
+                logln("PP setIndex tested.");
+            }else{
+                errln("*** PP getIndex or setIndex result");
+            }
+        }
+
+        ParsePosition pp2, pp3;
+        pp2 = new ParsePosition( 3 );
+        pp3 = new ParsePosition( 5 );
+        ParsePosition pp4 = new ParsePosition(5);
+        if (! pp2.equals(pp3)) {
+            logln("PP not equals tested.");
+        }else{
+            errln("*** PP not equals fails");
+        }
+        if (pp3.equals(pp4)) {
+            logln("PP equals tested.");
+        }else{
+            errln("*** PP equals fails (" + pp3.getIndex() + " != " + pp4.getIndex() + ")");
+        }
+
+        ParsePosition pp5;
+        pp5 = pp4;
+        if (pp4.equals(pp5)) {
+            logln("PP operator= tested.");
+        }else{
+            errln("*** PP operator= operator== or operator != result");
+        }
+
+    }
+
+    public void TestFieldPosition() {
+        FieldPosition fp = new FieldPosition( 7 );
+
+        if (fp.getField() == 7) {
+            logln("FP constructor(int) and getField tested.");
+        }else{
+            errln("*** FP constructor(int) or getField");
+        }
+
+        FieldPosition fph = new FieldPosition( 3 );
+        if ( fph.getField() != 3) errln("*** FP getField or heap constr.");
+
+        boolean err1 = false;
+        boolean err2 = false;
+        boolean err3 = false;
+//        for (long i = -50; i < 50; i++ ) {
+//            fp.setField( i+8 );
+//            fp.setBeginIndex( i+6 );
+//            fp.setEndIndex( i+7 );
+//            if (fp.getField() != i+8)  err1 = true;
+//            if (fp.getBeginIndex() != i+6) err2 = true;
+//            if (fp.getEndIndex() != i+7) err3 = true;
+//        }
+        if (!err1) {
+            logln("FP setField and getField tested.");
+        }else{
+            errln("*** FP setField or getField");
+        }
+        if (!err2) {
+            logln("FP setBeginIndex and getBeginIndex tested.");
+        }else{
+            errln("*** FP setBeginIndex or getBeginIndex");
+        }
+        if (!err3) {
+            logln("FP setEndIndex and getEndIndex tested.");
+        }else{
+            errln("*** FP setEndIndex or getEndIndex");
+        }
+
+        logln("");
+    }
+
+    public void TestFieldPosition_example() {
+        //***** no error detection yet !!!!!!!
+        //***** this test is for compiler checks and visual verification only.
+        double doubleNum[] = { 123456789.0, -12345678.9, 1234567.89, -123456.789,
+            12345.6789, -1234.56789, 123.456789, -12.3456789, 1.23456789};
+        int dNumSize = doubleNum.length;
+
+        DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance();
+        fmt.setDecimalSeparatorAlwaysShown(true);
+
+        final int tempLen = 20;
+        StringBuffer temp;
+
+        for (int i=0; i<dNumSize; i++) {
+            temp = new StringBuffer(); // Get new buffer
+
+            FieldPosition pos = new FieldPosition(NumberFormat.INTEGER_FIELD);
+            StringBuffer buf = new StringBuffer();
+            //char fmtText[tempLen];
+            //ToCharString(fmt->format(doubleNum[i], buf, pos), fmtText);
+            StringBuffer res = fmt.format(doubleNum[i], buf, pos);
+            int tempOffset = (tempLen <= (tempLen - pos.getEndIndex())) ?
+                tempLen : (tempLen - pos.getEndIndex());
+            for (int j=0; j<tempOffset; j++) temp.append('='); // initialize
+            //cout << temp << fmtText   << endl;
+            logln("FP " + temp + res);
+        }
+
+        logln("");
+    }
+    /* @bug 4109023
+     * Need to override ParsePosition.equals and FieldPosition.equals.
+     */
+    public void Test4109023()
+    {
+
+        ParsePosition p = new ParsePosition(3);
+        ParsePosition p2 = new ParsePosition(3);
+        if (!p.equals(p2))
+            errln("Error : ParsePosition.equals() failed");
+        FieldPosition fp = new FieldPosition(2);
+        FieldPosition fp2 = new FieldPosition(2);
+        if (!fp.equals(fp2))
+            errln("Error : FieldPosition.equals() failed");
+    }
+
+    /**
+     * @bug 4153060
+     * ParsePosition.hashCode() returns different values on equal objects.
+     */
+    public void Test4153060() {
+        ParsePosition p = new ParsePosition(53);
+        ParsePosition q = new ParsePosition(53);
+        if (!p.equals(q)) {
+            errln("" + p + " and " + q + " are not equal and should be");
+        }
+        if (p.hashCode() != q.hashCode()) {
+            errln("ParsePosition.hashCode() different for equal objects");
+        } else {
+            logln("hashCode(" + p + ") = " + p.hashCode());
+        }
+    }
+
+    /**
+     * @bug 4153061
+     * FieldPosition.hashCode() returns different values on equal objects.
+     */
+    public void Test4153061() {
+        FieldPosition p = new FieldPosition(53);
+        FieldPosition q = new FieldPosition(53);
+        if (!p.equals(q)) {
+            errln("" + p + " and " + q + " are not equal and should be");
+        }
+        if (p.hashCode() != q.hashCode()) {
+            errln("FieldPosition.hashCode() different for equal objects");
+        } else {
+            logln("hashCode(" + p + ") = " + p.hashCode());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/SerializationLoadTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4101150
+ * @library /java/text/testlib
+ * @build SerializationLoadTest HexDumpReader
+ * @run main SerializationLoadTest
+ * @summary test serialization compatibility of DecimalFormat and DecimalFormatSymbols
+ * @key randomness
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class SerializationLoadTest {
+
+    public static void main(String[] args)
+    {
+        try {
+            InputStream istream1 = HexDumpReader.getStreamFromHexDump("DecimalFormat.114.txt");
+            ObjectInputStream p = new ObjectInputStream(istream1);
+            CheckDecimalFormat it = (CheckDecimalFormat)p.readObject();
+            System.out.println("1.1.4 DecimalFormat Loaded ok.");
+            System.out.println(it.Update());
+            System.out.println("Called Update successfully.");
+            istream1.close();
+
+            InputStream istream2 = HexDumpReader.getStreamFromHexDump("DecimalFormatSymbols.114.txt");
+            ObjectInputStream p2 = new ObjectInputStream(istream2);
+            CheckDecimalFormatSymbols it2 = (CheckDecimalFormatSymbols)p2.readObject();
+            System.out.println("1.1.4 DecimalFormatSymbols Loaded ok.");
+            System.out.println("getDigit : "  + it2.Update());
+            System.out.println("Called Update successfully.");
+            istream2.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
+
+class CheckDecimalFormat implements Serializable
+{
+    DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
+
+    public String Update()
+    {
+        Random r = new Random();
+        return _decFormat.format(r.nextDouble());
+    }
+}
+
+class CheckDecimalFormatSymbols implements Serializable
+{
+    DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
+
+    public char Update()
+    {
+        return  _decFormatSymbols.getDigit();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/SerializationSaveTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on JDK 1.1.4.
+ * Instead, the resulting serialized files DecimalFormat.114 and
+ * DecimalFormatSymbols.114 are archived.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class SerializationSaveTest {
+
+    public static void main(String[] args)
+    {
+        try {
+            CheckDecimalFormat it = new CheckDecimalFormat();
+            System.out.println(it.Update());
+            FileOutputStream ostream = new FileOutputStream("DecimalFormat.114");
+            ObjectOutputStream p = new ObjectOutputStream(ostream);
+            p.writeObject(it);
+            ostream.close();
+            System.out.println("DecimalFormat saved ok.");
+            CheckDecimalFormatSymbols it2 = new CheckDecimalFormatSymbols();
+            System.out.println("getDigit : "  + it2.Update());
+            FileOutputStream ostream2 = new FileOutputStream("DecimalFormatSymbols.114");
+            ObjectOutputStream p2 = new ObjectOutputStream(ostream2);
+            p2.writeObject(it2);
+            ostream2.close();
+            System.out.println("DecimalFormatSymbols saved ok.");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
+
+class CheckDecimalFormat implements Serializable
+{
+    DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
+
+    public String Update()
+    {
+        Random r = new Random();
+        return _decFormat.format(r.nextDouble());
+    }
+}
+
+class CheckDecimalFormatSymbols implements Serializable
+{
+    DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
+
+    public char Update()
+    {
+        return  _decFormatSymbols.getDigit();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/NumberFormat/TestgetPatternSeparator_ja.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * 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 4201262
+ * @summary Make sure that DecimalFormatSymbols.getPatternSeparator returns ';' in ja locale.
+ */
+
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+public class TestgetPatternSeparator_ja {
+
+    public static void main(String[] argv) throws Exception {
+        DecimalFormat df = (DecimalFormat)NumberFormat.getInstance(Locale.JAPAN);
+        DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
+        if (dfs.getPatternSeparator() != ';') {
+            throw new Exception("DecimalFormatSymbols.getPatternSeparator doesn't return ';' in ja locale");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/Bug4769840.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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
+ * 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 1.1 03/10/27
+ * @bug 4769840
+ * @library /java/text/testlib
+ * @build Bug4769840 HexDumpReader
+ * @run main Bug4769840
+ * @summary Confirm serialization compatibility
+ */
+
+import java.io.*;
+import java.text.*;
+
+public class Bug4769840 {
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 1 && args[0].equals("-ser")) {
+            serialize();
+        } else {
+            deserialize();
+        }
+    }
+
+    /* Serialization */
+    private static void serialize() throws Exception {
+        /* Serialize with JDK 1.1 */
+        serialize("ChoiceFormat.ser", new ChoiceFormat("0# foo|1# bar"));
+
+        /*
+         * Serialize with JDK1.4.0 because the Field class was added in the
+         * version.
+         */
+        serialize("DateFormat.Field.ser", DateFormat.Field.TIME_ZONE);
+        serialize("MessageFormat.Field.ser", MessageFormat.Field.ARGUMENT);
+        serialize("NumberFormat.Field.ser", NumberFormat.Field.INTEGER);
+    }
+
+    private static void serialize(String filename, Object o) throws Exception {
+        FileOutputStream fos = new FileOutputStream(filename);
+        ObjectOutputStream out = new ObjectOutputStream(fos);
+        out.writeObject(o);
+        out.close();
+    }
+
+    /* Deserialization */
+    private static void deserialize() throws Exception {
+        deserialize("ChoiceFormat.ser");
+        deserialize("DateFormat.Field.ser");
+        deserialize("MessageFormat.Field.ser");
+        deserialize("NumberFormat.Field.ser");
+    }
+
+    private static void deserialize(String filename) throws Exception {
+        InputStream is = HexDumpReader.getStreamFromHexDump(filename + ".txt");
+        ObjectInputStream in = new ObjectInputStream(is);
+        Object obj = in.readObject();
+        in.close();
+        System.out.println("Deserialization of <" + filename + "> succeeded.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/Bug6215962.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6215962
+ * @summary Confirm that replacing Utility.arayEquals methods have with
+ * Arrays.equals introduces no problem.
+ */
+import java.text.*;
+import java.util.*;
+
+public class Bug6215962 {
+
+    public static void main(String[] args) {
+        testMessageFormat();
+        testChoiceFormat();
+        testDateFormatSymbols();
+    }
+
+    /**
+     * Test cases for MessageFormat
+     */
+    static void testMessageFormat() {
+        MessageFormat mf1 = new MessageFormat("{0}", null);
+        MessageFormat mf2 = new MessageFormat("{0}", null);
+        check(mf1, mf2, true);
+
+        mf1.setLocale(null);
+        check(mf1, mf2, true);
+
+        mf1 = new MessageFormat("{0}", Locale.US);
+        check(mf1, mf2, false);
+
+        mf2 = new MessageFormat("{0}", Locale.JAPAN);
+        check(mf1, mf2, false);
+
+        mf1 = new MessageFormat("{0}", new Locale("ja", "JP"));
+        check(mf1, mf2, true);
+
+        mf1.setLocale(null);
+        check(mf1, mf2, false);
+
+        mf1 = new MessageFormat("{0}", new Locale("ja", "JP", "FOO"));
+        check(mf1, mf2, false);
+
+        mf2 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO"));
+        check(mf1, mf2, false);
+
+        mf1 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO"));
+        check(mf1, mf2, true);
+
+        mf1 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO"));
+        check(mf1, mf2, false);
+
+        mf2 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO"));
+        check(mf1, mf2, true);
+    }
+
+    static void check(MessageFormat f1, MessageFormat f2, boolean expected) {
+        boolean got = f1.equals(f2);
+        if (got != expected) {
+            throw new RuntimeException("Test failed for MessageFormat.equals(). Got: " + got + ", Expected: " + expected);
+        }
+    }
+
+    /**
+     * Test cases for MessageFormat
+     */
+    static void testChoiceFormat() {
+        double[] limits0 = {0,1,2,3,4,5,6};
+        double[] limits1 = {1,2,3,4,5,6,7};
+        String[] monthNames0 = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
+        String[] monthNames1 = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
+
+        ChoiceFormat cf1 = new ChoiceFormat(limits1, monthNames0);
+        ChoiceFormat cf2 = new ChoiceFormat(limits1, monthNames0);
+        check(cf1, cf2, true);
+
+        cf2 = new ChoiceFormat(limits0, monthNames0);
+        check(cf1, cf2, false);
+
+        cf2 = new ChoiceFormat(limits1, monthNames1);
+        check(cf1, cf2, false);
+    }
+
+    static void check(ChoiceFormat f1, ChoiceFormat f2, boolean expected) {
+        boolean got = f1.equals(f2);
+        if (got != expected) {
+            throw new RuntimeException("Test failed for ChoiceFormat.equals(). Got: " + got + ", Expected: " + expected);
+        }
+    }
+
+    /**
+     * Test cases for DateFormatSymbols
+     */
+    static void testDateFormatSymbols() {
+        DateFormatSymbols dfs1 = new DateFormatSymbols();
+        DateFormatSymbols dfs2 = new DateFormatSymbols();
+        check(dfs1, dfs2, true);
+
+        // Becase eras, months, shortmonths, weekdays, shortweekdays, ampms are
+        // the same data type (String[]) and are treated in the same way, here
+        // I test only Months.
+        String[] tmp = dfs1.getMonths();
+        String saved = tmp[0];
+        tmp[0] = "Foo";
+        dfs1.setMonths(tmp);
+        check(dfs1, dfs2, false);
+
+        tmp[0] = saved;
+        dfs1.setMonths(tmp);
+        check(dfs1, dfs2, true);
+
+        // Test LocalizedpatternChars (String)
+        String pattern = dfs2.getLocalPatternChars();
+        dfs2.setLocalPatternChars("Bar");
+        check(dfs1, dfs2, false);
+
+        dfs2.setLocalPatternChars(pattern);
+        check(dfs1, dfs2, true);
+
+        // Test TimeZone strings (String[][])
+        String[][] zones = dfs1.getZoneStrings();
+        saved = zones[0][1];
+        zones[0][1] = "Yokohama Summer Time";
+        dfs1.setZoneStrings(zones);
+        check(dfs1, dfs2, false);
+
+        zones[0][1] = saved;
+        dfs1.setZoneStrings(zones);
+        check(dfs1, dfs2, true);
+    }
+
+    static void check(DateFormatSymbols dfs1, DateFormatSymbols dfs2, boolean expected) {
+        boolean got = dfs1.equals(dfs2);
+        if (got != expected) {
+            throw new RuntimeException("Test failed for DateFormatSymbols.equals(). Got: " + got + ", Expected: " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/ChoiceFormat.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,37 @@
+#
+# 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
+# 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.
+#
+
+# Hex dump of a serialized ChoiceFormat for Bug4769840.
+
+aced0005737200166a6176612e746578742e43686f696365466f726d617418e9
+c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61
+76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400
+025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3
+bf137d07e80200065a000c67726f7570696e67557365644200116d6178467261
+6374696f6e4469676974734200106d6178496e74656765724469676974734200
+116d696e4672616374696f6e4469676974734200106d696e496e746567657244
+69676974735a00107061727365496e74656765724f6e6c79787200106a617661
+2e746578742e466f726d6174fbd8bc12e90f1843020000787001032800010075
+7200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200
+0078700000000274000420666f6f74000420626172757200025b443ea68c14ab
+635a1e02000078700000000200000000000000003ff0000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/DateFormat.Field.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,32 @@
+#
+# 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
+# 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.
+#
+
+# Hex dump of a serialized DateFormat.Field for Bug4769840.
+
+aced00057372001a6a6176612e746578742e44617465466f726d617424466965
+6c646744fc81f123e71002000149000d63616c656e6461724669656c64787200
+166a6176612e746578742e466f726d6174244669656c6403d7fbbd383b0f9b02
+00007872002f6a6176612e746578742e41747472696275746564436861726163
+7465724974657261746f7224417474726962757465811e7426cd47175c020001
+4c00046e616d657400124c6a6176612f6c616e672f537472696e673b78707400
+0974696d65207a6f6e65ffffffff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/FormatIteratorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4018937
+ * @library /java/text/testlib
+ * @build FormatIteratorTest PParser IntlTest
+ * @run main FormatIteratorTest
+ * @summary Tests the formatToCharacterIterator method of SimpleDateFormat,
+ *          MessageFormat and DecimalFormat.
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * FormatTester creates Formats, and tests the resulting FieldPositions
+ * and AttributedCharacterIterator based on a file. The file is a hierarchical
+ * set of key/value pairs, where each value can also be an array or map. The
+ * top map must contain a tests entry, which will be an array consisting
+ * of pairs of maps. The first map specifies the Format that
+ * should be created, and consists of:
+ * <pre>
+ *   class = className
+ *   args = (arg1 arg2 ...)
+ *   valueClass = className
+ *   valueArgs = (arg1 arg2 ...)
+ * </pre>
+ * The second map dictates what to test, and should consist of the following:
+ * <pre>
+ *   length = lengthOfFormattedString
+ *   text = Result of Formatting
+ *   0...lengthOfFormattedString = (arg1 arg2 ...)
+ *   limits = ( range1 range2 ...)
+ *   fieldPositions = ( fp1 fp2 ...)
+ * </pre>
+ * <code>lengthOfFormattedString</code> indicate the total length of formatted
+ * string. <code>text</code> indicates the resulting string.
+ * <code>0...x</code> where x == <code>lengthOfFormattedString - 1</code> is
+ * an array of the attributes that should exist at the particular
+ * location. <code>limits</code> is an array of maps, where each map
+ * can be used to test the bounds of a set of attributes. Each map will
+ * consist of:
+ * <pre>
+ *   attributes = array of attributes
+ *   begin = start location
+ *   begin2 = second start location
+ *   end = limit location
+ *   end2 = second limit location
+ * </pre>
+ * These are tested by iterating from begin to end in the CharacterIterator
+ * and doing the following at each index:
+ * <pre>
+ *   getRunStart() == begin
+ *   getRunStart(attributes) == begin2
+ *   getRunLimit() == end
+ *   getRunLimit(attributes) == end2
+ * </pre>
+ * <code>fieldPositions</code> is used to test the results of invoking
+ * <code>format</code> with a <code>FieldPosition</code>.
+ * <code>fieldPositions</code> is an array of maps, where each map contains
+ * the following:
+ * <pre>
+ *   field = Integer field reference (optional)
+ *   fieldID = Object reference
+ *   begin = begin index of FieldPosition after formatting
+ *   end = end index of FieldPosition after formatting
+ * </pre>
+ * Any lines starting with {@code '#'} are comment lines and ignored.
+ */
+public class FormatIteratorTest extends IntlTest {
+    private static HashMap attrs;
+    private Format format;
+    private Object value;
+    private String text;
+
+    public static final Object ARG0_FIELD_ID = MessageFormat.
+                                                     Field.ARGUMENT;
+    public static final Object ARG1_FIELD_ID = MessageFormat.
+                                                     Field.ARGUMENT;
+    public static final Object ARG2_FIELD_ID = MessageFormat.
+                                                     Field.ARGUMENT;
+    public static final Object ARG3_FIELD_ID = MessageFormat.
+                                                     Field.ARGUMENT;
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        TimeZone reservedTimeZone = TimeZone.getDefault();
+        try {
+            // The current tests are only appropriate for US. If tests are
+            // added for other locales are added, then a property should be
+            // added to each file (test) to be able to specify the locale.
+            Locale.setDefault(Locale.US);
+            TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+            new FormatIteratorTest().run(args);
+        } finally {
+            // restore the reserved locale and time zone
+            Locale.setDefault(reservedLocale);
+            TimeZone.setDefault(reservedTimeZone);
+        }
+    }
+
+    public FormatIteratorTest() {
+    }
+
+    public void testDecimalFormat() {
+        _test(new File(System.getProperty("test.src", "."),
+                       "decimalFormat.props"));
+    }
+
+    public void testMessageFormat() {
+        _test(new File(System.getProperty("test.src", "."),
+                       "messageFormat.props"));
+    }
+
+    public void testDateFormat() {
+        _test(new File(System.getProperty("test.src", "."),
+                       "dateFormat.props"));
+    }
+
+    private void _test(File file) {
+        try {
+            attrs = new HashMap();
+            logln("testing: " + file);
+            PParser parser = new PParser();
+            Hashtable contents = parser.parse(new BufferedReader(
+                new FileReader(file)));
+            Vector test = (Vector)contents.get("tests");
+
+            for (int counter = 0; counter < test.size(); counter++) {
+                logln("creating: " + (counter / 2));
+
+                AttributedCharacterIterator iterator =
+                    create((Hashtable)test.get(counter));
+
+                logln("verifying: " + (counter / 2));
+                verify(iterator, (Hashtable)test.get(++counter));
+            }
+        } catch (IOException ioe) {
+            errln("Error reading: " + ioe);
+        }
+    }
+
+    public void verify(AttributedCharacterIterator iterator,Hashtable table) {
+        int length = Integer.parseInt((String)table.get("length"));
+
+        // Verify the text
+        if (!getText(iterator).equals(
+                escapeIfNecessary((String)table.get("text")))) {
+            String text = getText(iterator);
+
+            errln("text doesn't match, got: " + getText(iterator));
+        }
+        if (iterator.getBeginIndex() != 0) {
+            errln("Bogus start: " + iterator.getBeginIndex());
+        }
+        if (iterator.getEndIndex() != length) {
+            errln("Bogus end: " + iterator.getEndIndex());
+        }
+        for (int counter = 0; counter < length; counter++) {
+            iterator.setIndex(counter);
+            if (!verifyAttributes(iterator.getAttributes().keySet(),
+                    makeAttributes((Vector)table.get(Integer.
+                                                      toString(counter))))) {
+                errln("Attributes don't match at " + counter + " expecting " +
+                      makeAttributes((Vector)table.get(Integer.toString
+                                                       (counter))) + " got " +
+                      iterator.getAttributes().keySet());
+            }
+        }
+        for (int counter = length - 1; counter >= 0; counter--) {
+            iterator.setIndex(counter);
+            if (!verifyAttributes(iterator.getAttributes().keySet(),
+                    makeAttributes((Vector)table.get(Integer.
+                                                      toString(counter))))) {
+                errln("Attributes don't match at " + counter + " expecting " +
+                      makeAttributes((Vector)table.get(Integer.toString
+                                                       (counter))) + " got " +
+                      iterator.getAttributes().keySet());
+            }
+        }
+        verifyLimits(iterator, table);
+
+        text = escapeIfNecessary((String)table.get("text"));
+        Vector fps = (Vector)table.get("fieldPositions");
+
+        if (fps != null) {
+            for (int counter = 0; counter < fps.size(); counter++) {
+                verifyFieldPosition(counter, (Hashtable)fps.get(counter));
+            }
+        }
+    }
+
+    private void verifyLimits(AttributedCharacterIterator iterator,
+                              Hashtable table) {
+        Vector limits = (Vector)table.get("limits");
+
+        if (limits != null) {
+            for (int counter = 0; counter < limits.size(); counter++) {
+                verifyLimit(iterator, (Hashtable)limits.get(counter));
+            }
+        }
+    }
+
+    private void verifyLimit(AttributedCharacterIterator iterator,
+                             Hashtable table) {
+        int begin = Integer.parseInt((String)table.get("begin"));
+        int end = Integer.parseInt((String)table.get("end"));
+        Set attrs = makeAttributes((Vector)table.get("attributes"));
+        String begin2S = (String)table.get("begin2");
+        int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin;
+        String end2S = (String)table.get("end2");
+        int end2 = (end2S != null) ? Integer.parseInt(end2S) : end;
+
+        for (int counter = begin; counter < end; counter++) {
+            iterator.setIndex(counter);
+            if (iterator.getRunStart() != begin) {
+                errln("Begin doesn't match want " + begin + " got " +
+                      iterator.getRunStart() + " at " + counter + " attrs " +
+                      attrs);
+            }
+            if (iterator.getRunStart(attrs) != begin2) {
+                errln("Begin2 doesn't match want " + begin2 + " got " +
+                      iterator.getRunStart(attrs) + " at " + counter +
+                      " attrs " + attrs);
+            }
+            if (iterator.getRunLimit() != end) {
+                errln("End doesn't match want " + end + " got " +
+                      iterator.getRunLimit() + " at " + counter + " attrs " +
+                      attrs);
+            }
+            if (iterator.getRunLimit(attrs) != end2) {
+                errln("End2 doesn't match want " + end2 + " got " +
+                      iterator.getRunLimit(attrs) + " at " + counter +
+                      " attrs " + attrs);
+            }
+        }
+    }
+
+    private boolean verifyAttributes(Set a, Set b) {
+        boolean aEmpty = (a.size() == 0);
+        boolean bEmpty = (b.size() == 0);
+
+        if (aEmpty && bEmpty) {
+            return true;
+        }
+        else if (aEmpty || bEmpty) {
+            return false;
+        }
+        return a.equals(b);
+    }
+
+    private String getText(AttributedCharacterIterator iterator) {
+        StringBuffer buffer = new StringBuffer();
+
+        for (int counter = 0; counter < iterator.getEndIndex(); counter++) {
+            buffer.append(iterator.setIndex(counter));
+        }
+        return buffer.toString();
+    }
+
+    private void verifyFieldPosition(int index, Hashtable table) {
+        Object o = table.get("field");
+        int begin = Integer.parseInt((String)table.get("begin"));
+        int end = Integer.parseInt((String)table.get("end"));
+
+        if (o != null) {
+            FieldPosition fp = new FieldPosition(((Integer)
+                                          lookupField((String)o)).intValue());
+
+            verifyFieldPosition(fp, begin, end, index);
+        }
+        o = table.get("fieldID");
+        if (o != null) {
+            FieldPosition fp = new FieldPosition((Format.Field)
+                                                 lookupField((String)o));
+            verifyFieldPosition(fp, begin, end, index);
+        }
+    }
+
+    private void verifyFieldPosition(FieldPosition fp, int begin, int end,
+                                     int index) {
+        StringBuffer buffer = new StringBuffer();
+
+        format.format(value, buffer, fp);
+        if (fp.getBeginIndex() != begin) {
+            errln("bogus begin want " + begin + " got " + fp.getBeginIndex() +
+                  " for " + fp + " at " + index);
+        }
+        if (fp.getEndIndex() != end) {
+            errln("bogus end want " + end + " got " + fp.getEndIndex() +
+                  " for " + fp + " at " + index);
+        }
+        if (!buffer.toString().equals(text)) {
+            errln("Text does not match, want !" + buffer.toString() +
+                  "! got !" + text + "!");
+        }
+    }
+
+    public AttributedCharacterIterator create(Hashtable table) {
+        format = (Format)createInstance((String)table.get("class"),
+                                        ((Vector)table.get("args")).toArray());
+        value = createInstance((String)table.get("valueClass"),
+                               ((Vector)table.get("valueArgs")).toArray());
+
+        logln("Created format: " + format + " value " + value);
+        AttributedCharacterIterator aci = format.
+                           formatToCharacterIterator(value);
+
+        logln("Obtained Iterator: " + aci);
+        return aci;
+    }
+
+    public Format.Field makeAttribute(String name) {
+        return (Format.Field)lookupField(name);
+    }
+
+    private Object createInstance(String className, Object[] args) {
+        if (className.equals("java.lang.reflect.Array")) {
+            for (int counter = 0; counter < args.length; counter++) {
+                if (args[counter] instanceof Vector) {
+                    Vector v = (Vector)args[counter];
+
+                    args[counter] = createInstance((String)v.get(0),
+                                               ((Vector)v.get(1)).toArray());
+                }
+            }
+            return args;
+        }
+        for (int counter = 0; counter < args.length; counter++) {
+            args[counter] = escapeIfNecessary((String)args[counter]);
+        }
+        try {
+            if (className.equals("java.util.concurrent.atomic.AtomicInteger")) {
+                return new AtomicInteger(Integer.valueOf((String)args[0]));
+            } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) {
+                return new AtomicLong(Long.valueOf((String)args[0]));
+            } else {
+                Class klass = lookupClass(className);
+                Constructor cons = klass.getConstructor(
+                    new Class[] { String.class });
+                Object value = cons.newInstance(args);
+
+                return value;
+            }
+        } catch (Throwable th) {
+            errln("Error creating instance " + th);
+            return null;
+        }
+    }
+
+    private Class lookupClass(String name) throws ClassNotFoundException {
+        try {
+            Class klass = Class.forName(name);
+
+            return klass;
+        } catch (ClassNotFoundException e1) {}
+
+        try {
+            Class klass = Class.forName("java.lang." + name);
+
+            return klass;
+        } catch (ClassNotFoundException e1) {}
+
+        Class klass = Class.forName("java.text." + name);
+
+        return klass;
+    }
+
+    private Object lookupField(String name) {
+        Throwable error = null;
+
+        try {
+            int dotIndex = name.indexOf('.');
+            Class klass = lookupClass(name.substring(0, dotIndex));
+            String fieldName = name.substring(dotIndex + 1);
+            Field[] fields = klass.getFields();
+
+            for (int counter = fields.length - 1; counter >= 0; counter--) {
+                if (fields[counter].getName().equals(fieldName)) {
+                    return fields[counter].get(null);
+                }
+            }
+        } catch (Throwable th) {
+            error = th;
+        }
+        errln("Could not lookup field " + name + " " + error);
+        return null;
+    }
+
+    protected String escapeIfNecessary(String string) {
+        if (string != null) {
+            int index;
+
+            if ((index = string.indexOf("\\u")) != -1) {
+                StringBuffer sb = new StringBuffer(string.substring(0, index));
+
+                sb.append((char)Integer.parseInt(
+                    string.substring(index + 2, index + 6), 16));
+                sb.append(string.substring(index + 6));
+                string = sb.toString();
+            }
+        }
+        return string;
+    }
+
+    public Set makeAttributes(Vector names) {
+        HashSet set = new HashSet(Math.max(1, names.size()));
+
+        for (int counter = 0; counter < names.size(); counter++) {
+            set.add(makeAttribute((String)names.get(counter)));
+        }
+        return set;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/MessageFormat.Field.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,32 @@
+#
+# 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
+# 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.
+#
+
+# Hex dump of a serialized MessageFormat.Field for Bug4769840.
+
+aced00057372001d6a6176612e746578742e4d657373616765466f726d617424
+4669656c646da23d2c7b46bfaa020000787200166a6176612e746578742e466f
+726d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e7465
+78742e417474726962757465644368617261637465724974657261746f722441
+7474726962757465811e7426cd47175c0200014c00046e616d657400124c6a61
+76612f6c616e672f537472696e673b78707400166d6573736167652061726775
+6d656e74206669656c64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/NumberFormat.Field.ser.txt	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,31 @@
+#
+# 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
+# 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.
+#
+
+# Hex dump of a serialized NumberFormat.Field for Bug4769840.
+
+aced00057372001c6a6176612e746578742e4e756d626572466f726d61742446
+69656c646802a038193ff37a020000787200166a6176612e746578742e466f72
+6d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e746578
+742e417474726962757465644368617261637465724974657261746f72244174
+74726962757465811e7426cd47175c0200014c00046e616d657400124c6a6176
+612f6c616e672f537472696e673b7870740007696e7465676572
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/PParser.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.util.*;
+
+/*
+ * assignment : key = value;
+ * key        : string
+ * value      : string | array | dict
+ * nValue     : , value
+ * array      : ( value nValue )
+ * nAssignment: , assignment|value
+ * dict       : { assignment* }
+ * string     : "*" or anything but a ,(){}=
+ *
+ * special characters: ,(){}=
+ */
+
+public class PParser {
+    protected static final int      OPEN_PAIR = 1;
+    protected static final int      CLOSE_PAIR = 2;
+    protected static final int      OPEN_ARRAY = 3;
+    protected static final int      CLOSE_ARRAY = 4;
+    protected static final int      MORE = 5;
+    protected static final int      EQUAL = 6;
+    protected static final int      STRING = 7;
+    protected static final int      WS = 8;
+
+    protected Reader          reader;
+    protected boolean         bufferedToken;
+    protected StringBuffer    stringBuffer = new StringBuffer();
+    protected int             lastChar;
+    protected int             lastToken;
+    protected int             lineNumber;
+    protected int             column;
+
+    public PParser() {
+    }
+
+    public Hashtable parse(Reader r) throws IOException {
+        this.reader = r;
+        bufferedToken = false;
+        lineNumber = 0;
+        column = 0;
+        if (getToken() != OPEN_PAIR) {
+            error("No initial open");
+        }
+        return parsePair();
+    }
+
+    protected Object parseValue(int lookAhead) throws IOException {
+        int           token;
+
+        if (lookAhead == -1) {
+            token = getToken();
+        } else {
+            token = lookAhead;
+        }
+        switch (token) {
+        case STRING:
+            return stringBuffer.toString();
+        case OPEN_ARRAY:
+            return parseArray();
+        case OPEN_PAIR:
+            return parsePair();
+        default:
+            error("Expecting value");
+        }
+        return null;
+    }
+
+    protected Object parseArray() throws IOException {
+        Vector       array = new Vector();
+        int          token;
+
+        while ((token = getToken()) != CLOSE_ARRAY) {
+            if (token == MORE) {
+                token = getToken();
+            }
+            if (token != CLOSE_ARRAY) {
+                array.addElement(parseValue(token));
+            }
+        }
+        return array;
+    }
+
+    protected Hashtable parsePair() throws IOException {
+        Hashtable           ht = new Hashtable(11);
+        int                 token;
+
+        while ((token = getToken()) != CLOSE_PAIR) {
+            if (token != STRING) {
+                error("Pair expecting string got");
+            }
+            String     key = stringBuffer.toString();
+
+            if (getToken() != EQUAL) {
+                error("Expecting = ");
+            }
+
+            Object     value = parseValue(-1);
+            ht.put(key, value);
+        }
+        return ht;
+    }
+
+    protected void ungetToken() {
+        if (bufferedToken) {
+            error("Can not buffer more than one token");
+        }
+        bufferedToken = true;
+    }
+
+    protected int getToken() throws IOException {
+        int            token = getToken(false, false);
+
+        return token;
+    }
+
+    protected int getToken(boolean wantsWS, boolean inString)
+        throws IOException {
+        if (bufferedToken) {
+            bufferedToken = false;
+            if (lastToken != WS || wantsWS) {
+                return lastToken;
+            }
+        }
+        while ((lastChar = reader.read()) != -1) {
+            // If a line starts with '#', skip the line.
+            if (column == 0 && lastChar == '#') {
+                while ((lastChar = reader.read()) != -1
+                       && lastChar != '\n') {
+                }
+                if (lastChar == -1) {
+                    break;
+                }
+            }
+
+            column++;
+            switch(lastChar) {
+            case '\n':
+                lineNumber++;
+                column = 0;
+            case ' ':
+            case '\r':
+            case '\t':
+                if (wantsWS) {
+                    lastToken = WS;
+                    return WS;
+                }
+                break;
+            case ',':
+                lastToken = MORE;
+                return MORE;
+            case '(':
+                lastToken = OPEN_ARRAY;
+                return OPEN_ARRAY;
+            case ')':
+                lastToken = CLOSE_ARRAY;
+                return CLOSE_ARRAY;
+            case '{':
+                lastToken = OPEN_PAIR;
+                return OPEN_PAIR;
+            case '}':
+                lastToken = CLOSE_PAIR;
+                return CLOSE_PAIR;
+            case '=':
+                lastToken = EQUAL;
+                return EQUAL;
+            case '"':
+                lastToken = STRING;
+                if (!inString) {
+                    stringBuffer.setLength(0);
+                    while (true) {
+                        getToken(true, true);
+                        if (lastChar == '"') {
+                            lastToken = STRING;
+                            return STRING;
+                        }
+                        stringBuffer.append((char)lastChar);
+                    }
+                }
+                return STRING;
+            default:
+                lastToken = STRING;
+                if (!inString) {
+                    stringBuffer.setLength(0);
+                    stringBuffer.append((char)lastChar);
+                    while (getToken(true, true) == STRING) {
+                        if (lastChar == '"') {
+                            error("Unexpected quote");
+                        }
+                        stringBuffer.append((char)lastChar);
+                    }
+                    ungetToken();
+                }
+                return STRING;
+            }
+        }
+        return -1;
+    }
+
+    protected void error(String errorString) {
+        throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column);
+    }
+
+    public static void dump(Object o) {
+        if (o instanceof String) {
+            System.out.print(o);
+        } else if(o instanceof Vector) {
+            Enumeration     e = ((Vector)o).elements();
+
+            dump(" (");
+            while (e.hasMoreElements()) {
+                dump(e.nextElement());
+                dump(" -- ");
+            }
+            dump(" )");
+        } else {
+            Hashtable       ht = (Hashtable)o;
+            Enumeration     e = ht.keys();
+
+            dump(" {");
+            while (e.hasMoreElements()) {
+                Object       key = e.nextElement();
+
+                dump(key);
+                dump(" = ");
+                dump(ht.get(key));
+                dump(";");
+            }
+            dump(" }");
+        }
+    }
+
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            System.out.println("need filename");
+        } else {
+            try {
+                FileReader          fr = new FileReader(args[0]);
+                PParser             parser = new PParser();
+                Hashtable           ht = parser.parse(fr);
+
+                dump(ht);
+                System.out.println();
+            }
+            catch (IOException ioe) {
+                System.out.println("Couldn't parse: " + ioe);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/dateFormat.props	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,333 @@
+#
+# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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 data for FormatIteratorTest
+
+{
+  tests =
+  (
+    {
+      class = java.text.SimpleDateFormat
+      args = ("M/dd/yy")
+      valueClass = java.util.Date
+      valueArgs = ("7/10/71")
+    }
+    {
+      length = 7
+      text = "7/10/71"
+      0 = (DateFormat$Field.MONTH)
+      1 = ()
+      2 = (DateFormat$Field.DAY_OF_MONTH)
+      3 = (DateFormat$Field.DAY_OF_MONTH)
+      4 = ()
+      5 = (DateFormat$Field.YEAR)
+      6 = (DateFormat$Field.YEAR)
+      limits = ( { attributes = (DateFormat$Field.MONTH)
+                   begin = 0 end = 1}
+                 { attributes = ()
+                   begin = 1 begin2 = 0 end = 2 end2 = 7}
+                 { attributes = (DateFormat$Field.DAY_OF_MONTH)
+                   begin = 2 end = 4}
+                 { attributes = ()
+                   begin = 4 begin2 = 0 end = 5 end2 = 7}
+                 { attributes = (DateFormat$Field.YEAR)
+                   begin = 5 end = 7}
+               )
+      fieldPositions =
+      (
+        {
+          field = DateFormat.MONTH_FIELD
+          fieldID = DateFormat$Field.MONTH
+          begin = 0 end = 1
+        }
+        {
+          field = DateFormat.DATE_FIELD
+          fieldID = DateFormat$Field.DAY_OF_MONTH
+          begin = 2 end = 4
+        }
+        {
+          field = DateFormat.YEAR_FIELD
+          fieldID = DateFormat$Field.YEAR
+          begin = 5 end = 7
+        }
+      )
+    }
+
+    {
+      class = java.text.SimpleDateFormat
+      args = ("EEEEEEE MMMMMMMMMMMMM yyyy GG")
+      valueClass = java.util.Date
+      valueArgs = ("12/10/2020")
+    }
+    {
+      length = 25
+      text = "Thursday December 2020 AD"
+      0 = (DateFormat$Field.DAY_OF_WEEK)
+      1 = (DateFormat$Field.DAY_OF_WEEK)
+      2 = (DateFormat$Field.DAY_OF_WEEK)
+      3 = (DateFormat$Field.DAY_OF_WEEK)
+      4 = (DateFormat$Field.DAY_OF_WEEK)
+      5 = (DateFormat$Field.DAY_OF_WEEK)
+      6 = (DateFormat$Field.DAY_OF_WEEK)
+      7 = (DateFormat$Field.DAY_OF_WEEK)
+      8 = ()
+      9 = (DateFormat$Field.MONTH)
+      10 = (DateFormat$Field.MONTH)
+      11 = (DateFormat$Field.MONTH)
+      12 = (DateFormat$Field.MONTH)
+      13 = (DateFormat$Field.MONTH)
+      14 = (DateFormat$Field.MONTH)
+      15 = (DateFormat$Field.MONTH)
+      16 = (DateFormat$Field.MONTH)
+      17 = ()
+      18 = (DateFormat$Field.YEAR)
+      19 = (DateFormat$Field.YEAR)
+      20 = (DateFormat$Field.YEAR)
+      21 = (DateFormat$Field.YEAR)
+      22 = ()
+      23 = (DateFormat$Field.ERA)
+      24 = (DateFormat$Field.ERA)
+      limits = ( { attributes = (DateFormat$Field.DAY_OF_WEEK)
+                   begin = 0 end = 8}
+                 { attributes = ()
+                   begin = 8 begin2 = 0 end = 9 end2 = 25}
+                 { attributes = (DateFormat$Field.MONTH)
+                   begin = 9 end = 17}
+                 { attributes = ()
+                   begin = 17 begin2 = 0 end = 18 end2 = 25}
+                 { attributes = (DateFormat$Field.YEAR)
+                   begin = 18 end = 22}
+                 { attributes = ()
+                   begin = 22 begin2 = 0 end = 23 end2 = 25}
+                 { attributes = (DateFormat$Field.ERA)
+                   begin = 23 end = 25}
+               )
+      fieldPositions =
+      (
+        {
+          field = DateFormat.DAY_OF_WEEK_FIELD
+          fieldID = DateFormat$Field.DAY_OF_WEEK
+          begin = 0 end = 8
+        }
+        {
+          field = DateFormat.MONTH_FIELD
+          fieldID = DateFormat$Field.MONTH
+          begin = 9 end = 17
+        }
+        {
+          field = DateFormat.YEAR_FIELD
+          fieldID = DateFormat$Field.YEAR
+          begin = 18 end = 22
+        }
+        {
+          field = DateFormat.ERA_FIELD
+          fieldID = DateFormat$Field.ERA
+          begin = 23 end = 25
+        }
+      )
+    }
+
+    {
+      class = java.text.SimpleDateFormat
+      args = ("h HH:mm:ss:SSS aa")
+      valueClass = java.util.Date
+      valueArgs = ("1/1/2000 2:52:12 PM")
+    }
+    {
+      length = 17
+      text = "2 14:52:12:000 PM"
+      0 = (DateFormat$Field.HOUR1)
+      1 = ()
+      2 = (DateFormat$Field.HOUR_OF_DAY0)
+      3 = (DateFormat$Field.HOUR_OF_DAY0)
+      4 = ()
+      5 = (DateFormat$Field.MINUTE)
+      6 = (DateFormat$Field.MINUTE)
+      7 = ()
+      8 = (DateFormat$Field.SECOND)
+      9 = (DateFormat$Field.SECOND)
+      10 = ()
+      11 = (DateFormat$Field.MILLISECOND)
+      12 = (DateFormat$Field.MILLISECOND)
+      13 = (DateFormat$Field.MILLISECOND)
+      14 = ()
+      15 = (DateFormat$Field.AM_PM)
+      16 = (DateFormat$Field.AM_PM)
+      limits = ( { attributes = (DateFormat$Field.HOUR1)
+                   begin = 0 end = 1}
+                 { attributes = ()
+                   begin = 1 begin2 = 0 end = 2 end2 = 17}
+                 { attributes = (DateFormat$Field.HOUR_OF_DAY0)
+                   begin = 2 end = 4}
+                 { attributes = ()
+                   begin = 4 begin2 = 0 end = 5 end2 = 17}
+                 { attributes = (DateFormat$Field.MINUTE)
+                   begin = 5 end = 7}
+                 { attributes = ()
+                   begin = 7 begin2 = 0 end = 8 end2 = 17}
+                 { attributes = (DateFormat$Field.SECOND)
+                   begin = 8 end = 10}
+                 { attributes = ()
+                   begin = 10 begin2 = 0 end = 11 end2 = 17}
+                 { attributes = (DateFormat$Field.MILLISECOND)
+                   begin = 11 end = 14}
+                 { attributes = ()
+                   begin = 14 begin2 = 0 end = 15 end2 = 17}
+                 { attributes = (DateFormat$Field.AM_PM)
+                   begin = 15 end = 17}
+               )
+      fieldPositions =
+      (
+        {
+          field = DateFormat.HOUR1_FIELD
+          fieldID = DateFormat$Field.HOUR1
+          begin = 0 end = 1
+        }
+        {
+          field = DateFormat.HOUR_OF_DAY0_FIELD
+          fieldID = DateFormat$Field.HOUR_OF_DAY0
+          begin = 2 end = 4
+        }
+        {
+          field = DateFormat.MINUTE_FIELD
+          fieldID = DateFormat$Field.MINUTE
+          begin = 5 end = 7
+        }
+        {
+          field = DateFormat.SECOND_FIELD
+          fieldID = DateFormat$Field.SECOND
+          begin = 8 end = 10
+        }
+        {
+          field = DateFormat.MILLISECOND_FIELD
+          fieldID = DateFormat$Field.MILLISECOND
+          begin = 11 end = 14
+        }
+        {
+          field = DateFormat.AM_PM_FIELD
+          fieldID = DateFormat$Field.AM_PM
+          begin = 15 end = 17
+        }
+      )
+    }
+
+
+    {
+      class = java.text.SimpleDateFormat
+      args = ("kk KK DDD FF ww WW zz")
+      valueClass = java.util.Date
+      valueArgs = ("4/26/2031 2:02:52 AM")
+    }
+    {
+      length = 22
+      text = "02 02 116 04 17 04 PDT"
+      0 = (DateFormat$Field.HOUR_OF_DAY1)
+      1 = (DateFormat$Field.HOUR_OF_DAY1)
+      2 = ()
+      3 = (DateFormat$Field.HOUR0)
+      4 = (DateFormat$Field.HOUR0)
+      5 = ()
+      6 = (DateFormat$Field.DAY_OF_YEAR)
+      7 = (DateFormat$Field.DAY_OF_YEAR)
+      8 = (DateFormat$Field.DAY_OF_YEAR)
+      9 = ()
+      10 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+      11 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+      12 = ()
+      13 = (DateFormat$Field.WEEK_OF_YEAR)
+      14 = (DateFormat$Field.WEEK_OF_YEAR)
+      15 = ()
+      16 = (DateFormat$Field.WEEK_OF_MONTH)
+      17 = (DateFormat$Field.WEEK_OF_MONTH)
+      18 = ()
+      19 = (DateFormat$Field.TIME_ZONE)
+      20 = (DateFormat$Field.TIME_ZONE)
+      21 = (DateFormat$Field.TIME_ZONE)
+      limits = ( { attributes = (DateFormat$Field.HOUR_OF_DAY1)
+                   begin = 0 end = 2}
+                 { attributes = ()
+                   begin = 2 begin2 = 0 end = 3 end2 = 22}
+                 { attributes = (DateFormat$Field.HOUR0)
+                   begin = 3 end = 5}
+                 { attributes = ()
+                   begin = 5 begin2 = 0 end = 6 end2 = 22}
+                 { attributes = (DateFormat$Field.DAY_OF_YEAR)
+                   begin = 6 end = 9}
+                 { attributes = ()
+                   begin = 9 begin2 = 0 end = 10 end2 = 22}
+                 { attributes = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+                   begin = 10 end = 12}
+                 { attributes = ()
+                   begin = 12 begin2 = 0 end = 13 end2 = 22}
+                 { attributes = (DateFormat$Field.WEEK_OF_YEAR)
+                   begin = 13 end = 15}
+                 { attributes = ()
+                   begin = 15 begin2 = 0 end = 16 end2 = 22}
+                 { attributes = (DateFormat$Field.WEEK_OF_MONTH)
+                   begin = 16 end = 18}
+                 { attributes = ()
+                   begin = 18 begin2 = 0 end = 19 end2 = 22}
+                 { attributes = (DateFormat$Field.TIME_ZONE)
+                   begin = 19 end = 22}
+               )
+      fieldPositions =
+      (
+        {
+          field = DateFormat.HOUR_OF_DAY1_FIELD
+          fieldID = DateFormat$Field.HOUR_OF_DAY1
+          begin = 0 end = 2
+        }
+        {
+          field = DateFormat.HOUR0_FIELD
+          fieldID = DateFormat$Field.HOUR0
+          begin = 3 end = 5
+        }
+        {
+          field = DateFormat.DAY_OF_YEAR_FIELD
+          fieldID = DateFormat$Field.DAY_OF_YEAR
+          begin = 6 end = 9
+        }
+        {
+          field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD
+          fieldID = DateFormat$Field.DAY_OF_WEEK_IN_MONTH
+          begin = 10 end = 12
+        }
+        {
+          field = DateFormat.WEEK_OF_YEAR_FIELD
+          fieldID = DateFormat$Field.WEEK_OF_YEAR
+          begin = 13 end = 15
+        }
+        {
+          field = DateFormat.WEEK_OF_MONTH_FIELD
+          fieldID = DateFormat$Field.WEEK_OF_MONTH
+          begin = 16 end = 18
+        }
+        {
+          field = DateFormat.TIMEZONE_FIELD
+          fieldID = DateFormat$Field.TIME_ZONE
+          begin = 19 end = 22
+        }
+      )
+    }
+  )
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/decimalFormat.props	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1280 @@
+#
+# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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 data for FormatIteratorTest
+
+{
+  tests =
+  (
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.lang.Integer
+      valueArgs = ("1234567")
+    }
+    {
+      length = 9
+      text = "1,234,567"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      limits = ( { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 end2 = 9}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 9
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 1 end = 2
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###.##")
+      valueClass = java.lang.Float
+      valueArgs = ("567.78")
+    }
+    {
+      length = 6
+      text = "567.78"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      4 = (NumberFormat$Field.FRACTION)
+      5 = (NumberFormat$Field.FRACTION)
+      limits = ( { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 3 }
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 3 end = 4}
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 4 end = 6}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 3
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 3 end = 4
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 4 end = 6
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("0.#E00")
+      valueClass = java.lang.Float
+      valueArgs = ("1200")
+    }
+    {
+      length = 6
+      text = "1.2E03"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      2 = (NumberFormat$Field.FRACTION)
+      3 = (NumberFormat$Field.EXPONENT_SYMBOL)
+      4 = (NumberFormat$Field.EXPONENT)
+      5 = (NumberFormat$Field.EXPONENT)
+      limits = ( { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.EXPONENT_SYMBOL)
+                   begin = 3 end = 4}
+                 { attributes = (NumberFormat$Field.EXPONENT)
+                   begin = 4 end = 6}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 1
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 1 end = 2
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 2 end = 3
+        }
+        {
+          fieldID = NumberFormat$Field.EXPONENT_SYMBOL
+          begin = 3 end = 4
+        }
+        {
+          fieldID = NumberFormat$Field.EXPONENT
+          begin = 4 end = 6
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("0.#E00")
+      valueClass = java.lang.Float
+      valueArgs = ("-.0012")
+    }
+    {
+      length = 8
+      text = "-1.2E-03"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      3 = (NumberFormat$Field.FRACTION)
+      4 = (NumberFormat$Field.EXPONENT_SYMBOL)
+      5 = (NumberFormat$Field.EXPONENT_SIGN)
+      6 = (NumberFormat$Field.EXPONENT)
+      7 = (NumberFormat$Field.EXPONENT)
+      limits = ( { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 3 end = 4}
+                 { attributes = (NumberFormat$Field.EXPONENT_SYMBOL)
+                   begin = 4 end = 5}
+                 { attributes = (NumberFormat$Field.EXPONENT_SIGN)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.EXPONENT)
+                   begin = 6 end = 8}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 2
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 2 end = 3
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 3 end = 4
+        }
+        {
+          fieldID = NumberFormat$Field.EXPONENT_SYMBOL
+          begin = 4 end = 5
+        }
+        {
+          fieldID = NumberFormat$Field.EXPONENT_SIGN
+          begin = 5 end = 6
+        }
+        {
+          fieldID = NumberFormat$Field.EXPONENT
+          begin = 6 end = 8
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###;(#,###)")
+      valueClass = java.lang.Integer
+      valueArgs = ("-1234")
+    }
+    {
+      length = 7
+      text = "(1,234)"
+      0 = ()
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = ()
+      limits = ( { attributes = ()
+                   begin = 0 end = 1 end2 = 7 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2 end2 = 6}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = ()
+                   begin = 6 begin2 = 0 end = 7}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 6
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 2 end = 3
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###;-#,###")
+      valueClass = java.lang.Integer
+      valueArgs = ("-134")
+    }
+    {
+      length = 4
+      text = "-134"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      limits = ( { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 4 }
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 4
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("+#,###")
+      valueClass = java.lang.Integer
+      valueArgs = ("134")
+    }
+    {
+      length = 4
+      text = "+134"
+      0 = ()
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      limits = ( { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end2 = 4 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 4 }
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 4
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("##.0#%")
+      valueClass = java.lang.Float
+      valueArgs = (".1234")
+    }
+    {
+      length = 6
+      text = "12.34%"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      3 = (NumberFormat$Field.FRACTION)
+      4 = (NumberFormat$Field.FRACTION)
+      5 = (NumberFormat$Field.PERCENT)
+      limits = ( { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 2 }
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 2 end = 3 }
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 3 end = 5 }
+                 { attributes = (NumberFormat$Field.PERCENT)
+                   begin = 5 end = 6 }
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 2
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 2 end = 3
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 3 end = 5
+        }
+        {
+          fieldID = NumberFormat$Field.PERCENT
+          begin = 5 end = 6
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,##.#\u2030")
+      valueClass = java.lang.Float
+      valueArgs = (".1234")
+    }
+    {
+      length = 7
+      text = "1,23.4\u2030"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.GROUPING_SEPARATOR
+           NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      5 = (NumberFormat$Field.FRACTION)
+      6 = (NumberFormat$Field.PERMILLE)
+      limits = ( { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 end2 = 4 }
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2 }
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 4 end = 5 }
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 5 end = 6 }
+                 { attributes = (NumberFormat$Field.PERMILLE)
+                   begin = 6 end = 7 }
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 4
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 1 end = 2
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 4 end = 5
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 5 end = 6
+        }
+        {
+          fieldID = NumberFormat$Field.PERMILLE
+          begin = 6 end = 7
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("\u00A40,000.00")
+      valueClass = java.lang.Float
+      valueArgs = ("12.51")
+    }
+    {
+      length = 9
+      text = "$0,012.51"
+      0 = (NumberFormat$Field.CURRENCY)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.GROUPING_SEPARATOR
+           NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      7 = (NumberFormat$Field.FRACTION)
+      8 = (NumberFormat$Field.FRACTION)
+      limits = ( { attributes = (NumberFormat$Field.CURRENCY)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2 end2 = 6 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 3 begin2 = 1 end = 6 }
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 6 end = 7 }
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 7 end = 9 }
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.CURRENCY
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 6
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 2 end = 3
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 6 end = 7
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 7 end = 9
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.math.BigInteger
+      valueArgs = ("-12345678901234567890123456789012345")
+    }
+    {
+      length = 47
+      text = "-12,345,678,901,234,567,890,123,456,789,012,345"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER)
+      10 = (NumberFormat$Field.INTEGER)
+      11 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER)
+      14 = (NumberFormat$Field.INTEGER)
+      15 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      16 = (NumberFormat$Field.INTEGER)
+      17 = (NumberFormat$Field.INTEGER)
+      18 = (NumberFormat$Field.INTEGER)
+      19 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      20 = (NumberFormat$Field.INTEGER)
+      21 = (NumberFormat$Field.INTEGER)
+      22 = (NumberFormat$Field.INTEGER)
+      23 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      24 = (NumberFormat$Field.INTEGER)
+      25 = (NumberFormat$Field.INTEGER)
+      26 = (NumberFormat$Field.INTEGER)
+      27 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      28 = (NumberFormat$Field.INTEGER)
+      29 = (NumberFormat$Field.INTEGER)
+      30 = (NumberFormat$Field.INTEGER)
+      31 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      32 = (NumberFormat$Field.INTEGER)
+      33 = (NumberFormat$Field.INTEGER)
+      34 = (NumberFormat$Field.INTEGER)
+      35 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      36 = (NumberFormat$Field.INTEGER)
+      37 = (NumberFormat$Field.INTEGER)
+      38 = (NumberFormat$Field.INTEGER)
+      39 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      40 = (NumberFormat$Field.INTEGER)
+      41 = (NumberFormat$Field.INTEGER)
+      42 = (NumberFormat$Field.INTEGER)
+      43 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      44 = (NumberFormat$Field.INTEGER)
+      45 = (NumberFormat$Field.INTEGER)
+      46 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 3 end2 = 47 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 3 end = 4 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 4 begin2 = 1 end = 7 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 7 end = 8 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 8 begin2 = 1 end = 11 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 11 end = 12 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 12 begin2 = 1 end = 15 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 15 end = 16 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 16 begin2 = 1 end = 19 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 19 end = 20 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 20 begin2 = 1 end = 23 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 23 end = 24 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 24 begin2 = 1 end = 27 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 27 end = 28 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 28 begin2 = 1 end = 31 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 31 end = 32 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 32 begin2 = 1 end = 35 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 35 end = 36 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 36 begin2 = 1 end = 39 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 39 end = 40 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 40 begin2 = 1 end = 43 end2 = 47}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 43 begin2 = 43 end = 44 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 44 begin2 = 1 end = 47}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 47
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###.#####################")
+      valueClass = java.math.BigDecimal
+      valueArgs = ("-123456789012345678901234567890.12345678901234567890")
+    }
+    {
+      length = 60
+      text = "-123,456,789,012,345,678,901,234,567,890.1234567890123456789"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      9 = (NumberFormat$Field.INTEGER)
+      10 = (NumberFormat$Field.INTEGER)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      13 = (NumberFormat$Field.INTEGER)
+      14 = (NumberFormat$Field.INTEGER)
+      15 = (NumberFormat$Field.INTEGER)
+      16 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      17 = (NumberFormat$Field.INTEGER)
+      18 = (NumberFormat$Field.INTEGER)
+      19 = (NumberFormat$Field.INTEGER)
+      20 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      21 = (NumberFormat$Field.INTEGER)
+      22 = (NumberFormat$Field.INTEGER)
+      23 = (NumberFormat$Field.INTEGER)
+      24 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      25 = (NumberFormat$Field.INTEGER)
+      26 = (NumberFormat$Field.INTEGER)
+      27 = (NumberFormat$Field.INTEGER)
+      28 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      29 = (NumberFormat$Field.INTEGER)
+      30 = (NumberFormat$Field.INTEGER)
+      31 = (NumberFormat$Field.INTEGER)
+      32 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      33 = (NumberFormat$Field.INTEGER)
+      34 = (NumberFormat$Field.INTEGER)
+      35 = (NumberFormat$Field.INTEGER)
+      36 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+      37 = (NumberFormat$Field.INTEGER)
+      38 = (NumberFormat$Field.INTEGER)
+      39 = (NumberFormat$Field.INTEGER)
+      40 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+      41 = (NumberFormat$Field.FRACTION)
+      42 = (NumberFormat$Field.FRACTION)
+      43 = (NumberFormat$Field.FRACTION)
+      44 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      45 = (NumberFormat$Field.FRACTION)
+      46 = (NumberFormat$Field.FRACTION)
+      47 = (NumberFormat$Field.FRACTION)
+      48 = (NumberFormat$Field.FRACTION)
+      49 = (NumberFormat$Field.FRACTION)
+      50 = (NumberFormat$Field.FRACTION)
+      51 = (NumberFormat$Field.FRACTION)
+      52 = (NumberFormat$Field.FRACTION)
+      53 = (NumberFormat$Field.FRACTION)
+      54 = (NumberFormat$Field.FRACTION)
+      55 = (NumberFormat$Field.FRACTION)
+      56 = (NumberFormat$Field.FRACTION)
+      57 = (NumberFormat$Field.FRACTION)
+      58 = (NumberFormat$Field.FRACTION)
+      59 = (NumberFormat$Field.FRACTION)
+      limits = (
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 4 end2 = 40 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 4 end = 5 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 5 begin2 = 1 end = 8 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 8 end = 9 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 9 begin2 = 1 end = 12 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 12 end = 13 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 13 begin2 = 1 end = 16 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 16 end = 17 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 17 begin2 = 1 end = 20 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 20 end = 21 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 21 begin2 = 1 end = 24 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 24 end = 25 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 25 begin2 = 1 end = 28 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 28 end = 29 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 29 begin2 = 1 end = 32 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 32 end = 33 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 33 begin2 = 1 end = 36 end2 = 40}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 36 end = 37 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 37 begin2 = 1 end = 40 end2 = 40}
+                 { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+                   begin = 40 end = 41 }
+                 { attributes = (NumberFormat$Field.FRACTION)
+                   begin = 41 begin2 = 41 end = 60 }
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+          begin = 40 end = 41
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 40
+        }
+        {
+          field = NumberFormat.FRACTION_FIELD
+          fieldID = NumberFormat$Field.FRACTION
+          begin = 41 end = 60
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.lang.Long
+      valueArgs = ("9223372036854775807")
+    }
+    {
+      length = 25
+      text = "9,223,372,036,854,775,807"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      10 = (NumberFormat$Field.INTEGER)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      14 = (NumberFormat$Field.INTEGER)
+      15 = (NumberFormat$Field.INTEGER)
+      16 = (NumberFormat$Field.INTEGER)
+      17 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      18 = (NumberFormat$Field.INTEGER)
+      19 = (NumberFormat$Field.INTEGER)
+      20 = (NumberFormat$Field.INTEGER)
+      21 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      22 = (NumberFormat$Field.INTEGER)
+      23 = (NumberFormat$Field.INTEGER)
+      24 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 end2 = 25}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 13 end = 14}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 13 end = 14}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 17 end = 18}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 17 end = 18}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 21 end = 22}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 21 end = 22}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 25
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 1 end = 2
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.util.concurrent.atomic.AtomicLong
+      valueArgs = ("9223372036854775807")
+    }
+    {
+      length = 25
+      text = "9,223,372,036,854,775,807"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      10 = (NumberFormat$Field.INTEGER)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      14 = (NumberFormat$Field.INTEGER)
+      15 = (NumberFormat$Field.INTEGER)
+      16 = (NumberFormat$Field.INTEGER)
+      17 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      18 = (NumberFormat$Field.INTEGER)
+      19 = (NumberFormat$Field.INTEGER)
+      20 = (NumberFormat$Field.INTEGER)
+      21 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      22 = (NumberFormat$Field.INTEGER)
+      23 = (NumberFormat$Field.INTEGER)
+      24 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 end2 = 25}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 13 end = 14}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 13 end = 14}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 17 end = 18}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 17 end = 18}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 21 end = 22}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 21 end = 22}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 25
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 1 end = 2
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.lang.Long
+      valueArgs = ("-9223372036854775808")
+    }
+    {
+      length = 26
+      text = "-9,223,372,036,854,775,808"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER)
+      10 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER)
+      14 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      15 = (NumberFormat$Field.INTEGER)
+      16 = (NumberFormat$Field.INTEGER)
+      17 = (NumberFormat$Field.INTEGER)
+      18 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      19 = (NumberFormat$Field.INTEGER)
+      20 = (NumberFormat$Field.INTEGER)
+      21 = (NumberFormat$Field.INTEGER)
+      22 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      23 = (NumberFormat$Field.INTEGER)
+      24 = (NumberFormat$Field.INTEGER)
+      25 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2 end2 = 26}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 14 end = 15}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 14 end = 15}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 18 end = 19}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 18 end = 19}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 22 end = 23}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 22 end = 23}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 26
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 2 end = 3
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.util.concurrent.atomic.AtomicLong
+      valueArgs = ("-9223372036854775808")
+    }
+    {
+      length = 26
+      text = "-9,223,372,036,854,775,808"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER)
+      10 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER)
+      14 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      15 = (NumberFormat$Field.INTEGER)
+      16 = (NumberFormat$Field.INTEGER)
+      17 = (NumberFormat$Field.INTEGER)
+      18 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      19 = (NumberFormat$Field.INTEGER)
+      20 = (NumberFormat$Field.INTEGER)
+      21 = (NumberFormat$Field.INTEGER)
+      22 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      23 = (NumberFormat$Field.INTEGER)
+      24 = (NumberFormat$Field.INTEGER)
+      25 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2 end2 = 26}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 14 end = 15}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 14 end = 15}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 18 end = 19}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 18 end = 19}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 22 end = 23}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 22 end = 23}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 26
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 2 end = 3
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.util.concurrent.atomic.AtomicInteger
+      valueArgs = ("2147483647")
+    }
+    {
+      length = 13
+      text = "2,147,483,647"
+      0 = (NumberFormat$Field.INTEGER)
+      1 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      2 = (NumberFormat$Field.INTEGER)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      6 = (NumberFormat$Field.INTEGER)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      10 = (NumberFormat$Field.INTEGER)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 0 end = 1 end2 = 13}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 1 end = 2}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 5 end = 6}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 9 end = 10}
+               )
+      fieldPositions =
+      (
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 0 end = 13
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 1 end = 2
+        }
+      )
+    }
+
+    {
+      class = java.text.DecimalFormat
+      args = ("#,###")
+      valueClass = java.util.concurrent.atomic.AtomicInteger
+      valueArgs = ("-2147483648")
+    }
+    {
+      length = 14
+      text = "-2,147,483,648"
+      0 = (NumberFormat$Field.SIGN)
+      1 = (NumberFormat$Field.INTEGER)
+      2 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      3 = (NumberFormat$Field.INTEGER)
+      4 = (NumberFormat$Field.INTEGER)
+      5 = (NumberFormat$Field.INTEGER)
+      6 = (NumberFormat$Field.INTEGER
+           NumberFormat$Field.GROUPING_SEPARATOR)
+      7 = (NumberFormat$Field.INTEGER)
+      8 = (NumberFormat$Field.INTEGER)
+      9 = (NumberFormat$Field.INTEGER)
+      10 = (NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      11 = (NumberFormat$Field.INTEGER)
+      12 = (NumberFormat$Field.INTEGER)
+      13 = (NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 0 end = 1 }
+                 { attributes = (NumberFormat$Field.INTEGER)
+                   begin = 1 end = 2 end2 = 14}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 2 end = 3}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 6 end = 7}
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 10 end = 11}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = NumberFormat$Field.SIGN
+          begin = 0 end = 1
+        }
+        {
+          field = NumberFormat.INTEGER_FIELD
+          fieldID = NumberFormat$Field.INTEGER
+          begin = 1 end = 14
+        }
+        {
+          fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+          begin = 2 end = 3
+        }
+      )
+    }
+  )
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/common/messageFormat.props	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,520 @@
+#
+# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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 data for FormatIteratorTest
+
+{
+  tests =
+  (
+    {
+      class = java.text.MessageFormat
+      args = ("0={0} 1={1}")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ("zero" "one")
+    }
+    {
+      length = 12
+      text = "0=zero 1=one"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT)
+      3 = (MessageFormat$Field.ARGUMENT)
+      4 = (MessageFormat$Field.ARGUMENT)
+      5 = (MessageFormat$Field.ARGUMENT)
+      6 = ()
+      7 = ()
+      8 = ()
+      9 = (MessageFormat$Field.ARGUMENT)
+      10 = (MessageFormat$Field.ARGUMENT)
+      11 = (MessageFormat$Field.ARGUMENT)
+      limits = ( { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 6}
+                 { attributes = ()
+                   begin = 0 begin2 = 0 end = 2 end2 = 12}
+                 { attributes = ()
+                   begin = 6 begin2 = 0 end = 9 end2 = 12}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 9 end = 12}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 6
+        }
+      )
+    }
+
+    {
+      class = java.text.MessageFormat
+      args = ("0={0} 1={1} 0={0}")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ("ze" "on")
+    }
+    {
+      length = 14
+      text = "0=ze 1=on 0=ze"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT)
+      3 = (MessageFormat$Field.ARGUMENT)
+      4 = ()
+      5 = ()
+      6 = ()
+      7 = (MessageFormat$Field.ARGUMENT)
+      8 = (MessageFormat$Field.ARGUMENT)
+      9 = ()
+      10 = ()
+      11 = ()
+      12 = (MessageFormat$Field.ARGUMENT)
+      13 = (MessageFormat$Field.ARGUMENT)
+      limits = (
+                 { attributes = ()
+                   begin = 0 end = 2 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 4}
+                 { attributes = ()
+                   begin = 4 begin2 = 0 end = 7 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 7 end = 9}
+                 { attributes = ()
+                   begin = 9 begin2 = 0 end = 12 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 12 end = 14}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 4
+        }
+      )
+    }
+
+    {
+      class = java.text.MessageFormat
+      args = ("0={0,date} 1={1,number}")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ((java.util.Date ("5/23/2001")) (Integer ("20122")))
+    }
+    {
+      length = 23
+      text = "0=May 23, 2001 1=20,122"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      5 = (MessageFormat$Field.ARGUMENT)
+      6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      8 = (MessageFormat$Field.ARGUMENT)
+      9 = (MessageFormat$Field.ARGUMENT)
+      10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      14 = ()
+      15 = ()
+      16 = ()
+      17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = ()
+                   begin = 0 end = 2 end2 = 23}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 5 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 DateFormat$Field.MONTH)
+                   begin = 2 end = 5}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 5 begin2 = 2 end = 6 end2 = 14}
+                 { attributes = (DateFormat$Field.DAY_OF_MONTH)
+                   begin = 6 end = 8}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 8 begin2 = 2 end = 10 end2 = 14}
+                 { attributes = ()
+                   begin = 14 begin2 = 0 end = 17 end2 = 23}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 17 end = 19 end2 = 23}
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 NumberFormat$Field.INTEGER)
+                   begin = 17 end = 19 end2 = 23}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 19 end = 20 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 20 begin2 = 17 end = 23}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 14
+        }
+      )
+    }
+
+    {
+      class = java.text.MessageFormat
+      args = ("0={0,date} 1={1,number}")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ((java.util.Date ("1/22/2003")) (java.math.BigInteger ("12345678901234567890123456789012345")))
+    }
+    {
+      length = 63
+      text = "0=Jan 22, 2003 1=12,345,678,901,234,567,890,123,456,789,012,345"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      5 = (MessageFormat$Field.ARGUMENT)
+      6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      8 = (MessageFormat$Field.ARGUMENT)
+      9 = (MessageFormat$Field.ARGUMENT)
+      10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      14 = ()
+      15 = ()
+      16 = ()
+      17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      48 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      49 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      50 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      51 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      52 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      53 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      54 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      55 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      56 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      57 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      58 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      59 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      60 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      61 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      62 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      limits = (
+                 { attributes = ()
+                   begin = 0 end = 2 end2 = 63}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 5 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 DateFormat$Field.MONTH)
+                   begin = 2 end = 5}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 5 begin2 = 2 end = 6 end2 = 14}
+                 { attributes = (DateFormat$Field.DAY_OF_MONTH)
+                   begin = 6 end = 8}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 8 begin2 = 2 end = 10 end2 = 14}
+                 { attributes = ()
+                   begin = 14 begin2 = 0 end = 17 end2 = 63}
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 NumberFormat$Field.INTEGER)
+                   begin = 17 end = 19 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 19 end = 20 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 20 begin2 = 17 end = 23 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 23 end = 24 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 24 begin2 = 17 end = 27 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 27 end = 28 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 28 begin2 = 17 end = 31 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 31 end = 32 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 32 begin2 = 17 end = 35 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 35 end = 36 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 36 begin2 = 17 end = 39 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 39 end = 40 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 40 begin2 = 17 end = 43 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 43 end = 44 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 44 begin2 = 17 end = 47 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 47 end = 48 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 48 begin2 = 17 end = 51 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 51 end = 52 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 52 begin2 = 17 end = 55 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 55 end = 56 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 56 begin2 = 17 end = 59 end2 = 63}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 59 end = 60 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 60 begin2 = 17 end = 63}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 14
+        }
+      )
+    }
+
+    {
+      class = java.text.MessageFormat
+      args = ("0={0,date} 1={1,number}")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ((java.util.Date ("1/26/2003")) (java.math.BigDecimal ("-12345678901234567890.1239")))
+    }
+    {
+      length = 48
+      text = "0=Jan 26, 2003 1=-12,345,678,901,234,567,890.124"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+      5 = (MessageFormat$Field.ARGUMENT)
+      6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+      8 = (MessageFormat$Field.ARGUMENT)
+      9 = (MessageFormat$Field.ARGUMENT)
+      10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+      14 = ()
+      15 = ()
+      16 = ()
+      17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.SIGN)
+      18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+            NumberFormat$Field.GROUPING_SEPARATOR)
+      41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+      44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.DECIMAL_SEPARATOR)
+      45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+      46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+      47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+      limits = (
+                 { attributes = ()
+                   begin = 0 end = 2 end2 = 48}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 5 end2 = 14}
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 DateFormat$Field.MONTH)
+                   begin = 2 end = 5}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 5 begin2 = 2 end = 6 end2 = 14}
+                 { attributes = (DateFormat$Field.DAY_OF_MONTH)
+                   begin = 6 end = 8}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 8 begin2 = 2 end = 10 end2 = 14}
+                 { attributes = ()
+                   begin = 14 begin2 = 0 end = 17 end2 = 48}
+
+                 { attributes = (NumberFormat$Field.SIGN)
+                   begin = 17 end = 18 }
+                 { attributes = (MessageFormat$Field.ARGUMENT
+                                 NumberFormat$Field.INTEGER)
+                   begin = 18 end = 20 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 20 end = 21 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 21 begin2 = 18 end = 24 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 24 end = 25 }
+
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 25 begin2 = 18 end = 28 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 28 end = 29 }
+
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 29 begin2 = 18 end = 32 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 32 end = 33 }
+
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 33 begin2 = 18 end = 36 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 36 end = 37 }
+
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 37 begin2 = 18 end = 40 end2 = 44}
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 40 end = 41 }
+                 { attributes = (NumberFormat$Field.INTEGER
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 41 begin2 = 18 end = 44 end2 = 44}
+
+                 { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+                   begin = 44 begin2 = 41 end = 45 end2 = 48}
+
+                 { attributes = (NumberFormat$Field.FRACTION
+                                 MessageFormat$Field.ARGUMENT)
+                   begin = 45 end = 48}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 14
+        }
+      )
+    }
+
+    {
+      class = java.text.MessageFormat
+      args = ("0={0,choice,-1#neg| 0#zero | 1#more}xx")
+      valueClass = java.lang.reflect.Array
+      valueArgs = ((Integer ("-11")))
+    }
+    {
+      length = 7
+      text = "0=negxx"
+      0 = ()
+      1 = ()
+      2 = (MessageFormat$Field.ARGUMENT)
+      3 = (MessageFormat$Field.ARGUMENT)
+      4 = (MessageFormat$Field.ARGUMENT)
+      5 = ()
+      6 = ()
+      limits = (
+                 { attributes = ()
+                   begin = 0 end = 2 end2 = 7}
+                 { attributes = (MessageFormat$Field.ARGUMENT)
+                   begin = 2 end = 5}
+                 { attributes = ()
+                   begin = 5 begin2 = 0 end = 7}
+               )
+      fieldPositions =
+      (
+        {
+          fieldID = MessageFormat$Field.ARGUMENT
+          begin = 2 end = 5
+        }
+      )
+    }
+  )
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/testlib/HexDumpReader.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * 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.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * HexDumpReader provides utility methods to read a hex dump text file
+ * and convert to an InputStream.  The format supported by the methods
+ * can be generated by the following command.
+ *
+ * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d'
+ */
+public class HexDumpReader {
+    public static InputStream getStreamFromHexDump(String fileName) {
+        return getStreamFromHexDump(new File(System.getProperty("test.src", "."),
+                                             fileName));
+    }
+
+    public static InputStream getStreamFromHexDump(File hexFile) {
+        ByteArrayBuilder bab = new ByteArrayBuilder();
+        int lineNo = 0;
+        try (BufferedReader reader
+                 = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile),
+                                                            "us-ascii"))) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                lineNo++;
+                line = line.trim();
+                // Skip blank and comment lines.
+                if (line.length() == 0) {
+                    continue;
+                }
+                int x = line.indexOf('#');
+                if (x == 0) {
+                    continue;
+                }
+                if (x > 0) {
+                    line = line.substring(0, x).trim();
+                }
+                int len = line.length();
+                for (int i = 0; i < len; i += 2) {
+                    bab.put((byte)Integer.parseInt(line, i, i + 2, 16));
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e);
+        }
+        return new ByteArrayInputStream(bab.toArray());
+    }
+
+
+    private static class ByteArrayBuilder {
+        private static final int BUFFER_SIZE = 4096;
+
+        private int size;
+        private List<byte[]> bytes;
+        private byte[] current;
+        private int offset;
+
+        ByteArrayBuilder() {
+            bytes = new ArrayList<>();
+            current = new byte[BUFFER_SIZE];
+        }
+
+        void put(byte b) {
+            if (offset == BUFFER_SIZE) {
+                bytes.add(current);
+                current = new byte[BUFFER_SIZE];
+                offset = 0;
+            }
+            current[offset++] = b;
+            size++;
+        }
+
+        byte[] toArray() {
+            byte[] buf = new byte[size];
+            int ptr = 0;
+            for (byte[] ba : bytes) {
+                System.arraycopy(ba, 0, buf, ptr, ba.length);
+                ptr += ba.length;
+            }
+            System.arraycopy(current, 0, buf, ptr, offset);
+            assert ptr + offset == size;
+            return buf;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/testlib/IntlTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.IOException;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * IntlTest is a base class for tests that can be run conveniently from
+ * the command line as well as under the Java test harness.
+ * <p>
+ * Sub-classes implement a set of public void methods named "Test*" or
+ * "test*" with no arguments. Each of these methods performs some
+ * test. Test methods should indicate errors by calling either err() or
+ * errln().  This will increment the errorCount field and may optionally
+ * print a message to the log.  Debugging information may also be added to
+ * the log via the log and logln methods.  These methods will add their
+ * arguments to the log only if the test is being run in verbose mode.
+ */
+public abstract class IntlTest {
+
+    //------------------------------------------------------------------------
+    // Everything below here is boilerplate code that makes it possible
+    // to add a new test by simply adding a method to an existing class.
+    //------------------------------------------------------------------------
+
+    protected IntlTest() {
+        // Populate testMethods with all the test methods.
+        Method[] methods = getClass().getDeclaredMethods();
+        for (Method method : methods) {
+            if (Modifier.isPublic(method.getModifiers())
+                && method.getReturnType() == void.class
+                && method.getParameterCount() == 0) {
+                String name = method.getName();
+                if (name.length() > 4) {
+                    if (name.startsWith("Test") || name.startsWith("test")) {
+                        testMethods.put(name, method);
+                    }
+                }
+            }
+        }
+    }
+
+    protected void run(String[] args) throws Exception
+    {
+        // Set up the log and reference streams.  We use PrintWriters in order to
+        // take advantage of character conversion.  The JavaEsc converter will
+        // convert Unicode outside the ASCII range to Java's \\uxxxx notation.
+        log = new PrintWriter(System.out, true);
+
+        // Parse the test arguments.  They can be either the flag
+        // "-verbose" or names of test methods. Create a list of
+        // tests to be run.
+        List<Method> testsToRun = new ArrayList<>(args.length);
+        for (String arg : args) {
+            switch (arg) {
+            case "-verbose":
+                verbose = true;
+                break;
+            case "-prompt":
+                prompt = true;
+                break;
+            case "-nothrow":
+                nothrow = true;
+                break;
+            default:
+                Method m = testMethods.get(arg);
+                if (m == null) {
+                    System.out.println("Method " + arg + ": not found");
+                    usage();
+                    return;
+                }
+                testsToRun.add(m);
+                break;
+            }
+        }
+
+        // If no test method names were given explicitly, run them all.
+        if (testsToRun.isEmpty()) {
+            testsToRun.addAll(testMethods.values());
+        }
+
+        System.out.println(getClass().getName() + " {");
+        indentLevel++;
+
+        // Run the list of tests given in the test arguments
+        for (Method testMethod : testsToRun) {
+            int oldCount = errorCount;
+
+            writeTestName(testMethod.getName());
+
+            try {
+                testMethod.invoke(this, new Object[0]);
+            } catch (IllegalAccessException e) {
+                errln("Can't acces test method " + testMethod.getName());
+            } catch (InvocationTargetException e) {
+                errln("Uncaught exception thrown in test method "
+                        + testMethod.getName());
+                e.getTargetException().printStackTrace(this.log);
+            }
+            writeTestResult(errorCount - oldCount);
+        }
+        indentLevel--;
+        writeTestResult(errorCount);
+
+        if (prompt) {
+            System.out.println("Hit RETURN to exit...");
+            try {
+                System.in.read();
+            } catch (IOException e) {
+                System.out.println("Exception: " + e.toString() + e.getMessage());
+            }
+        }
+        if (nothrow) {
+            System.exit(errorCount);
+        }
+    }
+
+    /**
+     * Adds the given message to the log if we are in verbose mode.
+     */
+    protected void log(String message) {
+        logImpl(message, false);
+    }
+
+    protected void logln(String message) {
+        logImpl(message, true);
+    }
+
+    protected void logln() {
+        logImpl(null, true);
+    }
+
+    private void logImpl(String message, boolean newline) {
+        if (verbose) {
+            if (message != null) {
+                indent(indentLevel + 1);
+                log.print(message);
+            }
+            if (newline) {
+                log.println();
+            }
+        }
+    }
+
+    protected void err(String message) {
+        errImpl(message, false);
+    }
+
+    protected void errln(String message) {
+        errImpl(message, true);
+    }
+
+    private void errImpl(String message, boolean newline) {
+        errorCount++;
+        indent(indentLevel + 1);
+        log.print(message);
+        if (newline) {
+            log.println();
+        }
+        log.flush();
+
+        if (!nothrow) {
+            throw new RuntimeException(message);
+        }
+    }
+
+    protected int getErrorCount() {
+        return errorCount;
+    }
+
+    protected void writeTestName(String testName) {
+        indent(indentLevel);
+        log.print(testName);
+        log.flush();
+        needLineFeed = true;
+    }
+
+    protected void writeTestResult(int count) {
+        if (!needLineFeed) {
+            indent(indentLevel);
+            log.print("}");
+        }
+        needLineFeed = false;
+
+        if (count != 0) {
+            log.println(" FAILED");
+        } else {
+            log.println(" Passed");
+        }
+    }
+
+    /*
+     * Returns a spece-delimited hex String.
+     */
+    protected static String toHexString(String s) {
+        StringBuilder sb = new StringBuilder(" ");
+
+        for (int i = 0; i < s.length(); i++) {
+            sb.append(Integer.toHexString(s.charAt(i)));
+            sb.append(' ');
+        }
+
+        return sb.toString();
+    }
+
+    private void indent(int distance) {
+        if (needLineFeed) {
+            log.println(" {");
+            needLineFeed = false;
+        }
+        log.print(SPACES.substring(0, distance * 2));
+    }
+
+    /**
+     * Print a usage message for this test class.
+     */
+    void usage() {
+        System.out.println(getClass().getName() +
+                            ": [-verbose] [-nothrow] [-prompt] [test names]");
+
+        System.out.println("  Available test names:");
+        for (String methodName : testMethods.keySet()) {
+            System.out.println("\t" + methodName);
+        }
+    }
+
+    private boolean     prompt;
+    private boolean     nothrow;
+    protected boolean   verbose;
+
+    private PrintWriter log;
+    private int         indentLevel;
+    private boolean     needLineFeed;
+    private int         errorCount;
+
+    private final Map<String, Method> testMethods = new LinkedHashMap<>();
+
+    private static final String SPACES = "                                          ";
+}
--- a/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/time/tck/java/time/temporal/TCKIsoFields.java	Wed Jul 05 21:46:22 2017 +0200
@@ -442,29 +442,45 @@
     }
 
     //-----------------------------------------------------------------------
-    // range refinedby
+    // rangeRefinedBy
     //-----------------------------------------------------------------------
     @DataProvider(name="isofields")
     Object[][] data_isofields() {
         return new Object[][] {
-               {IsoFields.DAY_OF_QUARTER},
-               {IsoFields.QUARTER_OF_YEAR},
-               {IsoFields.WEEK_OF_WEEK_BASED_YEAR},
-               {IsoFields.WEEK_BASED_YEAR},
+               {IsoFields.DAY_OF_QUARTER, 49, ValueRange.of(1, 91)},
+               {IsoFields.QUARTER_OF_YEAR, 2, ValueRange.of(1, 4)},
+               {IsoFields.WEEK_OF_WEEK_BASED_YEAR, 20, ValueRange.of(1, 52)},
+               {IsoFields.WEEK_BASED_YEAR, 2016, ValueRange.of(LocalDate.MIN.getYear(),
+                                                               LocalDate.MAX.getYear())},
         };
     }
 
     @Test(dataProvider = "isofields")
-    public void test_isofields_rangerefinedby(TemporalField field) {
-        field.rangeRefinedBy(LocalDate.now());
+    public void test_isofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) {
+        LocalDate date = LocalDate.of(2016, 5, 19);
+        assertEquals(field.rangeRefinedBy(date), valueRange);
     }
 
     @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class)
-    public void test_nonisofields_rangerefinedby(TemporalField field) {
+    public void test_nonisofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) {
         field.rangeRefinedBy(ThaiBuddhistDate.now());
     }
 
     //-----------------------------------------------------------------------
+    // getFrom
+    //-----------------------------------------------------------------------
+    @Test(dataProvider = "isofields")
+    public void test_isofields_getFrom(TemporalField field, int value, ValueRange valueRange) {
+        LocalDate date = LocalDate.of(2016, 5, 19);
+        assertEquals(field.getFrom(date), value);
+    }
+
+    @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class)
+    public void test_nonisofields_getFrom(TemporalField field, int value, ValueRange valueRange) {
+        field.getFrom(ThaiBuddhistDate.now());
+    }
+
+    //-----------------------------------------------------------------------
     public void test_loop() {
         // loop round at least one 400 year cycle, including before 1970
         LocalDate date = LocalDate.of(1960, 1, 5);  // Tuseday of week 1 1960
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/BuddhistCalendarTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,243 @@
+/*
+ * 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
+ * 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 4817812 4847186 4956227 4956479
+ * @summary Confirm that BuddhistCalendar's add(), roll() and toString() work correctly with Buddhist Era years.
+ */
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import static java.util.Calendar.*;
+
+public class BuddhistCalendarTest {
+
+    private static final Locale THAI_LOCALE = new Locale("th", "TH");
+
+    public static void main(String[] args) {
+        testAddRoll();
+        testToString();
+        testException();
+        testLeastMax();
+    }
+
+    /**
+     * 4817812
+     */
+    static void testAddRoll() {
+        Calendar cal;
+        int base, year;
+
+        /*
+         * Test: BuddhistCalendar.add(YEAR)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.add(YEAR, 1);
+        year = cal.get(YEAR);
+        check(year, base+1, "add(+YEAR)");
+
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.add(YEAR, -3);
+        year = cal.get(YEAR);
+        check(year, base-3, "add(-YEAR)");
+
+        /*
+         * Test BuddhistCalendar.add(MONTH)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.set(MONTH, DECEMBER);
+        cal.add(MONTH, 2);
+        year = cal.get(YEAR);
+        check(year, base+1, "add(+MONTH)");
+
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.set(MONTH, FEBRUARY);
+        cal.add(MONTH, -4);
+        year = cal.get(YEAR);
+        check(year, base-1, "add(-MONTH)");
+
+        /*
+         * Test BuddhistCalendar.roll(YEAR)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.roll(YEAR, 2);
+        year = cal.get(YEAR);
+        check(year, base+2, "roll(+YEAR)");
+
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.roll(YEAR, -4);
+        year = cal.get(YEAR);
+        check(year, base-4, "roll(-YEAR)");
+
+        /*
+         * Test BuddhistCalendar.roll(WEEK_OF_YEAR)
+         */
+        cal = getBuddhistCalendar();
+        cal.set(YEAR, 2543);   // A.D.2000
+        cal.set(MONTH, DECEMBER);
+        cal.set(DATE, 31);
+        base = cal.get(YEAR);
+        check(base, 2543, "roll(+WEEK_OF_YEAR)");
+        cal.roll(WEEK_OF_YEAR, 10);
+        year = cal.get(YEAR);
+        check(year, base, "roll(+WEEK_OF_YEAR)");
+
+        cal = getBuddhistCalendar();
+        cal.set(YEAR, 2543);   // A.D.2000
+        cal.set(MONTH, JANUARY);
+        cal.set(DATE, 1);
+        base = cal.get(YEAR);
+        check(base, 2543, "roll(+WEEK_OF_YEAR)");
+        cal.roll(WEEK_OF_YEAR, -10);
+        year = cal.get(YEAR);
+        check(year, base, "roll(-WEEK_OF_YEAR)");
+
+        /*
+         * Test Calendar.set(year, month, date)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.set(3001, APRIL, 10);
+        year = cal.get(YEAR);
+        check(year, 3001, "set(year, month, date)");
+
+        /*
+         * Test Calendar.set(year, month, date, hour, minute)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.set(3020, MAY, 20, 9, 10);
+        year = cal.get(YEAR);
+        check(year, 3020, "set(year, month, date, hour, minute)");
+
+        /*
+         * Test Calendar.set(year, month, date, hour, minute, second)
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        cal.set(3120, MAY, 20, 9, 10, 52);
+        year = cal.get(YEAR);
+        check(year, 3120, "set(year, month, date, hour, minute, second)");
+
+        /*
+         * Test BuddhistCalendar.getActualMaximum(YEAR);
+         *    set(YEAR)/get(YEAR) in this method doesn't affect the real
+         *    YEAR value because a clone is used with set()&get().
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        int limit = cal.getActualMaximum(YEAR);
+        year = cal.get(YEAR);
+        check(year, base, "BuddhistCalendar.getActualMaximum(YEAR)");
+
+        /*
+         * Test BuddhistCalendar.getActualMinimum(YEAR);
+         *   This doesn't call set(YEAR) nor get(YEAR), though.
+         */
+        cal = getBuddhistCalendar();
+        base = cal.get(YEAR);
+        limit = cal.getActualMinimum(YEAR);
+        year = cal.get(YEAR);
+        check(year, base, "BuddhistCalendar.getActualMinimum(YEAR)");
+    }
+
+    /**
+     * 4847186: BuddhistCalendar: toString() returns Gregorian year
+     */
+    static void testToString() {
+        Calendar cal = getBuddhistCalendar();
+        int year = cal.get(YEAR);
+        String s = cal.toString();
+        String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1");
+        if (Integer.parseInt(y) != year) {
+            throw new RuntimeException("toString(): wrong year value: got " + y
+                                       + ", expected " + year);
+        }
+    }
+
+    /**
+     * 4956479: BuddhistCalendar methods may return wrong values after exception
+     */
+    static void testException() {
+        Calendar cal = getBuddhistCalendar();
+        int year = cal.get(YEAR);
+        boolean exceptionOccurred = false;
+        try {
+            cal.add(100, +1); // cause exception
+        } catch (Exception e) {
+            exceptionOccurred = true;
+        }
+        if (!exceptionOccurred) {
+            throw new RuntimeException("testException: test case failed: no exception thrown");
+        }
+        int year2 = cal.get(YEAR);
+        if (year2 != year) {
+            throw new RuntimeException("wrong year value after exception: got " + year2
+                                       + ", expected " + year);
+        }
+    }
+
+    /**
+     * 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar
+     */
+    static void testLeastMax() {
+        Calendar bc = getBuddhistCalendar();
+        // Specify THAI_LOCALE to get the same params for WEEK
+        // calculations (6904680).
+        Calendar gc = new GregorianCalendar(THAI_LOCALE);
+        for (int f = 0; f < Calendar.FIELD_COUNT; f++) {
+            if (f == ERA || f == YEAR) {
+                continue;
+            }
+            int bn = bc.getLeastMaximum(f);
+            int gn = gc.getLeastMaximum(f);
+            if (bn != gn) {
+                throw new RuntimeException("inconsistent Least Max value for " + Koyomi.getFieldName(f)
+                                           + ": Buddhist=" + bn
+                                           + ": Gregorian=" + gn);
+            }
+        }
+    }
+
+    /**
+     * @return a BuddhistCalendar
+     */
+    static Calendar getBuddhistCalendar() {
+        return Calendar.getInstance(THAI_LOCALE);
+    }
+
+    static void check(int got, int expected, String s) {
+        if (got != expected) {
+            throw new RuntimeException("Failed: " +
+                s + ": got:" + got + ", expected:" + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug4302966.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4302966
+ * @summary In Czech Republic first day of week is Monday not Sunday
+ */
+
+import java.util.Calendar;
+import java.util.Locale;
+
+public class Bug4302966 {
+
+    public static void main(String[] args) {
+        Calendar czechCalendar = Calendar.getInstance(new Locale("cs"));
+        int firstDayOfWeek = czechCalendar.getFirstDayOfWeek();
+        if (firstDayOfWeek != Calendar.MONDAY) {
+            throw new RuntimeException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug4766302.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4766302
+ * @summary Make sure that computeTime call doesn't reset the isTimeSet value.
+ */
+
+import java.util.GregorianCalendar;
+
+public class Bug4766302 {
+
+    static class MyCalendar extends GregorianCalendar {
+        boolean isTimeStillSet() {
+            return isTimeSet;
+        }
+
+        protected void computeTime() {
+            super.computeTime();
+        }
+    }
+
+    public static void main(String[] args) {
+        MyCalendar cal = new MyCalendar();
+        cal.computeTime();
+        if (!cal.isTimeStillSet()) {
+            throw new RuntimeException("computeTime() call reset isTimeSet.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug4851640.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * 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 4851640
+ * @summary Make sure not to set UNSET fields to COMPUTED after time calculation.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.*;
+
+public class Bug4851640 {
+
+    public static void main(String args[]) {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.clear();
+        cal.set(YEAR, 2003);
+        long t = cal.getTime().getTime();
+
+        // For the time calculation, the MONTH and DAY_OF_MONTH fields
+        // (with the default values) have been used for determining
+        // the date.  However, both the MONTH and DAY_OF_MONTH fields
+        // should be kept UNSET after the time calculation.
+        if (cal.isSet(MONTH) || cal.isSet(DAY_OF_MONTH)) {
+            throw new RuntimeException("After getTime(): MONTH field=" + cal.isSet(MONTH)
+                                       + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH));
+        }
+
+        // After calling get() for any field, all field values are
+        // recalculated and their field states are set to
+        // COMPUTED. isSet() must return true.
+        int y = cal.get(YEAR);
+        if (!(cal.isSet(MONTH) && cal.isSet(DAY_OF_MONTH))) {
+            throw new RuntimeException("After get(): MONTH field=" + cal.isSet(MONTH)
+                                       + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug4958050.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,255 @@
+/*
+ * 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
+ * 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 4958050
+ * @summary Make sure that add() and roll() handle time zone offset changes (both raw and DST) correctly.
+ */
+
+import java.util.Locale;
+import java.util.TimeZone;
+import static java.util.Calendar.*;
+
+public class Bug4958050 {
+    static int errorCount = 0;
+
+    public static void main(String[] args) {
+        // All the test cases depend on historical GMT offset changes
+        // of Asia/Novosibirsk.
+        Koyomi cal = new Koyomi(TimeZone.getTimeZone("Asia/Novosibirsk"), Locale.US);
+        System.out.println("Time zone = " + cal.getTimeZone().getID());
+
+        // Test the week fields
+        int[] weekFields = { WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH };
+        for (int i = 0; i < weekFields.length; i++) {
+            int field = weekFields[i];
+            // add()
+            cal.clear();
+            cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
+            cal.add(weekFields[i], +1);
+            if (!cal.checkDate(1919, DECEMBER, 14)) {
+                error("1919/12/07: add("+cal.getFieldName(weekFields[i])+", +1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1930, JUNE, 21-7);
+            cal.add(weekFields[i], +1);
+            if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+                error("1930/6/14: add("+cal.getFieldName(weekFields[i])+", +1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+
+            // roll()
+            cal.clear();
+            cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
+            cal.roll(weekFields[i], +1);
+            if (!cal.checkDate(1919, DECEMBER, 14)) {
+                error("1919/12/07: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1930, JUNE, 21-7);
+            cal.roll(weekFields[i], +1);
+            if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+                error("1930/6/14: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+        }
+
+        // Test the day fields
+        int[] dayFields = { DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK };
+        for (int i = 0; i < dayFields.length; i++) {
+            int field = dayFields[i];
+            // add()
+            cal.clear();
+            cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+            cal.add(field, +1);
+            if (!cal.checkDate(1919, DECEMBER, 14)) {
+                error("1919/12/13: add("+cal.getFieldName(field)+", +1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1919, DECEMBER, 14, 00, 00, 00);
+            cal.add(field, -1);
+            if (!cal.checkDate(1919, DECEMBER, 13)) {
+                error("1919/12/14: add("+cal.getFieldName(field)+", -1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1930, JUNE, 21-1);
+            cal.add(field, +1);
+            if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+                error("1930/6/20: add("+cal.getFieldName(field)+", +1)\n"
+                      + cal.getMessage() + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1930, JUNE, 21, 01, 00, 00);
+            cal.add(field, -1);
+            if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
+                error("1930/6/21: add("+cal.getFieldName(field)+", -1)\n"
+                      + cal.getMessage()+" " + cal.toDateTimeString());
+            }
+
+            // roll()
+            cal.clear();
+            cal.set(1930, JUNE, 21-1);
+            int amount = +1;
+            if (field == DAY_OF_WEEK) {
+                amount += 700;
+            }
+            cal.roll(field, amount);
+            if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+                error("1930/6/20: roll("+cal.getFieldName(field)+", +"+amount+")\n"
+                      + cal.getMessage() + " " + cal.toDateTimeString());
+            }
+            cal.clear();
+            cal.set(1930, JUNE, 21, 01, 00, 00);
+            amount = -1;
+            if (field == DAY_OF_WEEK) {
+                amount -= 700;
+            }
+            cal.roll(field, amount);
+            if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
+                error("1930/6/21: roll("+cal.getFieldName(field)+", "+amount+")\n"
+                      + cal.getMessage()+" "+cal.toDateTimeString());
+            }
+        }
+
+        // Test the AM_PM field
+        // add()
+        cal.clear();
+        cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+        cal.add(AM_PM, +1);
+        if (!cal.checkDate(1919, DECEMBER, 14)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1919/12/13: add(AM_PM, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21-1, 12, 00, 00);
+        cal.add(AM_PM, +1);
+        if (!cal.checkDate(1930, JUNE, 21)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1930/6/20: add(AM_PM, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21-2, 12, 00, 00);
+        cal.add(AM_PM, +3);
+        if (!cal.checkDate(1930, JUNE, 21)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1930/6/10: add(AM_PM, +3)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1919, DECEMBER, 14, 11, 50, 00);
+        cal.add(AM_PM, -1);
+        if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23, 50, 00, 000)
+            || !cal.checkFieldValue(AM_PM, PM)) {
+            error("1919/12/14 11:50:00: add(AM_PM, -1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21, 01, 00, 00);
+        cal.add(AM_PM, -1);
+        if (!cal.checkDateTime(1930, JUNE, 21-1, 01+12, 00, 00, 000)
+            || !cal.checkFieldValue(AM_PM, PM)) {
+            error("1930/6/20: add(AM_PM, -1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21, 01, 00, 00);
+        cal.add(AM_PM, -3);
+        if (!cal.checkDateTime(1930, JUNE, 21-2, 01+12, 00, 00, 000)
+            || !cal.checkFieldValue(AM_PM, PM)) {
+            error("1930/6/10: add(AM_PM, -3)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        // roll() (should NOT change the date)
+        cal.clear();
+        cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+        cal.roll(AM_PM, +1);
+        if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23-12, 50, 00, 000)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1919/12/13: roll(AM_PM, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21-1, 12, 00, 00);
+        cal.roll(AM_PM, +1);
+        if (!cal.checkDateTime(1930, JUNE, 21-1, 12-12, 00, 00, 000)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1930/6/20: roll(AM_PM, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        cal.clear();
+        cal.set(1930, JUNE, 21-2, 12, 00, 00);
+        cal.roll(AM_PM, +3);
+        if (!cal.checkDateTime(1930, JUNE, 21-2, 12-12, 00, 00, 000)
+            || !cal.checkFieldValue(AM_PM, AM)) {
+            error("1930/6/10: roll(AM_PM, +3)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        // Test the HOUR_OF_DAY field
+        // add()
+        cal.clear();
+        cal.set(1930, JUNE, 20, 23, 00, 00);
+        cal.add(HOUR_OF_DAY, +1);
+        if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+            error("1930/6/20 23:00:00: add(HOUR_OF_DAY, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        // roll() (should NOT change the date)
+        cal.clear();
+        cal.set(1930, JUNE, 20, 23, 00, 00);
+        cal.roll(HOUR_OF_DAY, +1);
+        if (!cal.checkDateTime(1930, JUNE, 20, 00, 00, 00, 000)) {
+            error("1930/6/20 23:00:00: roll(HOUR_OF_DAY, +1)\n"
+                  + cal.getMessage()+" "+cal.toDateTimeString());
+        }
+
+        checkErrors();
+    }
+
+    static void error(String s) {
+        System.out.println(s);
+        errorCount++;
+    }
+
+    static void checkErrors() {
+        if (errorCount > 0) {
+            throw new RuntimeException("Failed: " + errorCount + " error(s)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug5078053.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,100 @@
+/*
+ * 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
+ * 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 5078053
+ * @summary Make sure that Calendar.complete() normalizes stamp[] to
+ * COMPUTED. This can be observed through add() and roll().
+ */
+
+import java.util.TimeZone;
+import static java.util.Calendar.*;
+
+public class Bug5078053 {
+    static int errorCount = 0;
+
+    public static void main(String[] args) {
+        TimeZone defaultTz = TimeZone.getDefault();
+
+        try {
+            TimeZone tz = TimeZone.getTimeZone("Australia/Adelaide");
+            TimeZone.setDefault(tz);
+            Koyomi cal = new Koyomi();
+            cal.setFirstDayOfWeek(2);
+            cal.setMinimalDaysInFirstWeek(4);
+
+            // test roll()
+            cal.clear();
+            // 2002-01-01T00:00:00 in Australia/Adelaide
+            cal.setTimeInMillis(1009805400000L);
+            System.out.println(cal.getTime());
+            // The following set calls shouldn't affect roll() and add()
+            cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK));
+            cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR));
+            cal.getTime();
+            cal.roll(MONTH, +1);
+            System.out.println("roll: " + cal.getTime());
+            if (!cal.checkDate(2002, FEBRUARY, 1)) {
+                error("roll(MONTH, +1): " + cal.getMessage());
+            }
+            cal.roll(MONTH, -1);
+            if (!cal.checkDate(2002, JANUARY, 1)) {
+                error("roll(MONTH, -1): " + cal.getMessage());
+            }
+
+            // test add()
+            cal.clear();
+            // 2002-01-01T00:00:00+0930 in Australia/Adelaide
+            cal.setTimeInMillis(1009805400000L);
+            cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK));
+            cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR));
+            cal.getTime();
+            cal.add(MONTH, +1);
+            System.out.println(" add: " + cal.getTime());
+            if (!cal.checkDate(2002, FEBRUARY, 1)) {
+                error("add(MONTH, +1): " + cal.getMessage());
+            }
+            cal.add(MONTH, -1);
+            if (!cal.checkDate(2002, JANUARY, 1)) {
+                error("add(MONTH, -1): " + cal.getMessage());
+            }
+        }
+        finally {
+            TimeZone.setDefault(defaultTz);
+        }
+
+        checkErrors();
+    }
+
+    static void error(String s) {
+        System.out.println(s);
+        errorCount++;
+    }
+
+    static void checkErrors() {
+        if (errorCount > 0) {
+            throw new RuntimeException("Failed: " + errorCount + " error(s)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug6178071.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6178071 6440854
+ * @summary Make sure that setting HOUR right after a construction works
+ *          as expected.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.*;
+
+public class Bug6178071 {
+    public static void main(String[] args) {
+        GregorianCalendar cal = new GregorianCalendar(2004, JANUARY, 1);
+        cal.set(HOUR, 1);
+        if (cal.get(HOUR_OF_DAY) != 1 ||
+            cal.get(HOUR) != 1 || cal.get(AM_PM) != AM) {
+            throw new RuntimeException("Unexpected hour of day: " + cal.getTime());
+        }
+
+        // Test case for 6440854
+        GregorianCalendar gc = new GregorianCalendar(2006,5,16);
+        gc.setLenient(false);
+        gc.set(HOUR_OF_DAY, 10);
+        // The following line shouldn't throw an IllegalArgumentException.
+        gc.get(YEAR);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug6234795.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6234795
+ * @summary Rolling of HOUR or HOUR_OF_SET must set the other hour field.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.AM;
+import static java.util.Calendar.AM_PM;
+import static java.util.Calendar.HOUR;
+import static java.util.Calendar.HOUR_OF_DAY;
+import static java.util.Calendar.SEPTEMBER;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class Bug6234795 {
+    public static void main(String[] args) {
+        testRoll(HOUR);
+        testRoll(HOUR_OF_DAY);
+    }
+
+    static void testRoll(int field) {
+        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
+        cal.clear();
+        cal.set(2005, SEPTEMBER, 12);
+
+        int otherField = (field == HOUR) ? HOUR_OF_DAY : HOUR;
+        int unit = (field == HOUR) ? 12 : 24;
+        int h;
+        for (h = 0; h <= 72; h++) {
+            int hour = cal.get(otherField);
+            int expected = h % 12;
+            if (hour != expected) {
+                throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+                                           + "+: h=" + h + ", got " + hour
+                                           + ", expected " + expected);
+            }
+            if (field == HOUR_OF_DAY) {
+                int ampm = cal.get(AM_PM);
+                expected = (h % unit) / 12;
+                if (ampm != expected) {
+                    throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+                                               + "+: h=" + h + ", got "
+                                               + toString(ampm)
+                                               + ", expected " + toString(expected));
+                }
+            }
+            cal.roll(field, +1);
+        }
+        for (; h >= 0; h--) {
+            int hour = cal.get(otherField);
+            int expected = h % 12;
+            if (hour != expected) {
+                throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+                                           + "-: h=" + h + ", got " + hour
+                                           + ", expected " + expected);
+            }
+            if (field == HOUR_OF_DAY) {
+                int ampm = cal.get(AM_PM);
+                expected = (h % unit) / 12;
+                if (ampm != expected) {
+                    throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+                                               + "-: h=" + h + ", got " + toString(ampm)
+                                               + ", expected " + toString(expected));
+                }
+            }
+            cal.roll(field, -1);
+        }
+    }
+
+    static String toString(int ampm) {
+        return ampm == AM ? "AM" : "PM";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Bug6448234.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006, 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 6448234
+ * @summary Make sure indexing of DAY_OF_WEEK is correct in JapaneseImperialCalendar.getDisplayName.
+ */
+
+import java.util.Calendar;
+import java.util.Locale;
+import static java.util.Calendar.*;
+
+public class Bug6448234 {
+    public static void main(String[] args) {
+        Calendar jcal = Calendar.getInstance(new Locale("ja", "JP", "JP"));
+        Calendar gcal = Calendar.getInstance(Locale.US);
+
+        for (int i = SUNDAY; i <= SATURDAY; i++) {
+            jcal.set(DAY_OF_WEEK, i);
+            gcal.set(DAY_OF_WEEK, i);
+
+            // Test LONG
+            String j = jcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US);
+            String g = gcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US);
+            if (!j.equals(g)) {
+                throw new RuntimeException("Got " + j + ", expected " + g);
+            }
+
+            // Test SHORT
+            j = jcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US);
+            g = gcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US);
+            if (!j.equals(g)) {
+                throw new RuntimeException("Got " + j + ", expected " + g);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/CalendarLimitTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4033662
+ * @library /java/text/testlib
+ * @summary test for limit on Calendar
+ * @run main CalendarLimitTest -verbose
+ */
+
+import java.util.*;
+import java.text.*;
+
+/**
+ * This test verifies the behavior of Calendar around the very earliest limits
+ * which it can handle.  It also verifies the behavior for large values of millis.
+ *
+ * Note: There used to be a limit, due to a bug, for early times.  There is
+ * currently no limit.
+ *
+ * March 17, 1998: Added code to make sure big + dates are big + AD years, and
+ * big - dates are big + BC years.
+ */
+public class CalendarLimitTest extends IntlTest
+{
+    // This number determined empirically; this is the old limit,
+    // which we test for to make sure it isn't there anymore.
+    static final long EARLIEST_SUPPORTED_MILLIS = -210993120000000L;
+
+    static final int EPOCH_JULIAN_DAY   = 2440588; // Jaunary 1, 1970 (Gregorian)
+    static final int JAN_1_1_JULIAN_DAY = 1721426; // January 1, year 1 (Gregorian)
+
+    // Useful millisecond constants
+    static final int  ONE_SECOND = 1000;
+    static final int  ONE_MINUTE = 60*ONE_SECOND;
+    static final int  ONE_HOUR   = 60*ONE_MINUTE;
+    static final int  ONE_DAY    = 24*ONE_HOUR;
+    static final int  ONE_WEEK   = 7*ONE_DAY;
+    static final long ONE_YEAR   = (long)(365.2425 * ONE_DAY);
+
+    static long ORIGIN; // This is the *approximate* point at which BC switches to AD
+
+    public static void main(String argv[]) throws Exception {
+        new CalendarLimitTest().run(argv);
+    }
+
+    /**
+     * Converts Julian day to time as milliseconds.
+     * @param julian the given Julian day number.
+     * @return time as milliseconds.
+     */
+    private static final long julianDayToMillis(long julian) {
+        return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
+    }
+
+    /**
+     * Verify that the given time is processed without problem.
+     * @return the adjust year, with 0 = 1 BC, -1 = 2 BC, etc.
+     */
+    int test(long millis, Calendar cal, DateFormat fmt)
+    {
+        Exception exception = null;
+        String theDate = "";
+        try {
+            Date d= new Date(millis);
+            cal.setTime(d);
+            theDate = fmt.format(d);
+        }
+        catch (IllegalArgumentException e) {
+            exception = e;
+        }
+        String s = "0x" + Long.toHexString(millis) + " " + theDate;
+
+        int era=cal.get(Calendar.ERA), year=cal.get(Calendar.YEAR),
+            dom=cal.get(Calendar.DATE), mon=cal.get(Calendar.MONTH);
+
+        cal.clear();
+        cal.set(year, mon, dom);
+        cal.set(Calendar.ERA, era);
+        Date rt = cal.getTime();
+
+        boolean ok = true;
+        if (exception != null) {
+            errln("FAIL: Exception " + s);
+            ok = false;
+        }
+        if (((millis >= ORIGIN) && (era != GregorianCalendar.AD)) ||
+                 ((millis < ORIGIN) && (era != GregorianCalendar.BC)) ||
+                 (year < 1)) {
+            errln("FAIL: Bad year/era " + s);
+            ok = false;
+        }
+        if (dom<1 || dom>31) {
+            errln("FAIL: Bad DOM " + s);
+            ok = false;
+        }
+        if (Math.abs(millis - rt.getTime()) > ONE_DAY) {
+            errln("FAIL: RT fail " + s + " -> 0x" +
+                  Long.toHexString(rt.getTime()) + " " +
+                  fmt.format(rt));
+            ok = false;
+        }
+        if (ok) logln(s);
+        if (era==GregorianCalendar.BC) year = 1-year;
+        return year;
+    }
+
+    public void TestCalendarLimit()
+    {
+        ORIGIN = julianDayToMillis(JAN_1_1_JULIAN_DAY);
+
+        Calendar cal = Calendar.getInstance();
+        // You must set the time zone to GMT+0 or the edge cases like
+        // Long.MIN_VALUE, Long.MAX_VALUE, and right around the threshold
+        // won't work, since before converting to fields the calendar code
+        // will add the offset for the zone.
+        cal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
+
+        DateFormat dateFormat = DateFormat.getDateInstance();
+        dateFormat.setCalendar(cal); // Make sure you do this -- same reason as above
+        ((SimpleDateFormat)dateFormat).applyPattern("MMM d, yyyy G");
+
+        // Don't expect any failure for positive longs
+        int lastYear=0;
+        boolean first=true;
+        for (long m = Long.MAX_VALUE; m > 0; m >>= 1)
+        {
+            int y = test(m, cal, dateFormat);
+            if (!first && y > lastYear)
+                errln("FAIL: Years should be decreasing " + lastYear + " " + y);
+            first = false;
+            lastYear = y;
+        }
+
+        // Expect failures for negative millis below threshold
+        first = true;
+        for (long m = Long.MIN_VALUE; m < 0; m /= 2) // Don't use m >>= 1
+        {
+            int y = test(m, cal, dateFormat);
+            if (!first && y < lastYear)
+                errln("FAIL: Years should be increasing " + lastYear + " " + y);
+            first = false;
+            lastYear = y;
+        }
+
+        // Test right around the threshold
+        test(EARLIEST_SUPPORTED_MILLIS,   cal, dateFormat);
+        test(EARLIEST_SUPPORTED_MILLIS-1, cal, dateFormat);
+
+        // Test a date that should work
+        test(Long.MIN_VALUE + ONE_DAY,    cal, dateFormat);
+
+        // Try hours in the earliest day or two
+        // JUST FOR DEBUGGING:
+        if (false) {
+            ((SimpleDateFormat)dateFormat).applyPattern("H:mm MMM d, yyyy G");
+            for (int dom=2; dom<=3; ++dom) {
+                for (int h=0; h<24; ++h) {
+                    cal.clear();
+                    cal.set(Calendar.ERA, GregorianCalendar.BC);
+                    cal.set(292269055, Calendar.DECEMBER, dom, h, 0);
+                    Date d = cal.getTime();
+                    cal.setTime(d);
+                    logln("" + h + ":00 Dec "+dom+", 292269055 BC -> " +
+                          Long.toHexString(d.getTime()) + " -> " +
+                          dateFormat.format(cal.getTime()));
+                }
+            }
+            // Other way
+            long t = 0x80000000018c5c00L; // Dec 3, 292269055 BC
+            while (t<0) {
+                cal.setTime(new Date(t));
+                logln("0x" + Long.toHexString(t) + " -> " +
+                      dateFormat.format(cal.getTime()));
+                t -= ONE_HOUR;
+            }
+        }
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/CalendarRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,2496 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385
+ * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271
+ * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933
+ * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516
+ * 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 4623997
+ * 4685354 4655637 4683492 4080631 4080631 4167995 4340146 4639407
+ * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642
+ * 4973919 4980088 4965624 5013094 5006864 8152077
+ * @library /java/text/testlib
+ */
+
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class CalendarRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new CalendarRegression().run(args);
+    }
+
+    /*
+      Synopsis: java.sql.Timestamp constructor works wrong on Windows 95
+
+      ==== Here is the test ====
+      public static void main (String args[]) {
+        java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700);
+        logln("expected=1901-04-05 05:08:13.1234567");
+        logln(" result="+t);
+      }
+
+      ==== Here is the output of the test on Solaris or NT ====
+      expected=1901-04-05 05:08:13.1234567
+      result=1901-04-05 05:08:13.1234567
+
+      ==== Here is the output of the test on Windows95 ====
+      expected=1901-04-05 05:08:13.1234567
+      result=1901-04-05 06:08:13.1234567
+      */
+
+    public void Test4031502() {
+        // This bug actually occurs on Windows NT as well, and doesn't
+        // require the host zone to be set; it can be set in Java.
+        String[] ids = TimeZone.getAvailableIDs();
+        boolean bad = false;
+        for (int i=0; i<ids.length; ++i) {
+            TimeZone zone = TimeZone.getTimeZone(ids[i]);
+            GregorianCalendar cal = new GregorianCalendar(zone);
+            cal.clear();
+            cal.set(1900, 15, 5, 5, 8, 13);
+            if (cal.get(Calendar.HOUR) != 5) {
+                logln(zone.getID() + " " +
+                                   //zone.useDaylightTime() + " " +
+                                   cal.get(Calendar.DST_OFFSET) / (60*60*1000) + " " +
+                                   zone.getRawOffset() / (60*60*1000) +
+                                   ": HOUR = " + cal.get(Calendar.HOUR));
+                bad = true;
+            }
+        }
+        if (bad) errln("TimeZone problems with GC");
+    }
+
+    public void Test4035301() {
+        GregorianCalendar c = new GregorianCalendar(98, 8, 7);
+        GregorianCalendar d = new GregorianCalendar(98, 8, 7);
+        if (c.after(d) ||
+            c.after(c) ||
+            c.before(d) ||
+            c.before(c) ||
+            !c.equals(c) ||
+            !c.equals(d))
+            errln("Fail");
+    }
+
+    public void Test4040996() {
+        String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
+        SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
+        pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        Calendar calendar = new GregorianCalendar(pdt);
+
+        calendar.set(Calendar.MONTH,3);
+        calendar.set(Calendar.DAY_OF_MONTH,18);
+        calendar.set(Calendar.SECOND, 30);
+
+        logln("MONTH: " + calendar.get(Calendar.MONTH));
+        logln("DAY_OF_MONTH: " +
+                           calendar.get(Calendar.DAY_OF_MONTH));
+        logln("MINUTE: " + calendar.get(Calendar.MINUTE));
+        logln("SECOND: " + calendar.get(Calendar.SECOND));
+
+        calendar.add(Calendar.SECOND,6);
+        //This will print out todays date for MONTH and DAY_OF_MONTH
+        //instead of the date it was set to.
+        //This happens when adding MILLISECOND or MINUTE also
+        logln("MONTH: " + calendar.get(Calendar.MONTH));
+        logln("DAY_OF_MONTH: " +
+                           calendar.get(Calendar.DAY_OF_MONTH));
+        logln("MINUTE: " + calendar.get(Calendar.MINUTE));
+        logln("SECOND: " + calendar.get(Calendar.SECOND));
+        if (calendar.get(Calendar.MONTH) != 3 ||
+            calendar.get(Calendar.DAY_OF_MONTH) != 18 ||
+            calendar.get(Calendar.SECOND) != 36)
+            errln("Fail: Calendar.add misbehaves");
+    }
+
+    public void Test4051765() {
+        Calendar cal = Calendar.getInstance();
+        cal.setLenient(false);
+        cal.set(Calendar.DAY_OF_WEEK, 0);
+        try {
+            cal.getTime();
+            errln("Fail: DAY_OF_WEEK 0 should be disallowed");
+        }
+        catch (IllegalArgumentException e) {
+            return;
+        }
+    }
+
+    /* User error - no bug here
+    public void Test4059524() {
+        // Create calendar for April 10, 1997
+        GregorianCalendar calendar  = new GregorianCalendar();
+        // print out a bunch of interesting things
+        logln("ERA: " + calendar.get(calendar.ERA));
+        logln("YEAR: " + calendar.get(calendar.YEAR));
+        logln("MONTH: " + calendar.get(calendar.MONTH));
+        logln("WEEK_OF_YEAR: " +
+                           calendar.get(calendar.WEEK_OF_YEAR));
+        logln("WEEK_OF_MONTH: " +
+                           calendar.get(calendar.WEEK_OF_MONTH));
+        logln("DATE: " + calendar.get(calendar.DATE));
+        logln("DAY_OF_MONTH: " +
+                           calendar.get(calendar.DAY_OF_MONTH));
+        logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
+        logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
+        logln("DAY_OF_WEEK_IN_MONTH: " +
+                           calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
+        logln("AM_PM: " + calendar.get(calendar.AM_PM));
+        logln("HOUR: " + calendar.get(calendar.HOUR));
+        logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
+        logln("MINUTE: " + calendar.get(calendar.MINUTE));
+        logln("SECOND: " + calendar.get(calendar.SECOND));
+        logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
+        logln("ZONE_OFFSET: "
+                           + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000)));
+        logln("DST_OFFSET: "
+                           + (calendar.get(calendar.DST_OFFSET)/(60*60*1000)));
+        calendar  = new GregorianCalendar(1997,3,10);
+        calendar.getTime();
+        logln("April 10, 1997");
+        logln("ERA: " + calendar.get(calendar.ERA));
+        logln("YEAR: " + calendar.get(calendar.YEAR));
+        logln("MONTH: " + calendar.get(calendar.MONTH));
+        logln("WEEK_OF_YEAR: " +
+                           calendar.get(calendar.WEEK_OF_YEAR));
+        logln("WEEK_OF_MONTH: " +
+                           calendar.get(calendar.WEEK_OF_MONTH));
+        logln("DATE: " + calendar.get(calendar.DATE));
+        logln("DAY_OF_MONTH: " +
+                           calendar.get(calendar.DAY_OF_MONTH));
+        logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
+        logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
+        logln("DAY_OF_WEEK_IN_MONTH: " + calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
+        logln("AM_PM: " + calendar.get(calendar.AM_PM));
+        logln("HOUR: " + calendar.get(calendar.HOUR));
+        logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
+        logln("MINUTE: " + calendar.get(calendar.MINUTE));
+        logln("SECOND: " + calendar.get(calendar.SECOND));
+        logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
+        logln("ZONE_OFFSET: "
+                           + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
+        logln("DST_OFFSET: "
+                           + (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); // in hours
+    }
+    */
+
+    public void Test4059654() {
+        GregorianCalendar gc = new GregorianCalendar();
+
+        gc.set(1997, 3, 1, 15, 16, 17); // April 1, 1997
+
+        gc.set(Calendar.HOUR, 0);
+        gc.set(Calendar.AM_PM, Calendar.AM);
+        gc.set(Calendar.MINUTE, 0);
+        gc.set(Calendar.SECOND, 0);
+        gc.set(Calendar.MILLISECOND, 0);
+
+        Date cd = gc.getTime();
+        Date exp = new Date(97, 3, 1, 0, 0, 0);
+        if (!cd.equals(exp))
+            errln("Fail: Calendar.set broken. Got " + cd + " Want " + exp);
+    }
+
+    public void Test4061476() {
+        SimpleDateFormat fmt = new SimpleDateFormat("ddMMMyy", Locale.UK);
+        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"),
+                                                     Locale.UK);
+        fmt.setCalendar(cal);
+        try
+            {
+                Date date = fmt.parse("29MAY97");
+                cal.setTime(date);
+            }
+        catch (Exception e) {;}
+        cal.set(Calendar.HOUR_OF_DAY, 13);
+        logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
+        cal.add(Calendar.HOUR_OF_DAY, 6);
+        logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
+        if (cal.get(Calendar.HOUR_OF_DAY) != 19)
+            errln("Fail: Want 19 Got " + cal.get(Calendar.HOUR_OF_DAY));
+    }
+
+    public void Test4070502() {
+        Date d = getAssociatedDate(new Date(98, 0, 30));
+        Calendar cal = new GregorianCalendar();
+        cal.setTime(d);
+        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
+            cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
+            errln("Fail: Want weekday Got " + d);
+    }
+
+    /**
+     * Get the associated date starting from a specified date
+     * NOTE: the unnecessary "getTime()'s" below are a work-around for a
+     * bug in jdk 1.1.3 (and probably earlier versions also)
+     * <p>
+     * @param date The date to start from
+     */
+    public static Date getAssociatedDate(Date d) {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.setTime(d);
+        //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
+        // cal.getTime();  // <--- REMOVE THIS TO SEE BUG
+        while (true) {
+            int wd = cal.get(Calendar.DAY_OF_WEEK);
+            if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) {
+                cal.add(Calendar.DATE, 1);
+                // cal.getTime();
+            }
+            else
+                break;
+        }
+        return cal.getTime();
+    }
+
+    public void Test4071197() {
+        dowTest(false);
+        dowTest(true);
+    }
+
+    void dowTest(boolean lenient) {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.set(1997, Calendar.AUGUST, 12); // Wednesday
+        // cal.getTime(); // Force update
+        cal.setLenient(lenient);
+        cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
+        int dow = cal.get(Calendar.DAY_OF_WEEK);
+        int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
+        int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
+        logln(cal.getTime().toString());
+        if (min != Calendar.SUNDAY || max != Calendar.SATURDAY)
+            errln("FAIL: Min/max bad");
+        if (dow < min || dow > max)
+            errln("FAIL: Day of week " + dow + " out of range");
+        if (dow != Calendar.SUNDAY)
+            errln("FAIL: Day of week should be SUNDAY Got " + dow);
+    }
+
+    public void Test4071385() {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(new Date(98, Calendar.JUNE, 24));
+        cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24)))
+            errln("Fail");
+    }
+
+    public void Test4073929() {
+        GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27);
+        foo1.add(Calendar.DAY_OF_MONTH, +1);
+        int testyear = foo1.get(Calendar.YEAR);
+        int testmonth = foo1.get(Calendar.MONTH);
+        int testday = foo1.get(Calendar.DAY_OF_MONTH);
+        if (testyear != 1997 ||
+            testmonth != 8 ||
+            testday != 28)
+            errln("Fail: Calendar not initialized");
+    }
+
+    public void Test4083167() {
+        TimeZone saveZone = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+            Date firstDate = new Date();
+            Calendar cal = new GregorianCalendar();
+            cal.setTime(firstDate);
+            long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
+                                    cal.get(Calendar.MINUTE) * 60000L +
+                                    cal.get(Calendar.SECOND) * 1000L +
+                                    cal.get(Calendar.MILLISECOND);
+
+            logln("Current time: " + firstDate.toString());
+
+            for (int validity=0; validity<30; validity++) {
+                Date lastDate = new Date(firstDate.getTime() +
+                                         (long)validity*1000*24*60*60);
+                cal.setTime(lastDate);
+                long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
+                                   cal.get(Calendar.MINUTE) * 60000L +
+                                   cal.get(Calendar.SECOND) * 1000L +
+                                   cal.get(Calendar.MILLISECOND);
+                if (firstMillisInDay != millisInDay) {
+                    errln("Day has shifted " + lastDate);
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    public void Test4086724() {
+        SimpleDateFormat date;
+        TimeZone saveZone = TimeZone.getDefault();
+        Locale saveLocale = Locale.getDefault();
+
+        String summerTime = "British Summer Time";
+        String standardTime = "Greenwich Mean Time";
+        try {
+            Locale.setDefault(Locale.UK);
+            TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
+            date = new SimpleDateFormat("zzzz");
+
+            Calendar cal=Calendar.getInstance();
+            cal.set(1997,Calendar.SEPTEMBER,30);
+            Date now=cal.getTime();
+            String formattedDate = date.format(now);
+            if (!formattedDate.equals(summerTime)) {
+                errln("Wrong display name \"" + formattedDate
+                      + "\" for <" + now + ">");
+            }
+            int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+            if (weekOfYear != 40) {
+                errln("Wrong week-of-year " + weekOfYear
+                      + " for <" + now + ">");
+            }
+
+            cal.set(1996,Calendar.DECEMBER,31);
+            now=cal.getTime();
+            formattedDate = date.format(now);
+            if (!formattedDate.equals(standardTime)) {
+                errln("Wrong display name \"" + formattedDate
+                      + "\" for <" + now + ">");
+            }
+            weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+            if (weekOfYear != 1) {
+                errln("Wrong week-of-year " + weekOfYear
+                      + " for <" + now + ">");
+            }
+
+            cal.set(1997,Calendar.JANUARY,1);
+            now=cal.getTime();
+            formattedDate = date.format(now);
+            if (!formattedDate.equals(standardTime)) {
+                errln("Wrong display name \"" + formattedDate
+                      + "\" for <" + now + ">");
+            }
+            weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+            if (weekOfYear != 1) {
+                errln("Wrong week-of-year " + weekOfYear
+                      + " for <" + now + ">");
+            }
+
+            cal.set(1997,Calendar.JANUARY,8);
+            now=cal.getTime();
+            formattedDate = date.format(now);
+            if (!formattedDate.equals(standardTime)) {
+                errln("Wrong display name \"" + formattedDate
+                      + "\" for <" + now + ">");
+            }
+            weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+            if (weekOfYear != 2) {
+                errln("Wrong week-of-year " + weekOfYear
+                      + " for <" + now + ">");
+            }
+
+        }
+        finally {
+            Locale.setDefault(saveLocale);
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    public void Test4092362() {
+        GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
+        /*cal1.set( Calendar.YEAR, 1997 );
+        cal1.set( Calendar.MONTH, 10 );
+        cal1.set( Calendar.DATE, 11 );
+        cal1.set( Calendar.HOUR, 10 );
+        cal1.set( Calendar.MINUTE, 20 );
+        cal1.set( Calendar.SECOND, 40 ); */
+
+        logln( " Cal1 = " + cal1.getTime().getTime() );
+        logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) );
+        for( int k = 0; k < 100 ; k++ );
+
+        GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
+        /*cal2.set( Calendar.YEAR, 1997 );
+        cal2.set( Calendar.MONTH, 10 );
+        cal2.set( Calendar.DATE, 11 );
+        cal2.set( Calendar.HOUR, 10 );
+        cal2.set( Calendar.MINUTE, 20 );
+        cal2.set( Calendar.SECOND, 40 ); */
+
+        logln( " Cal2 = " + cal2.getTime().getTime() );
+        logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) );
+        if( !cal1.equals( cal2 ) )
+            errln("Fail: Milliseconds randomized");
+    }
+
+    public void Test4095407() {
+        GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13);
+        int dow = a.get(Calendar.DAY_OF_WEEK);
+        if (dow != Calendar.THURSDAY)
+            errln("Fail: Want THURSDAY Got " + dow);
+    }
+
+    public void Test4096231() {
+        TimeZone GMT = TimeZone.getTimeZone("GMT");
+        TimeZone PST = TimeZone.getTimeZone("PST");
+        int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
+
+        Calendar cal1 = new GregorianCalendar(PST);
+        cal1.setTime(new Date(880698639000L));
+        int p;
+        logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY)));
+        cal1.setTimeZone(GMT);
+        // Issue 1: Changing the timezone doesn't change the
+        //          represented time.
+        int h1,h2;
+        logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY)));
+        cal1.setTime(new Date(880698639000L));
+        logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY)));
+        // Note: This test had a bug in it.  It wanted h1!=h2, when
+        // what was meant was h1!=p.  Fixed this concurrent with fix
+        // to 4177484.
+        if (p == h1 || h1 != h2)
+            errln("Fail: Hour same in different zones");
+
+        Calendar cal2 = new GregorianCalendar(GMT);
+        Calendar cal3 = new GregorianCalendar(PST);
+        cal2.set(Calendar.MILLISECOND, 0);
+        cal3.set(Calendar.MILLISECOND, 0);
+
+        cal2.set(cal1.get(cal1.YEAR),
+                 cal1.get(cal1.MONTH),
+                 cal1.get(cal1.DAY_OF_MONTH),
+                 cal1.get(cal1.HOUR_OF_DAY),
+                 cal1.get(cal1.MINUTE),
+                 cal1.get(cal1.SECOND));
+
+        long t1,t2,t3,t4;
+        logln("RGMT 1 is: " + (t1=cal2.getTime().getTime()));
+        cal3.set(year, month, day, hr, min, sec);
+        logln("RPST 1 is: " + (t2=cal3.getTime().getTime()));
+        cal3.setTimeZone(GMT);
+        logln("RGMT 2 is: " + (t3=cal3.getTime().getTime()));
+        cal3.set(cal1.get(cal1.YEAR),
+                 cal1.get(cal1.MONTH),
+                 cal1.get(cal1.DAY_OF_MONTH),
+                 cal1.get(cal1.HOUR_OF_DAY),
+                 cal1.get(cal1.MINUTE),
+                 cal1.get(cal1.SECOND));
+        // Issue 2: Calendar continues to use the timezone in its
+        //          constructor for set() conversions, regardless
+        //          of calls to setTimeZone()
+        logln("RGMT 3 is: " + (t4=cal3.getTime().getTime()));
+        if (t1 == t2 ||
+            t1 != t4 ||
+            t2 != t3)
+            errln("Fail: Calendar zone behavior faulty");
+    }
+
+    public void Test4096539() {
+        int[] y = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+        for (int x=0;x<12;x++) {
+            GregorianCalendar gc = new
+                GregorianCalendar(1997,x,y[x]);
+            int m1,m2;
+            log((m1=gc.get(Calendar.MONTH)+1)+"/"+
+                             gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+
+                             " + 1mo = ");
+
+            gc.add(Calendar.MONTH, 1);
+            logln((m2=gc.get(Calendar.MONTH)+1)+"/"+
+                               gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)
+                               );
+            int m = (m1 % 12) + 1;
+            if (m2 != m)
+                errln("Fail: Want " + m + " Got " + m2);
+        }
+
+    }
+
+    public void Test4100311() {
+        GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
+        cal.set(Calendar.YEAR, 1997);
+        cal.set(Calendar.DAY_OF_YEAR, 1);
+        Date d = cal.getTime();             // Should be Jan 1
+        logln(d.toString());
+        if (cal.get(Calendar.DAY_OF_YEAR) != 1)
+            errln("Fail: DAY_OF_YEAR not set");
+    }
+
+    public void Test4103271() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        SimpleDateFormat sdf = new SimpleDateFormat();
+        int numYears=40, startYear=1997, numDays=15;
+        String output, testDesc;
+        GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
+        testCal.clear();
+        sdf.setCalendar(testCal);
+        sdf.applyPattern("d MMM yyyy");
+        boolean fail = false;
+        for (int firstDay=1; firstDay<=2; firstDay++) {
+            for (int minDays=1; minDays<=7; minDays++) {
+                testCal.setMinimalDaysInFirstWeek(minDays);
+                testCal.setFirstDayOfWeek(firstDay);
+                testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays));
+                logln(testDesc + " => 1st day of week=" +
+                                   String.valueOf(firstDay) +
+                                   ", minimum days in first week=" +
+                                   String.valueOf(minDays));
+                for (int j=startYear; j<=startYear+numYears; j++) {
+                    testCal.set(j,11,25);
+                    for(int i=0; i<numDays; i++) {
+                        testCal.add(Calendar.DATE,1);
+                        String calWOY;
+                        int actWOY = testCal.get(Calendar.WEEK_OF_YEAR);
+                        if (actWOY < 1 || actWOY > 53) {
+                            Date d = testCal.getTime();
+                            calWOY = String.valueOf(actWOY);
+                            output = testDesc + " - " + sdf.format(d) + "\t";
+                            output = output + "\t" + calWOY;
+                            logln(output);
+                            fail = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        int[] DATA = {
+            3, 52, 52, 52, 52, 52, 52, 52,
+                1,  1,  1,  1,  1,  1,  1,
+                2,  2,  2,  2,  2,  2,  2,
+            4, 52, 52, 52, 52, 52, 52, 52,
+               53, 53, 53, 53, 53, 53, 53,
+                1,  1,  1,  1,  1,  1,  1,
+        };
+        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+        for (int j=0; j<DATA.length; j+=22) {
+            logln("Minimal days in first week = " + DATA[j] +
+                               "  Week starts on Sunday");
+            testCal.setMinimalDaysInFirstWeek(DATA[j]);
+            testCal.set(1997, Calendar.DECEMBER, 21);
+            for (int i=0; i<21; ++i) {
+                int woy = testCal.get(Calendar.WEEK_OF_YEAR);
+                log("\t" + testCal.getTime() + " " + woy);
+                if (woy != DATA[j + 1 + i]) {
+                    log(" ERROR");
+                    fail = true;
+                } else {
+                    logln(" OK");
+                }
+
+                // Now compute the time from the fields, and make sure we
+                // get the same answer back.  This is a round-trip test.
+                Date save = testCal.getTime();
+                testCal.clear();
+                testCal.set(Calendar.YEAR, DATA[j+1+i] < 25 ? 1998 : 1997);
+                testCal.set(Calendar.WEEK_OF_YEAR, DATA[j+1+i]);
+                testCal.set(Calendar.DAY_OF_WEEK, (i%7) + Calendar.SUNDAY);
+                if (!testCal.getTime().equals(save)) {
+                    logln("  Parse failed: " + testCal.getTime());
+                    fail= true;
+                } else {
+                    logln("  Passed");
+                }
+
+                testCal.setTime(save);
+                testCal.add(Calendar.DAY_OF_MONTH, 1);
+            }
+        }
+
+        // Test field disambiguation with a few special hard-coded cases.
+        // This shouldn't fail if the above cases aren't failing.
+        Object[] DISAM = {
+            new Integer(1998), new Integer(1), new Integer(Calendar.SUNDAY),
+                new Date(97, Calendar.DECEMBER, 28),
+            new Integer(1998), new Integer(2), new Integer(Calendar.SATURDAY),
+                new Date(98, Calendar.JANUARY, 10),
+            new Integer(1998), new Integer(53), new Integer(Calendar.THURSDAY),
+                new Date(98, Calendar.DECEMBER, 31),
+            new Integer(1998), new Integer(53), new Integer(Calendar.FRIDAY),
+                new Date(99, Calendar.JANUARY, 1),
+        };
+        testCal.setMinimalDaysInFirstWeek(3);
+        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+        for (int i=0; i<DISAM.length; i+=4) {
+            int y = ((Integer)DISAM[i]).intValue();
+            int woy = ((Integer)DISAM[i+1]).intValue();
+            int dow = ((Integer)DISAM[i+2]).intValue();
+            Date exp = (Date)DISAM[i+3];
+            testCal.clear();
+            testCal.set(Calendar.YEAR, y);
+            testCal.set(Calendar.WEEK_OF_YEAR, woy);
+            testCal.set(Calendar.DAY_OF_WEEK, dow);
+            log(y + "-W" + woy + "-DOW" + dow);
+            if (!testCal.getTime().equals(exp)) {
+                logln("  FAILED expect: " + exp + "\n            got: " +testCal.getTime());
+                fail = true;
+            } else {
+                logln("  OK");
+            }
+        }
+
+        // Now try adding and rolling
+        Object ADD = new Object();
+        Object ROLL = new Object();
+        Object[] ADDROLL = {
+            ADD, new Integer(1), new Date(98, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 1),
+            ADD, new Integer(1), new Date(97, Calendar.DECEMBER, 28), new Date(98, Calendar.JANUARY, 4),
+            ROLL, new Integer(1), new Date(98, Calendar.DECEMBER, 27), new Date(98, Calendar.JANUARY, 4),
+            ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 24), new Date(99, Calendar.DECEMBER, 31),
+            ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 9),
+        };
+        testCal.setMinimalDaysInFirstWeek(3);
+        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+        for (int i=0; i<ADDROLL.length; i+=4) {
+            int amount = ((Integer)ADDROLL[i+1]).intValue();
+            Date before = (Date)ADDROLL[i+2];
+            Date after = (Date)ADDROLL[i+3];
+
+            testCal.setTime(before);
+            if (ADDROLL[i] == ADD)
+                testCal.add(Calendar.WEEK_OF_YEAR, amount);
+            else
+                testCal.roll(Calendar.WEEK_OF_YEAR, amount);
+            log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
+                amount + ")\t     " + before +
+                "\n\t\t  => " + testCal.getTime());
+            if (!after.equals(testCal.getTime())) {
+                logln("\tFAIL\n\t\texp: " + after);
+                fail = true;
+            } else
+                logln("  OK");
+
+            testCal.setTime(after);
+            if (ADDROLL[i] == ADD)
+                testCal.add(Calendar.WEEK_OF_YEAR, -amount);
+            else
+                testCal.roll(Calendar.WEEK_OF_YEAR, -amount);
+            log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
+                (-amount) + ")     " + after +
+                "\n\t\t  => " + testCal.getTime());
+            if (!before.equals(testCal.getTime())) {
+                logln("\tFAIL\n\t\texp: " + before);
+                fail = true;
+            }
+            else logln("\tOK");
+        }
+
+        if (fail) {
+            errln("Fail: Week of year misbehaving");
+        }
+    }
+
+    public void Test4106136() {
+        Locale saveLocale = Locale.getDefault();
+        try {
+            Locale[] locales = { Locale.CHINESE, Locale.CHINA };
+            for (int i=0; i<locales.length; ++i) {
+                Locale.setDefault(locales[i]);
+                int[] n = {
+                    Calendar.getAvailableLocales().length,
+                    DateFormat.getAvailableLocales().length,
+                    NumberFormat.getAvailableLocales().length
+                };
+                for (int j=0; j<n.length; ++j) {
+                    if (n[j] == 0) {
+                        errln("Fail: No locales for " + locales[i]);
+                    }
+                }
+            }
+        }
+        finally {
+            Locale.setDefault(saveLocale);
+        }
+    }
+
+    public void Test4108764() {
+        Date d00 = new Date(97, Calendar.MARCH, 15, 12, 00, 00);
+        Date d01 = new Date(97, Calendar.MARCH, 15, 12, 00, 56);
+        Date d10 = new Date(97, Calendar.MARCH, 15, 12, 34, 00);
+        Date d11 = new Date(97, Calendar.MARCH, 15, 12, 34, 56);
+        Date epoch = new Date(70, Calendar.JANUARY, 1);
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(d11);
+
+        cal.clear( Calendar.MINUTE );
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(d01))
+            errln("Fail: clear(MINUTE) broken");
+
+        cal.set( Calendar.SECOND, 0 );
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(d00))
+            errln("Fail: set(SECOND, 0) broken");
+
+        cal.setTime(d11);
+        cal.set( Calendar.SECOND, 0 );
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(d10))
+            errln("Fail: set(SECOND, 0) broken #2");
+
+        cal.clear( Calendar.MINUTE );
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(d00))
+            errln("Fail: clear(MINUTE) broken #2");
+
+        cal.clear();
+        logln(cal.getTime().toString());
+        if (!cal.getTime().equals(epoch))
+            errln("Fail: clear() broken Want " + epoch);
+    }
+
+    public void Test4114578() {
+        int ONE_HOUR = 60*60*1000;
+        TimeZone saveZone = TimeZone.getDefault();
+        boolean fail = false;
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+            Calendar cal = Calendar.getInstance();
+            long onset = new Date(98, Calendar.APRIL, 5, 1, 0).getTime() + ONE_HOUR;
+            long cease = new Date(98, Calendar.OCTOBER, 25, 0, 0).getTime() + 2*ONE_HOUR;
+
+            final int ADD = 1;
+            final int ROLL = 2;
+
+            long[] DATA = {
+                // Start            Action   Amt    Expected_change
+                onset - ONE_HOUR,   ADD,      1,     ONE_HOUR,
+                onset,              ADD,     -1,    -ONE_HOUR,
+                onset - ONE_HOUR,   ROLL,     1,     ONE_HOUR,
+                onset,              ROLL,    -1,    -ONE_HOUR,
+                cease - ONE_HOUR,   ADD,      1,     ONE_HOUR,
+                cease,              ADD,     -1,    -ONE_HOUR,
+                // roll() was changed to support wall-clock-based roll (JDK-8152077). The
+                // time value may jump 2 hours by skipping non-existent wall-clock time.
+                // Note that JDK-4114578 was a problem of add(), not roll().
+                cease - ONE_HOUR,   ROLL,     1,     ONE_HOUR * 2,
+                cease,              ROLL,    -1,    -ONE_HOUR * 2,
+            };
+
+            for (int i=0; i<DATA.length; i+=4) {
+                Date date = new Date(DATA[i]);
+                int amt = (int) DATA[i+2];
+                long expectedChange = DATA[i+3];
+
+                log(date.toString());
+                cal.setTime(date);
+
+                switch ((int) DATA[i+1]) {
+                case ADD:
+                    log(" add (HOUR," + (amt<0?"":"+")+amt + ")= ");
+                    cal.add(Calendar.HOUR, amt);
+                    break;
+                case ROLL:
+                    log(" roll(HOUR," + (amt<0?"":"+")+amt + ")= ");
+                    cal.roll(Calendar.HOUR, amt);
+                    break;
+                }
+
+                log(cal.getTime().toString());
+
+                long change = cal.getTime().getTime() - date.getTime();
+                if (change != expectedChange) {
+                    fail = true;
+                    logln(" FAIL");
+                }
+                else logln(" OK");
+            }
+        } finally {
+            TimeZone.setDefault(saveZone);
+        }
+
+        if (fail) {
+            errln("Fail: roll/add misbehaves around DST onset/cease");
+        }
+    }
+
+    /**
+     * Make sure maximum for HOUR field is 11, not 12.
+     */
+    public void Test4118384() {
+        Calendar cal = Calendar.getInstance();
+        if (cal.getMaximum(Calendar.HOUR) != 11 ||
+            cal.getLeastMaximum(Calendar.HOUR) != 11 ||
+            cal.getActualMaximum(Calendar.HOUR) != 11)
+            errln("Fail: maximum of HOUR field should be 11");
+    }
+
+    /**
+     * Check isLeapYear for BC years.
+     */
+    public void Test4125881() {
+        GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
+        DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
+        cal.clear();
+        for (int y=-20; y<=10; ++y) {
+            cal.set(Calendar.ERA, y < 1 ? GregorianCalendar.BC : GregorianCalendar.AD);
+            cal.set(Calendar.YEAR, y < 1 ? 1 - y : y);
+            logln(y + " = " + fmt.format(cal.getTime()) + " " +
+                               cal.isLeapYear(y));
+            if (cal.isLeapYear(y) != ((y+40)%4 == 0))
+                errln("Leap years broken");
+        }
+    }
+
+    /**
+     * Prove that GregorianCalendar is proleptic (it used to cut off
+     * at 45 BC, and not have leap years before then).
+     */
+    public void Test4125892() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
+        DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
+        cal.clear();
+        cal.set(Calendar.ERA, GregorianCalendar.BC);
+        cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically)
+        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
+        cal.set(Calendar.DATE, 28);
+        cal.add(Calendar.DATE, 1);
+        if (cal.get(Calendar.DATE) != 29 ||
+            !cal.isLeapYear(-80)) // -80 == 81 BC
+            errln("Calendar not proleptic");
+    }
+
+    /**
+     * Calendar and GregorianCalendar hashCode() methods need improvement.
+     * Calendar needs a good implementation that subclasses can override,
+     * and GregorianCalendar should use that implementation.
+     */
+    public void Test4136399() {
+        /* Note: This test is actually more strict than it has to be.
+         * Technically, there is no requirement that unequal objects have
+         * unequal hashes.  We only require equal objects to have equal hashes.
+         * It is desirable for unequal objects to have distributed hashes, but
+         * there is no hard requirement here.
+         *
+         * In this test we make assumptions about certain attributes of calendar
+         * objects getting represented in the hash, which need not always be the
+         * case (although it does work currently with the given test). */
+        Calendar a = Calendar.getInstance();
+        Calendar b = (Calendar)a.clone();
+        if (a.hashCode() != b.hashCode()) {
+            errln("Calendar hash code unequal for cloned objects");
+        }
+
+        b.setMinimalDaysInFirstWeek(7 - a.getMinimalDaysInFirstWeek());
+        if (a.hashCode() == b.hashCode()) {
+            errln("Calendar hash code ignores minimal days in first week");
+        }
+        b.setMinimalDaysInFirstWeek(a.getMinimalDaysInFirstWeek());
+
+        b.setFirstDayOfWeek((a.getFirstDayOfWeek() % 7) + 1); // Next day
+        if (a.hashCode() == b.hashCode()) {
+            errln("Calendar hash code ignores first day of week");
+        }
+        b.setFirstDayOfWeek(a.getFirstDayOfWeek());
+
+        b.setLenient(!a.isLenient());
+        if (a.hashCode() == b.hashCode()) {
+            errln("Calendar hash code ignores lenient setting");
+        }
+        b.setLenient(a.isLenient());
+
+        // Assume getTimeZone() returns a reference, not a clone
+        // of a reference -- this is true as of this writing
+        b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset() + 60*60*1000);
+        if (a.hashCode() == b.hashCode()) {
+            errln("Calendar hash code ignores zone");
+        }
+        b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset());
+
+        GregorianCalendar c = new GregorianCalendar();
+        GregorianCalendar d = (GregorianCalendar)c.clone();
+        if (c.hashCode() != d.hashCode()) {
+            errln("GregorianCalendar hash code unequal for clones objects");
+        }
+        Date cutover = c.getGregorianChange();
+        d.setGregorianChange(new Date(cutover.getTime() + 24*60*60*1000));
+        if (c.hashCode() == d.hashCode()) {
+            errln("GregorianCalendar hash code ignores cutover");
+        }
+    }
+
+    /**
+     * GregorianCalendar.equals() ignores cutover date
+     */
+    public void Test4141665() {
+        GregorianCalendar cal = new GregorianCalendar();
+        GregorianCalendar cal2 = (GregorianCalendar)cal.clone();
+        Date cut = cal.getGregorianChange();
+        Date cut2 = new Date(cut.getTime() + 100*24*60*60*1000L); // 100 days later
+        if (!cal.equals(cal2)) {
+            errln("Cloned GregorianCalendars not equal");
+        }
+        cal2.setGregorianChange(cut2);
+        if (cal.equals(cal2)) {
+            errln("GregorianCalendar.equals() ignores cutover");
+        }
+    }
+
+    /**
+     * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar.roll()
+     * when IllegalArgumentException should be.
+     */
+    public void Test4142933() {
+        GregorianCalendar calendar = new GregorianCalendar();
+        try {
+            calendar.roll(-1, true);
+            errln("Test failed, no exception trown");
+        }
+        catch (IllegalArgumentException e) {
+            // OK: Do nothing
+            // logln("Test passed");
+        }
+        catch (Exception e) {
+            errln("Test failed. Unexpected exception is thrown: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
+     * confusing; unless the time zone has a raw offset of zero, one or the
+     * other of these will wrap.  We've modified the test given in the bug
+     * report to therefore only check the behavior of a calendar with a zero raw
+     * offset zone.
+     */
+    public void Test4145158() {
+        GregorianCalendar calendar = new GregorianCalendar();
+
+        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+        calendar.setTime(new Date(Long.MIN_VALUE));
+        int year1 = calendar.get(Calendar.YEAR);
+        int era1 = calendar.get(Calendar.ERA);
+
+        calendar.setTime(new Date(Long.MAX_VALUE));
+        int year2 = calendar.get(Calendar.YEAR);
+        int era2 = calendar.get(Calendar.ERA);
+
+        if (year1 == year2 && era1 == era2) {
+            errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
+        }
+    }
+
+    /**
+     * Maximum value for YEAR field wrong.
+     */
+    public void Test4145983() {
+        GregorianCalendar calendar = new GregorianCalendar();
+        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+        Date[] DATES = { new Date(Long.MAX_VALUE), new Date(Long.MIN_VALUE) };
+        for (int i=0; i<DATES.length; ++i) {
+            calendar.setTime(DATES[i]);
+            int year = calendar.get(Calendar.YEAR);
+            int maxYear = calendar.getMaximum(Calendar.YEAR);
+            if (year > maxYear) {
+                errln("Failed for "+DATES[i].getTime()+" ms: year=" +
+                      year + ", maxYear=" + maxYear);
+            }
+        }
+    }
+
+    /**
+     * This is a bug in the validation code of GregorianCalendar.  As reported,
+     * the bug seems worse than it really is, due to a bug in the way the bug
+     * report test was written.  In reality the bug is restricted to the DAY_OF_YEAR
+     * field. - liu 6/29/98
+     */
+    public void Test4147269() {
+        final String[] fieldName = {
+            "ERA",
+            "YEAR",
+            "MONTH",
+            "WEEK_OF_YEAR",
+            "WEEK_OF_MONTH",
+            "DAY_OF_MONTH",
+            "DAY_OF_YEAR",
+            "DAY_OF_WEEK",
+            "DAY_OF_WEEK_IN_MONTH",
+            "AM_PM",
+            "HOUR",
+            "HOUR_OF_DAY",
+            "MINUTE",
+            "SECOND",
+            "MILLISECOND",
+            "ZONE_OFFSET",
+            "DST_OFFSET"
+        };
+        GregorianCalendar calendar = new GregorianCalendar();
+        calendar.setLenient(false);
+        Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date
+        for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+            calendar.setTime(date);
+            // Note: In the bug report, getActualMaximum() was called instead
+            // of getMaximum() -- this was an error.  The validation code doesn't
+            // use getActualMaximum(), since that's too costly.
+            int max = calendar.getMaximum(field);
+            int value = max+1;
+            calendar.set(field, value);
+            try {
+                calendar.getTime(); // Force time computation
+                // We expect an exception to be thrown. If we fall through
+                // to the next line, then we have a bug.
+                errln("Test failed with field " + fieldName[field] +
+                      ", date before: " + date +
+                      ", date after: " + calendar.getTime() +
+                      ", value: " + value + " (max = " + max +")");
+            } catch (IllegalArgumentException e) {}
+        }
+    }
+
+    /**
+     * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
+     * doesn't behave as a pure Julian calendar.
+     * CANNOT REPRODUCE THIS BUG
+     */
+    public void Test4149677() {
+        TimeZone[] zones = { TimeZone.getTimeZone("GMT"),
+                             TimeZone.getTimeZone("PST"),
+                             TimeZone.getTimeZone("EAT") };
+        for (int i=0; i<zones.length; ++i) {
+            GregorianCalendar calendar = new GregorianCalendar(zones[i]);
+
+            // Make sure extreme values don't wrap around
+            calendar.setTime(new Date(Long.MIN_VALUE));
+            if (calendar.get(Calendar.ERA) != GregorianCalendar.BC) {
+                errln("Fail: Date(Long.MIN_VALUE) has an AD year in " + zones[i]);
+            }
+            calendar.setTime(new Date(Long.MAX_VALUE));
+            if (calendar.get(Calendar.ERA) != GregorianCalendar.AD) {
+                errln("Fail: Date(Long.MAX_VALUE) has a BC year in " + zones[i]);
+            }
+
+            calendar.setGregorianChange(new Date(Long.MAX_VALUE));
+            // to obtain a pure Julian calendar
+
+            boolean is100Leap = calendar.isLeapYear(100);
+            if (!is100Leap) {
+                errln("test failed with zone " + zones[i].getID());
+                errln(" cutover date is Date(Long.MAX_VALUE)");
+                errln(" isLeapYear(100) returns: " + is100Leap);
+            }
+        }
+    }
+
+    /**
+     * Calendar and Date HOUR broken.  If HOUR is out-of-range, Calendar
+     * and Date classes will misbehave.
+     */
+    public void Test4162587() {
+        TimeZone savedTz = TimeZone.getDefault();
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        TimeZone.setDefault(tz);
+        GregorianCalendar cal = new GregorianCalendar(tz);
+        Date d;
+
+        try {
+            for (int i=0; i<5; ++i) {
+                if (i>0) logln("---");
+
+                cal.clear();
+                cal.set(1998, Calendar.APRIL, 5, i, 0);
+                d = cal.getTime();
+                String s0 = d.toString();
+                logln("0 " + i + ": " + s0);
+
+                cal.clear();
+                cal.set(1998, Calendar.APRIL, 4, i+24, 0);
+                d = cal.getTime();
+                String sPlus = d.toString();
+                logln("+ " + i + ": " + sPlus);
+
+                cal.clear();
+                cal.set(1998, Calendar.APRIL, 6, i-24, 0);
+                d = cal.getTime();
+                String sMinus = d.toString();
+                logln("- " + i + ": " + sMinus);
+
+                if (!s0.equals(sPlus) || !s0.equals(sMinus)) {
+                    errln("Fail: All three lines must match");
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(savedTz);
+        }
+    }
+
+    /**
+     * Adding 12 months behaves differently from adding 1 year
+     */
+    public void Test4165343() {
+        GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29);
+        Date start = calendar.getTime();
+        logln("init date: " + start);
+        calendar.add(Calendar.MONTH, 12);
+        Date date1 = calendar.getTime();
+        logln("after adding 12 months: " + date1);
+        calendar.setTime(start);
+        calendar.add(Calendar.YEAR, 1);
+        Date date2 = calendar.getTime();
+        logln("after adding one year : " + date2);
+        if (date1.equals(date2)) {
+            logln("Test passed");
+        } else {
+            errln("Test failed");
+        }
+    }
+
+    /**
+     * GregorianCalendar.getActualMaximum() does not account for first day of week.
+     */
+    public void Test4166109() {
+        /* Test month:
+         *
+         *      March 1998
+         * Su Mo Tu We Th Fr Sa
+         *  1  2  3  4  5  6  7
+         *  8  9 10 11 12 13 14
+         * 15 16 17 18 19 20 21
+         * 22 23 24 25 26 27 28
+         * 29 30 31
+         */
+        boolean passed = true;
+        int field = Calendar.WEEK_OF_MONTH;
+
+        GregorianCalendar calendar = new GregorianCalendar(Locale.US);
+        calendar.set(1998, Calendar.MARCH, 1);
+        calendar.setMinimalDaysInFirstWeek(1);
+        logln("Date:  " + calendar.getTime());
+
+        int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH);
+
+        for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) {
+            calendar.setFirstDayOfWeek(firstInWeek);
+            int returned = calendar.getActualMaximum(field);
+            int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
+
+            logln("First day of week = " + firstInWeek +
+                  "  getActualMaximum(WEEK_OF_MONTH) = " + returned +
+                  "  expected = " + expected +
+                  ((returned == expected) ? "  ok" : "  FAIL"));
+
+            if (returned != expected) {
+                passed = false;
+            }
+        }
+        if (!passed) {
+            errln("Test failed");
+        }
+    }
+
+    /**
+     * Calendar.getActualMaximum(YEAR) works wrong.
+     *
+     * Note: Before 1.5, this test case assumed that
+     * setGregorianChange didn't change object's date. But it was
+     * changed. See 4928615.
+     */
+    public void Test4167060() {
+        int field = Calendar.YEAR;
+        DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G",
+                                                 Locale.US);
+
+        int[][] dates = {
+            // year, month, day of month
+            { 100, Calendar.NOVEMBER, 1 },
+            { -99 /*100BC*/, Calendar.JANUARY, 1 },
+            { 1996, Calendar.FEBRUARY, 29 }};
+
+        String[] id = { "Hybrid", "Gregorian", "Julian" };
+
+        for (int k=0; k<3; ++k) {
+            logln("--- " + id[k] + " ---");
+
+            for (int j = 0; j < dates.length; ++j) {
+                GregorianCalendar calendar = new GregorianCalendar();
+                if (k == 1) {
+                    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
+                } else if (k == 2) {
+                    calendar.setGregorianChange(new Date(Long.MAX_VALUE));
+                }
+                calendar.set(dates[j][0], dates[j][1], dates[j][2]);
+                format.setCalendar((Calendar)calendar.clone());
+
+                Date dateBefore = calendar.getTime();
+
+                int maxYear = calendar.getActualMaximum(field);
+                logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime()));
+                logln("date before: " + format.format(dateBefore));
+
+                int years[] = {2000, maxYear-1, maxYear, maxYear+1};
+
+                for (int i = 0; i < years.length; i++) {
+                    boolean valid = years[i] <= maxYear;
+                    calendar.set(field, years[i]);
+                    Date dateAfter = calendar.getTime();
+                    int newYear = calendar.get(field);
+                    calendar.setTime(dateBefore); // restore calendar for next use
+
+                    logln(" Year " + years[i] + (valid? " ok " : " bad") +
+                          " => " + format.format(dateAfter));
+                    if (valid && newYear != years[i]) {
+                        errln("  FAIL: " + newYear + " should be valid; date, month and time shouldn't change");
+                    } else if (!valid && newYear == years[i]) {
+                        errln("  FAIL: " + newYear + " should be invalid");
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Calendar.roll broken
+     * This bug relies on the TimeZone bug 4173604 to also be fixed.
+     */
+    public void Test4173516() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        int fieldsList[][] = {
+            { 1997, Calendar.FEBRUARY,  1, 10, 45, 15, 900 },
+            { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 },
+            // test case for 4960642 with default cutover
+            { 1582, Calendar.OCTOBER,   4, 23, 59, 59, 999 },
+        };
+        String[] fieldNames = {
+            "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
+            "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH",
+            "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND",
+            "ZONE_OFFSET", "DST_OFFSET"
+        };
+
+        Locale savedLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        int limit = 40;
+
+        try {
+            GregorianCalendar cal = new GregorianCalendar();
+
+            cal.setTime(new Date(0));
+            cal.roll(Calendar.HOUR,  0x7F000000);
+            cal.roll(Calendar.HOUR, -0x7F000000);
+            if (cal.getTime().getTime() != 0) {
+                errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime());
+            }
+
+            for (int op=0; op<2; ++op) {
+                logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll"));
+
+                for (int field=0; field < Calendar.FIELD_COUNT; ++field) {
+                    if (field != Calendar.ZONE_OFFSET &&
+                        field != Calendar.DST_OFFSET) {
+                        for (int j=0; j<fieldsList.length; ++j) {
+                            int fields[] = fieldsList[j];
+                            cal.clear();
+                            cal.set(fields[0], fields[1], fields[2],
+                                    fields[3], fields[4], fields[5]);
+                            cal.set(Calendar.MILLISECOND, fields[6]);
+                            for (int i = 0; i < 2*limit; i++) {
+                                if (op == 0) {
+                                    cal.add(field, i < limit ? 1 : -1);
+                                } else {
+                                    cal.roll(field, i < limit ? 1 : -1);
+                                }
+                            }
+
+                            if (cal.get(Calendar.YEAR) != fields[0] ||
+                                cal.get(Calendar.MONTH) != fields[1] ||
+                                cal.get(Calendar.DATE) != fields[2] ||
+                                cal.get(Calendar.HOUR_OF_DAY) != fields[3] ||
+                                cal.get(Calendar.MINUTE) != fields[4] ||
+                                cal.get(Calendar.SECOND) != fields[5] ||
+                                cal.get(Calendar.MILLISECOND) != fields[6]) {
+                                errln("Field " + field +
+                                      " (" + fieldNames[field] +
+                                      ") FAIL, expected " +
+                                      fields[0] +
+                                      "/" + (fields[1] + 1) +
+                                      "/" + fields[2] +
+                                      " " + fields[3] +
+                                      ":" + fields[4] +
+                                      ":" + fields[5] +
+                                      "." + fields[6] +
+                                      ", got " + cal.get(Calendar.YEAR) +
+                                      "/" + (cal.get(Calendar.MONTH) + 1) +
+                                      "/" + cal.get(Calendar.DATE) +
+                                      " " + cal.get(Calendar.HOUR_OF_DAY) +
+                                      ":" + cal.get(Calendar.MINUTE) +
+                                      ":" + cal.get(Calendar.SECOND) +
+                                      "." + cal.get(Calendar.MILLISECOND));
+
+                                cal.clear();
+                                cal.set(fields[0], fields[1], fields[2],
+                                        fields[3], fields[4], fields[5]);
+                                cal.set(Calendar.MILLISECOND, fields[6]);
+                                errln(cal.get(Calendar.YEAR) +
+                                      "/" + (cal.get(Calendar.MONTH) + 1) +
+                                      "/" + cal.get(Calendar.DATE) +
+                                      " " + cal.get(Calendar.HOUR_OF_DAY) +
+                                      ":" + cal.get(Calendar.MINUTE) +
+                                      ":" + cal.get(Calendar.SECOND) +
+                                      "." + cal.get(Calendar.MILLISECOND));
+
+                                long prev = cal.getTime().getTime();
+                                for (int i = 0; i < 2*limit; i++) {
+                                    if (op == 0) {
+                                        cal.add(field, i < limit ? 1 : -1);
+                                    } else {
+                                        cal.roll(field, i < limit ? 1 : -1);
+                                    }
+                                    long t = cal.getTime().getTime();
+                                    long delta = t - prev;
+                                    prev = t;
+                                    errln((op == 0 ? "add(" : "roll(") +
+                                          fieldNames[field] + ", " +
+                                          (i < limit ? "+" : "-") + "1) => " +
+                                          cal.get(Calendar.YEAR) +
+                                          "/" + (cal.get(Calendar.MONTH) + 1) +
+                                          "/" + cal.get(Calendar.DATE) +
+                                          " " + cal.get(Calendar.HOUR_OF_DAY) +
+                                          ":" + cal.get(Calendar.MINUTE) +
+                                          ":" + cal.get(Calendar.SECOND) +
+                                          "." + cal.get(Calendar.MILLISECOND) +
+                                          " d=" + delta);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            Locale.setDefault(savedLocale);
+        }
+    }
+
+    public void Test4174361() {
+        GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29);
+
+        calendar.add(Calendar.MONTH, 10);
+        Date date1 = calendar.getTime();
+        int d1 = calendar.get(Calendar.DAY_OF_MONTH);
+
+        calendar = new GregorianCalendar(1996, 1, 29);
+        calendar.add(Calendar.MONTH, 11);
+        Date date2 = calendar.getTime();
+        int d2 = calendar.get(Calendar.DAY_OF_MONTH);
+
+        if (d1 != d2) {
+            errln("adding months to Feb 29 broken");
+        }
+    }
+
+    /**
+     * Calendar does not update field values when setTimeZone is called.
+     */
+    public void Test4177484() {
+        TimeZone PST = TimeZone.getTimeZone("PST");
+        TimeZone EST = TimeZone.getTimeZone("EST");
+
+        Calendar cal = Calendar.getInstance(PST, Locale.US);
+        cal.clear();
+        cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary
+        int h1 = cal.get(Calendar.HOUR_OF_DAY);
+        cal.setTimeZone(EST);
+        int h2 = cal.get(Calendar.HOUR_OF_DAY);
+        if (h1 == h2) {
+            errln("FAIL: Fields not updated after setTimeZone");
+        }
+
+        // getTime() must NOT change when time zone is changed.
+        // getTime() returns zone-independent time in ms.
+        cal.clear();
+        cal.setTimeZone(PST);
+        cal.set(Calendar.HOUR_OF_DAY, 10);
+        Date pst10 = cal.getTime();
+        cal.setTimeZone(EST);
+        Date est10 = cal.getTime();
+        if (!pst10.equals(est10)) {
+            errln("FAIL: setTimeZone changed time");
+        }
+    }
+
+    /**
+     * Week of year is wrong at the start and end of the year.
+     */
+    public void Test4197699() {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.setFirstDayOfWeek(Calendar.MONDAY);
+        cal.setMinimalDaysInFirstWeek(4);
+        DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy  'DOY='D 'WOY='w");
+        fmt.setCalendar(cal);
+
+        int[] DATA = {
+            2000,  Calendar.JANUARY,   1,   52,
+            2001,  Calendar.DECEMBER,  31,  1,
+        };
+
+        for (int i=0; i<DATA.length; ) {
+            cal.set(DATA[i++], DATA[i++], DATA[i++]);
+            int expWOY = DATA[i++];
+            int actWOY = cal.get(Calendar.WEEK_OF_YEAR);
+            if (expWOY == actWOY) {
+                logln("Ok: " + fmt.format(cal.getTime()));
+            } else {
+                errln("FAIL: " + fmt.format(cal.getTime())
+                      + ", expected WOY=" + expWOY);
+                cal.add(Calendar.DATE, -8);
+                for (int j=0; j<14; ++j) {
+                    cal.add(Calendar.DATE, 1);
+                    logln(fmt.format(cal.getTime()));
+                }
+            }
+        }
+    }
+
+    /**
+     * Calendar DAY_OF_WEEK_IN_MONTH fields->time broken.  The problem
+     * is in the field disambiguation code in GregorianCalendar.  This
+     * code is supposed to choose the most recent set of fields
+     * among the following:
+     *
+     *   MONTH + DAY_OF_MONTH
+     *   MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+     *   MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+     *   DAY_OF_YEAR
+     *   WEEK_OF_YEAR + DAY_OF_WEEK
+     */
+    public void Test4209071() {
+        Calendar cal = Calendar.getInstance(Locale.US);
+
+        // General field setting test
+        int Y = 1995 - 1900;
+
+        Object[] FIELD_DATA = {
+            // Add new test cases as needed.
+
+            // 0
+            new int[] {}, new Date(Y, Calendar.JANUARY, 1),
+            // 1
+            new int[] { Calendar.MONTH, Calendar.MARCH },
+            new Date(Y, Calendar.MARCH, 1),
+            // 2
+            new int[] { Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY },
+            new Date(Y, Calendar.JANUARY, 4),
+            // 3
+            new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
+                        Calendar.DAY_OF_MONTH, 18, },
+            new Date(Y, Calendar.JANUARY, 18),
+            // 4
+            new int[] { Calendar.DAY_OF_MONTH, 18,
+                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+            new Date(Y, Calendar.JANUARY, 18),
+            // 5  (WOM -1 is in previous month)
+            new int[] { Calendar.DAY_OF_MONTH, 18,
+                        Calendar.WEEK_OF_MONTH, -1,
+                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+            new Date(Y-1, Calendar.DECEMBER, 22),
+            // 6
+            new int[] { Calendar.DAY_OF_MONTH, 18,
+                        Calendar.WEEK_OF_MONTH, 4,
+                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+            new Date(Y, Calendar.JANUARY, 26),
+            // 7  (DIM -1 is in same month)
+            new int[] { Calendar.DAY_OF_MONTH, 18,
+                        Calendar.DAY_OF_WEEK_IN_MONTH, -1,
+                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+            new Date(Y, Calendar.JANUARY, 26),
+            // 8
+            new int[] { Calendar.WEEK_OF_YEAR, 9,
+                        Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, },
+            new Date(Y, Calendar.MARCH, 1),
+            // 9
+            new int[] { Calendar.MONTH, Calendar.OCTOBER,
+                        Calendar.DAY_OF_WEEK_IN_MONTH, 1,
+                        Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
+            new Date(Y, Calendar.OCTOBER, 6),
+            // 10
+            new int[] { Calendar.MONTH, Calendar.OCTOBER,
+                        Calendar.WEEK_OF_MONTH, 2,
+                        Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
+            new Date(Y, Calendar.OCTOBER, 13),
+            // 11
+            new int[] { Calendar.MONTH, Calendar.OCTOBER,
+                        Calendar.DAY_OF_MONTH, 15,
+                        Calendar.DAY_OF_YEAR, 222, },
+            new Date(Y, Calendar.AUGUST, 10),
+            // 12
+            new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
+                        Calendar.MONTH, Calendar.DECEMBER, },
+            new Date(Y, Calendar.DECEMBER, 7),
+        };
+
+        for (int i=0; i<FIELD_DATA.length; i+=2) {
+            int[] fields = (int[]) FIELD_DATA[i];
+            Date exp = (Date) FIELD_DATA[i+1];
+
+            cal.clear();
+            cal.set(Calendar.YEAR, Y + 1900);
+            for (int j=0; j<fields.length; j+=2) {
+                cal.set(fields[j], fields[j+1]);
+            }
+
+            Date act = cal.getTime();
+            if (!act.equals(exp)) {
+                errln("FAIL: Test " + (i/2) + " got " + act +
+                      ", want " + exp +
+                      " (see test/java/util/Calendar/CalendarRegression.java");
+            }
+        }
+
+        // Test specific failure reported in bug
+        Object[] DATA = {
+            new Integer(1), new Date(1997-1900, Calendar.JANUARY, 5),
+            new Integer(4), new Date(1997-1900, Calendar.JANUARY, 26),
+            new Integer(8), new Date(1997-1900, Calendar.FEBRUARY, 23),
+            new Integer(-1), new Date(1997-1900, Calendar.JANUARY, 26),
+            new Integer(-4), new Date(1997-1900, Calendar.JANUARY, 5),
+            new Integer(-8), new Date(1996-1900, Calendar.DECEMBER, 8),
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            cal.clear();
+            cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,
+                    ((Number) DATA[i]).intValue());
+            cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
+            cal.set(Calendar.MONTH, Calendar.JANUARY);
+            cal.set(Calendar.YEAR, 1997);
+            Date actual = cal.getTime();
+            if (!actual.equals(DATA[i+1])) {
+                errln("FAIL: Sunday " + DATA[i] +
+                      " of Jan 1997 -> " + actual +
+                      ", want " + DATA[i+1]);
+            }
+        }
+    }
+
+    public void Test4288792() throws Exception
+    {
+        TimeZone savedTZ = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+        GregorianCalendar cal = new GregorianCalendar();
+        try {
+            for (int i = 1900; i < 2100; i++) {
+                for (int j1 = 1; j1 <= 7; j1++) {
+                    // Loop for MinimalDaysInFirstWeek: 1..7
+                    for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) {
+                        // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+                        cal.clear();
+                        cal.setMinimalDaysInFirstWeek(j1);
+                        cal.setFirstDayOfWeek(j);
+                        cal.set(Calendar.YEAR, i);
+                        int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR);
+                        cal.set(Calendar.WEEK_OF_YEAR, maxWeek);
+                        cal.set(Calendar.DAY_OF_WEEK, j);
+
+                        for (int k = 1; k < 7; k++) {
+                            cal.add(Calendar.DATE, 1);
+                            int WOY = cal.get(Calendar.WEEK_OF_YEAR);
+                            if (WOY != maxWeek) {
+                                errln(cal.getTime() + ",got=" + WOY
+                                      + ",expected=" + maxWeek
+                                      + ",min=" + j1 + ",first=" + j);
+                            }
+                        }
+
+                        cal.add(Calendar.DATE, 1);
+                        int WOY = cal.get(Calendar.WEEK_OF_YEAR);
+                        if (WOY != 1) {
+                            errln(cal.getTime() + ",got=" + WOY
+                                  + ",expected=1,min=" + j1 + ",first" + j);
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(savedTZ);
+        }
+    }
+
+    public void Test4328747() throws Exception {
+        Calendar c = (Calendar)Calendar.getInstance(Locale.US);
+        c.clear();
+        c.set(1966,0,1); // 1 jan 1966
+
+        // serialize
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ObjectOutputStream s = new ObjectOutputStream(out);
+        s.writeObject(c);
+        s.flush();
+
+        // deserialize
+        ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+        Calendar result = (Calendar)t.readObject();
+
+        // let recalculate fields with the same UTC time
+        result.setTime(result.getTime());
+        // Bug gives 1965 11 19
+        if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0)
+            || (result.get(c.DATE) != 1)) {
+            errln("deserialized Calendar returned wrong date field(s): "
+                  + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE)
+                  + ", expected 1966/0/1");
+        }
+    }
+
+    /**
+     * Test whether Calendar can be serialized/deserialized correctly
+     * even if invalid/customized TimeZone is used.
+     */
+    public void Test4413980() {
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        try {
+            boolean pass = true;
+            String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",
+                                         "GMT+3:00", "GMT-01:30"};
+            for (int i = 0; i < IDs.length; i++) {
+                TimeZone tz = TimeZone.getTimeZone(IDs[i]);
+                TimeZone.setDefault(tz);
+
+                Calendar c = (Calendar)Calendar.getInstance();
+
+                // serialize
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                ObjectOutputStream s = new ObjectOutputStream(out);
+                s.writeObject(c);
+                s.flush();
+
+                // deserialize
+                ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+
+                if (!c.equals(t.readObject())) {
+                    pass = false;
+                    logln("Calendar instance which uses TimeZone <" +
+                          IDs[i] + "> is incorrectly serialized/deserialized.");
+                } else {
+                    logln("Calendar instance which uses TimeZone <" +
+                          IDs[i] + "> is correctly serialized/deserialized.");
+                }
+            }
+            if (!pass) {
+                errln("Fail: Calendar serialization/equality bug");
+            }
+        }
+        catch (IOException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        catch (ClassNotFoundException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        finally {
+            TimeZone.setDefault(savedTimeZone);
+        }
+    }
+
+    /**
+     * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week
+     */
+    public void Test4546637() {
+        GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04);
+        day.setMinimalDaysInFirstWeek(1);
+        int wom = day.get(Calendar.WEEK_OF_MONTH);
+
+        day.setFirstDayOfWeek(Calendar.MONDAY);
+        if (day.get(Calendar.WEEK_OF_MONTH) != 1) {
+            errln("Fail: 2001/11/4 must be the first week of the month.");
+        }
+    }
+
+    /**
+     * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR
+     */
+    public void Test4623997() {
+        GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1);
+
+        int dow = cal.get(GregorianCalendar.DAY_OF_WEEK);
+
+        cal.setFirstDayOfWeek(GregorianCalendar.MONDAY);
+        cal.setMinimalDaysInFirstWeek(4);
+
+        if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) {
+            errln("Fail: 2000/1/1 must be the 52nd week of the year.");
+        }
+    }
+
+    /**
+     * 4685354: Handling of Calendar fields setting state is broken
+     *
+     * <p>Need to use SimpleDateFormat to test because a call to
+     * get(int) changes internal states of a Calendar.
+     */
+    public void Test4685354() {
+        if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+            return;
+        }
+
+        Calendar calendar = Calendar.getInstance(Locale.US);
+        DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+        String expected = "1999/12/31";
+        Date t;
+        String s;
+
+        try {
+            calendar.setTime(df.parse(expected));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected parse exception", e);
+        }
+
+        t = calendar.getTime();
+        calendar.set(Calendar.DAY_OF_MONTH, 33);
+        t = calendar.getTime();
+        calendar.set(Calendar.DAY_OF_MONTH, 0);
+        s = df.format(calendar.getTime());
+        if (!expected.equals(s)) {
+            errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s);
+        }
+
+        // The same thing must work with ZONE_OFFSET set
+        try {
+            calendar.setTime(df.parse(expected));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected parse exception", e);
+        }
+        t = calendar.getTime();
+        calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+        calendar.set(Calendar.DAY_OF_MONTH, 33);
+        t = calendar.getTime();
+        calendar.set(Calendar.DAY_OF_MONTH, 0);
+        s = df.format(calendar.getTime());
+        if (!expected.equals(s)) {
+            errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s);
+        }
+
+        expected = "1999/12/24"; // 0th week of 2000
+        calendar.clear();
+        Date initialDate = null;
+        try {
+            initialDate = df.parse(expected);
+            calendar.setTime(initialDate);
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected parse exception", e);
+        }
+        t = calendar.getTime();
+        calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+        // jump to the next year
+        calendar.set(Calendar.WEEK_OF_YEAR, 100);
+        t = calendar.getTime();
+        calendar.set(Calendar.WEEK_OF_YEAR, 0);
+        s = df.format(calendar.getTime());
+        if (!expected.equals(s)) {
+            errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s);
+        }
+        // change the state back
+        calendar.clear();
+        calendar.setTime(initialDate);
+        calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+        // jump to next month
+        calendar.set(Calendar.WEEK_OF_MONTH, 7);
+        t = calendar.getTime();
+        calendar.set(Calendar.WEEK_OF_MONTH, 0);
+        s = df.format(calendar.getTime());
+        if (!expected.equals(s)) {
+            errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s);
+        }
+
+        // Make sure the time fields work correctly.
+        calendar.clear();
+        df = new SimpleDateFormat("HH:mm:ss");
+        TimeZone tz = TimeZone.getTimeZone("GMT");
+        df.setTimeZone(tz);
+        calendar.setTimeZone(tz);
+        expected = "22:59:59";
+        try {
+            calendar.setTime(df.parse(expected));
+        } catch (Exception e) {
+            throw new RuntimeException("Unexpected parse exception", e);
+        }
+        t = calendar.getTime();
+        // time should be 22:59:59.
+        calendar.set(Calendar.MINUTE, 61);
+        // time should be 23:01:59.
+        t = calendar.getTime();
+        calendar.set(Calendar.MINUTE, -1);
+        // time should be back to 22:59:59.
+        s = df.format(calendar.getTime());
+        if (!expected.equals(s)) {
+            errln("MINUTE: expected: " + expected + ", got: " + s);
+        }
+    }
+
+    /**
+     * 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value
+     *
+     * <p>Need to use SimpleDateFormat to test because a call to
+     * get(int) changes internal states of a Calendar.
+     */
+    public void Test4655637() {
+        // Skip this test case if it's Thai locale
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(new Date(1029814211523L));
+        cal.set(Calendar.YEAR, 2001);
+        Date t = cal.getTime();
+        cal.set(Calendar.MONTH, Calendar.JANUARY);
+        t = cal.getTime();
+
+        cal.set(Calendar.DAY_OF_MONTH, 8);
+        t = cal.getTime();
+
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
+        DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+        String expected = "2001/01/08";
+        String s = df.format(cal.getTime());
+        if (!expected.equals(s)) {
+            errln("expected: " + expected + ", got: " + s);
+        }
+    }
+
+    /**
+     * 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime().
+     *
+     * <p>Need to use SimpleDateFormat to test because a call to
+     * get(int) changes internal states of a Calendar.
+     *
+     * <p>This test case throws ArrayIndexOutOfBoundsException without the fix.
+     */
+    public void Test4683492() {
+        Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0);
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
+        cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
+        cal.set(Calendar.MONTH, 12);
+        DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+        String expected = "2003/01/31";
+        String s = df.format(cal.getTime());
+        if (!expected.equals(s)) {
+            errln("expected: " + expected + ", got: " + s);
+        }
+    }
+
+    /**
+     * 4080631: Calendar.hashCode is amazingly bad
+     */
+    public void Test4080631() {
+        Calendar cal = Calendar.getInstance();
+        int h1 = cal.hashCode();
+        cal.add(cal.SECOND, +1);
+        int h2 = cal.hashCode();
+        Calendar cal2 = (Calendar) cal.clone();
+        cal.add(cal.MILLISECOND, +1);
+        int h3 = cal.hashCode();
+        logln("hash code: h1="+h1+", h2="+h2+", h3="+h3);
+        if (h1 == h2 || h1 == h3 || h2 == h3) {
+            errln("hash code is poor: hashCode="+h1);
+        }
+        h2 = cal2.hashCode();
+        cal.add(cal.MILLISECOND, -1);
+        int h4 = cal.hashCode();
+        logln("hash code: h2="+h2+", h4="+h4);
+        if (cal.equals(cal2) && h2 != h4) {
+            errln("broken hash code: h2="+h2+", h4="+h4);
+        }
+        int x = cal.getFirstDayOfWeek() + 3;
+        if (x > cal.SATURDAY) {
+            x -= 7;
+        }
+        cal.setFirstDayOfWeek(x);
+        int h5 = cal.hashCode();
+        logln("hash code: h4="+h4+", h5="+h5);
+        if (h4 == h5) {
+            errln("has code is poor with first day of week param: hashCode="+h4);
+        }
+    }
+
+    /**
+     * 4125161: RFE: GregorianCalendar needs more era names (BCE and CE)
+     */
+    /*
+    public void Test4125161() throws Exception {
+        Class gc = GregorianCalendar.class;
+        Field f;
+        int mod;
+        f = gc.getDeclaredField("BCE");
+        mod = f.getModifiers();
+        if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
+            errln("BCE: wrong modifiers: " + mod);
+        }
+        f = gc.getDeclaredField("CE");
+        mod = f.getModifiers();
+        if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
+            errln("CE: wrong modifiers: " + mod);
+        }
+        if (GregorianCalendar.BCE != GregorianCalendar.BC
+            || GregorianCalendar.CE != GregorianCalendar.AD) {
+            errln("Wrong BCE and/or CE values");
+        }
+    }
+    */
+
+    /**
+     * 4167995: GregorianCalendar.setGregorianChange() not to spec
+     */
+    public void Test4167995() {
+        Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT"));
+        logln("Hybrid: min date");
+        gc.setTime(new Date(Long.MIN_VALUE));
+        if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+            errln(gc.getMessage());
+        }
+        logln("Hybrid: max date");
+        gc.setTime(new Date(Long.MAX_VALUE));
+        if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+            errln(gc.getMessage());
+        }
+
+        gc.setGregorianChange(new Date(Long.MIN_VALUE));
+        logln("Gregorian: min date");
+        gc.setTime(new Date(Long.MIN_VALUE));
+        if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+            errln(gc.getMessage());
+        }
+        logln("Gregorian: max date");
+        gc.setTime(new Date(Long.MAX_VALUE));
+        if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+            errln(gc.getMessage());
+        }
+
+        gc.setGregorianChange(new Date(Long.MAX_VALUE));
+        logln("Julian: min date");
+        gc.setTime(new Date(Long.MIN_VALUE));
+        if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+            errln(gc.getMessage());
+        }
+        logln("Julian: max date");
+        gc.setTime(new Date(Long.MAX_VALUE));
+        if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY)
+            || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+            errln(gc.getMessage());
+        }
+    }
+
+    /**
+     * 4340146: Calendar.equals modifies state
+     */
+    public void Test4340146() {
+        Koyomi cal = new Koyomi();
+        cal.clear();
+        cal.set(2003, cal.OCTOBER, 32);
+        cal.equals(new Koyomi());
+        if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
+            errln(cal.getMessage());
+        }
+        new Koyomi().equals(cal);
+        if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    /**
+     * 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking
+     */
+    public void Test4639407() {
+        // The following operations in non-lenient mode shouldn't
+        // throw IllegalArgumentException.
+        Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati"));
+        cal.setLenient(false);
+        cal.set(2003, cal.OCTOBER, 10);
+        cal.getTime();
+        cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu"));
+        cal.set(2003, cal.OCTOBER, 10);
+        cal.getTime();
+    }
+
+    /**
+     * 4652815: rolling week-of-year back hundreds of weeks changes year
+     */
+    public void Test4652815() {
+        Koyomi cal = new Koyomi(Locale.US);
+        testRoll(cal, 2003, cal.SEPTEMBER, 29);
+        testRoll(cal, 2003, cal.DECEMBER, 24);
+        testRoll(cal, 1582, cal.DECEMBER, 19);
+        testRoll(cal, 1582, cal.DECEMBER, 20);
+    }
+
+    private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) {
+        cal.clear();
+        cal.set(year, month, dayOfMonth);
+        cal.getTime(); // normalize fields
+        logln("Roll backwards from " + cal.toDateString());
+        for (int i = 0; i < 1000; i++) {
+            cal.roll(cal.WEEK_OF_YEAR, -i);
+            if (!cal.checkFieldValue(cal.YEAR, year)) {
+                errln(cal.getMessage());
+            }
+        }
+        logln("Roll forewards from " + cal.toDateString());
+        for (int i = 0; i < 1000; i++) {
+            cal.roll(cal.WEEK_OF_YEAR, +i);
+            if (!cal.checkFieldValue(cal.YEAR, year)) {
+                errln(cal.getMessage());
+            }
+        }
+    }
+
+    /**
+     * 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era
+     */
+    public void Test4652830() {
+        Koyomi cal = new Koyomi(Locale.US);
+        cal.clear();
+        logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice");
+        cal.set(cal.ERA, cal.BC);
+        cal.set(9, cal.FEBRUARY, 28);
+        if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) {
+            errln("    wrong actual max of DAY_OF_YEAR: got "
+                  + cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366);
+        }
+        cal.roll(cal.DAY_OF_MONTH, +1);
+        if (!cal.checkFieldValue(cal.ERA, cal.BC)
+            || !cal.checkDate(9, cal.FEBRUARY, 29)) {
+            errln(cal.getMessage());
+        }
+        cal.roll(cal.DAY_OF_MONTH, +1);
+        if (!cal.checkFieldValue(cal.ERA, cal.BC)
+            || !cal.checkDate(9, cal.FEBRUARY, 1)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    /**
+     * 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization
+     */
+    public void Test4740554() {
+        logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum");
+        Koyomi cal = new Koyomi(Locale.US);
+        cal.clear();
+        cal.set(1999, cal.FEBRUARY + 12, 1);
+        if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    /**
+     * 4936355: GregorianCalendar causes overflow/underflow with time of day calculation
+     */
+    public void Test4936355() {
+        Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT"));
+        cal.clear();
+        cal.set(1970, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE,
+                             (long)Integer.MAX_VALUE * 60 * 60 * 1000);
+
+        cal.clear();
+        cal.set(1970, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE,
+                             (long)Integer.MAX_VALUE * 60 * 60 * 1000);
+
+        cal.clear();
+        cal.set(1970, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE,
+                             (long)Integer.MAX_VALUE * 60 * 1000);
+
+        cal.clear();
+        // Make sure to use Gregorian dates (before and after the
+        // set() call) for testing
+        cal.set(250000, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE,
+                             (long)Integer.MIN_VALUE * 60 * 60 * 1000);
+
+        cal.clear();
+        cal.set(250000, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE,
+                             (long)Integer.MIN_VALUE * 60 * 60 * 1000);
+
+        cal.clear();
+        cal.set(250000, cal.JANUARY, 1);
+        checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE,
+                             (long)Integer.MIN_VALUE * 60 * 1000);
+    }
+
+    private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) {
+        long time = cal.getTimeInMillis();
+        cal.set(field, value);
+        long time2 = cal.getTimeInMillis();
+        if ((time + expectedDelta) != time2) {
+            String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE";
+            errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time2
+                  + ", expected " + (time+expectedDelta));
+        }
+    }
+
+    /**
+     * 4722650: Calendar.equals can throw an exception in non-lenient
+     * (piggy-back tests for compareTo() which is new in 1.5)
+     */
+    public void Test4722650() {
+        Calendar cal1 = new GregorianCalendar();
+        cal1.clear();
+        Calendar cal2 = new GregorianCalendar();
+        cal2.clear();
+        cal2.setLenient(false);
+
+        cal1.set(2003, Calendar.OCTOBER, 31);
+        cal2.set(2003, Calendar.OCTOBER, 31);
+        try {
+            if (cal1.equals(cal2)) {
+                errln("lenient and non-lenient shouldn't be equal. (2003/10/31)");
+            }
+            if (cal1.compareTo(cal2) != 0) {
+                errln("cal1 and cal2 should represent the same time. (2003/10/31)");
+            }
+        } catch (IllegalArgumentException e) {
+            errln("equals threw IllegalArugumentException with non-lenient");
+        }
+
+        cal1.set(2003, Calendar.OCTOBER, 32);
+        cal2.set(2003, Calendar.OCTOBER, 32);
+        try {
+            if (cal1.equals(cal2)) {
+                errln("lenient and non-lenient shouldn't be equal. (2003/10/32)");
+            }
+            if (cal1.compareTo(cal2) != 0) {
+                errln("cal1 and cal2 should represent the same time. (2003/10/32)");
+            }
+        } catch (IllegalArgumentException e) {
+            errln("equals threw IllegalArugumentException with non-lenient");
+        }
+
+        cal1 = Calendar.getInstance(new Locale("th", "TH"));
+        cal1.setTimeInMillis(0L);
+        cal2 = Calendar.getInstance(Locale.US);
+        cal2.setTimeInMillis(0L);
+        if (cal1.equals(cal2)) {
+            errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)");
+        }
+        if (cal1.compareTo(cal2) != 0) {
+            errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)");
+        }
+    }
+
+    /**
+     * 4738710: API: Calendar comparison methods should be improved
+     */
+    public void Test4738710() {
+        Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30);
+        Comparable<Calendar> cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1);
+        Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2);
+        if (!(cal1.compareTo(cal0) > 0)) {
+            errln("!(cal1 > cal0)");
+        }
+        if (!(cal1.compareTo(cal2) < 0)) {
+            errln("!(cal1 < cal2)");
+        }
+        if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) {
+            errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)");
+        }
+
+        if (cal0.after(cal2)) {
+            errln("cal0 shouldn't be after cal2");
+        }
+        if (cal2.before(cal0)) {
+            errln("cal2 shouldn't be before cal0");
+        }
+
+        if (cal0.after(new Integer(0))) {
+            errln("cal0.after() returned true with an Integer.");
+        }
+        if (cal0.before(new Integer(0))) {
+            errln("cal0.before() returned true with an Integer.");
+        }
+        if (cal0.after(null)) {
+            errln("cal0.after() returned true with null.");
+        }
+        if (cal0.before(null)) {
+            errln("cal0.before() returned true with null.");
+        }
+    }
+
+    /**
+     * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date
+     */
+    public void Test4633646() {
+        Koyomi cal = new Koyomi(Locale.US);
+        cal.setTime(new Date(2002-1900, 1-1, 28));
+        sub4633646(cal);
+
+        cal.setLenient(false);
+        cal.setTime(new Date(2002-1900, 1-1, 28));
+        sub4633646(cal);
+
+        cal = new Koyomi(Locale.US);
+        cal.clear();
+        cal.set(2002, cal.JANUARY, 28);
+        sub4633646(cal);
+
+        cal.clear();
+        cal.setLenient(false);
+        cal.set(2002, cal.JANUARY, 28);
+        sub4633646(cal);
+    }
+
+    void sub4633646(Koyomi cal) {
+        cal.getTime();
+        cal.set(cal.WEEK_OF_MONTH, 1);
+        if (cal.isLenient()) {
+            if (!cal.checkDate(2001, cal.DECEMBER, 31)) {
+                errln(cal.getMessage());
+            }
+            if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) {
+                errln(cal.getMessage());
+            }
+        } else {
+            try {
+                Date d = cal.getTime();
+                errln("didn't throw IllegalArgumentException in non-lenient");
+            } catch (IllegalArgumentException e) {
+            }
+        }
+    }
+
+    /**
+     * 4846659: Calendar: Both set() and roll() don't work for AM_PM time field
+     * (Partially fixed only roll as of 1.5)
+     */
+    public void Test4846659() {
+        Koyomi cal = new Koyomi();
+        cal.clear();
+        cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+        cal.getTime();
+        // Test roll()
+        cal.roll(cal.AM_PM, +1); // should turn to PM
+        if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
+            errln("roll: AM_PM didn't change to PM");
+        }
+
+        cal.clear();
+        cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+        cal.getTime();
+        // Test set()
+        cal.set(cal.AM_PM, cal.PM); // should turn to PM
+        if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
+            errln("set: AM_PM didn't change to PM");
+        }
+
+        cal.clear();
+        cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+        cal.getTime();
+        cal.set(cal.AM_PM, cal.PM);
+        cal.set(cal.HOUR, 9);
+        if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) {
+            errln("set: both AM_PM and HOUT didn't change to PM");
+        }
+    }
+
+    /**
+     * 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek()
+     */
+    public void Test4822110() {
+        Koyomi cal = new Koyomi(Locale.US);
+        //    June 2003
+        //  S  M Tu  W Th  F  S
+        //  1  2  3  4  5  6  7
+        //  8  9 10 11 12 13 14
+        // 15 16 17 18 19 20 21
+        // 22 23 24 25 26 27 28
+        // 29 30
+        cal.clear();
+        // 6/1 to 6/7 should be the 1st week of June.
+        cal.set(2003, cal.JUNE, 2);
+        cal.getTime();                  // Let cal calculate time.
+        cal.setFirstDayOfWeek(cal.MONDAY);
+        // Now 6/2 to 6/8 should be the 2nd week of June. Sunday of
+        // that week is 6/8.
+        logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH));
+        cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
+        logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY");
+        if (!cal.checkDate(2003, cal.JUNE, 8)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    /**
+     * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization
+     */
+    public void Test4966499() throws Exception {
+        GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7);
+
+        // Serialize date1
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);
+        oos.writeObject(date1);
+
+        byte[] buffer = baos.toByteArray();
+
+        // Deserialize it
+        ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        GregorianCalendar date2 = (GregorianCalendar)ois.readObject();
+
+        if (!date1.equals(date2)) {
+            errln("date1.equals(date2) != true");
+        }
+        if (date1.hashCode() != date2.hashCode()) {
+            errln("inconsistent hashCode() value (before=0x"
+                  +Integer.toHexString(date1.hashCode())+
+                  ", after=0x"+Integer.toHexString(date2.hashCode())+")");
+        }
+    }
+
+    /**
+     * 4980088: GregorianCalendar.getActualMaximum doesn't throw exception
+     */
+    public void Test4980088() {
+        GregorianCalendar cal = new GregorianCalendar();
+        try {
+            int x = cal.getMaximum(100);
+            errln("getMaximum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+
+        try {
+            int x = cal.getLeastMaximum(100);
+            errln("getLeastMaximum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+
+        try {
+            int x = cal.getActualMaximum(100);
+            errln("getActualMaximum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+
+        try {
+            int x = cal.getMinimum(100);
+            errln("getMinimum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+
+        try {
+            int x = cal.getGreatestMinimum(100);
+            errln("getGreatestMinimum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+
+        try {
+            int x = cal.getActualMinimum(100);
+            errln("getActualMinimum(100) didn't throw an exception.");
+        } catch (IndexOutOfBoundsException e) {
+            logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+        }
+    }
+
+    /**
+     * 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value
+     */
+    public void Test4965624() {
+        // 5013094: This test case needs to use "GMT" to specify
+        // Gregorian cutover dates.
+        TimeZone savedZone = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+        try {
+            Map<Date, Boolean> data = new HashMap<Date, Boolean>();
+            data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE);
+            data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE);
+            data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE);
+            data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE);
+            data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE);
+            data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE);
+            data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE);
+            data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE);
+
+            Iterator<Date> itr = data.keySet().iterator();
+            while (itr.hasNext()) {
+                Date d = itr.next();
+                boolean expected = data.get(d).booleanValue();
+                GregorianCalendar cal = new GregorianCalendar();
+                cal.setGregorianChange(d);
+                if (cal.isLeapYear(1000) != expected) {
+                    errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) +
+                          " with cutover date (Julian) " + d);
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(savedZone);
+        }
+    }
+
+    // Note that we can't use Date to produce Gregorian calendar dates
+    // before the default cutover date.
+    static Date getGregorianDate(int year, int month, int dayOfMonth) {
+        GregorianCalendar g = new GregorianCalendar();
+        // Make g a pure Gregorian calendar
+        g.setGregorianChange(new Date(Long.MIN_VALUE));
+        g.clear();
+        g.set(year, month, dayOfMonth);
+        return g.getTime();
+    }
+
+    /**
+     * 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 1
+     */
+    public void Test5006864() {
+        GregorianCalendar cal = new GregorianCalendar();
+        int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH);
+        if (min != 1) {
+            errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned "
+                  + min + ", expected 1.");
+        }
+        min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH);
+        if (min != 1) {
+            errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned "
+                  + min + ", expected 1.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/CalendarTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,1102 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4064654 4374886 4984320 4984574 4944795
+ * @library /java/text/testlib
+ * @summary test for Calendar
+ * @key randomness
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class CalendarTest extends IntlTest {
+    static final int ONE_DAY = 24*60*60*1000;
+    static final int EPOCH_JULIAN = 2440588;
+
+    public static void main(String argv[]) throws Exception {
+        new CalendarTest().run(argv);
+    }
+
+    /**
+     * Test the behavior of the GregorianCalendar around the changeover.
+     */
+    public void TestGregorianChangeover() {
+        TimeZone savedZone = TimeZone.getDefault();
+        /*
+          Changeover -7 days: 1582/9/28 dow=6
+          Changeover -6 days: 1582/9/29 dow=7
+          Changeover -5 days: 1582/9/30 dow=1
+          Changeover -4 days: 1582/10/1 dow=2
+          Changeover -3 days: 1582/10/2 dow=3
+          Changeover -2 days: 1582/10/3 dow=4
+          Changeover -1 days: 1582/10/4 dow=5
+          Changeover +0 days: 1582/10/15 dow=6
+          Changeover +1 days: 1582/10/16 dow=7
+          Changeover +2 days: 1582/10/17 dow=1
+          Changeover +3 days: 1582/10/18 dow=2
+          Changeover +4 days: 1582/10/19 dow=3
+          Changeover +5 days: 1582/10/20 dow=4
+          Changeover +6 days: 1582/10/21 dow=5
+          Changeover +7 days: 1582/10/22 dow=6
+          */
+        int MON[] = {  9,  9,  9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 };
+        int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 };
+        int DOW[] = {  6,  7,  1, 2, 3, 4, 5,  6,  7,  1,  2,  3,  4,  5,  6 };
+        //                                     ^ <-Changeover Fri Oct 15 1582
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Date co = new Date(1582-1900, Calendar.OCTOBER, 15);
+            GregorianCalendar cal = new GregorianCalendar();
+            int j = 0;
+            for (int i = -7; i <= 7; ++i, ++j) {
+                Date d = new Date(co.getTime() + i*ONE_DAY);
+                cal.setTime(d);
+                int y = cal.get(Calendar.YEAR);
+                int mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY;
+                int dom = cal.get(Calendar.DATE);
+                int dow = cal.get(Calendar.DAY_OF_WEEK);
+
+                logln("Changeover " + (i>=0?"+":"") + i +
+                      " days: " + y + "/" + mon + "/" + dom + " dow=" + dow);
+                if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j]) {
+                    errln(" Fail: Above line is wrong");
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(savedZone);
+        }
+    }
+
+    /**
+     * Test the mapping between millis and fields.  For the purposes
+     * of this test, we don't care about timezones and week data
+     * (first day of week, minimal days in first week).
+     */
+    public void TestMapping() {
+        TimeZone saveZone = TimeZone.getDefault();
+        int[] DATA = {
+            // Julian#   Year  Month               DOM   JULIAN:Year, Month,       DOM
+            2440588,     1970, Calendar.JANUARY,   1,    1969, Calendar.DECEMBER,  19,
+            2415080,     1900, Calendar.MARCH,     1,    1900, Calendar.FEBRUARY,  17,
+            2451604,     2000, Calendar.FEBRUARY,  29,   2000, Calendar.FEBRUARY,  16,
+            2452269,     2001, Calendar.DECEMBER,  25,   2001, Calendar.DECEMBER,  12,
+            2416526,     1904, Calendar.FEBRUARY,  15,   1904, Calendar.FEBRUARY,  2,
+            2416656,     1904, Calendar.JUNE,      24,   1904, Calendar.JUNE,      11,
+            1721426,        1, Calendar.JANUARY,   1,       1, Calendar.JANUARY,   3,
+            2000000,      763, Calendar.SEPTEMBER, 18,    763, Calendar.SEPTEMBER, 14,
+            4000000,     6239, Calendar.JULY,      12,   6239, Calendar.MAY,       28,
+            8000000,    17191, Calendar.FEBRUARY,  26,  17190, Calendar.OCTOBER,   22,
+            10000000,   22666, Calendar.DECEMBER,  20,  22666, Calendar.JULY,      5,
+        };
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+            Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
+            Date PURE_JULIAN = new Date(Long.MAX_VALUE);
+            GregorianCalendar cal = new GregorianCalendar();
+            for (int i = 0; i < DATA.length; i += 7) {
+                int julian = DATA[i];
+                int year = DATA[i+1];
+                int month = DATA[i+2];
+                int dom = DATA[i+3];
+                int year2, month2, dom2;
+                long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY;
+                String s;
+
+                // Test Gregorian computation
+                cal.setGregorianChange(PURE_GREGORIAN);
+                cal.clear();
+                cal.set(year, month, dom);
+                long calMillis = cal.getTime().getTime();
+                long delta = calMillis - millis;
+                cal.setTime(new Date(millis));
+                year2 = cal.get(Calendar.YEAR);
+                month2 = cal.get(Calendar.MONTH);
+                dom2 = cal.get(Calendar.DAY_OF_MONTH);
+                s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
+                    " => " + calMillis +
+                    " (" + ((float)delta/ONE_DAY) + " day delta) => " +
+                    year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
+                if (delta != 0 || year != year2 || month != month2 ||
+                    dom != dom2) {
+                    errln(s + " FAIL");
+                } else {
+                    logln(s);
+                }
+
+                // Test Julian computation
+                year = DATA[i+4];
+                month = DATA[i+5];
+                dom = DATA[i+6];
+                cal.setGregorianChange(PURE_JULIAN);
+                cal.clear();
+                cal.set(year, month, dom);
+                calMillis = cal.getTime().getTime();
+                delta = calMillis - millis;
+                cal.setTime(new Date(millis));
+                year2 = cal.get(Calendar.YEAR);
+                month2 = cal.get(Calendar.MONTH);
+                dom2 = cal.get(Calendar.DAY_OF_MONTH);
+                s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
+                    " => " + calMillis +
+                    " (" + ((float)delta/ONE_DAY) + " day delta) => " +
+                    year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
+                if (delta != 0 || year != year2 || month != month2 ||
+                    dom != dom2) {
+                    errln(s + " FAIL");
+                } else {
+                    logln(s);
+                }
+            }
+
+            cal.setGregorianChange(new Date(1582-1900, Calendar.OCTOBER, 15));
+            auxMapping(cal, 1582, Calendar.OCTOBER, 4);
+            auxMapping(cal, 1582, Calendar.OCTOBER, 15);
+            auxMapping(cal, 1582, Calendar.OCTOBER, 16);
+            for (int y = 800; y < 3000; y += 1+(int)100*Math.random()) {
+                for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; ++m) {
+                    auxMapping(cal, y, m, 15);
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+    private void auxMapping(Calendar cal, int y, int m, int d) {
+        cal.clear();
+        cal.set(y, m, d);
+        long millis = cal.getTime().getTime();
+        cal.setTime(new Date(millis));
+        int year2 = cal.get(Calendar.YEAR);
+        int month2 = cal.get(Calendar.MONTH);
+        int dom2 = cal.get(Calendar.DAY_OF_MONTH);
+        if (y != year2 || m != month2 || dom2 != d)
+            errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " +
+                  year2 + "-" + (month2+1) + "-" + dom2);
+    }
+
+    public void TestGenericAPI() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        String str;
+
+        Date when = new Date(90, Calendar.APRIL, 15);
+
+        String tzid = "TestZone";
+        int tzoffset = 123400;
+
+        SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid);
+        Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone());
+
+        if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed");
+
+        Calendar cal2 = Calendar.getInstance(cal.getTimeZone());
+
+        cal.setTime(when);
+        cal2.setTime(when);
+
+        if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed");
+        // if ((*cal != *cal2))  errln("FAIL: Calendar.operator!= failed");
+        if (!cal.equals(cal2) ||
+            cal.before(cal2) ||
+            cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+        cal2.setTime(new Date(when.getTime() + 1000));
+        if (cal.equals(cal2) ||
+            cal2.before(cal) ||
+            cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+        cal.roll(Calendar.SECOND, true);
+        if (!cal.equals(cal2) ||
+            cal.before(cal2) ||
+            cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+        // Roll back to January
+        cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH)));
+        if (cal.equals(cal2) ||
+            cal2.before(cal) ||
+            cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+        // C++ only
+        /* TimeZone z = cal.orphanTimeZone();
+           if (z.getID(str) != tzid ||
+           z.getRawOffset() != tzoffset)
+           errln("FAIL: orphanTimeZone failed");
+           */
+
+        for (int i = 0; i < 2; ++i) {
+            boolean lenient = ( i > 0 );
+            cal.setLenient(lenient);
+            if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed");
+            // Later: Check for lenient behavior
+        }
+
+        int i;
+        for (i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) {
+            cal.setFirstDayOfWeek(i);
+            if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
+        }
+
+        for (i = 0; i <= 7; ++i) {
+            cal.setMinimalDaysInFirstWeek(i);
+            if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
+        }
+
+        for (i = 0; i < Calendar.FIELD_COUNT; ++i) {
+            if (cal.getMinimum(i) != cal.getGreatestMinimum(i))
+                errln("FAIL: getMinimum doesn't match getGreatestMinimum for field " + i);
+            if (cal.getLeastMaximum(i) > cal.getMaximum(i))
+                errln("FAIL: getLeastMaximum larger than getMaximum for field " + i);
+            if (cal.getMinimum(i) >= cal.getMaximum(i))
+                errln("FAIL: getMinimum not less than getMaximum for field " + i);
+        }
+
+        cal.setTimeZone(TimeZone.getDefault());
+        cal.clear();
+        cal.set(1984, 5, 24);
+        if (cal.getTime().getTime() != new Date(84, 5, 24).getTime()) {
+            errln("FAIL: Calendar.set(3 args) failed");
+            logln(" Got: " + cal.getTime() + "  Expected: " + new Date(84, 5, 24));
+        }
+
+        cal.clear();
+        cal.set(1985, 3, 2, 11, 49);
+        if (cal.getTime().getTime() != new Date(85, 3, 2, 11, 49).getTime()) {
+            errln("FAIL: Calendar.set(5 args) failed");
+            logln(" Got: " + cal.getTime() + "  Expected: " + new Date(85, 3, 2, 11, 49));
+        }
+
+        cal.clear();
+        cal.set(1995, 9, 12, 1, 39, 55);
+        if (cal.getTime().getTime() != new Date(95, 9, 12, 1, 39, 55).getTime()) {
+            errln("FAIL: Calendar.set(6 args) failed");
+            logln(" Got: " + cal.getTime() + "  Expected: " + new Date(95, 9, 12, 1, 39, 55));
+        }
+
+        cal.getTime();
+        for (i = 0; i < Calendar.FIELD_COUNT; ++i) {
+            switch(i) {
+            case Calendar.YEAR: case Calendar.MONTH: case Calendar.DATE:
+            case Calendar.HOUR_OF_DAY: case Calendar.MINUTE: case Calendar.SECOND:
+                if (!cal.isSet(i))
+                    errln("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]);
+                break;
+            default:
+                if (cal.isSet(i))
+                    errln("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]);
+            }
+            cal.clear(i);
+            if (cal.isSet(i)) errln("FAIL: Calendar.clear/isSet failed");
+        }
+
+        // delete cal;
+        // delete cal2;
+
+        Locale[] loc = Calendar.getAvailableLocales();
+        long count = loc.length;
+        if (count < 1 || loc == null) {
+            errln("FAIL: getAvailableLocales failed");
+        }
+        else {
+            for (i = 0; i < count; ++i) {
+                cal = Calendar.getInstance(loc[i]);
+                // delete cal;
+            }
+        }
+
+        cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH);
+        // delete cal;
+
+        cal = Calendar.getInstance(zone, Locale.ENGLISH);
+        // delete cal;
+
+        GregorianCalendar gc = new GregorianCalendar(zone);
+        // delete gc;
+
+        gc = new GregorianCalendar(Locale.ENGLISH);
+        // delete gc;
+
+        gc = new GregorianCalendar(Locale.ENGLISH);
+        // delete gc;
+
+        gc = new GregorianCalendar(zone, Locale.ENGLISH);
+        // delete gc;
+
+        gc = new GregorianCalendar(zone);
+        // delete gc;
+
+        gc = new GregorianCalendar(1998, 10, 14, 21, 43);
+        if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime())
+            errln("FAIL: new GregorianCalendar(ymdhm) failed");
+        // delete gc;
+
+        gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55);
+        if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime())
+            errln("FAIL: new GregorianCalendar(ymdhms) failed");
+
+        // C++ only:
+        // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH);
+        // gc2 = gc;
+        // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
+        // delete gc;
+        // delete z;
+    }
+
+    // Verify Roger Webster's bug
+    public void TestRog() {
+        GregorianCalendar gc = new GregorianCalendar();
+
+        int year = 1997, month = Calendar.APRIL, date = 1;
+        gc.set(year, month, date); // April 1, 1997
+
+        gc.set(Calendar.HOUR_OF_DAY, 23);
+        gc.set(Calendar.MINUTE, 0);
+        gc.set(Calendar.SECOND, 0);
+        gc.set(Calendar.MILLISECOND, 0);
+
+        for (int i = 0; i < 9; i++, gc.add(Calendar.DATE, 1)) {
+            if (gc.get(Calendar.YEAR) != year ||
+                gc.get(Calendar.MONTH) != month ||
+                gc.get(Calendar.DATE) != (date + i))
+                errln("FAIL: Date " + gc.getTime() + " wrong");
+        }
+    }
+
+    // Verify DAY_OF_WEEK
+    public void TestDOW943() {
+        dowTest(false);
+        dowTest(true);
+    }
+
+    void dowTest(boolean lenient) {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.set(1997, Calendar.AUGUST, 12); // Wednesday
+        cal.getTime(); // Force update
+        cal.setLenient(lenient);
+        cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
+        int dow = cal.get(Calendar.DAY_OF_WEEK);
+        int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
+        int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
+        if (dow < min || dow > max) errln("FAIL: Day of week " + dow + " out of range");
+        if (dow != Calendar.SUNDAY) {
+            errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime());
+        }
+        if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) errln("FAIL: Min/max bad");
+    }
+
+    // Verify that the clone method produces distinct objects with no
+    // unintentionally shared fields.
+    public void TestClonesUnique908() {
+        Calendar c = Calendar.getInstance();
+        Calendar d = (Calendar)c.clone();
+        c.set(Calendar.MILLISECOND, 123);
+        d.set(Calendar.MILLISECOND, 456);
+        if (c.get(Calendar.MILLISECOND) != 123 ||
+            d.get(Calendar.MILLISECOND) != 456) {
+            errln("FAIL: Clones share fields");
+        }
+    }
+
+    // Verify effect of Gregorian cutoff value
+    public void TestGregorianChange768() {
+        boolean b;
+        GregorianCalendar c = new GregorianCalendar();
+        logln("With cutoff " + c.getGregorianChange());
+        logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
+        logln(" (should be FALSE)");
+        if (b != false) errln("FAIL");
+        c.setGregorianChange(new Date(0, 0, 1)); // Jan 1 1900
+        logln("With cutoff " + c.getGregorianChange());
+        logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
+        logln(" (should be TRUE)");
+        if (b != true) errln("FAIL");
+    }
+
+    // Test the correct behavior of the disambiguation algorithm.
+    public void TestDisambiguation765() throws Exception {
+      Locale savedLocale = Locale.getDefault();
+      try {
+        Locale.setDefault(Locale.US);
+        Calendar c = Calendar.getInstance();
+        c.setLenient(false);
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.MONTH, Calendar.JUNE);
+        c.set(Calendar.DATE, 3);
+
+        verify765("1997 third day of June = ", c, 1997, Calendar.JUNE, 3);
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.MONTH, Calendar.JUNE);
+        c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
+        verify765("1997 first Tuesday in June = ", c, 1997, Calendar.JUNE, 3);
+
+        c.setLenient(true); // for 4944795
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.MONTH, Calendar.JUNE);
+        c.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
+        verify765("1997 last Tuesday in June = ", c, 1997, Calendar.JUNE, 24);
+
+        c.setLenient(false);
+        IllegalArgumentException e = null;
+        try {
+            c.clear();
+            c.set(Calendar.YEAR, 1997);
+            c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+            c.set(Calendar.MONTH, Calendar.JUNE);
+            c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 0);
+            c.getTime();
+        }
+        catch (IllegalArgumentException ex) {
+            e = ex;
+        }
+        verify765("1997 zero-th Tuesday in June = ", e);
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.MONTH, Calendar.JUNE);
+        c.set(Calendar.WEEK_OF_MONTH, 1);
+        verify765("1997 Tuesday in week 1 of June = ", c, 1997, Calendar.JUNE, 3);
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.MONTH, Calendar.JUNE);
+        c.set(Calendar.WEEK_OF_MONTH, 4);
+        verify765("1997 Tuesday in week 4 of June = ", c, 1997, Calendar.JUNE, 24);
+
+        try {
+            c.clear();
+            c.set(Calendar.YEAR, 1997);
+            c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+            c.set(Calendar.MONTH, Calendar.JUNE);
+            c.set(Calendar.WEEK_OF_MONTH, 1);
+            verify765("1997 Tuesday in week 0 of June = ", c, 1997, Calendar.JUNE, 3);
+        }
+        catch (IllegalArgumentException ex) {
+            errln("FAIL: Exception seen: " + ex.getMessage());
+            // ex.printStackTrace(log);
+        }
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.WEEK_OF_YEAR, 2);
+        verify765("1997 Tuesday in week 2 of year = ", c, 1997, Calendar.JANUARY, 7);
+
+        c.clear();
+        c.set(Calendar.YEAR, 1997);
+        c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+        c.set(Calendar.WEEK_OF_YEAR, 10);
+        verify765("1997 Tuesday in week 10 of year = ", c, 1997, Calendar.MARCH, 4);
+
+        try {
+            c.clear();
+            c.set(Calendar.YEAR, 1997);
+            c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+            c.set(Calendar.WEEK_OF_YEAR, 0);
+            verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar.DECEMBER, 24);
+            throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal");
+        }
+        catch (IllegalArgumentException ex) {}
+      }
+      finally {
+          Locale.setDefault(savedLocale);
+      }
+    }
+    void verify765(String msg, Calendar c, int year, int month, int day) {
+        if (c.get(Calendar.YEAR) == year &&
+            c.get(Calendar.MONTH) == month &&
+            c.get(Calendar.DATE) == day) {
+            logln("PASS: " + msg + c.getTime());
+        }
+        else {
+            errln("FAIL: " + msg + c.getTime() +
+                  "; expected " +
+                  year + "/" + (month+1) + "/" + day);
+        }
+    }
+    // Called when e expected to be non-null
+    void verify765(String msg, IllegalArgumentException e) {
+        if (e == null) errln("FAIL: No IllegalArgumentException for " + msg);
+        else logln("PASS: " + msg + "IllegalArgument as expected");
+    }
+
+    // Test the behavior of GMT vs. local time
+    public void TestGMTvsLocal4064654() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        // Sample output 1:
+        // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0
+        // date = Wed Jan 01 04:00:00 PST 1997
+        // offset for Wed Jan 01 04:00:00 PST 1997= -8hr
+        test4064654(1997, 1, 1, 12, 0, 0);
+
+        // Sample output 2:
+        // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0
+        // date = Wed Apr 16 10:30:00 PDT 1997
+        // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr
+
+        // Note that in sample output 2 according to the offset, the gmt time
+        // of the result would be 1997 4 16 17 30 0 which is different from the
+        // input of 1997 4 16 18 30 0.
+        test4064654(1997, 4, 16, 18, 30, 0);
+    }
+    void test4064654(int yr, int mo, int dt, int hr, int mn, int sc) {
+        Date date;
+        Calendar gmtcal = Calendar.getInstance();
+        gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
+        gmtcal.set(yr, mo-1, dt, hr, mn, sc);
+        gmtcal.set(Calendar.MILLISECOND, 0);
+
+        date = gmtcal.getTime();
+        logln("date = "+date);
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+        cal.setTime(date);
+
+        int offset = cal.getTimeZone().getOffset(cal.get(Calendar.ERA),
+                                                 cal.get(Calendar.YEAR),
+                                                 cal.get(Calendar.MONTH),
+                                                 cal.get(Calendar.DATE),
+                                                 cal.get(Calendar.DAY_OF_WEEK),
+                                                 cal.get(Calendar.MILLISECOND));
+
+        logln("offset for "+date+"= "+(offset/1000/60/60.0) + "hr");
+
+        int utc = ((cal.get(Calendar.HOUR_OF_DAY) * 60 +
+                    cal.get(Calendar.MINUTE)) * 60 +
+                   cal.get(Calendar.SECOND)) * 1000 +
+            cal.get(Calendar.MILLISECOND) - offset;
+
+        int expected = ((hr * 60 + mn) * 60 + sc) * 1000;
+
+        if (utc != expected)
+            errln("FAIL: Discrepancy of " +
+                  (utc - expected) + " millis = " +
+                  ((utc-expected)/1000/60/60.0) + " hr");
+    }
+
+    // Verify that add and set work regardless of the order in which
+    // they are called.
+    public void TestAddSetOrder621() {
+        Date d = new Date(97, 4, 14, 13, 23, 45);
+
+        Calendar cal = Calendar.getInstance ();
+        cal.setTime (d);
+        cal.add (Calendar.DATE, -5);
+        cal.set (Calendar.HOUR_OF_DAY, 0);
+        cal.set (Calendar.MINUTE, 0);
+        cal.set (Calendar.SECOND, 0);
+        // ma feb 03 00:00:00 GMT+00:00 1997
+        String s = cal.getTime ().toString ();
+
+        cal = Calendar.getInstance ();
+        cal.setTime (d);
+        cal.set (Calendar.HOUR_OF_DAY, 0);
+        cal.set (Calendar.MINUTE, 0);
+        cal.set (Calendar.SECOND, 0);
+        cal.add (Calendar.DATE, -5);
+        // ma feb 03 13:11:06 GMT+00:00 1997
+        String s2 = cal.getTime ().toString ();
+
+        if (s.equals(s2))
+            logln("Pass: " + s + " == " + s2);
+        else
+            errln("FAIL: " + s + " != " + s2);
+    }
+
+    // Verify that add works.
+    public void TestAdd520() {
+        int y = 1997, m = Calendar.FEBRUARY, d = 1;
+        GregorianCalendar temp = new GregorianCalendar( y, m, d );
+        check520(temp, y, m, d);
+
+        temp.add( temp.YEAR, 1 );
+        y++;
+        check520(temp, y, m, d);
+
+        temp.add( temp.MONTH, 1 );
+        m++;
+        check520(temp, y, m, d);
+
+        temp.add( temp.DATE, 1 );
+        d++;
+        check520(temp, y, m, d);
+
+        temp.add( temp.DATE, 2 );
+        d += 2;
+        check520(temp, y, m, d);
+
+        temp.add( temp.DATE, 28 );
+        d = 1; ++m;
+        check520(temp, y, m, d);
+    }
+    void check520(Calendar c, int y, int m, int d) {
+        if (c.get(Calendar.YEAR) != y ||
+            c.get(Calendar.MONTH) != m ||
+            c.get(Calendar.DATE) != d) {
+            errln("FAILURE: Expected YEAR/MONTH/DATE of " +
+                  y + "/" + (m+1) + "/" + d +
+                  "; got " +
+                  c.get(Calendar.YEAR) + "/" +
+                  (c.get(Calendar.MONTH)+1) + "/" +
+                  c.get(Calendar.DATE));
+        }
+        else logln("Confirmed: " +
+                   y + "/" + (m+1) + "/" + d);
+    }
+
+    // Verify that setting fields works.  This test fails when an exception is thrown.
+    public void TestFieldSet4781() {
+        try {
+            GregorianCalendar g = new GregorianCalendar();
+            GregorianCalendar g2 = new GregorianCalendar();
+            // At this point UTC value is set, various fields are not.
+            // Now set to noon.
+            g2.set(Calendar.HOUR, 12);
+            g2.set(Calendar.MINUTE, 0);
+            g2.set(Calendar.SECOND, 0);
+            // At this point the object thinks UTC is NOT set, but fields are set.
+            // The following line will result in IllegalArgumentException because
+            // it thinks the YEAR is set and it is NOT.
+            if (g2.equals(g))
+                logln("Same");
+            else
+                logln("Different");
+        }
+        catch (IllegalArgumentException e) {
+            errln("Unexpected exception seen: " + e);
+        }
+    }
+
+    // Test serialization of a Calendar object
+    public void TestSerialize337() {
+        Calendar cal = Calendar.getInstance();
+
+        boolean ok = false;
+
+        try {
+            FileOutputStream f = new FileOutputStream(FILENAME);
+            ObjectOutput s = new ObjectOutputStream(f);
+            s.writeObject(PREFIX);
+            s.writeObject(cal);
+            s.writeObject(POSTFIX);
+            f.close();
+
+            FileInputStream in = new FileInputStream(FILENAME);
+            ObjectInputStream t = new ObjectInputStream(in);
+            String pre = (String)t.readObject();
+            Calendar c = (Calendar)t.readObject();
+            String post = (String)t.readObject();
+            in.close();
+
+            ok = pre.equals(PREFIX) &&
+                post.equals(POSTFIX) &&
+                cal.equals(c);
+
+            File fl = new File(FILENAME);
+            fl.delete();
+        }
+        catch (IOException e) {
+            errln("FAIL: Exception received:");
+            // e.printStackTrace(log);
+        }
+        catch (ClassNotFoundException e) {
+            errln("FAIL: Exception received:");
+            // e.printStackTrace(log);
+        }
+
+        if (!ok) errln("Serialization of Calendar object failed.");
+    }
+    static final String PREFIX = "abc";
+    static final String POSTFIX = "def";
+    static final String FILENAME = "tmp337.bin";
+
+    // Try to zero out the seconds field
+    public void TestSecondsZero121() {
+        Calendar        cal = new GregorianCalendar();
+        // Initialize with current date/time
+        cal.setTime(new Date());
+        // Round down to minute
+        cal.set(Calendar.SECOND, 0);
+        Date    d = cal.getTime();
+        String s = d.toString();
+        if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s);
+    }
+
+    // Try various sequences of add, set, and get method calls.
+    public void TestAddSetGet0610() {
+        //
+        // Error case 1:
+        // - Upon initialization calendar fields, millis = System.currentTime
+        // - After set is called fields are initialized, time is not
+        // - Addition uses millis which are still *now*
+        //
+        {
+            Calendar calendar = new GregorianCalendar( ) ;
+            calendar.set( 1993, Calendar.JANUARY, 4 ) ;
+            logln( "1A) " + value( calendar ) ) ;
+            calendar.add( Calendar.DATE, 1 ) ;
+            String v = value(calendar);
+            logln( "1B) " + v );
+            logln( "--) 1993/0/5" ) ;
+            if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+                                                "; saw " + v);
+        }
+
+        //
+        // Error case 2:
+        // - Upon initialization calendar fields set, millis = 0
+        // - Addition uses millis which are still 1970, 0, 1
+        //
+
+        {
+            Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
+            logln( "2A) " + value( calendar ) ) ;
+            calendar.add( Calendar.DATE, 1 ) ;
+            String v = value(calendar);
+            logln( "2B) " + v );
+            logln( "--) 1993/0/5" ) ;
+            if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+                                                "; saw " + v);
+        }
+
+        //
+        // Error case 3:
+        // - Upon initialization calendar fields, millis = 0
+        // - getTime( ) is called which forces the millis to be set
+        // - Addition uses millis which are correct
+        //
+
+        {
+            Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
+            logln( "3A) " + value( calendar ) ) ;
+            calendar.getTime( ) ;
+            calendar.add( Calendar.DATE, 1 ) ;
+            String v = value(calendar);
+            logln( "3B) " + v ) ;
+            logln( "--) 1993/0/5" ) ;
+            if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+                                                "; saw " + v);
+        }
+    }
+    static String value( Calendar calendar ) {
+        return( calendar.get( Calendar.YEAR )  + "/" +
+                calendar.get( Calendar.MONTH ) + "/" +
+                calendar.get( Calendar.DATE ) ) ;
+    }
+    static String EXPECTED_0610 = "1993/0/5";
+
+    // Test that certain fields on a certain date are as expected.
+    public void TestFields060() {
+        int year = 1997;
+        int month = java.util.Calendar.OCTOBER;  //october
+        int dDate = 22;   //DAYOFWEEK should return 3 for Wednesday
+        GregorianCalendar calendar = null;
+
+        calendar = new GregorianCalendar( year, month, dDate);
+        for (int i = 0; i < EXPECTED_FIELDS.length; ) {
+            int field = EXPECTED_FIELDS[i++];
+            int expected = EXPECTED_FIELDS[i++];
+            if (calendar.get(field) != expected) {
+                errln("Expected field " + field + " to have value " + expected +
+                      "; received " + calendar.get(field) + " instead");
+            }
+        }
+    }
+    static int EXPECTED_FIELDS[] = {
+        Calendar.YEAR, 1997,
+        Calendar.MONTH, Calendar.OCTOBER,
+        Calendar.DAY_OF_MONTH, 22,
+        Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY,
+        Calendar.DAY_OF_WEEK_IN_MONTH, 4,
+        Calendar.DAY_OF_YEAR, 295
+    };
+
+    static final String[] calendarFieldNames = {
+      /*  0 */  "ERA",
+      /*  1 */  "YEAR",
+      /*  2 */  "MONTH",
+      /*  3 */  "WEEK_OF_YEAR",
+      /*  4 */  "WEEK_OF_MONTH",
+      /*  5 */  "DAY_OF_MONTH",
+      /*  6 */  "DAY_OF_YEAR",
+      /*  7 */  "DAY_OF_WEEK",
+      /*  8 */  "DAY_OF_WEEK_IN_MONTH",
+      /*  9 */  "AM_PM",
+      /* 10 */  "HOUR",
+      /* 11 */  "HOUR_OF_DAY",
+      /* 12 */  "MINUTE",
+      /* 13 */  "SECOND",
+      /* 14 */  "MILLISECOND",
+      /* 15 */  "ZONE_OFFSET",
+      /* 16 */  "DST_OFFSET"
+    };
+
+    // Verify that the fields are as expected (mostly zero) at the epoch start.
+    // Note that we adjust for the default timezone to get most things to zero.
+    public void TestEpochStartFields() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        String[][] lt = {
+          {"en", "US", "US/Pacific"},        /* First day = 1, Minimum day = 1 */
+          {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */
+          {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */
+          {"en", "MH", "Pacific/Majuro"},    /* First day = 1, Minimum day = 1 */
+          {"ja", "JP", "Asia/Tokyo"},        /* First day = 1, Minimum day = 1 */
+          {"iw", "IL", "Asia/Jerusalem"},    /* First day = 1, Minimum day = 1 */
+          {"hi", "IN", "Asia/Jakarta"},      /* First day = 1, Minimum day = 1 */
+          {"en", "GB", "Europe/London"},     /* First day = 2, Minimum day = 1 */
+          {"en", "GB", "GMT"},               /* First day = 2, Minimum day = 1 */
+          {"de", "DE", "Europe/Berlin"},     /* First day = 2, Minimum day = 4 */
+          {"ar", "EG", "Africa/Cairo"},      /* First day = 7, Minimum day = 1 */
+        };
+
+        int[][] goldenData = {
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0},
+              {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0},
+              {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0},
+        };
+
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+
+        try {
+            for (int j = 0; j < lt.length; j++) {
+                Locale l = new Locale(lt[j][0], lt[j][1]);
+                TimeZone z = TimeZone.getTimeZone(lt[j][2]);
+                Locale.setDefault(l);
+                TimeZone.setDefault(z);
+                Calendar c = Calendar.getInstance();
+                Date d = new Date(-z.getRawOffset());
+
+                int val;
+                int[] EPOCH_FIELDS = goldenData[j];
+                c.setTime(d);
+
+                boolean err = false;
+                for (int i = 0; i < calendarFieldNames.length; ++i) {
+                    if ((val = c.get(i)) != EPOCH_FIELDS[i]) {
+                        errln("Wrong value: " + val +
+                              " for field(" + calendarFieldNames[i] +
+                              "), expected: " + EPOCH_FIELDS[i]);
+                        err = true;
+                    }
+                }
+                if (err) {
+                    errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z +
+                          "\n\tLocale=" + l + "\n\tCalendar=" + c);
+                }
+            }
+        }
+        finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+        }
+    }
+
+    // Verify that as you add days to the calendar (e.g., 24 day periods),
+    // the day of the week shifts in the expected pattern.
+    public void TestDOWProgression() {
+        Calendar cal =
+            new GregorianCalendar(1972, Calendar.OCTOBER, 26);
+        marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7
+    }
+
+    // Supply a delta which is not a multiple of 7.
+    void marchByDelta(Calendar cal, int delta) {
+        Calendar cur = (Calendar)cal.clone();
+        int initialDOW = cur.get(Calendar.DAY_OF_WEEK);
+        int DOW, newDOW = initialDOW;
+        do {
+            DOW = newDOW;
+            logln("DOW = " + DOW + "  " + cur.getTime());
+
+            cur.add(Calendar.DAY_OF_WEEK, delta);
+            newDOW = cur.get(Calendar.DAY_OF_WEEK);
+            int expectedDOW = 1 + (DOW + delta - 1) % 7;
+            if (newDOW != expectedDOW) {
+                errln("Day of week should be " + expectedDOW +
+                      " instead of " + newDOW + " on " + cur.getTime());
+                return;
+            }
+        }
+        while (newDOW != initialDOW);
+    }
+
+    public void TestActualMinMax() {
+        Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10);
+        cal.setFirstDayOfWeek(Calendar.SUNDAY);
+        cal.setMinimalDaysInFirstWeek(3);
+
+        if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) != 1)
+            errln("Actual minimum date for 3/10/1967 should have been 1; got " +
+                  cal.getActualMinimum(Calendar.DAY_OF_MONTH));
+        if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 31)
+            errln("Actual maximum date for 3/10/1967 should have been 31; got " +
+                  cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+
+        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
+        if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 28)
+            errln("Actual maximum date for 2/10/1967 should have been 28; got " +
+                  cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+        if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 365)
+            errln("Number of days in 1967 should have been 365; got " +
+                  cal.getActualMaximum(Calendar.DAY_OF_YEAR));
+
+        cal.set(Calendar.YEAR, 1968);
+        if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 29)
+            errln("Actual maximum date for 2/10/1968 should have been 29; got " +
+                  cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+        if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 366)
+            errln("Number of days in 1968 should have been 366; got " +
+                  cal.getActualMaximum(Calendar.DAY_OF_YEAR));
+        // Using week settings of SUNDAY/3 (see above)
+        if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 52)
+            errln("Number of weeks in 1968 should have been 52; got " +
+                  cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
+
+        cal.set(Calendar.YEAR, 1976);
+        // Using week settings of SUNDAY/3 (see above)
+        if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 53)
+            errln("Number of weeks in 1976 should have been 53; got " +
+                  cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
+    }
+
+    public void TestRoll() {
+        Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 31);
+
+        int[] dayValues = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
+
+        for (int i = 0; i < dayValues.length; i++) {
+            Calendar cal2 = (Calendar)cal.clone();
+            cal2.roll(Calendar.MONTH, i);
+            if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues[i])
+                errln("Rolling the month in 1/31/1997 up by " + i + " should have yielded "
+                      + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded "
+                      + ((i + 1) % 12) + "/" + cal2.get(Calendar.DAY_OF_MONTH) + "/1997.");
+        }
+
+        cal.set(1996, Calendar.FEBRUARY, 29);
+
+        int[] monthValues = { 1, 2, 2, 2, 1, 2, 2, 2, 1, 2 };
+        int[] dayValues2 = { 29, 1, 1, 1, 29, 1, 1, 1, 29, 1 };
+
+        for (int i = 0; i < dayValues2.length; i++) {
+            Calendar cal2 = (Calendar)cal.clone();
+            cal2.roll(Calendar.YEAR, i);
+            if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues2[i] || cal2.get(Calendar.MONTH)
+                != monthValues[i])
+                errln("Rolling the year in 2/29/1996 up by " + i + " should have yielded "
+                      + (monthValues[i] + 1) + "/" + dayValues2[i] + "/"
+                      + (1996 + i) + ", but actually yielded "
+                      + (cal2.get(Calendar.MONTH) + 1) + "/" +
+                      cal2.get(Calendar.DAY_OF_MONTH) + "/" + (1996 + i) + ".");
+        }
+
+        // Test rolling hour of day
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.roll(Calendar.HOUR_OF_DAY, -2);
+        int f = cal.get(Calendar.HOUR_OF_DAY);
+        if (f != 22) errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22");
+        cal.roll(Calendar.HOUR_OF_DAY, 5);
+        f = cal.get(Calendar.HOUR_OF_DAY);
+        if (f != 3) errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3");
+        cal.roll(Calendar.HOUR_OF_DAY, 21);
+        f = cal.get(Calendar.HOUR_OF_DAY);
+        if (f != 0) errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0");
+
+        // Test rolling hour
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.roll(Calendar.HOUR, -2);
+        f = cal.get(Calendar.HOUR);
+        if (f != 10) errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10");
+        cal.roll(Calendar.HOUR, 5);
+        f = cal.get(Calendar.HOUR);
+        if (f != 3) errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3");
+        cal.roll(Calendar.HOUR, 9);
+        f = cal.get(Calendar.HOUR);
+        if (f != 0) errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0");
+    }
+
+    /*
+     * Confirm that multiple calls to Calendar.set() works correctly.
+     */
+    public void Test4374886() {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+
+        try {
+            Locale.setDefault(Locale.US);
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+            Calendar cal = Calendar.getInstance();
+            cal.set(Calendar.YEAR, 2001);
+            cal.set(Calendar.MONTH, Calendar.OCTOBER);
+            cal.set(Calendar.WEEK_OF_YEAR, 4);
+            cal.set(Calendar.DAY_OF_WEEK, 2);
+
+            if (cal.get(Calendar.YEAR) != 2001 ||
+                cal.get(Calendar.MONTH) != Calendar.JANUARY ||
+                cal.get(Calendar.DATE) != 22 ||
+                cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
+                errln("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001");
+            }
+        }
+        finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+        }
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/FieldStateTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,216 @@
+/*
+ * 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
+ * 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 4860664 4916815 4867075
+ * @library /java/text/testlib
+ * @build Koyomi
+ * @run main FieldStateTest
+ * @summary Unit tests for internal fields states.
+ */
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static java.util.Calendar.*;
+
+public class FieldStateTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        TimeZone reservedTimeZone = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Locale.setDefault(Locale.US);
+
+            new FieldStateTest().run(args);
+        } finally {
+            // restore the reserved locale and time zone
+            Locale.setDefault(reservedLocale);
+            TimeZone.setDefault(reservedTimeZone);
+        }
+    }
+
+    public void TestFieldState() {
+        Koyomi cal = new Koyomi();
+        logln("Right after instantialtion:");
+        if (!cal.checkAllSet()) {
+            errln(cal.getMessage());
+        }
+
+        logln("Set date to 2003/10/31 after the instantiation:");
+        cal.set(2003, OCTOBER, 31);
+        // let cal calculate the time
+        cal.getTime();
+        // At this point, all fields have to be recalculated and
+        // happen to have the set-state from the instantiation. The
+        // three fields should have "externally set" and the rest of
+        // the fields have "computed". But we can't distinguish them
+        // outside the package.
+        if (!cal.checkAllSet()) {
+            errln(cal.getMessage());
+        }
+        // Make sure that the correct date was produced.
+        if (!cal.checkInternalDate(2003, OCTOBER, 31, FRIDAY)) {
+            errln(cal.getMessage());
+        }
+
+        logln("Change to Monday of the week, which is 2003/10/27:");
+        cal.set(DAY_OF_WEEK, MONDAY);
+        cal.getTime();
+        if (!cal.checkDate(2003, OCTOBER, 27)) {
+            errln(cal.getMessage());
+        }
+
+        // The same operation didn't work after calling clear() before
+        // 1.5 because the set-state was just depends on its previous
+        // operations. After the instantiation, all the fields are set
+        // to "computed". But after calling clear(), the state becomes
+        // "unset".
+        logln("Set to 2003/10/31 after clear():");
+        cal.clear();
+        cal.set(2003, OCTOBER, 31);
+        cal.getTime();
+        cal.set(DAY_OF_WEEK, MONDAY);
+        if (!cal.checkDate(2003, OCTOBER, 27, MONDAY)) {
+            errln(cal.getMessage());
+        }
+
+        logln("Set to 2003/10/31 after clear(), then to the 51st week of year (12/19):");
+        cal.clear();
+        cal.set(2003, OCTOBER, 31);
+        cal.getTime();
+        cal.set(WEEK_OF_YEAR, 51);
+        if (!cal.checkFieldValue(WEEK_OF_YEAR, 51)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkDate(2003, DECEMBER, 19, FRIDAY)) {
+            errln(cal.getMessage());
+        }
+
+        logln("Set to 2003/10 Mon of 4th week (10/20: 43rd week of year, 293rd day):");
+        cal.clear();
+        cal.set(YEAR, 2003);
+        cal.set(MONTH, OCTOBER);
+        cal.set(DAY_OF_WEEK, MONDAY);
+        cal.set(WEEK_OF_MONTH, 4);
+        cal.getTime();
+        if (!cal.checkFieldValue(DAY_OF_MONTH, 20)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkFieldValue(WEEK_OF_YEAR, 43)) {
+            errln(cal.getMessage());
+        }
+
+        logln("Set to 2003/10 Mon of 43rd week of year (10/20: 4th week of month, 293rd day):");
+        cal.clear();
+        cal.set(YEAR, 2003);
+        cal.set(DAY_OF_WEEK, MONDAY);
+        cal.set(WEEK_OF_YEAR, 43);
+        cal.getTime();
+        if (!cal.checkDate(2003, OCTOBER, 20, MONDAY)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkFieldValue(WEEK_OF_MONTH, 4)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
+            errln(cal.getMessage());
+        }
+
+        logln("Set day of week to SUNDAY and date to 2003/10/31. "
+              + "Then, getTime and set week of year to 43.");
+        cal.setTime(new Date(2003-1990, OCTOBER, 31));
+        cal.set(DAY_OF_WEEK, SUNDAY);
+        cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday.
+        cal.set(ZONE_OFFSET, 0);
+        cal.set(DST_OFFSET, 0);
+
+        // This call should change the day of week to FRIDAY since the
+        // selected field combination should be YEAR, MONTH and
+        // DAY_OF_MONTH. The other calendar fields must be normalized
+        // with the selected date.
+        cal.getTime();
+        cal.set(WEEK_OF_YEAR, 43);
+        if (!cal.checkDate(2003, OCTOBER, 24, FRIDAY)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    /*
+     * 4916815: REGRESSION: Problem with java.util.Calendar VM 1.4.2-b28
+     */
+    public void Test4916815() {
+        logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. "+
+              "Set dayofweek to Sunday which should be 2003/9/21.");
+        Koyomi cal = new Koyomi();
+        cal.clear();
+        // 2003/9/26 (Fri)
+        cal.set(2003, SEPTEMBER, 26);
+        // Go to August then back to September
+        cal.roll(MONTH, -1);
+        cal.roll(MONTH, +1);
+        Koyomi cal2 = (Koyomi) cal.clone();
+        cal2.getTime();
+        // Sunday of the week should be 2003/9/21.
+        cal2.set(DAY_OF_WEEK, SUNDAY);
+        if (!cal2.checkDate(2003, SEPTEMBER, 21, SUNDAY)) {
+            errln(cal2.getMessage());
+        }
+    }
+
+    /*
+     * 4867075: GregorianCalendar get() calls complete() internally, should getTime() too?
+     */
+    public void Test4867075() {
+        Koyomi cal = new Koyomi(Locale.US);
+        cal.clear();
+        cal.set(YEAR, 2004);
+        cal.set(WEEK_OF_YEAR, 1);
+        checkDate(cal, SUNDAY,    2003, DECEMBER, 28);
+        checkDate(cal, MONDAY,    2003, DECEMBER, 29);
+        checkDate(cal, TUESDAY,   2003, DECEMBER, 30);
+        checkDate(cal, WEDNESDAY, 2003, DECEMBER, 31);
+        checkDate(cal, THURSDAY,  2004, JANUARY,   1);
+        checkDate(cal, FRIDAY,    2004, JANUARY,   2);
+        checkDate(cal, SATURDAY,  2004, JANUARY,   3);
+    }
+
+    private void checkDate(Koyomi cal, int dayOfWeek,
+                           int expectedYear, int expectedMonth, int expectedDayOfMonth) {
+        cal.set(DAY_OF_WEEK, dayOfWeek);
+        cal.getTime();
+        if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) {
+            errln(cal.getMessage());
+        }
+    }
+
+    static String toHexString(int x) {
+        return Integer.toHexString(x);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/GregorianCutoverTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,324 @@
+/*
+ * 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
+ * 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 4359204 4928615 4743587 4956232 6459836 6549953
+ * @library /java/text/testlib
+ * @build Koyomi
+ * @run main GregorianCutoverTest
+ * @summary Unit tests related to the Gregorian cutover support.
+ */
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static java.util.GregorianCalendar.*;
+
+public class GregorianCutoverTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        TimeZone tz = TimeZone.getDefault();
+        Locale lc = Locale.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Locale.setDefault(Locale.US);
+
+            new GregorianCutoverTest().run(args);
+        } finally {
+            TimeZone.setDefault(tz);
+            Locale.setDefault(lc);
+        }
+    }
+
+    /**
+     * 4359204: GregorianCalendar.get(cal.DAY_OF_YEAR) is inconsistent for year 1582
+     */
+    public void Test4359204() {
+        Koyomi cal = new Koyomi();
+
+        cal.set(1582, JANUARY, 1);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+        cal.set(1582, OCTOBER, 1);
+        checkContinuity(cal, WEEK_OF_MONTH);
+
+        // JCK tests the cutover date 1970-1-1 (Epoch)
+        cal.setGregorianChange(new Date(0));
+        cal.set(1969, JANUARY, 1);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+        cal.set(1969, DECEMBER, 1);
+        checkContinuity(cal, WEEK_OF_MONTH);
+        cal.set(1970, JANUARY, 1);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+
+        // Use large date (year >= 50000)
+        cal.setGregorianChange(new Date(50000-1900, JANUARY, 20));
+        cal.set(49998, JANUARY, 1);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+        cal.set(49999, JANUARY, 1);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+        cal.set(50000, JANUARY, 20);
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+
+        // Handling of "overlapping" dates may still be incorrect as
+        // of 1.5. Also, there's no way to disambiguate "overlapping"
+        // dates.
+        // millis=-112033929600000: date=-1581-10-15T00:00:00.000Z
+        cal.setGregorianChange(new Date(-112033929600000L));
+        cal.set(ERA, AD);
+        cal.set(-1581, JANUARY, 1);
+        // The year should have 379 days.
+        checkContinuity(cal, DAY_OF_YEAR);
+        checkContinuity(cal, WEEK_OF_YEAR);
+
+        logln("Default cutover");
+        cal = new Koyomi();
+        cal.set(1582, OCTOBER, 1);
+        logln("  roll --DAY_OF_MONTH from 1582/10/01");
+        cal.roll(DAY_OF_MONTH, -1);
+        if (!cal.checkDate(1582, OCTOBER, 31)) {
+            errln(cal.getMessage());
+        }
+        logln("  roll DAY_OF_MONTH+10 from 1582/10/31");
+        cal.roll(DAY_OF_MONTH, +10);
+        if (!cal.checkDate(1582, OCTOBER, 20)) {
+            errln(cal.getMessage());
+        }
+        logln("  roll DAY_OF_MONTH-10 from 1582/10/20");
+        cal.roll(DAY_OF_MONTH, -10);
+        if (!cal.checkDate(1582, OCTOBER, 31)) {
+            errln(cal.getMessage());
+        }
+        logln("  roll back one day further");
+        cal.roll(DAY_OF_MONTH, +1);
+        if (!cal.checkDate(1582, OCTOBER, 1)) {
+            errln(cal.getMessage());
+        }
+
+        // should handle the gap between 1969/12/22 (Julian) to 1970/1/5 (Gregorian)
+        logln("Cutover date is 1970/1/5");
+        cal.setGregorianChange(new Date(1970-1900, JANUARY, 5));
+        cal.set(ERA, AD);
+        cal.set(YEAR, 1970);
+        logln("  Set DAY_OF_YEAR to the 28th day of 1970");
+        cal.set(DAY_OF_YEAR, 28);
+        if (!cal.checkDate(1970, FEBRUARY, 1)) {
+            errln(cal.getMessage());
+        }
+        if (!cal.checkFieldValue(WEEK_OF_YEAR, 5)) {
+            errln(cal.getMessage());
+        }
+        logln("  1969/12/22 should be the 356th day of the year.");
+        cal.set(1969, DECEMBER, 22);
+        if (!cal.checkFieldValue(DAY_OF_YEAR, 356)) {
+            errln(cal.getMessage());
+        }
+        logln("  Set DAY_OF_YEAR to autual maximum.");
+        int actualMaxDayOfYear = cal.getActualMaximum(DAY_OF_YEAR);
+        if (actualMaxDayOfYear != 356) {
+            errln("actual maximum of DAY_OF_YEAR: got " + actualMaxDayOfYear + ", expected 356");
+        }
+        cal.set(DAY_OF_YEAR, actualMaxDayOfYear);
+        if (!cal.checkDate(1969, DECEMBER, 22)) {
+            errln(cal.getMessage());
+        }
+        cal.set(1969, DECEMBER, 22);
+        cal.roll(DAY_OF_YEAR, +1);
+        logln("  Set to 1969/12/22 and roll DAY_OF_YEAR++");
+        if (!cal.checkDate(1969, JANUARY, 1)) {
+            errln(cal.getMessage());
+        }
+        logln("  1970/1/5 should be the first day of the year.");
+        cal.set(1970, JANUARY, 5);
+        if (!cal.checkFieldValue(DAY_OF_YEAR, 1)) {
+            errln(cal.getMessage());
+        }
+        logln("  roll --DAY_OF_MONTH from 1970/1/5");
+        cal.roll(DAY_OF_MONTH, -1);
+        if (!cal.checkDate(1970, JANUARY, 31)) {
+            errln(cal.getMessage());
+        }
+        logln("  roll back one day of month");
+        cal.roll(DAY_OF_MONTH, +1);
+        if (!cal.checkDate(1970, JANUARY, 5)) {
+            errln(cal.getMessage());
+        }
+
+        // Test "missing" dates in non-lenient.
+        cal = new Koyomi(); // new instance for the default cutover
+        cal.setLenient(false);
+        try {
+            // the next day of 1582/10/4 (Julian) is 1582/10/15 (Gregorian)
+            logln("1582/10/10 doesn't exit with the default cutover.");
+            cal.set(1582, OCTOBER, 10);
+            cal.getTime();
+            errln("    Didn't throw IllegalArgumentException in non-lenient.");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    private void checkContinuity(Koyomi cal, int field) {
+        cal.getTime();
+        logln(Koyomi.getFieldName(field) + " starting on " + cal.toDateString());
+        int max = cal.getActualMaximum(field);
+        for (int i = 1; i <= max; i++) {
+            logln(i + "    " + cal.toDateString());
+            if (!cal.checkFieldValue(field, i)) {
+                errln("    " + cal.toDateString() + ":\t" + cal.getMessage());
+            }
+            cal.add(field, +1);
+        }
+    }
+
+    /**
+     * 4928615: GregorianCalendar returns wrong dates after setGregorianChange
+     */
+    public void Test4928615() {
+        Koyomi cal = new Koyomi();
+        logln("Today is 2003/10/1 Gregorian.");
+        Date x = new Date(2003-1900, 10-1, 1);
+        cal.setTime(x);
+
+        logln("  Changing the cutover date to yesterday...");
+        cal.setGregorianChange(new Date(x.getTime() - (24*3600*1000)));
+        if (!cal.checkDate(2003, OCTOBER, 1)) {
+            errln("    " + cal.getMessage());
+        }
+        logln("  Changing the cutover date to tomorrow...");
+        cal.setGregorianChange(new Date(x.getTime() + (24*3600*1000)));
+        if (!cal.checkDate(2003, SEPTEMBER, 18)) {
+            errln("    " + cal.getMessage());
+        }
+    }
+
+    /**
+     * 4743587: GregorianCalendar.getLeastMaximum() returns wrong values
+     */
+    public void Test4743587() {
+        Koyomi cal = new Koyomi();
+        Koyomi cal2 = (Koyomi) cal.clone();
+        logln("getLeastMaximum should handle cutover year.\n"
+              +"  default cutover date");
+        if (!cal.checkLeastMaximum(DAY_OF_YEAR, 365-10)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52-((10+6)/7))) {
+            errln("    " + cal.getMessage());
+        }
+        // Corrected for 4956232
+        if (!cal.checkLeastMaximum(DAY_OF_MONTH, 28)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkLeastMaximum(WEEK_OF_MONTH, 3)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkLeastMaximum(DAY_OF_WEEK_IN_MONTH, 3)) {
+            errln("    " + cal.getMessage());
+        }
+        // make sure that getLeastMaximum calls didn't affect the date
+        if (!cal.equals(cal2)) {
+            errln("    getLeastMaximum calls modified the object.");
+        }
+        if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 1)) {
+            errln("    " + cal.getMessage());
+        }
+
+        logln("  changing the date to 1582/10/20 for actual min/max tests");
+        cal.set(1582, OCTOBER, 20);
+        if (!cal.checkActualMinimum(DAY_OF_MONTH, 1)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) {
+            errln("    " + cal.getMessage());
+        }
+
+        cal = new Koyomi();
+        logln("Change the cutover date to 1970/1/5.");
+        cal.setGregorianChange(new Date(1970-1900, 0, 5));
+        if (!cal.checkLeastMaximum(DAY_OF_YEAR, 356)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkLeastMaximum(DAY_OF_MONTH, 22)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 5)) {
+            errln("    " + cal.getMessage());
+        }
+        cal.set(1970, JANUARY, 10);
+        if (!cal.checkActualMinimum(DAY_OF_MONTH, 5)) {
+            errln("    " + cal.getMessage());
+        }
+        if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) {
+            errln("    " + cal.getMessage());
+        }
+    }
+
+    /**
+     * 6459836: (cal) GregorianCalendar set method provides wrong result
+     */
+    public void Test6459836() {
+        int hour = 13865672;
+        Koyomi gc1 = new Koyomi();
+        gc1.clear();
+        gc1.set(1, gc1.JANUARY, 1, 0, 0, 0);
+        gc1.set(gc1.HOUR_OF_DAY, hour);
+        if (!gc1.checkDate(1582, gc1.OCTOBER, 4)) {
+            errln("test case 1: " + gc1.getMessage());
+        }
+        gc1.clear();
+        gc1.set(1, gc1.JANUARY, 1, 0, 0, 0);
+        gc1.set(gc1.HOUR_OF_DAY, hour + 24);
+        if (!gc1.checkDate(1582, gc1.OCTOBER, 15)) {
+            errln("test case 2: " + gc1.getMessage());
+        }
+    }
+
+    /**
+     * 6549953 (cal) WEEK_OF_YEAR and DAY_OF_YEAR calculation problems around Gregorian cutover
+     */
+    public void Test6549953() {
+        Koyomi cal = new Koyomi();
+
+        cal.set(YEAR, 1582);
+        cal.set(WEEK_OF_YEAR, 42);
+        cal.set(DAY_OF_WEEK, FRIDAY);
+        cal.checkFieldValue(WEEK_OF_YEAR, 42);
+        cal.checkFieldValue(DAY_OF_WEEK, FRIDAY);
+        if (!cal.checkDate(1582, OCTOBER, 29)) {
+            errln(cal.getMessage());
+        }
+        cal.clear();
+        cal.set(1582, OCTOBER, 1);
+        cal.set(DAY_OF_YEAR, 292);
+        if (!cal.checkDate(1582, OCTOBER, 29)) {
+            errln(cal.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/JulianTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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
+ * 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 5029449
+ * @summary Tests for the Julian calendar system (before the Gregorian cutover)
+ * @library /java/text/testlib
+ */
+
+import static java.util.GregorianCalendar.*;
+
+public class JulianTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new JulianTest().run(args);
+    }
+
+    /*
+     * 5029449: Regression: GregorianCalendar produces wrong Julian calendar dates in BC 1
+     */
+    public void Test5029449() {
+        Koyomi cal = new Koyomi();
+        cal.clear();
+        cal.set(1, JANUARY, 0);
+        // Date should be BC 1/12/31
+        if (!cal.checkFieldValue(ERA, BC)
+            || !cal.checkDate(1, DECEMBER, 31)) {
+            errln(cal.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Koyomi.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,289 @@
+/*
+ * 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
+ * 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 static java.util.Calendar.*;
+
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * GregorianCalendar subclass for testing.
+ */
+public class Koyomi extends GregorianCalendar {
+    static final String[] FIELD_NAMES = {
+        "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
+        "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
+        "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
+        "DST_OFFSET"
+    };
+
+    static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;
+
+    public Koyomi() {
+    }
+
+    public Koyomi(TimeZone tz) {
+        super(tz);
+    }
+
+    public Koyomi(Locale loc) {
+        super(loc);
+    }
+
+    public Koyomi(TimeZone tz, Locale loc) {
+        super(tz, loc);
+    }
+
+    @Override
+    public void computeTime() {
+        super.computeTime();
+    }
+
+    @Override
+    public void computeFields() {
+        super.computeFields();
+    }
+
+    @Override
+    public void complete() {
+        super.complete();
+    }
+
+    static String getFieldName(int field) {
+        return FIELD_NAMES[field];
+    }
+
+    String toDateString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(internalGet(ERA) == 0 ? "BCE " : "");
+        sb.append(internalGet(YEAR)).append('-');
+        sb.append(internalGet(MONTH)+1).append('-');
+        sb.append(internalGet(DAY_OF_MONTH));
+        return sb.toString();
+    }
+
+    String toTimeString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(internalGet(HOUR_OF_DAY)).append(':');
+        sb.append(internalGet(MINUTE)).append(':');
+        sb.append(internalGet(SECOND)).append('.');
+        int ms = internalGet(MILLISECOND);
+        if (ms < 100) {
+            sb.append('0');
+            if (ms < 10) {
+                sb.append('0');
+            }
+        }
+        sb.append(ms);
+        int offset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
+        offset /= 60000;
+        offset = (offset/60) * 100 + (offset%60);
+        if (offset >= 0) {
+            sb.append('+');
+        } else {
+            sb.append('-');
+            offset = -offset;
+        }
+        if (offset < 1000) {
+            sb.append('0');
+            if (offset < 100) {
+                sb.append('0');
+            }
+        }
+        sb.append(offset);
+        return sb.toString();
+    }
+
+    String toDateTimeString() {
+        return toDateString() + "T" + toTimeString();
+    }
+
+    StringBuilder msg = new StringBuilder();
+
+    void initTest() {
+        msg = new StringBuilder();
+    }
+
+    String getMessage() {
+        String s = msg.toString();
+        msg = new StringBuilder();
+        return "    " + s;
+    }
+
+    void setMessage(String msg) {
+        this.msg = new StringBuilder(msg);
+    }
+
+    void appendMessage(String msg) {
+        this.msg.append(msg);
+    }
+
+    boolean getStatus() {
+        return msg.length() == 0;
+    }
+
+    int getSetStateFields() {
+        int mask = 0;
+        for (int i = 0; i < FIELD_COUNT; i++) {
+            if (isSet(i)) {
+                mask |= 1 << i;
+            }
+        }
+        return mask;
+    }
+
+    int[] getFields() {
+        int[] fds = new int[fields.length];
+        System.arraycopy(fields, 0, fds, 0, fds.length);
+        return fds;
+    }
+
+    boolean checkAllSet() {
+        initTest();
+        for (int i = 0; i < FIELD_COUNT; i++) {
+            checkFieldState(i, true);
+        }
+        return getStatus();
+    }
+
+    boolean checkInternalDate(int year, int month, int dayOfMonth) {
+        initTest();
+        checkInternalFieldValue(YEAR, year);
+        checkInternalFieldValue(MONTH, month);
+        checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth);
+        return getStatus();
+    }
+
+    boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) {
+        initTest();
+        checkInternalFieldValue(YEAR, year);
+        checkInternalFieldValue(MONTH, month);
+        checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth);
+        checkInternalFieldValue(DAY_OF_WEEK, dayOfWeek);
+        return getStatus();
+    }
+
+    boolean checkActualMaximum(int field, int expectedValue) {
+        int val;
+        if ((val = getActualMaximum(field)) != expectedValue) {
+            appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val
+                          + " expected " + expectedValue);
+        }
+        return getStatus();
+    }
+
+    boolean checkLeastMaximum(int field, int expectedValue) {
+        int val;
+        if ((val = getLeastMaximum(field)) != expectedValue) {
+            appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val
+                          + " expected " + expectedValue);
+        }
+        return getStatus();
+    }
+
+    boolean checkActualMinimum(int field, int expectedValue) {
+        int val;
+        if ((val = getActualMinimum(field)) != expectedValue) {
+            appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val
+                          + " expected " + expectedValue);
+        }
+        return getStatus();
+    }
+
+    boolean checkGreatestMinimum(int field, int expectedValue) {
+        int val;
+        if ((val = getGreatestMinimum(field)) != expectedValue) {
+            appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val
+                          + " expected " + expectedValue);
+        }
+        return getStatus();
+    }
+
+    boolean checkDate(int year, int month, int dayOfMonth) {
+        initTest();
+        checkFieldValue(YEAR, year);
+        checkFieldValue(MONTH, month);
+        checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+        return getStatus();
+    }
+
+    boolean checkDate(int year, int month, int dayOfMonth, int dayOfWeek) {
+        initTest();
+        checkFieldValue(YEAR, year);
+        checkFieldValue(MONTH, month);
+        checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+        checkFieldValue(DAY_OF_WEEK, dayOfWeek);
+        return getStatus();
+    }
+
+    boolean checkDateTime(int year, int month, int dayOfMonth,
+                          int hourOfDay, int minute, int second, int ms) {
+        initTest();
+        checkFieldValue(YEAR, year);
+        checkFieldValue(MONTH, month);
+        checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+        checkFieldValue(HOUR_OF_DAY, hourOfDay);
+        checkFieldValue(MINUTE, minute);
+        checkFieldValue(SECOND, second);
+        checkFieldValue(MILLISECOND, ms);
+        return getStatus();
+    }
+
+    boolean checkTime(int hourOfDay, int minute, int second, int ms) {
+        initTest();
+        checkFieldValue(HOUR_OF_DAY, hourOfDay);
+        checkFieldValue(MINUTE, minute);
+        checkFieldValue(SECOND, second);
+        checkFieldValue(MILLISECOND, ms);
+        return getStatus();
+    }
+
+    boolean checkFieldState(int field, boolean expectedState) {
+        if (isSet(field) != expectedState) {
+            appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; ");
+            return false;
+        }
+        return true;
+    }
+
+    boolean checkFieldValue(int field, int expectedValue) {
+        int val;
+        if ((val = get(field)) != expectedValue) {
+            appendMessage("get(" + FIELD_NAMES[field] + "): got " + val +
+                          ", expected " + expectedValue + "; ");
+            return false;
+        }
+        return true;
+    }
+
+    boolean checkInternalFieldValue(int field, int expectedValue) {
+        int val;
+        if ((val = internalGet(field)) != expectedValue) {
+            appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val +
+                          ", expected " + expectedValue + "; ");
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/Limit.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.util.*;
+import java.text.*;
+
+/**
+ * Test GregorianCalendar limits, which should not exist.
+ * @test
+ * @bug 4056585
+ * @summary Make sure that GregorianCalendar works far in the past and future.
+ * @author Alan Liu
+ */
+public class Limit {
+    static final long ONE_DAY = 24*60*60*1000L;
+
+    public static void main(String args[]) throws Exception {
+        GregorianCalendar c = new GregorianCalendar();
+        DateFormat fmt = new SimpleDateFormat("EEEE, MMMM dd, yyyy G", Locale.US);
+        long bigMillis = 300000000000000L;
+
+        try {
+            // We check two things:
+            // 1. That handling millis in the range of +/- bigMillis works.
+            //    bigMillis is a value that used to blow up.
+            // 2. The round-trip format/parse works in these extreme areas.
+            c.setTime(new Date(-bigMillis));
+            String s = fmt.format(c.getTime());
+            Date d = fmt.parse(s);
+            if (Math.abs(d.getTime() + bigMillis) >= ONE_DAY) {
+                throw new Exception(s + " != " + fmt.format(d));
+            }
+
+            c.setTime(new Date(+bigMillis));
+            s = fmt.format(c.getTime());
+            d = fmt.parse(s);
+            if (Math.abs(d.getTime() - bigMillis) >= ONE_DAY) {
+                throw new Exception(s + " != " + fmt.format(d));
+            }
+        } catch (IllegalArgumentException | ParseException e) {
+            throw e;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/NonLenientTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,221 @@
+/*
+ * 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
+ * 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 4147269 4266783 4726030
+ * @summary Make sure that validation is adequate in non-lenient mode.
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+import static java.util.Calendar.*;
+
+public class NonLenientTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        Locale reservedLocale = Locale.getDefault();
+        TimeZone reservedTimeZone = TimeZone.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+            new NonLenientTest().run(args);
+        } finally {
+            // restore the reserved locale and time zone
+            Locale.setDefault(reservedLocale);
+            TimeZone.setDefault(reservedTimeZone);
+        }
+    }
+
+    public void TestValidationInNonLenient() {
+        Koyomi cal = getNonLenient();
+
+        // 2003 isn't a leap year.
+        cal.set(2003, FEBRUARY, 29);
+        validate(cal, "2003/2/29");
+
+        // October has only 31 days.
+        cal.set(2003, OCTOBER, 32);
+        validate(cal, "2003/10/32");
+
+        // 2003/10/31 is Friday.
+        cal.set(2003, OCTOBER, 31);
+        cal.set(DAY_OF_WEEK, SUNDAY);
+        validate(cal, "2003/10/31 SUNDAY");
+
+        // 2003/10/31 is the 304th day of the year.
+        cal.clear();
+        cal.set(DAY_OF_YEAR, 1);
+        cal.set(2003, OCTOBER, 31);
+        validate(cal, "2003/10/31 DAY_OF_YEAR=1");
+
+        // 2003/10 isn't the 1st week of the year.
+        cal.clear();
+        cal.set(YEAR, 2003);
+        cal.set(WEEK_OF_YEAR, 1);
+        cal.set(MONTH, OCTOBER);
+        validate(cal, "2003/10 WEEK_OF_YEAR=1");
+
+        // The 1st week of 2003 doesn't have Monday.
+        cal.clear();
+        cal.set(YEAR, 2003);
+        cal.set(WEEK_OF_YEAR, 1);
+        cal.set(DAY_OF_WEEK, MONDAY);
+        validate(cal, "2003 WEEK_OF_YEAR=1 MONDAY.");
+
+        // 2003 has 52 weeks.
+        cal.clear();
+        cal.set(YEAR, 2003);
+        cal.set(WEEK_OF_YEAR, 53);
+        cal.set(DAY_OF_WEEK, WEDNESDAY);
+        validate(cal, "2003 WEEK_OF_YEAR=53");
+
+        /*
+         * These test cases assume incompatible behavior in Tiger as
+         * the result of the validation bug fixes. However, it looks
+         * like we have to allow applications to set ZONE_OFFSET and
+         * DST_OFFSET values to modify the time zone offsets given by
+         * a TimeZone. The definition of non-leniency for time zone
+         * offsets is somewhat vague.  (See 6231602)
+         *
+         * The following test cases are now disabled.
+
+        // America/Los_Angeles is GMT-08:00
+        cal.clear();
+        cal.set(2003, OCTOBER, 31);
+        cal.set(ZONE_OFFSET, 0);
+        validate(cal, "ZONE_OFFSET=0:00 in America/Los_Angeles");
+
+        // 2003/10/31 shouldn't be in DST.
+        cal.clear();
+        cal.set(2003, OCTOBER, 31);
+        cal.set(DST_OFFSET, 60*60*1000);
+        validate(cal, "2003/10/31 DST_OFFSET=1:00 in America/Los_Angeles");
+
+        */
+    }
+
+    /**
+     * 4266783: java.util.GregorianCalendar: incorrect validation in non-lenient
+     */
+    public void Test4266783() {
+        Koyomi cal = getNonLenient();
+        // 2003/1 has up to 5 weeks.
+        cal.set(YEAR, 2003);
+        cal.set(MONTH, JANUARY);
+        cal.set(WEEK_OF_MONTH, 6);
+        cal.set(DAY_OF_WEEK, SUNDAY);
+        validate(cal, "6th Sunday in Jan 2003");
+    }
+
+
+    /**
+     * 4726030: GregorianCalendar doesn't check invalid dates in non-lenient
+     */
+    public void Test4726030() {
+        Koyomi cal = getNonLenient();
+        // Default year is 1970 in GregorianCalendar which isn't a leap year.
+        cal.set(MONTH, FEBRUARY);
+        cal.set(DAY_OF_MONTH, 29);
+        validate(cal, "2/29 in the default year 1970");
+    }
+
+    /**
+     * 4147269: java.util.GregorianCalendar.computeTime() works wrong when lenient is false
+     */
+    public void Test4147269() {
+        Koyomi calendar = getNonLenient();
+        Date date = (new GregorianCalendar(1996,0,3)).getTime();
+
+        for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+            calendar.setTime(date);
+            int max = calendar.getActualMaximum(field);
+            int value = max+1;
+            calendar.set(field, value);
+            try {
+                calendar.computeTime(); // call method under test
+                errln("Test failed with field " + calendar.getFieldName(field)
+                      + "\n\tdate before:  " + date
+                      + "\n\tdate after:   " + calendar.getTime()
+                      + "\n\tvalue: " + value + "  (max = " + max +")");
+            } catch (IllegalArgumentException e) {
+            }
+        }
+
+        for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+            calendar.setTime(date);
+            int min = calendar.getActualMinimum(field);
+            int value = min-1;
+            calendar.set(field, value);
+            try {
+                calendar.computeTime(); // call method under test
+                errln("Test failed with field " + calendar.getFieldName(field)
+                      + "\n\tdate before:  " + date
+                      + "\n\tdate after:   " + calendar.getTime()
+                      + "\n\tvalue: " + value + "  (min = " + min +")");
+            } catch (IllegalArgumentException e) {
+            }
+        }
+    }
+
+    void validate(Koyomi cal, String desc) {
+        int[] originalFields = cal.getFields();
+        int setFields = cal.getSetStateFields();
+
+        try {
+            cal.complete();
+            errln(desc + " should throw IllegalArgumentException in non-lenient.");
+        } catch (IllegalArgumentException e) {
+        }
+
+        // The code below will be executed with the -nothrow option
+
+        // In non-lenient, calendar field values that have beeb set by
+        // user shouldn't be modified.
+        int[] afterFields = cal.getFields();
+        for (int i = 0; i < Calendar.FIELD_COUNT; i++) {
+            if (cal.isSet(i) && originalFields[i] != afterFields[i]) {
+                errln("    complete() modified fields[" + cal.getFieldName(i) + "] got "
+                      + afterFields[i] + ", expected " + originalFields[i]);
+            }
+        }
+        // In non-lenient, set state of fields shouldn't be modified.
+        int afterSetFields = cal.getSetStateFields();
+        if (setFields != afterSetFields) {
+            errln("    complate() modified set states: before 0x" + toHex(setFields)
+                  + ", after 0x"+ toHex(afterSetFields));
+        }
+    }
+
+    static Koyomi getNonLenient() {
+        Koyomi cal = new Koyomi();
+        cal.clear();
+        cal.setLenient(false);
+        return cal;
+    }
+
+    static String toHex(int x) {
+        return Integer.toHexString(x);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/ResolutionTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * 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 6452848
+ * @summary Make sure that the resolution of (WEKK_OF_MONTH +
+ * DAY_OF_WEEK) and (DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK) works as
+ * specified in the API.
+ * @key randomness
+ */
+
+import java.util.*;
+import static java.util.Calendar.*;
+
+public class ResolutionTest {
+    static Random rand = new Random();
+
+    public static void main(String[] args) {
+        for (int year = 1995; year < 2011; year++) {
+            for (int month = JANUARY; month <= DECEMBER; month++) {
+                for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+                    test(year, month, dow);
+                }
+            }
+        }
+    }
+
+    static void test(int year, int month, int dow) {
+        Calendar cal = new GregorianCalendar(year, month, 1);
+        int max = cal.getActualMaximum(DAY_OF_MONTH);
+        ArrayList<Integer> list = new ArrayList<Integer>();
+        for (int d = 1; d <= max; d++) {
+            cal.clear();
+            cal.set(year, month, d);
+            if (cal.get(DAY_OF_WEEK) == dow) {
+                list.add(d);
+            }
+        }
+        for (int i = 0; i < 100; i++) {
+            int nth = rand.nextInt(list.size()); // 0-based
+            int day = list.get(nth);
+            nth++; // 1-based
+            testDayOfWeekInMonth(year, month, nth, dow, day);
+        }
+
+        // Put WEEK_OF_MONTH-DAY_OF_MONTH pairs
+        list = new ArrayList<Integer>();
+        for (int d = 1; d <= max; d++) {
+            cal.clear();
+            cal.set(year, month, d);
+            if (cal.get(DAY_OF_WEEK) == dow) {
+                list.add(cal.get(WEEK_OF_MONTH));
+                list.add(d);
+            }
+        }
+        for (int i = 0; i < list.size(); i++) {
+            int nth = list.get(i++);
+            int day = list.get(i);
+            testWeekOfMonth(year, month, nth, dow, day);
+        }
+    }
+
+    static Koyomi cal = new Koyomi();
+
+    static void testDayOfWeekInMonth(int year, int month, int nth, int dow, int expected) {
+        // don't call clear() here
+        cal.set(YEAR, year);
+        cal.set(MONTH, month);
+        // Set DAY_OF_WEEK_IN_MONTH before DAY_OF_WEEK
+        cal.set(DAY_OF_WEEK_IN_MONTH, nth);
+        cal.set(DAY_OF_WEEK, dow);
+        if (!cal.checkDate(year, month, expected)) {
+            throw new RuntimeException(String.format("DOWIM: year=%d, month=%d, nth=%d, dow=%d:%s%n",
+                                                     year, month+1, nth, dow, cal.getMessage()));
+        }
+    }
+
+    static void testWeekOfMonth(int year, int month, int nth, int dow, int expected) {
+        // don't call clear() here
+        cal.set(YEAR, year);
+        cal.set(MONTH, month);
+        // Set WEEK_OF_MONTH before DAY_OF_WEEK
+        cal.set(WEEK_OF_MONTH, nth);
+        cal.set(DAY_OF_WEEK, dow);
+        if (!cal.checkDate(year, month, expected)) {
+            throw new RuntimeException(String.format("WOM: year=%d, month=%d, nth=%d, dow=%d:%s%n",
+                                                     year, month+1, nth, dow, cal.getMessage()));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/RollDayOfWeekTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * 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
+ * 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 5090555 5091805
+ * @summary Make sure that rolling DAY_OF_WEEK stays in the same week
+ * around year boundaries.
+ * @run main/othervm RollDayOfWeekTest 5 5
+ */
+
+import java.util.*;
+
+import static java.util.Calendar.*;
+
+// Usage: java RollDayOfWeekTest [pastYears futureYears]
+public class RollDayOfWeekTest {
+    public static void main(String[] args) {
+        int pastYears = 5, futureYears = 23;
+        if (args.length == 2) {
+            pastYears = Integer.parseInt(args[0]);
+            pastYears = Math.max(1, Math.min(pastYears, 5));
+            futureYears = Integer.parseInt(args[1]);
+            futureYears = Math.max(1, Math.min(futureYears, 28));
+        }
+
+        System.out.printf("Test [%d .. %+d] year range.%n", -pastYears, futureYears);
+        Calendar cal = new GregorianCalendar();
+        int year = cal.get(YEAR) - pastYears;
+
+        // Use the all combinations of firstDayOfWeek and
+        // minimalDaysInFirstWeek values in the year range current
+        // year - pastYears to current year + futureYears.
+        for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) {
+            for (int mdifw = 1; mdifw <= 7; mdifw++) {
+                cal.clear();
+                cal.setFirstDayOfWeek(fdw);
+                cal.setMinimalDaysInFirstWeek(mdifw);
+                cal.set(year, JANUARY, 1);
+                checkRoll(cal, futureYears);
+            }
+        }
+
+        // testing roll from BCE to CE
+        year = -1;
+        for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) {
+            for (int mdifw = 1; mdifw <= 7; mdifw++) {
+                cal.clear();
+                cal.setFirstDayOfWeek(fdw);
+                cal.setMinimalDaysInFirstWeek(mdifw);
+                cal.set(year, JANUARY, 1);
+                checkRoll(cal, 4);
+            }
+        }
+    }
+
+
+    static void checkRoll(Calendar cal, int years) {
+        Calendar cal2 = null, cal3 = null, prev = null;
+        // Check 28 years
+        for (int x = 0; x < (int)(365.2425*years); x++) {
+            cal2 = (Calendar) cal.clone();
+            cal3 = (Calendar) cal.clone();
+
+            // roll foreword
+            for (int i = 0; i < 10; i++) {
+                prev = (Calendar) cal2.clone();
+                cal2.roll(Calendar.DAY_OF_WEEK, +1);
+                roll(cal3, +1);
+                long t2 = cal2.getTimeInMillis();
+                long t3 = cal3.getTimeInMillis();
+                if (t2 != t3) {
+                    System.err.println("prev: " + prev.getTime() + "\n" + prev);
+                    System.err.println("cal2: " + cal2.getTime() + "\n" + cal2);
+                    System.err.println("cal3: " + cal3.getTime() + "\n" + cal3);
+                    throw new RuntimeException("+1: t2=" + t2 + ", t3=" + t3);
+                }
+            }
+
+            // roll backward
+            for (int i = 0; i < 10; i++) {
+                prev = (Calendar) cal2.clone();
+                cal2.roll(Calendar.DAY_OF_WEEK, -1);
+                roll(cal3, -1);
+                long t2 = cal2.getTimeInMillis();
+                long t3 = cal3.getTimeInMillis();
+                if (t2 != t3) {
+                    System.err.println("prev: " + prev.getTime() + "\n" + prev);
+                    System.err.println("cal2: " + cal2.getTime() + "\n" + cal2);
+                    System.err.println("cal3: " + cal3.getTime() + "\n" + cal3);
+                    throw new RuntimeException("-1: t2=" + t2 + ", t3=" + t3);
+                }
+            }
+            cal.add(DAY_OF_YEAR, +1);
+        }
+    }
+
+    // Another way to roll within the same week.
+    static void roll(Calendar cal, int n) {
+        int doy = cal.get(DAY_OF_YEAR);
+        int diff = cal.get(DAY_OF_WEEK) - cal.getFirstDayOfWeek();
+        if (diff < 0) {
+            diff += 7;
+        }
+
+        // dow1: first day of the week
+        int dow1 = doy - diff;
+        n %= 7;
+        doy += n;
+        if (doy < dow1) {
+            doy += 7;
+        } else if (doy >= dow1 + 7) {
+            doy -= 7;
+        }
+        cal.set(DAY_OF_YEAR, doy);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/StampOverflow.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4404619 6348819
+ * @summary Make sure that Calendar doesn't cause nextStamp overflow.
+ */
+
+import java.lang.reflect.*;
+import java.util.*;
+import static java.util.Calendar.*;
+
+// Calendar fails when turning negative to positive (zero), not
+// positive to negative with nextStamp. If a negative value was set to
+// nextStamp, it would fail even with the fix. So, there's no way to
+// reproduce the symptom in a short time -- at leaset it would take a
+// couple of hours even if we started with Integer.MAX_VALUE. So, this
+// test case just checks that set() calls don't cause any nextStamp
+// overflow.
+
+public class StampOverflow {
+    public static void main(String[] args) throws IllegalAccessException {
+        // Get a Field for "nextStamp".
+        Field nextstamp = null;
+        try {
+            nextstamp = Calendar.class.getDeclaredField("nextStamp");
+        } catch (NoSuchFieldException e) {
+            throw new RuntimeException("implementation changed?", e);
+        }
+
+        nextstamp.setAccessible(true);
+
+        Calendar cal = new GregorianCalendar();
+        int initialValue = nextstamp.getInt(cal);
+        // Set nextStamp to a very large number
+        nextstamp.setInt(cal, Integer.MAX_VALUE - 100);
+
+        for (int i = 0; i < 1000; i++) {
+            invoke(cal);
+            int stampValue = nextstamp.getInt(cal);
+            // nextStamp must not be less than initialValue.
+            if (stampValue < initialValue) {
+                throw new RuntimeException("invalid nextStamp: " + stampValue);
+            }
+        }
+    }
+
+    static void invoke(Calendar cal) {
+        cal.clear();
+        cal.set(2000, NOVEMBER, 2, 0, 0, 0);
+        int y = cal.get(YEAR);
+        int m = cal.get(MONTH);
+        int d = cal.get(DAY_OF_MONTH);
+        if (y != 2000 || m != NOVEMBER || d != 2) {
+            throw new RuntimeException("wrong date produced ("
+                                       + y + "/" + (m+1) + "/" + d + ")");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/ZoneOffsets.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6231602
+ * @summary Make sure that ZONE_OFFSET and/or DST_OFFSET setting is
+ * taken into account for time calculations.
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+public class ZoneOffsets {
+    // This TimeZone always returns the dstOffset value.
+    private static class TestTimeZone extends TimeZone {
+        private int gmtOffset;
+        private int dstOffset;
+
+        TestTimeZone(int gmtOffset, String id, int dstOffset) {
+            this.gmtOffset = gmtOffset;
+            setID(id);
+            this.dstOffset = dstOffset;
+        }
+
+        public int getOffset(int era, int year, int month, int day,
+                             int dayOfWeek, int milliseconds) {
+            return gmtOffset + dstOffset;
+        }
+
+        public int getOffset(long date) {
+            return gmtOffset + dstOffset;
+        }
+
+        public void setRawOffset(int offsetMillis) {
+            gmtOffset = offsetMillis;
+        }
+
+        public int getRawOffset() {
+            return gmtOffset;
+        }
+
+        public int getDSTSavings() {
+            return dstOffset;
+        }
+
+        public boolean useDaylightTime() {
+            return dstOffset != 0;
+        }
+
+        public boolean inDaylightTime(Date date) {
+            return dstOffset != 0;
+        }
+
+        public String toString() {
+            return "TestTimeZone[" + getID() + ", " + gmtOffset + ", " + dstOffset + "]";
+        }
+    }
+
+    private static Locale[] locales = {
+        Locale.getDefault(),
+        new Locale("th", "TH"),
+        new Locale("ja", "JP", "JP"),
+    };
+
+    private static final int HOUR = 60 * 60 * 1000;
+
+    private static int[][] offsets = {
+        { 0, 0 },
+        { 0, HOUR },
+        { 0, 2 * HOUR },
+        { -8 * HOUR, 0 },
+        { -8 * HOUR, HOUR },
+        { -8 * HOUR, 2 * HOUR },
+        { 9 * HOUR, 0 },
+        { 9 * HOUR, HOUR },
+        { 9 * HOUR, 2 * HOUR },
+    };
+
+    public static void main(String[] args) {
+        for (int l = 0; l < locales.length; l++) {
+            Locale loc = locales[l];
+            for (int i = 0; i < offsets.length; i++) {
+                test(loc, offsets[i][0], offsets[i][1]);
+            }
+        }
+
+        // The test case in the bug report.
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.setLenient(false);
+        cal.setGregorianChange(new Date(Long.MIN_VALUE));
+        cal.clear();
+        cal.set(ZONE_OFFSET, 0);
+        cal.set(DST_OFFSET, 0);
+        cal.set(ERA, AD);
+        cal.set(2004, FEBRUARY, 3, 0, 0, 0);
+        cal.set(MILLISECOND, 0);
+        // The following line should not throw an IllegalArgumentException.
+        cal.getTime();
+    }
+
+    private static void test(Locale loc, int gmtOffset, int dstOffset) {
+        TimeZone tz1 = new TestTimeZone(gmtOffset,
+                                        "GMT" + (gmtOffset/HOUR) + "." + (dstOffset/HOUR),
+                                        dstOffset);
+        int someDifferentOffset = gmtOffset + 2 * HOUR;
+        TimeZone tz2 = new TestTimeZone(someDifferentOffset,
+                                        "GMT"+ (someDifferentOffset/HOUR) + "." + (dstOffset/HOUR),
+                                        dstOffset);
+
+        int someDifferentDSTOffset = dstOffset == 2 * HOUR ? HOUR : dstOffset + HOUR;
+        TimeZone tz3 = new TestTimeZone(gmtOffset,
+                                        "GMT"+ (gmtOffset/HOUR) + "." + (someDifferentDSTOffset/HOUR),
+                                        someDifferentDSTOffset);
+
+        // cal1 is the base line.
+        Calendar cal1 = Calendar.getInstance(tz1, loc);
+        cal1.clear();
+        cal1.set(2005, MARCH, 11);
+        long t1 = cal1.getTime().getTime();
+        int gmt = cal1.get(ZONE_OFFSET);
+        int dst = cal1.get(DST_OFFSET);
+
+        // Test 8 cases with cal2.
+        Calendar cal2 = Calendar.getInstance(tz2, loc);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test1: set only ZONE_OFFSET
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) {
+            error("Test1", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz3);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test2: set only DST_OFFSET
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) {
+            error("Test2", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz2);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test3: set both ZONE_OFFSET and DST_OFFSET
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime()) {
+            error("Test3", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz3);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test4: set both ZONE_OFFSET and DST_OFFSET
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime()) {
+            error("Test4", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        // Test the same thing in non-lenient
+        cal2.setLenient(false);
+
+        cal2.setTimeZone(tz2);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test5: set only ZONE_OFFSET in non-lenient
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) {
+            error("Test5", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz3);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test6: set only DST_OFFSET in non-lenient
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) {
+            error("Test6", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz2);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test7: set both ZONE_OFFSET and DST_OFFSET in non-lenient
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime()) {
+            error("Test7", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+
+        cal2.setTimeZone(tz3);
+        cal2.clear();
+        cal2.set(2005, MARCH, 11);
+        // test8: set both ZONE_OFFSET and DST_OFFSET in non-lenient
+        cal2.set(ZONE_OFFSET, gmtOffset);
+        cal2.set(DST_OFFSET, dstOffset);
+        if (t1 != cal2.getTime().getTime()) {
+            error("Test8", loc, cal2, gmtOffset, dstOffset, t1);
+        }
+    }
+
+    private static void error(String msg, Locale loc, Calendar cal2, int gmtOffset, int dstOffset, long t1) {
+        System.err.println(cal2);
+        throw new RuntimeException(msg + ": Locale=" + loc
+                                   + ", gmtOffset=" + gmtOffset + ", dstOffset=" + dstOffset
+                                   + ", cal1 time=" + t1 + ", cal2 time=" + cal2.getTime().getTime());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4028518.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4028518
+ * @summary Make sure cloned GregorianCalendar is unchanged by modifying its original.
+ */
+
+import java.util.GregorianCalendar ;
+import static java.util.Calendar.*;
+
+public class bug4028518 {
+
+    public static void main(String[] args)
+    {
+        GregorianCalendar cal1 = new GregorianCalendar() ;
+        GregorianCalendar cal2 = (GregorianCalendar) cal1.clone() ;
+
+        printdate(cal1, "cal1: ") ;
+        printdate(cal2, "cal2 - cloned(): ") ;
+        cal1.add(DAY_OF_MONTH, 1) ;
+        printdate(cal1, "cal1 after adding 1 day: ") ;
+        printdate(cal2, "cal2 should be unmodified: ") ;
+        if (cal1.get(DAY_OF_MONTH) == cal2.get(DAY_OF_MONTH)) {
+            throw new RuntimeException("cloned GregorianCalendar modified");
+        }
+    }
+
+    private static void printdate(GregorianCalendar cal, String string)
+    {
+        System.out.println(string + (cal.get(MONTH) + 1)
+                           + "/" + cal.get(DAY_OF_MONTH)
+                           + "/" + cal.get(YEAR)) ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4100311.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4100311
+ * @summary Make sure set(DAY_OF_YEAR, 1) works.
+ */
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Date;
+
+public class bug4100311
+{
+    @SuppressWarnings("deprecation")
+    public static void main(String args[])
+    {
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.set(Calendar.YEAR, 1997);
+        cal.set(Calendar.DAY_OF_YEAR, 1);
+        Date d = cal.getTime();             // Should be Jan 1
+        if (d.getMonth() != 0 || d.getDate() != 1) {
+            throw new RuntimeException("Date isn't Jan 1");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4243802.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4243802
+ * @summary confirm that Calendar.setTimeInMillis() and
+ * getTimeInMillis() can be called from a user program. (They used to
+ * be protected methods.)
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+public class bug4243802 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new bug4243802().run(args);
+    }
+
+    /**
+     * 4243802: RFE: need way to set the date of a calendar without a Date object
+     */
+    public void Test4243802() {
+        TimeZone saveZone = TimeZone.getDefault();
+        Locale saveLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(Locale.US);
+            TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+
+            Calendar cal1 = Calendar.getInstance();
+            Calendar cal2 = Calendar.getInstance();
+
+            cal1.clear();
+            cal2.clear();
+            cal1.set(2001, Calendar.JANUARY, 25, 1, 23, 45);
+            cal2.setTimeInMillis(cal1.getTimeInMillis());
+            if ((cal2.get(Calendar.YEAR) != 2001) ||
+                (cal2.get(Calendar.MONTH) != Calendar.JANUARY) ||
+                (cal2.get(Calendar.DAY_OF_MONTH) != 25) ||
+                (cal2.get(Calendar.HOUR_OF_DAY) != 1) ||
+                (cal2.get(Calendar.MINUTE) != 23) ||
+                (cal2.get(Calendar.SECOND) != 45) ||
+                (cal2.get(Calendar.MILLISECOND) != 0)) {
+                 errln("Failed: expected 1/25/2001 1:23:45.000" +
+                       ", got " + (cal2.get(Calendar.MONTH)+1) + "/" +
+                       cal2.get(Calendar.DAY_OF_MONTH) +"/" +
+                       cal2.get(Calendar.YEAR) + " " +
+                       cal2.get(Calendar.HOUR_OF_DAY) + ":" +
+                       cal2.get(Calendar.MINUTE) + ":" +
+                       cal2.get(Calendar.SECOND) + "." +
+                       toMillis(cal2.get(Calendar.MILLISECOND)));
+            }
+            logln("Passed.");
+        }
+        finally {
+            Locale.setDefault(saveLocale);
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    private String toMillis(int m) {
+        StringBuffer sb = new StringBuffer();
+        if (m < 100) {
+            sb.append('0');
+        }
+        if (m < 10) {
+            sb.append('0');
+        }
+        sb.append(m);
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4316678.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.util.*;
+import java.text.*;
+
+/**
+ * @test
+ * @bug 4316678
+ * @summary test that Calendar's Serializasion works correctly.
+ * @library /java/text/testlib
+ */
+public class bug4316678 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new bug4316678().run(args);
+    }
+
+    public void Test4316678() throws Exception {
+        GregorianCalendar gc1;
+        GregorianCalendar gc2;
+        TimeZone saveZone = TimeZone.getDefault();
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+            gc1 = new GregorianCalendar(2000, Calendar.OCTOBER, 10);
+            try (ObjectOutputStream out
+                    = new ObjectOutputStream(new FileOutputStream("bug4316678.ser"))) {
+                out.writeObject(gc1);
+            }
+
+            try (ObjectInputStream in
+                    = new ObjectInputStream(new FileInputStream("bug4316678.ser"))) {
+                gc2 = (GregorianCalendar)in.readObject();
+            }
+
+            gc1.set(Calendar.DATE, 16);
+            gc2.set(Calendar.DATE, 16);
+            if (!gc1.getTime().equals(gc2.getTime())) {
+                errln("Invalid Time :" + gc2.getTime() +
+                    ", expected :" + gc1.getTime());
+            }
+        } finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4372743.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4372743
+ * @summary test that checks transitions of ERA and YEAR which are caused by add(MONTH).
+ * @library /java/text/testlib
+ */
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import static java.util.GregorianCalendar.*;
+
+public class bug4372743 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new bug4372743().run(args);
+    }
+
+    private int[][] data = {
+            {AD, 2, MARCH},
+            {AD, 2, FEBRUARY},
+            {AD, 2, JANUARY},
+            {AD, 1, DECEMBER},
+            {AD, 1, NOVEMBER},
+            {AD, 1, OCTOBER},
+            {AD, 1, SEPTEMBER},
+            {AD, 1, AUGUST},
+            {AD, 1, JULY},
+            {AD, 1, JUNE},
+            {AD, 1, MAY},
+            {AD, 1, APRIL},
+            {AD, 1, MARCH},
+            {AD, 1, FEBRUARY},
+            {AD, 1, JANUARY},
+            {BC, 1, DECEMBER},
+            {BC, 1, NOVEMBER},
+            {BC, 1, OCTOBER},
+            {BC, 1, SEPTEMBER},
+            {BC, 1, AUGUST},
+            {BC, 1, JULY},
+            {BC, 1, JUNE},
+            {BC, 1, MAY},
+            {BC, 1, APRIL},
+            {BC, 1, MARCH},
+            {BC, 1, FEBRUARY},
+            {BC, 1, JANUARY},
+            {BC, 2, DECEMBER},
+            {BC, 2, NOVEMBER},
+            {BC, 2, OCTOBER},
+        };
+    private int tablesize = data.length;
+
+    private void check(GregorianCalendar gc, int index) {
+        if (gc.get(ERA) != data[index][ERA]) {
+            errln("Invalid era :" + gc.get(ERA) +
+                ", expected :" + data[index][ERA]);
+        }
+        if (gc.get(YEAR) != data[index][YEAR]) {
+            errln("Invalid year :" + gc.get(YEAR) +
+                ", expected :" + data[index][YEAR]);
+        }
+        if (gc.get(MONTH) != data[index][MONTH]) {
+            errln("Invalid month :" + gc.get(MONTH) +
+                ", expected :" + data[index][MONTH]);
+        }
+    }
+
+    public void Test4372743() {
+        GregorianCalendar gc;
+        TimeZone saveZone = TimeZone.getDefault();
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+            /* Set March 3, A.D. 2 */
+            gc  = new GregorianCalendar(2, MARCH, 3);
+            for (int i = 0; i < tablesize; i++) {
+                check(gc, i);
+                gc.add(gc.MONTH, -1);
+            }
+
+            /* Again, Set March 3, A.D. 2 */
+            gc  = new GregorianCalendar(2, MARCH, 3);
+            for (int i = 0; i < tablesize; i+=7) {
+                check(gc, i);
+                gc.add(gc.MONTH, -7);
+            }
+
+            /* Set March 10, 2 B.C. */
+            gc  = new GregorianCalendar(2, OCTOBER, 10);
+            gc.add(gc.YEAR, -3);
+            for (int i = tablesize -1; i >= 0; i--) {
+                check(gc, i);
+                gc.add(gc.MONTH, 1);
+            }
+
+            /* Again, Set March 10, 2 B.C. */
+            gc  = new GregorianCalendar(2, OCTOBER, 10);
+            gc.add(gc.YEAR, -3);
+            for (int i = tablesize -1; i >= 0; i-=8) {
+                check(gc, i);
+                gc.add(gc.MONTH, 8);
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4401223.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4401223
+ * @summary Make sure that GregorianCalendar doesn't cause IllegalArgumentException at some special situations which are related to the Leap Year.
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+public class bug4401223 extends IntlTest {
+
+    public void Test4401223a() {
+        int status = 0;
+        String s = null;
+
+        try {
+            Date date = new Date(2000-1900, Calendar.FEBRUARY, 29);
+            GregorianCalendar gc = new GregorianCalendar();
+            gc.setTime(date);
+            gc.setLenient(false);
+            gc.set(Calendar.YEAR, 2001);
+            s = "02/29/00 & set(YEAR,2001) = " + gc.getTime().toString();
+        } catch (Exception ex) {
+            status++;
+            s = "Exception occurred for 2/29/00 & set(YEAR,2001): " + ex;
+        }
+        if (status > 0) {
+            errln(s);
+        } else {
+            logln(s);
+        }
+    }
+
+    public void Test4401223b() {
+        int status = 0;
+        String s = null;
+
+        try {
+            Date date = new Date(2000-1900, Calendar.DECEMBER, 31);
+            GregorianCalendar gc = new GregorianCalendar();
+            gc.setTime(date);
+            gc.setLenient(false);
+            gc.set(Calendar.YEAR, 2001);
+
+            if (gc.get(Calendar.YEAR) != 2001 ||
+                gc.get(Calendar.MONTH) != Calendar.DECEMBER ||
+                gc.get(Calendar.DATE) != 31 ||
+                gc.get(Calendar.DAY_OF_YEAR) != 365) {
+                status++;
+                s = "Wrong Date : 12/31/00 & set(YEAR,2001) ---> " + gc.getTime().toString();
+            } else {
+                s = "12/31/00 & set(YEAR,2001) = " + gc.getTime().toString();
+            }
+        } catch (Exception ex) {
+            status++;
+            s = "Exception occurred for 12/31/00 & set(YEAR,2001) : " + ex;
+        }
+        if (status > 0) {
+            errln(s);
+        } else {
+            logln(s);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        new bug4401223().run(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4409072.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4409072
+ * @summary tests for set(), add(), and roll() with various week parameters.
+ * @library /java/text/testlib
+ */
+
+import  java.util.*;
+import static java.util.Calendar.*;
+
+public class bug4409072 extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new bug4409072().run(args);
+    }
+
+    /* Confirm some public methods' behavior in Calendar.
+     * (e.g. add(), roll(), set())
+     */
+    public void Test4409072() {
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTZ = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            testSet();
+            testAdd();
+            testRoll();
+        } finally {
+            TimeZone.setDefault(savedTZ);
+            Locale.setDefault(savedLocale);
+        }
+    }
+
+    /*
+     * Golden data for set() test
+     */
+    static final int[][][] resultWOMForSetTest = {
+        { /* For year1998 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11},
+          /* Mon */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11},
+          /* Tue */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+          /* Wed */ {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+          /* Thu */ {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+          /* Fri */ {10,27}, {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+          /* Sat */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, {11,11},
+        },
+        { /* For year1999 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10},
+          /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10},
+          /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10},
+          /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10},
+        },
+        { /* For year2000 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+          /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+          /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8},
+          /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8},
+          /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8},
+          /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1},
+          /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+        },
+        { /* For year2001 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+          /* Mon */ {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+          /* Tue */ {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+          /* Wed */ {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7},
+          /* Thu */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7},
+          /* Fri */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7},
+          /* Sat */ {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+        },
+        { /* For year2002 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+          /* Mon */ {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+          /* Tue */ {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+          /* Wed */ {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+          /* Thu */ {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6},
+          /* Fri */ {10,29}, {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6},
+          /* Sat */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11,13},
+        },
+        { /* For year2003 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12},
+          /* Mon */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+          /* Tue */ {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+          /* Wed */ {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+          /* Thu */ {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+          /* Fri */ {10,28}, {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5},
+          /* Sat */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, {11,12},
+        },
+        { /* For year2004 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10},
+          /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10},
+          /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10},
+          /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+          /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10},
+        },
+        { /* For year2005 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9},
+          /* Mon */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9},
+          /* Tue */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9},
+          /* Wed */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9},
+          /* Thu */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2},
+          /* Fri */ {10,25}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2},
+          /* Sat */ {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, {11, 9},
+        },
+        { /* For year2006 */
+          /* Min =     1        2        3        4        5        6        7  */
+          /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+          /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+          /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8},
+          /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8},
+          /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8},
+          /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1},
+          /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+        },
+    };
+
+    static final int[][][] resultWOYForSetTest1 = {
+        { /* For year1998 */
+            /* FirstDayOfWeek = Sunday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9},
+              {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+            /* FirstDayOfWeek = Monday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+              {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+            /* FirstDayOfWeek = Tuesday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+              {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9},
+            /* FirstDayOfWeek = Wednesday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9},
+            /* FirstDayOfWeek = Thursday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+            /* FirstDayOfWeek = Friday */
+              {1997,11,26}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+            /* FirstDayOfWeek = Saturday */
+              {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9},
+              {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+        },
+        { /* For year1999 */
+            /* FirstDayOfWeek = Sunday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8},
+              {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+            /* FirstDayOfWeek = Monday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8},
+              {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+            /* FirstDayOfWeek = Tuesday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+              {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+            /* FirstDayOfWeek = Wednesday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+              {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8},
+            /* FirstDayOfWeek = Thursday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8},
+            /* FirstDayOfWeek = Friday */
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+              {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+            /* FirstDayOfWeek = Saturday */
+              {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+              {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+        },
+        { /* For year2000 */
+            /* FirstDayOfWeek = Sunday */
+              {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+            /* FirstDayOfWeek = Monday */
+              {1999,11,31}, {1999,11,31}, {2000, 0, 7}, {2000, 0, 7},
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+            /* FirstDayOfWeek = Tuesday */
+              {1999,11,31}, {1999,11,31}, {1999,11,31}, {2000, 0, 7},
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+            /* FirstDayOfWeek = Wednesday */
+              {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+            /* FirstDayOfWeek = Thursday */
+              {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+              {1999,11,31}, {2000, 0, 7}, {2000, 0, 7},
+            /* FirstDayOfWeek = Friday */
+              {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+              {1999,11,31}, {1999,11,31}, {2000, 0, 7},
+            /* FirstDayOfWeek = Saturday */
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+              {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+        },
+        { /* For year2001 */
+            /* FirstDayOfWeek = Sunday */
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0,12},
+            /* FirstDayOfWeek = Monday */
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+            /* FirstDayOfWeek = Tuesday */
+              {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+            /* FirstDayOfWeek = Wednesday */
+              {2000,11,29}, {2000,11,29}, {2001, 0, 5}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+            /* FirstDayOfWeek = Thursday */
+              {2000,11,29}, {2000,11,29}, {2000,11,29}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+            /* FirstDayOfWeek = Friday */
+              {2000,11,29}, {2000,11,29}, {2000,11,29}, {2000,11,29},
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+            /* FirstDayOfWeek = Saturday */
+              {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+              {2001, 0, 5}, {2001, 0,12}, {2001, 0,12},
+        },
+        { /* For year2002 */
+            /* FirstDayOfWeek = Sunday */
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0,11}, {2002, 0,11},
+            /* FirstDayOfWeek = Monday */
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0,11},
+            /* FirstDayOfWeek = Tuesday */
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+            /* FirstDayOfWeek = Wednesday */
+              {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+            /* FirstDayOfWeek = Thursday */
+              {2001,11,28}, {2001,11,28}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+            /* FirstDayOfWeek = Friday */
+              {2001,11,28}, {2001,11,28}, {2001,11,28}, {2002, 0, 4},
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+            /* FirstDayOfWeek = Saturday */
+              {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+              {2002, 0,11}, {2002, 0,11}, {2002, 0,11},
+        },
+        { /* For year2003 */
+            /* FirstDayOfWeek = Sunday */
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0,10}, {2003, 0,10}, {2003, 0,10},
+            /* FirstDayOfWeek = Monday */
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0, 3}, {2003, 0,10}, {2003, 0,10},
+            /* FirstDayOfWeek = Tuesday */
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10},
+            /* FirstDayOfWeek = Wednesday */
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+            /* FirstDayOfWeek = Thursday */
+              {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+            /* FirstDayOfWeek = Friday */
+              {2002,11,27}, {2002,11,27}, {2003, 0, 3}, {2003, 0, 3},
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+            /* FirstDayOfWeek = Saturday */
+              {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10},
+              {2003, 0,10}, {2003, 0,10}, {2003, 0,10},
+        },
+        { /* For year2004 */
+            /* FirstDayOfWeek = Sunday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9},
+              {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+            /* FirstDayOfWeek = Monday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+              {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+            /* FirstDayOfWeek = Tuesday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+              {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9},
+            /* FirstDayOfWeek = Wednesday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9},
+            /* FirstDayOfWeek = Thursday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+            /* FirstDayOfWeek = Friday */
+              {2003,11,26}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+            /* FirstDayOfWeek = Saturday */
+              {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9},
+              {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+        },
+        { /* For year2005 */
+            /* FirstDayOfWeek = Sunday */
+              {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+            /* FirstDayOfWeek = Monday */
+              {2004,11,31}, {2004,11,31}, {2005, 0, 7}, {2005, 0, 7},
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+            /* FirstDayOfWeek = Tuesday */
+              {2004,11,31}, {2004,11,31}, {2004,11,31}, {2005, 0, 7},
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+            /* FirstDayOfWeek = Wednesday */
+              {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+            /* FirstDayOfWeek = Thursday */
+              {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+              {2004,11,31}, {2005, 0, 7}, {2005, 0, 7},
+            /* FirstDayOfWeek = Friday */
+              {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+              {2004,11,31}, {2004,11,31}, {2005, 0, 7},
+            /* FirstDayOfWeek = Saturday */
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+              {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+        },
+        { /* For year2006 */
+            /* FirstDayOfWeek = Sunday */
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Monday */
+              {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Tuesday */
+              {2005,11,30}, {2005,11,30}, {2006, 0, 6}, {2006, 0, 6},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Wednesday */
+              {2005,11,30}, {2005,11,30}, {2005,11,30}, {2006, 0, 6},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Thursday */
+              {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Friday */
+              {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30},
+              {2005,11,30}, {2006, 0, 6}, {2006, 0, 6},
+            /* FirstDayOfWeek = Saturday */
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+              {2006, 0, 6}, {2006, 0, 6}, {2006, 0,13},
+        }
+    };
+
+    static final int[][] resultWOYForSetTest2 = {
+          /* Min =    1       2       3       4       5       6       7  */
+          /* Sun */ {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+          /* Mon */ {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+          /* Tue */ {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+          /* Wed */ {4,25}, {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1},
+          /* Thu */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, {5, 8},
+          /* Fri */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8},
+          /* Sat */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+    };
+
+    /**
+     * Test for set()
+     */
+    void testSet() {
+        boolean noerror = true;
+        Calendar cal = Calendar.getInstance();
+        int sYear=1998;
+        int eYear=2006;
+
+        // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+        for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+            // Loop for MinimalDaysInFirstWeek: 1..7
+            for (int minDow = 1; minDow <= 7; minDow++) {
+                int index = (dow-1)*7 + (minDow-1);
+
+                cal.clear();
+                cal.setLenient(true);
+                cal.setMinimalDaysInFirstWeek(minDow);
+                cal.setFirstDayOfWeek(dow);
+                cal.set(YEAR, 2005);
+                cal.set(DAY_OF_WEEK, WEDNESDAY);
+                cal.set(WEEK_OF_YEAR, 22);
+
+                int y = 2005;
+                int m = resultWOYForSetTest2[index][0];
+                int d = resultWOYForSetTest2[index][1];
+                int year = cal.get(YEAR);
+                int month = cal.get(MONTH);
+                int date = cal.get(DATE);
+
+                if (cal.get(WEEK_OF_YEAR) != 22) {
+                    noerror = false;
+                    errln("Failed : set(WEEK_OF_YEAR=22)" +
+                          " *** get(WEEK_OF_YEAR=" +
+                          cal.get(WEEK_OF_YEAR) + ")" +
+                          ", got " + (month+1)+"/"+date+"/"+year +
+                          ", expected " + (m+1)+"/"+d+"/"+2005 +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                } else if ((year != y) || (month != m) || (date != d)) {
+                    noerror = false;
+                    errln("Failed : set(WEEK_OF_YEAR=22)" +
+                          " got " + (month+1)+"/"+date+"/"+year +
+                          ", expected " + (m+1)+"/"+d+"/"+y +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+
+                for (int targetYear = sYear; targetYear<= eYear; targetYear++) {
+                    cal.clear();
+                    cal.setLenient(true);
+                    cal.setMinimalDaysInFirstWeek(minDow);
+                    cal.setFirstDayOfWeek(dow);
+                    cal.set(YEAR, targetYear);
+                    cal.set(DAY_OF_WEEK, FRIDAY);
+                    cal.set(MONTH, DECEMBER);
+                    cal.set(WEEK_OF_MONTH, 1);
+
+                    y = targetYear;
+                    m = resultWOMForSetTest[targetYear-sYear][index][0];
+                    d = resultWOMForSetTest[targetYear-sYear][index][1];
+                    year = cal.get(YEAR);
+                    month = cal.get(MONTH);
+                    date = cal.get(DATE);
+
+                    if ((year != y) || (month != m) || (date != d)) {
+                        noerror = false;
+                        errln("Failed : set(WEEK_OF_MONTH=1)" +
+                              " got " + (month+1)+"/"+date+"/"+year +
+                              ", expected " + (m+1)+"/"+d+"/"+y +
+                              ", MinFirstDOW=" + minDow +
+                              ", FirstDOW=" + dow);
+                    }
+
+                    cal.clear();
+                    cal.setLenient(true);
+                    cal.setMinimalDaysInFirstWeek(minDow);
+                    cal.setFirstDayOfWeek(dow);
+                    cal.set(YEAR, targetYear);
+                    cal.set(DAY_OF_WEEK, FRIDAY);
+                    cal.set(WEEK_OF_YEAR, 1);
+
+                    y = resultWOYForSetTest1[targetYear-sYear][index][0];
+                    m = resultWOYForSetTest1[targetYear-sYear][index][1];
+                    d = resultWOYForSetTest1[targetYear-sYear][index][2];
+                    year = cal.get(YEAR);
+                    month = cal.get(MONTH);
+                    date = cal.get(DATE);
+
+                    if (cal.get(WEEK_OF_YEAR) != 1) {
+                        noerror = false;
+                        errln("Failed : set(WEEK_OF_YEAR=1)" +
+                              " *** get(WEEK_OF_YEAR=" +
+                              cal.get(WEEK_OF_YEAR) + ")" +
+                              ", got " + (month+1)+"/"+date+"/"+year +
+                              ", expected " + (m+1)+"/"+d+"/"+y +
+                              ", MinFirstDOW=" + minDow +
+                              ", FirstDOW=" + dow);
+                    } else if ((year != y) || (month != m) || (date != d)) {
+                        noerror = false;
+                        errln("Failed : set(WEEK_OF_YEAR=1)" +
+                              " got " + (month+1)+"/"+date+"/"+year +
+                              ", expected " + (m+1)+"/"+d+"/"+y +
+                              ", MinFirstDOW=" + minDow +
+                              ", FirstDOW=" + dow);
+                    }
+                }
+            }
+        }
+
+        if (noerror) {
+            logln("Passed : set() test");
+        }
+    }
+
+    /**
+     * Test for add()
+     */
+    void testAdd() {
+        boolean noerror = true;
+        Calendar cal = Calendar.getInstance();
+
+        // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+        for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+            // Loop for MinimalDaysInFirstWeek: 1..7
+            for (int minDow = 1; minDow <= 7; minDow++) {
+                int oldWOY, newWOY;
+
+                cal.clear();
+                cal.setLenient(true);
+                cal.setMinimalDaysInFirstWeek(minDow);
+                cal.setFirstDayOfWeek(dow);
+                cal.set(2005, DECEMBER, 7);
+                oldWOY = cal.get(WEEK_OF_YEAR);
+
+                for (int cnt = 0; cnt < 7; cnt++) {
+                    cal.add(WEEK_OF_YEAR, 1);
+                }
+
+                int year = cal.get(YEAR);
+                int month = cal.get(MONTH);
+                int date = cal.get(DATE);
+
+                if ((year != 2006) || (month != 0) || (date != 25)) {
+                    noerror = false;
+                    errln("Failed : add(WEEK_OF_YEAR+1)" +
+                          " got " + (month+1)+"/"+date+"/"+year +
+                          ", expected 1/25/2006" +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+
+                for (int cnt = 0; cnt < 10; cnt++) {
+                    cal.add(WEEK_OF_YEAR, -1);
+                }
+                newWOY = cal.get(WEEK_OF_YEAR);
+
+                year = cal.get(YEAR);
+                month = cal.get(MONTH);
+                date = cal.get(DATE);
+
+                if ((oldWOY - newWOY) != 3) {
+                    errln("Failed : add(WEEK_OF_YEAR-1)" +
+                          " got " + (month+1)+"/"+date+"/"+year +
+                          ", expected 11/16/2005" +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow +
+                          ", WEEK_OF_YEAR=" + newWOY +
+                          " should be " + (oldWOY-3));
+                } else if ((year != 2005) || (month != 10) || (date != 16)) {
+                    errln("Failed : add(-1)" +
+                          " got " + (month+1)+"/"+date+"/"+year +
+                          ", expected 11/16/2005" +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+            }
+        }
+
+        if (noerror) {
+            logln("Passed : add() test");
+        }
+    }
+
+    /*
+     * Golden data for roll() test
+     */
+    static final int[] resultWOMForRollTest = {
+          /* Min =    1   2   3   4   5   6   7  */
+          /* Sun */   1,  1,  1, 26, 26, 26, 26,
+          /* Mon */   1,  1,  1,  1, 26, 26, 26,
+          /* Tue */  31, 31, 31, 31, 31, 24, 24,
+          /* Wed */  31, 31, 31, 31, 31, 31, 24,
+          /* Thu */  31, 31, 31, 31, 31, 31, 31,
+          /* Fri */   1, 31, 31, 31, 31, 31, 31,
+          /* Sat */   1,  1, 31, 31, 31, 31, 31,
+    };
+
+    static final int[][] resultWOYForRollTest = {
+          /* Min =    1       2       3       4       5       6       7  */
+          /* Sun */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+          /* Mon */ {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+          /* Tue */ {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+          /* Wed */ {1, 2}, {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26},
+          /* Thu */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, {1, 2},
+          /* Fri */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2},
+          /* Sat */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+    };
+
+    /**
+     * Test for roll()
+     */
+    void testRoll() {
+        boolean noerror = true;
+        Calendar cal = Calendar.getInstance();
+
+        // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+        for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+            // Loop for MinimalDaysInFirstWeek: 1..7
+            for (int minDow = 1; minDow <= 7; minDow++) {
+                int oldWOY, newWOY;
+                int index = (dow-1)*7 + (minDow-1);
+
+                cal.clear();
+                cal.setLenient(true);
+                cal.setMinimalDaysInFirstWeek(minDow);
+                cal.setFirstDayOfWeek(dow);
+                cal.set(2005, DECEMBER, 12);
+                oldWOY = cal.get(WEEK_OF_YEAR);
+                for (int cnt = 0; cnt < 2; cnt++) {
+                    cal.roll(WEEK_OF_MONTH, -1);
+                }
+                int y = 2005;
+                int m = DECEMBER;
+                int d = resultWOMForRollTest[index];
+                int year = cal.get(YEAR);
+                int month = cal.get(MONTH);
+                int date = cal.get(DATE);
+
+                if ((year != y) || (month != m) || (date != d)) {
+                    noerror = false;
+                    errln("Failed : roll(WEEK_OF_MONTH-1)" +
+                          " got " + (month+1) + "/" + date + "/" + year +
+                          ", expected " + (m+1) + "/" + d + "/" + y +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+
+                cal.clear();
+                cal.setLenient(true);
+                cal.setMinimalDaysInFirstWeek(minDow);
+                cal.setFirstDayOfWeek(dow);
+                cal.set(2005, DECEMBER, 7);
+                oldWOY = cal.get(WEEK_OF_YEAR);
+
+                for (int cnt = 0; cnt < 7; cnt++) {
+                    cal.roll(WEEK_OF_YEAR, 1);
+                }
+
+                y = 2005;
+                m = resultWOYForRollTest[index][0];
+                d = resultWOYForRollTest[index][1];
+                year = cal.get(YEAR);
+                month = cal.get(MONTH);
+                date = cal.get(DATE);
+
+                if ((year != y) || (month != m) || (date != d)) {
+                    noerror = false;
+                    errln("Failed : roll(WEEK_OF_YEAR+1)" +
+                          " got " + (month+1) + "/" + date + "/" + year +
+                          ", expected " + (m+1) + "/" + d + "/" + y +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+
+                for (int cnt = 0; cnt < 10; cnt++) {
+                    cal.roll(WEEK_OF_YEAR, -1);
+                }
+                newWOY = cal.get(WEEK_OF_YEAR);
+
+                y = 2005;
+                m = NOVEMBER;
+                d = 16;
+                year = cal.get(YEAR);
+                month = cal.get(MONTH);
+                date = cal.get(DATE);
+
+                if ((year != y) || (month != m) || (date != d)) {
+                    noerror = false;
+                    errln("Failed : roll(WEEK_OF_YEAR-1)" +
+                          " got " + (month+1)+"/"+date+"/"+year +
+                          ", expected " + (m+1)+"/"+d+"/"+y +
+                          ", MinFirstDOW=" + minDow +
+                          ", FirstDOW=" + dow);
+                }
+            }
+        }
+
+        if (noerror) {
+            logln("Passed : roll() test");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Calendar/bug4514831.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4514831
+ * @summary Confirm that GregorianCalendar.roll() works properly during transition from Daylight Saving Time to Standard Time.
+ */
+
+import java.util.*;
+
+public class bug4514831 {
+
+    public static void main(String[] args) {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        boolean err = false;
+
+        String golden_data1 ="27-28 28-29 29-30 30-31 31-1 1-2 2-3 ";
+        String golden_data2 ="27-28 28-29 29-30 30-31 31-25 25-26 26-27 ";
+        String golden_data3 ="1-8 8-15 15-22 22-29 29-1 1-8 8-15 ";
+
+        try {
+            Locale.setDefault(Locale.US);
+            TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific"));
+
+            String test_roll = "";
+            GregorianCalendar c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27);
+            for (int i=0; i < 7; i++) {
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+                c_roll.roll(c_roll.DAY_OF_YEAR, true);
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+            }
+            if (!test_roll.equals(golden_data1)) {
+                err = true;
+                System.err.println("Wrong roll(DAY_OF_YEAR) transition: got "+
+                                   test_roll + "expected " + golden_data1);
+            }
+
+            test_roll = "";
+            c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27);
+            c_roll.setFirstDayOfWeek(Calendar.THURSDAY);
+            for (int i=0; i < 7; i++) {
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+                c_roll.roll(c_roll.DAY_OF_WEEK, true);
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+            }
+            if (!test_roll.equals(golden_data2)) {
+                err = true;
+                System.err.println("Wrong roll(DAY_OF_WEEK) transition: got "+
+                                   test_roll + "expected " + golden_data2);
+            }
+
+            test_roll = "";
+            c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 1);
+            for (int i=0; i < 7; i++) {
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+                c_roll.roll(c_roll.DAY_OF_WEEK_IN_MONTH, true);
+                test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+            }
+            if (!test_roll.equals(golden_data3)) {
+                err = true;
+                System.err.println("Wrong roll(DAY_OF_WEEK_IN_MONTH) transition: got "+
+                                   test_roll + "expected " + golden_data3);
+            }
+        } finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+        }
+
+        if (err) {
+            throw new RuntimeException("Wrong roll() transition");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/Bug4955000.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4955000
+ * @summary Make sure that a Date and a GregorianCalendar produce the
+ * same date/time. Both are new implementations in 1.5.
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+@SuppressWarnings("deprecation")
+public class Bug4955000 {
+    // Tests for Date.UTC(), derived from JCK
+    // Date.miscTests.Date1025 and Date2015
+    public static void main(String[] args) {
+        TimeZone defaultTZ = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("NST"));
+            GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+            // Date1025
+            int[] years1 = {
+                Integer.MIN_VALUE,
+                Integer.MIN_VALUE + 1,
+                gc.getMinimum(YEAR) - 1,
+                gc.getMaximum(YEAR) + 1,
+                Integer.MAX_VALUE - 1,
+                Integer.MAX_VALUE
+            };
+            for (int i = 0; i < years1.length; i++) {
+                gc.clear();
+                gc.set(years1[i], gc.JANUARY, 1);
+                long t = gc.getTimeInMillis();
+                long utc = Date.UTC(years1[i] - 1900, 1-1, 1,
+                                    0, 0, 0); // Jan 1 00:00:00
+                if (t != utc) {
+                    throw new RuntimeException("t (" + t + ") != utc (" + utc +")");
+                }
+            }
+
+            // Date2015
+            int years[] = {
+                gc.getGreatestMinimum(YEAR),
+                gc.getGreatestMinimum(YEAR) + 1,
+                -1,
+                0,
+                1,
+                gc.getLeastMaximum(YEAR) - 1,
+                gc.getLeastMaximum(YEAR)
+            };
+
+            int months[] = {
+                gc.getMinimum(MONTH),
+                gc.getMinimum(MONTH) + 1,
+                gc.getMaximum(MONTH) - 1,
+                gc.getMaximum(MONTH)
+            };
+
+            int dates[] = {
+                gc.getMinimum(DAY_OF_MONTH),
+                gc.getMinimum(DAY_OF_MONTH) + 1,
+                gc.getMaximum(DAY_OF_MONTH) - 1,
+                gc.getMaximum(DAY_OF_MONTH)
+            };
+
+            int hs[] = {
+                gc.getMinimum(HOUR),
+                gc.getMinimum(HOUR) + 1,
+                gc.getMaximum(HOUR) - 1,
+                gc.getMaximum(HOUR)
+            };
+
+            int ms[] = {
+                gc.getMinimum(MINUTE),
+                gc.getMinimum(MINUTE) + 1,
+                gc.getMaximum(MINUTE) - 1,
+                gc.getMaximum(MINUTE)
+            };
+
+            int ss[] = {
+                gc.getMinimum(SECOND),
+                gc.getMinimum(SECOND) + 1,
+                gc.getMaximum(SECOND) - 1,
+                gc.getMaximum(SECOND)
+            };
+
+            for(int i = 0; i < years.length; i++) {
+                for(int j = 0; j < months.length; j++) {
+                    for(int k = 0; k < dates.length; k++) {
+                        for(int m = 0; m < hs.length; m++) {
+                            for(int n = 0; n < ms.length; n++) {
+                                for(int p = 0; p < ss.length; p++) {
+                                    int year = years[i] - 1900;
+                                    int month = months[j];
+                                    int date = dates[k];
+                                    int hours = hs[m];
+                                    int minutes = ms[n];
+                                    int seconds = ss[p];
+
+                                    long result = Date.UTC(year, month, date,
+                                                           hours, minutes, seconds);
+
+                                    gc.clear();
+                                    gc.set(year + 1900, month, date, hours, minutes, seconds);
+
+                                    long expected = gc.getTime().getTime();
+
+                                    if (expected != result) {
+                                        throw new RuntimeException("expected (" + expected
+                                                                   + ") != result (" + result +")");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            TimeZone.setDefault(defaultTZ);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/DateGregorianCalendarTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,235 @@
+/*
+ * 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
+ * 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 4614842
+ * @summary Make sure that a Date and a GregorianCalendar produce the same date/time. Both are new implementations in 1.5.
+ * @run main DateGregorianCalendarTest 15
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+// Usage: java DateGregorianCalendarTest [duration]
+
+@SuppressWarnings("deprecation")
+public class DateGregorianCalendarTest {
+    static volatile boolean runrun = true;
+    static int nThreads;
+
+    public static void main(String[] args) {
+        int duration = 600;
+        if (args.length == 1) {
+            duration = Math.max(10, Integer.parseInt(args[0]));
+        }
+
+        TimeZone savedTZ = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Thread[] t = new Thread[10]; // for future bugs...
+            int index = 0;
+            t[index++] = new Thread(new Runnable() {
+                    public void run() {
+                        GregorianCalendar gc = new GregorianCalendar();
+
+                        long delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+                        long count = 0;
+                        try {
+                            for (long t = Long.MIN_VALUE; runrun && t < Long.MAX_VALUE-delta; t += delta) {
+                                gc.setTimeInMillis(t);
+                                Date date = new Date(t);
+                                int y;
+                                if (!((y = gc.get(YEAR)) == (date.getYear()+1900) &&
+                                      gc.get(MONTH) == date.getMonth() &&
+                                      gc.get(DAY_OF_MONTH) == date.getDate() &&
+                                      gc.get(HOUR_OF_DAY) == date.getHours() &&
+                                      gc.get(MINUTE) == date.getMinutes() &&
+                                      gc.get(SECOND) == date.getSeconds())) {
+                                    throw new RuntimeException("GregorinCalendar and Date returned different dates."
+                                                               +" (millis=" + t + ")\n"
+                                                               +"GC=" + gc + "\nDate=" + date);
+                                }
+                                ++count;
+                                if (y >= 1) {
+                                    delta = (long)(365.2422 * 24 * 60 * 60 * 1000);
+                                }
+                                if (y >= 1970) {
+                                    delta = (24 * 60 * 60 * 1000);
+                                }
+                                if (y >= 2039) {
+                                    delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+                                }
+                            }
+                            if (runrun) {
+                                System.out.println("Part I (count="+count+"): Passed");
+                            } else {
+                                System.out.println("Part I (count="+count+"): Incomplete");
+                            }
+                        } catch (RuntimeException e) {
+                            System.out.println("Part I (count="+count+"): FAILED");
+                            runrun = false;
+                            throw e;
+                        } finally {
+                            decrementCounter();
+                        }
+                    }
+                });
+
+            t[index++] = new Thread(new Runnable() {
+                    public void run() {
+                        GregorianCalendar gc = new GregorianCalendar();
+
+                        long count = 0;
+                        int delta;
+                        try {
+                            for (long year = Integer.MIN_VALUE+1900;
+                                 runrun && year <= Integer.MAX_VALUE; year += delta) {
+                                checkTimes(gc, year, JANUARY, 1, 0, 0, 0);
+                                ++count;
+                                delta = getDelta((int)year);
+                            }
+
+                            for (long month = Integer.MIN_VALUE;
+                                 runrun && month <= Integer.MAX_VALUE; month += delta) {
+                                checkTimes(gc, 1900, month, 1, 0, 0, 0);
+                                ++count;
+                                delta = getDelta(gc.get(YEAR));
+                            }
+
+                            for (long dayOfMonth = Integer.MIN_VALUE;
+                                 runrun && dayOfMonth <= Integer.MAX_VALUE; dayOfMonth += delta) {
+                                checkTimes(gc, 1900, JANUARY, dayOfMonth, 0, 0, 0);
+                                ++count;
+                                delta = getDelta(gc.get(YEAR));
+                            }
+                            if (runrun) {
+                                System.out.println("Part II (count="+count+"): Passed");
+                            } else {
+                                System.out.println("Part II (count="+count+"): Incomplete");
+                            }
+                        } catch (RuntimeException e) {
+                            System.out.println("Part II (count="+count+"): FAILED");
+                            runrun = false;
+                            throw e;
+                        } finally {
+                            decrementCounter();
+                        }
+                    }
+                });
+
+            // t3 takes more than 10 minutes (on Ultra-60 450MHz) without
+            // the 4936355 fix due to getting the small delta.
+            t[index++] = new Thread(new Runnable() {
+                    public void run() {
+                        GregorianCalendar gc = new GregorianCalendar();
+
+                        long count = 0;
+                        int delta;
+                        try {
+                            for (long hourOfDay = Integer.MIN_VALUE;
+                                 runrun && hourOfDay <= Integer.MAX_VALUE; hourOfDay += delta) {
+                                checkTimes(gc, 1970, JANUARY, 1, hourOfDay, 0, 0);
+                                ++count;
+                                delta = getDelta(gc.get(YEAR));
+                            }
+                            for (long minutes = Integer.MIN_VALUE;
+                                 runrun && minutes <= Integer.MAX_VALUE; minutes += delta) {
+                                checkTimes(gc, 1970, JANUARY, 1, 0, minutes, 0);
+                                ++count;
+                                delta = getDelta(gc.get(YEAR)) * 60;
+                            }
+                            for (long seconds = Integer.MIN_VALUE;
+                                 runrun && seconds <= Integer.MAX_VALUE; seconds += delta) {
+                                checkTimes(gc, 1970, JANUARY, 1, 0, 0, seconds);
+                                ++count;
+                                delta = getDelta(gc.get(YEAR)) * 60 * 60;
+                            }
+                            if (runrun) {
+                                System.out.println("Part III (count="+count+"): Passed");
+                            } else {
+                                System.out.println("Part III (count="+count+"): Incomplete");
+                            }
+                        } catch (RuntimeException e) {
+                            System.out.println("Part III (count="+count+"): FAILED");
+                            runrun = false;
+                            throw e;
+                        } finally {
+                            decrementCounter();
+                        }
+                    }
+                });
+
+            for (int i = 0; i < index; i++) {
+                incrementCounter();
+                t[i].start();
+            }
+
+            try {
+                for (int i = 0; getCounter() > 0 && i < duration; i++) {
+                    Thread.sleep(1000);
+                }
+                runrun = false;
+                for (int i = 0; i < index; i++) {
+                    t[i].join();
+                }
+            } catch (InterruptedException e) {
+            }
+        } finally {
+            TimeZone.setDefault(savedTZ);
+        }
+    }
+
+    static void checkTimes(GregorianCalendar gc, long year, long month, long dayOfMonth,
+                           long hourOfDay, long minutes, long seconds) {
+        gc.clear();
+        gc.set((int)year, (int)month, (int)dayOfMonth, (int)hourOfDay, (int)minutes, (int)seconds);
+        long time = gc.getTimeInMillis();
+        Date date = new Date((int)year - 1900, (int)month, (int)dayOfMonth,
+                             (int)hourOfDay, (int)minutes, (int)seconds);
+        long time2 = date.getTime();
+        if (time != time2) {
+            throw new RuntimeException("GregorinCalendar and Date returned different values.\n"
+                                       +"year="+year+", month="+month+", dayOfMonth="+dayOfMonth
+                                       +"\nhourOfDay="+hourOfDay+", minutes="+minutes+", seconds="+seconds
+                                       +"\ntime=" + time + ", time2=" + time2
+                                       +"\nGC=" + gc + "\nDate=" + date);
+        }
+    }
+
+    static final int getDelta(int year) {
+        return (year >= 1970 && year <= 2039) ? 1 : 1<<13;
+    }
+
+    synchronized static void incrementCounter() {
+        nThreads++;
+    }
+
+    synchronized static void decrementCounter() {
+        nThreads--;
+    }
+
+    synchronized static int getCounter() {
+        return nThreads;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/DateRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 4136916 6274757 6314387
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+@SuppressWarnings("deprecation")
+public class DateRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new DateRegression().run(args);
+    }
+
+    /**
+     * @bug 4023247
+     */
+    public void Test4023247() {
+        Date d1 = new Date(0);
+        Date d2 = new Date(0);
+
+        d1.setYear(96);
+        d1.setMonth(11);
+        d1.setDate(22);
+        d1.setHours(0);
+        d1.setMinutes(0);
+        d1.setSeconds(0);
+
+        d2.setYear(96);
+        d2.setMonth(11);
+        d2.setDate(22);
+        d2.setHours(0);
+        d2.setMinutes(0);
+        d2.setSeconds(0);
+
+        if (d1.hashCode() != d2.hashCode())
+            errln("Fail: Date hashCode misbehaves");
+    }
+
+    /**
+     * @bug 4027685
+     */
+    public void Test4027685() {
+        // Should be 01/16/97 00:00:00
+        Date nite = new Date("16-JAN-97 12:00 AM");
+        // Should be 01/16/97 12:00:00
+        Date noon = new Date("16-JAN-97 12:00 PM");
+
+        logln("Midnight = " + nite + ", Noon = " + noon);
+        if (!nite.equals(new Date(97, Calendar.JANUARY, 16, 0, 0)) ||
+            !noon.equals(new Date(97, Calendar.JANUARY, 16, 12, 0)))
+            errln("Fail: Nite/Noon confused");
+    }
+
+    /**
+     * @bug 4032037
+     */
+    public void Test4032037() {
+        Date ref = new Date(97, 1, 10);
+        Date d = new Date(Date.parse("2/10/97"));
+        logln("Date.parse(2/10/97) => " + d);
+        if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+        d = new Date(Date.parse("10 feb 1997"));
+        logln("Date.parse(10 feb 1997) => " + d);
+        if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+        d = new Date("2/10/97");
+        logln("Date(2/10/97) => " + d);
+        if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+        d = new Date("10 feb 1997");
+        logln("Date(10 feb 1997) => " + d);
+        if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+    }
+
+    /**
+     * @bug 4072029
+     */
+    public void Test4072029() {
+        TimeZone saveZone = TimeZone.getDefault();
+
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+            Date now = new Date();
+            String s = now.toString();
+            Date now2 = new Date(now.toString());
+            String s2 = now2.toString(); // An hour's difference
+
+            if (!s.equals(s2) ||
+                Math.abs(now.getTime() - now2.getTime()) > 60000 /*one min*/) {
+                errln("Fail: Roundtrip toString/parse");
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    /**
+     * @bug 4073003
+     */
+    public void Test4073003() {
+        Date d = new Date(Date.parse("01/02/1984"));
+        if (!d.equals(new Date(84, 0, 2)))
+            errln("Fail: Want 1/2/1984 Got " + d);
+        d = new Date(Date.parse("02/03/2012"));
+        if (!d.equals(new Date(112, 1, 3)))
+            errln("Fail: Want 2/3/2012 Got " + d);
+        d = new Date(Date.parse("03/04/15"));
+        if (!d.equals(new Date(115, 2, 4)))
+            errln("Fail: Want 3/4/2015 Got " + d);
+    }
+
+    /**
+     * @bug 4118010
+     * Regress bug:
+     * Feb. 2000 has 29 days, but Date(2000, 1, 29) returns March 01, 2000
+     * NOTE: This turned out to be a user error (passing in 2000 instead
+     * of 2000-1900 to the Date constructor).
+     */
+    public void Test4118010() {
+        Date d=new java.util.Date(2000-1900, Calendar.FEBRUARY, 29);
+        int m=d.getMonth();
+        int date=d.getDate();
+        if (m != Calendar.FEBRUARY ||
+            date != 29)
+            errln("Fail: Want Feb 29, got " + d);
+    }
+
+    /**
+     * @bug 4120606
+     * Date objects share state after cloning.
+     */
+    public void Test4120606() {
+        Date d = new Date(98, Calendar.JUNE, 24);
+        d.setMonth(Calendar.MAY);
+        Date e = (Date)d.clone();
+        d.setMonth(Calendar.FEBRUARY);
+        if (e.getMonth() != Calendar.MAY) {
+            errln("Cloned Date objects share state");
+        }
+    }
+
+    /**
+     * @bug 4133833
+     * Date constructor crashes with parameters out of range, when it should
+     * normalize.
+     */
+    public void Test4133833() {
+        Date date = new java.util.Date(12,15,19);
+        Date exp  = new Date(1913-1900, Calendar.APRIL, 19);
+        if (!date.equals(exp))
+            errln("Fail: Want " + exp +
+                                "; got " + date);
+    }
+
+    /**
+     * @bug 4136916
+     * Date.toString() throws exception in 1.2b4-E
+     * CANNOT REPRODUCE this bug
+     */
+    public void Test4136916() {
+        Date time = new Date();
+        logln(time.toString());
+    }
+
+    /**
+     * @bug 6274757
+     * Date getTime and toString interaction for some time values
+     */
+    public void Test6274757() {
+        TimeZone savedTz = TimeZone.getDefault();
+        try {
+            // Use a time zone west of GMT.
+            TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+            TimeZone jdkGMT = TimeZone.getTimeZone("GMT");
+            Calendar jdkCal = Calendar.getInstance(jdkGMT);
+            jdkCal.clear();
+            jdkCal.set(1582, Calendar.OCTOBER, 15);
+            logln("JDK time: " + jdkCal.getTime().getTime() );
+            logln("JDK time (str): " + jdkCal.getTime() );
+            logln("Day of month: " + jdkCal.get(Calendar.DAY_OF_MONTH));
+            Date co = jdkCal.getTime();
+            logln("Change over (Oct 15 1582) = " + co + " (" +
+                  co.getTime() + ")");
+            long a = jdkCal.getTime().getTime();
+            Date c = jdkCal.getTime();
+            c.toString();
+            long b = c.getTime();
+
+            if (a != b) {
+                errln("ERROR: " + a + " != " + b);
+            } else {
+                logln(a + " = " + b);
+            }
+        } finally {
+            TimeZone.setDefault(savedTz);
+        }
+    }
+
+    /**
+     * @bug 6314387
+     * JCK6.0: api/java_util/Date/index.html#misc fails, mustang
+     */
+    public void Test6314387() {
+        Date d = new Date(Long.MAX_VALUE);
+        int y = d.getYear();
+        if (y != 292277094) {
+            errln("yesr: got " + y + ", expected 292277094");
+        }
+        d = new Date(Long.MIN_VALUE);
+        y = d.getYear();
+        if (y != 292267155) {
+            errln("yesr: got " + y + ", expected 292267155");
+        }
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/DateTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4143459
+ * @summary test Date
+ * @library /java/text/testlib
+ */
+
+import java.text.*;
+import java.util.*;
+
+@SuppressWarnings("deprecation")
+public class DateTest extends IntlTest
+{
+    public static void main(String[] args) throws Exception {
+        new DateTest().run(args);
+    }
+
+    /**
+     * @bug 4143459
+     * Warning: Use TestDefaultZone() for complete testing of this bug.
+     */
+    public void TestDefaultZoneLite() {
+        // Note: This test is redundant with TestDefaultZone().  It was added by
+        // request to provide a short&sweet test for this bug.  It does not test
+        // all cases though, so IF THIS TEST PASSES, THE BUG MAY STILL BE
+        // PRESENT.  Use TestDefaultZone() to be sure.
+        TimeZone save = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Date d = new Date();
+            d.setYear(98);
+            d.setMonth(Calendar.JANUARY);
+            d.setDate(1);
+            d.setHours(6);
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+            if (d.getHours() != 22) {
+                errln("Fail: Date.setHours()/getHours() ignoring default zone");
+            }
+        }
+        finally { TimeZone.setDefault(save); }
+    }
+
+    /**
+     * @bug 4143459
+     */
+    public void TestDefaultZone() {
+        // Various problems can creep up, with the current implementation of Date,
+        // when the default zone is changed.
+
+        TimeZone saveZone = TimeZone.getDefault();
+        try {
+
+            Date d = new Date(); // Trigger static init
+            Date ref = new Date(883634400000L); // This is Thu Jan 1 1998 6:00 am GMT
+            String refstr = "Jan 1 1998 6:00";
+            TimeZone GMT = TimeZone.getTimeZone("GMT");
+            TimeZone PST = TimeZone.getTimeZone("PST");
+
+            String[] names = { "year", "month", "date", "day of week", "hour", "offset" };
+            int[] GMT_EXP = { 98, Calendar.JANUARY, 1, Calendar.THURSDAY - Calendar.SUNDAY, 6, 0 };
+            int[] PST_EXP = { 97, Calendar.DECEMBER, 31, Calendar.WEDNESDAY - Calendar.SUNDAY, 22, 480 };
+
+            // There are two cases to consider: a Date object with no Calendar
+            // sub-object (most Date objects), and a Date object with a Calendar
+            // sub-object.  We make two passes to cover the two cases.
+            for (int pass=0; pass<2; ++pass) {
+                logln(pass == 0 ? "Normal Date object" : "Date with Calendar sub-object");
+
+                TimeZone.setDefault(GMT);
+                d = new Date(refstr);
+                if (pass == 1) {
+                    // Force creation of Calendar sub-object
+                    d.setYear(d.getYear());
+                }
+                if (d.getTime() != ref.getTime()) {
+                    errln("FAIL: new Date(\"" + refstr + "\") x GMT -> " + d +
+                          " " + d.getTime() + " ms");
+                }
+
+                int[] fields = { d.getYear(), d.getMonth(), d.getDate(),
+                                 d.getDay(), d.getHours(), d.getTimezoneOffset() };
+                for (int i=0; i<fields.length; ++i) {
+                    if (fields[i] != GMT_EXP[i]) {
+                        errln("FAIL: GMT Expected " + names[i] + " of " + GMT_EXP[i] +
+                              ", got " + fields[i]);
+                    }
+                }
+
+                TimeZone.setDefault(PST);
+                int[] fields2 = { d.getYear(), d.getMonth(), d.getDate(),
+                                  d.getDay(), d.getHours(), d.getTimezoneOffset() };
+                for (int i=0; i<fields2.length; ++i) {
+                    if (fields2[i] != PST_EXP[i]) {
+                        errln("FAIL: PST Expected " + names[i] + " of " + PST_EXP[i] +
+                              ", got " + fields2[i]);
+                    }
+                }
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveZone);
+        }
+    }
+
+    // Test the performance of Date
+    public void TestPerformance592()
+    {
+        int REPS = 500;
+
+        // Do timing test with Date
+        long start = new Date().getTime();
+        for (int i=0; i<REPS; ++i)
+        {
+            Date d = new Date();
+            int y = d.getYear();
+        }
+        long ms = new Date().getTime() - start;
+
+        double perLoop = ((double)ms) / REPS;
+        logln(REPS + " iterations at " + perLoop + " ms/loop");
+        if (perLoop > PER_LOOP_LIMIT)
+            logln("WARNING: Date constructor/getYear slower than " +
+                  PER_LOOP_LIMIT + " ms");
+    }
+    static double PER_LOOP_LIMIT = 3.0;
+
+    /**
+     * Verify that the Date(String) constructor works.
+     */
+    public void TestParseOfGMT()
+    {
+        Date OUT = null;
+
+        /* Input values */
+        String stringVal = "Jan 01 00:00:00 GMT 1900";
+        long expectedVal = -2208988800000L;
+
+        OUT = new Date( stringVal );
+
+        if( OUT.getTime( ) == expectedVal ) {
+            // logln("PASS");
+        }
+        else {
+            errln( "Expected: " +
+                   new Date( expectedVal ) +
+                   ": " +
+                   expectedVal +
+                   "  Received: " +
+                   OUT.toString() +
+                   ": " +
+                   OUT.getTime() );
+        }
+    }
+
+    // Check out Date's behavior with large negative year values; bug 664
+    // As of the fix to bug 4056585, Date should work correctly with
+    // large negative years.
+    public void TestDateNegativeYears()
+    {
+        Date d1= new Date(80,-1,2);
+        logln(d1.toString());
+        d1= new Date(-80,-1,2);
+        logln(d1.toString());
+        boolean e = false;
+        try {
+            d1= new Date(-800000,-1,2);
+            logln(d1.toString());
+        }
+        catch (IllegalArgumentException ex) {
+            e = true;
+        }
+        if (e) errln("FAIL: Saw exception for year -800000");
+        else logln("Pass: No exception for year -800000");
+    }
+
+    // Verify the behavior of Date
+    public void TestDate480()
+    {
+      TimeZone save = TimeZone.getDefault();
+      try {
+        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+        Date d1=new java.util.Date(97,8,13,10,8,13);
+        logln("d       = "+d1);
+        Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later
+        logln("d+20h   = "+d2);
+
+        double delta = (d2.getTime() - d1.getTime()) / 3600000;
+
+        logln("delta   = " + delta + "h");
+
+        if (delta != 20.0) errln("Expected delta of 20; got " + delta);
+
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(1997,8,13,10,8,13);
+        Date t1 = cal.getTime();
+        logln("d       = "+t1);
+        cal.clear();
+        cal.set(1997,8,13,30,8,13); // 20 hours later
+        Date t2 = cal.getTime();
+        logln("d+20h   = "+t2);
+
+        double delta2 = (t2.getTime() - t1.getTime()) / 3600000;
+
+        logln("delta   = " + delta2 + "h");
+
+        if (delta != 20.0) errln("Expected delta of 20; got " + delta2);
+      }
+      finally {
+        TimeZone.setDefault(save);
+      }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/TZ.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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      4108737
+ * @summary  java.util.Date doesn't fail if current TimeZone is changed
+ */
+
+import java.util.TimeZone;
+import java.util.Date;
+
+public class TZ {
+
+    public static void main(String args[]) {
+        TimeZone tz = TimeZone.getDefault();
+        try {
+            testMain();
+        } finally {
+            TimeZone.setDefault(tz);
+        }
+    }
+
+    static void testMain() {
+        String expectedResult = "Sat Feb 01 00:00:00 PST 1997";
+
+        // load the java.util.Date class in the GMT timezone
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+        new Date(); // load the class (to run static initializers)
+
+        // use the class in different timezone
+        TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+        @SuppressWarnings("deprecation")
+        Date date = new Date(97, 1, 1);
+        if (!date.toString().equals(expectedResult)) {
+            throw new RuntimeException("Regression bug id #4108737 - Date fails if default time zone changed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Date/TimestampTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,134 @@
+/*
+ * 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
+ * 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 5008227
+ * @summary Make sure that changes to the Date class don't break java.sql.Timestamp.
+ * @modules java.sql
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+import java.sql.Timestamp;
+
+public class TimestampTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new TimestampTest().run(args);
+    }
+
+    /**
+     * 5008227: java.sql.Timestamp.after() is not returning correct result
+     *
+     * Test before(), after(), equals(), compareTo() and getTime().
+     */
+    public void Test5008227() {
+        long t = System.currentTimeMillis();
+        Timestamp ts1 = new Timestamp(t), ts2 = new Timestamp(t);
+        ts1.setNanos(999999999);
+        ts2.setNanos(  1000000);
+        compareTimestamps(ts1, ts2, 1);
+
+        ts1.setTime(t + 1000);
+        ts2.setTime(t);
+        ts1.setNanos(   999999);
+        ts2.setNanos(999999999);
+        compareTimestamps(ts1, ts2, 1);
+
+        ts1.setTime(t);
+        ts2.setTime(t);
+        ts1.setNanos(123456789);
+        ts2.setNanos(123456789);
+        compareTimestamps(ts1, ts2, 0);
+
+        ts1.setTime(t);
+        ts2.setTime(t);
+        ts1.setNanos(1);
+        ts2.setNanos(2);
+        compareTimestamps(ts1, ts2, -1);
+
+        ts1.setTime(t);
+        ts2.setTime(t+1000);
+        ts1.setNanos(999999);
+        ts2.setNanos(     0);
+        compareTimestamps(ts1, ts2, -1);
+    }
+
+    /**
+     * Compares two Timestamps with the expected result.
+     *
+     * @param ts1 the first Timestamp
+     * @param ts2 the second Timestamp
+     * @param expect the expected relation between ts1 and ts2; 0 if
+     * ts1 equals to ts2, or 1 if ts1 is after ts2, or -1 if ts1 is
+     * before ts2.
+     */
+    private void compareTimestamps(Timestamp ts1, Timestamp ts2, int expected) {
+        boolean expectedResult = expected > 0;
+        boolean result = ts1.after(ts2);
+        if (result != expectedResult) {
+            errln("ts1.after(ts2) returned " + result
+                  + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+        }
+
+        expectedResult = expected < 0;
+        result = ts1.before(ts2);
+        if (result != expectedResult) {
+            errln("ts1.before(ts2) returned " + result
+                  + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+        }
+
+        expectedResult = expected == 0;
+        result = ts1.equals(ts2);
+        if (result != expectedResult) {
+            errln("ts1.equals(ts2) returned " + result
+                  + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+        }
+
+        int x = ts1.compareTo(ts2);
+        int y = (x > 0) ? 1 : (x < 0) ? -1 : 0;
+        if (y != expected) {
+            errln("ts1.compareTo(ts2) returned " + x + ", expected "
+                  + relation(expected, "") + "0"
+                  + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+        }
+        long t1 = ts1.getTime();
+        long t2 = ts2.getTime();
+        int z = (t1 > t2) ? 1 : (t1 < t2) ? -1 : 0;
+        if (z == 0) {
+            int n1 = ts1.getNanos();
+            int n2 = ts2.getNanos();
+            z = (n1 > n2) ? 1 : (n1 < n2) ? -1 : 0;
+        }
+        if (z != expected) {
+            errln("ts1.getTime() " + relation(z, "==") + " ts2.getTime(), expected "
+                  + relation(expected, "==")
+                  + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+        }
+    }
+
+    private static String relation(int x, String whenEqual) {
+        return (x > 0) ? ">" : (x < 0) ? "<" : whenEqual;
+    }
+}
--- a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.html	Thu May 26 17:19:03 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<!---->
-This is a test.
-<applet code=RestrictedBundleTest.class width=400 height=400></applet>
--- a/jdk/test/java/util/ResourceBundle/RestrictedBundleTest.java	Thu May 26 17:19:03 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2007, 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 4126805
- * @ignore until 6842022 is resolved
- * @run applet RestrictedBundleTest.html
- * @summary I was able to reproduce this bug with 1.2b2, but not with the current 1.2
- * build.  It appears that it was fixed by changes to the class-loading mechanism,
- * which now throws a ClassNotFoundException where before it was propagating through
- * a bogus ClassFormatError.  Therefore, this is just an additional regression test
- * for whatever bug that was.
- */
-
-import java.util.ResourceBundle;
-import java.applet.Applet;
-import java.util.MissingResourceException;
-
-public class RestrictedBundleTest extends Applet {
-    public void init() {
-        super.init();
-        try {
-            ResourceBundle bundle = ResourceBundle.getBundle("unavailable.base.name");
-
-            throw new RuntimeException("Error: MissingResourceException is not thrown");
-        }
-        catch (MissingResourceException e) {
-            // other types of error will propagate back out into the test harness
-            System.out.println("OK");
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/Bug4322313.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4322313
+ * @summary Make sure that new implementation of custom time zone
+ * support for TimeZone.getTimeZone() works correctly and the
+ * getDisplayName() methods are locale independent.
+ * @library /java/text/testlib
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4322313 extends IntlTest {
+    private static final int MPM = 60 * 1000;    /* Milliseconds per minute */
+    private static final Object[][] VALIDS = {
+        /* given ID    rawOffset   normalized ID */
+        {"GMT+00:00",  0,          "GMT+00:00"},
+        {"GMT+3:04",   184 * MPM,  "GMT+03:04"},
+        {"GMT+03:04",  184 * MPM,  "GMT+03:04"},
+        {"GMT+13:42",  822 * MPM,  "GMT+13:42"},
+        /* ISO-LATIN-1 digits */
+        {"GMT+\u0030\u0031:\u0032\u0033", 83 * MPM, "GMT+01:23"},
+
+        {"GMT+0",      0,          "GMT+00:00"},
+        {"GMT+3",      180 * MPM,  "GMT+03:00"},
+        {"GMT+13",     780 * MPM,  "GMT+13:00"},
+        {"GMT+034",    34 * MPM,   "GMT+00:34"},
+        {"GMT+1034",   634 * MPM,  "GMT+10:34"},
+
+        {"GMT-00:00",  0,          "GMT-00:00"},
+        {"GMT-3:04",   -184 * MPM, "GMT-03:04"},
+        {"GMT-03:04",  -184 * MPM, "GMT-03:04"},
+        {"GMT-13:42",  -822 * MPM, "GMT-13:42"},
+        /* ISO-LATIN-1 digits */
+        {"GMT-\u0030\u0031:\u0032\u0033", -83 * MPM, "GMT-01:23"},
+
+        {"GMT-0",      0,          "GMT-00:00"},
+        {"GMT-3",      -180 * MPM, "GMT-03:00"},
+        {"GMT-13",     -780 * MPM, "GMT-13:00"},
+        {"GMT-034",    -34 * MPM,  "GMT-00:34"},
+        {"GMT-1034",   -634 * MPM, "GMT-10:34"},
+    };
+
+    private static final String[] INVALIDS = {
+        "GMT+5:8",    "GMT+11:1",    "GMT+23:60",  "GMT+24:13",
+        "GMT+0a:0A",  "GMT +13:42",  "GMT+ 13:42", "GMT+13 :42",
+        "GMT+13: 42", "GMT+421:950", "GMT+-13:42", "GMT+!13:42",
+        "GMT+a",      "GMT+24",      "GMT+060",    "GMT+3003",
+        "GMT+42195",  "GMT+-1",      "GMT+-15",    " GMT",
+
+        "GMT-5:8",    "GMT-11:1",    "GMT-23:60",  "GMT-24:13",
+        "GMT-0a:0A",  "GMT -13:42",  "GMT- 13:42", "GMT-13 :42",
+        "GMT-13: 42", "GMT-421:950", "GMT-+13:42", "GMT-#13:42",
+        "GMT-a",      "GMT-24",      "GMT-060",    "GMT-2403",
+        "GMT-42195",  "GMT-+1",      "GMT-+15",    "G M T",
+        "GMT+09:00 ",
+    };
+
+    void Test4322313() {
+        Locale savedLocale = Locale.getDefault();
+        TimeZone savedTimeZone = TimeZone.getDefault();
+        boolean err = false;
+
+        Locale[] locs = Locale.getAvailableLocales();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+            for (int i = 0; i < locs.length; i++) {
+                Locale.setDefault(locs[i]);
+
+                /* Okay case */
+                for (int k = 0; k < VALIDS.length; k++) {
+                    TimeZone tz = TimeZone.getTimeZone((String)VALIDS[k][0]);
+                    int offset;
+
+                    if (!tz.getID().equals(VALIDS[k][2])) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           "\"] Invalid TimeZone ID, expected:" +
+                                           VALIDS[k][2] + ", got:" + tz.getID() + ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              "\"] Valid TimeZone ID, got:" + VALIDS[k][2]);
+                    }
+
+                    offset = tz.getRawOffset();
+                    if (offset != (int)VALIDS[k][1]) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           "\"] Invalid RawOffset, expected:" + VALIDS[k][1] +
+                                           ", got:" + offset + ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              "\"] Vaild RawOffset, got:" + offset);
+                    }
+
+                    offset = tz.getDSTSavings();
+                    if (offset != 0) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                                           "\"] DSTSavings should be zero, got:" + offset +
+                                           ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + VALIDS[k][0] +
+                              "\"] DSTSavings is zero.");
+                    }
+                }
+
+                /* Error case */
+                for (int k=0; k < INVALIDS.length; k++) {
+                    TimeZone tz = TimeZone.getTimeZone(INVALIDS[k]);
+                    int offset;
+
+                    if (!tz.getID().equals("GMT")) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           "\"] Invalid TimeZone ID, expected:GMT, got:" +
+                                           tz.getID() + ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              "\"] Valid TimeZone ID, got:" + tz.getID());
+                    }
+
+                    offset = tz.getRawOffset();
+                    if (offset != 0) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           "\"] RawOffset should be zero, got:" + offset +
+                                           ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              "\"] RawOffset is zero.");
+                    }
+
+                    offset = tz.getDSTSavings();
+                    if (offset != 0) {
+                        err = true;
+                        System.err.println("\tFailed [Locale=" +
+                                           Locale.getDefault() + ", \"" + INVALIDS[k] +
+                                           "\"] DSTSavings should be zero, got:" + offset +
+                                           ", " + tz);
+                    } else {
+                        logln("\tPassed [Locale=" +
+                              Locale.getDefault() + ", \"" + INVALIDS[k] +
+                              "\"] DSTSavings is zero.");
+                    }
+                }
+
+                // getDisplayName() tests
+                {
+                    String normalizedID = "GMT-08:00";
+                    TimeZone tz = TimeZone.getTimeZone("GMT-8");
+                    String s;
+                    s = tz.getDisplayName(true, tz.LONG);
+                    if (!normalizedID.equals(s)) {
+                        err = true;
+                        System.err.println("getDisplayName returned unexpected name: " + s +
+                                           " in " + Locale.getDefault());
+                    }
+                    s = tz.getDisplayName(true, tz.SHORT);
+                    if (!normalizedID.equals(s)) {
+                        err = true;
+                        System.err.println("getDisplayName returned unexpected name: " + s +
+                                           " in " + Locale.getDefault());
+                    }
+                    s = tz.getDisplayName(false, tz.LONG);
+                    if (!normalizedID.equals(s)) {
+                        err = true;
+                        System.err.println("getDisplayName returned unexpected name: " + s +
+                                           " in " + Locale.getDefault());
+                    }
+                    s = tz.getDisplayName(false, tz.SHORT);
+                    if (!normalizedID.equals(s)) {
+                        err = true;
+                        System.err.println("getDisplayName returned unexpected name: " + s +
+                                           " in " + Locale.getDefault());
+                    }
+                }
+            }
+        } finally {
+            Locale.setDefault(savedLocale);
+            TimeZone.setDefault(savedTimeZone);
+        }
+        if (err) {
+            errln("TimeZone.getTimeZone() test failed");
+        } else {
+            logln("TimeZone.getTimeZone() test passed");
+        }
+    }
+
+    public static void main (String[] args) throws Exception {
+        new Bug4322313().run(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/Bug5097350.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * 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 5097350
+ * @summary Make sure that TimeZone.getTimeZone returns a clone of a cached TimeZone instance.
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class Bug5097350 {
+    public static void main(String[] args) {
+        String[] tzids = TimeZone.getAvailableIDs();
+        List<String> ids = new ArrayList<>(tzids.length + 10);
+        ids.addAll(Arrays.asList(tzids));
+        // add some custom ids
+        ids.add("GMT+1");
+        ids.add("GMT-7:00");
+        ids.add("GMT+10:20");
+        ids.add("GMT-00:00");
+        ids.add("GMT+00:00");
+
+        for (String id : ids) {
+            test(id);
+        }
+    }
+
+    private static void test(String id) {
+        TimeZone tz1 = TimeZone.getTimeZone(id);
+        int offset1 = tz1.getRawOffset();
+        tz1.setRawOffset(offset1 + 13 * 60 * 60 * 1000);
+
+        TimeZone tz2 = TimeZone.getTimeZone(id);
+        if (tz1 == tz2) {
+            throw new RuntimeException("TimeZones are identical: " + id);
+        }
+        if (offset1 != tz2.getRawOffset()) {
+            throw new RuntimeException("Offset changed through aliasing: " + id);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/CheckDisplayNames.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6405639 8008577
+ * @summary Validate timezone display names in
+ *          src/java.base/share/classes/sun/util/resources/TimeZoneNames.java.
+ * @modules java.base/sun.util.resources
+ * @compile -XDignore.symbol.file CheckDisplayNames.java
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI CheckDisplayNames
+ */
+
+import java.util.*;
+import sun.util.resources.TimeZoneNames;
+
+/**
+ * CheckDisplayNames checks all available time zones in the Java run
+ * time environment and sees if those have their display names besides doing
+ * some other test cases. It outputs time zones that don't have display names
+ * if -source option is specified.
+ * <blockquote>
+ * <pre>
+ *    Usage: java CheckDisplayNames [-source]
+ *              -source ... produces source code for editing TimeZoneNames.java.
+ * </pre>
+ * </blockquote>
+ */
+public class CheckDisplayNames {
+
+    private static boolean err = false;
+    private static boolean src = false;
+
+    private static Locale[] locales = Locale.getAvailableLocales();
+    private static String[] zones = TimeZone.getAvailableIDs();
+
+    private static String[] zones_118 = {
+        "ACT",  "Australia/Darwin",
+        "AET",  "Australia/Sydney",
+        "AGT",  "America/Buenos_Aires",
+        "ART",  "Africa/Cairo",
+        "AST",  "America/Anchorage",
+        "BET",  "America/Sao_Paulo",
+        "BST",  "Asia/Dacca",
+        "CAT",  "Africa/Harare",
+        "CNT",  "America/St_Johns",
+        "CST",  "America/Chicago",
+        "CTT",  "Asia/Shanghai",
+        "EAT",  "Africa/Addis_Ababa",
+        "ECT",  "Europe/Paris",
+//      "EET",  "Africa/Istanbul",
+        "EST",  "America/New_York",
+        "HST",  "Pacific/Honolulu",
+        "IET",  "America/Indiana/Indianapolis",
+//      Comment out for this test case fails as the result of L10N for hi_IN.
+//      "IST",  "Asia/Calcutta",
+        "JST",  "Asia/Tokyo",
+//      "MET",  "Asia/Tehran",
+        "MIT",  "Pacific/Apia",
+        "MST",  "America/Denver",
+        "NET",  "Asia/Yerevan",
+        "NST",  "Pacific/Auckland",
+        "PLT",  "Asia/Karachi",
+        "PNT",  "America/Phoenix",
+        "PRT",  "America/Puerto_Rico",
+        "PST",  "America/Los_Angeles",
+        "SST",  "Pacific/Guadalcanal",
+        "VST",  "Asia/Saigon",
+    };
+
+
+    public static void main(String[] argv) {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            if (argv.length == 1 && "-source".equals(argv[0])) {
+                src = true;
+            }
+
+            testDisplayNames();
+            testRAWoffsetAndDisplayNames();
+            test118DisplayNames();
+
+            if (err) {
+                throw new RuntimeException(
+                    "TimeZone display name validation failed.");
+            } else {
+                System.out.println(
+                    "\nAll test passed.\nTotal number of valid TimeZone id is "
+                    + zones.length);
+            }
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+
+    }
+
+    /*
+     * Checks if each timezone ID has display names. If it doesn't and
+     * "-source" option was specified, source code is generated.
+     */
+    private static void testDisplayNames() {
+        System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID");
+
+        Locale.setDefault(Locale.US);
+        Enumeration data = new TimeZoneNames().getKeys();
+
+        while (data.hasMoreElements()) {
+            String name = (String)data.nextElement();
+            String id = TimeZone.getTimeZone(name).getID();
+            if (!name.equals(id)) {
+                System.err.println("\t" + name + " doesn't seem to be a valid TimeZone ID.");
+                err = true;
+            }
+        }
+
+        System.out.println("Checking if each TimeZone ID has display names.");
+
+        for (int i = 0; i < zones.length; i++) {
+            String id = zones[i];
+
+            if (id != null) {
+                if (id.startsWith("Etc/GMT")) {
+                    continue;
+                }
+                if (id.indexOf("Riyadh8") != -1) {
+                    continue;
+                }
+                if (id.equals("GMT0")) {
+                    continue;
+                }
+            }
+
+            TimeZone tz = TimeZone.getTimeZone(id);
+            String name = tz.getDisplayName();
+
+            if (name == null || name.startsWith("GMT+") || name.startsWith("GMT-")) {
+                if (src) {
+                    System.out.println("\t    {\"" + tz.getID() + "\", " +
+                                       "new String[] {\"Standard Time Name\", \"ST\",\n" +
+                                       "\t\t\t\t\t\t\"Daylight Time Name\", \"DT\"}},");
+                } else {
+                    System.err.println("\t" + tz.getID() + " doesn't seem to have display names");
+                    err = true;
+                }
+            }
+        }
+    }
+
+    /*
+     * Compares
+     *   - raw DST offset
+     *   - short display names in non-DST
+     *   - short display names in DST
+     *   - long display names in DST
+     * of two timezones whose long display names in non-DST are same.
+     * If one of these are different, there may be a bug.
+     */
+    private static void testRAWoffsetAndDisplayNames() {
+        System.out.println("Checking if each entry in TimeZoneNames is a valid TimeZone ID");
+
+        HashMap<String, TimeZone> map = new HashMap<String, TimeZone>();
+
+        for (int i = 0; i < locales.length; i++) {
+            map.clear();
+
+            for (int j = 0; j < zones.length; j++) {
+                TimeZone tz1 = TimeZone.getTimeZone(zones[j]);
+                String name = tz1.getDisplayName(false, TimeZone.LONG, locales[i]);
+
+                if (map.containsKey(name)) {
+                    TimeZone tz2 = map.get(name);
+
+                    int offset1 = tz1.getRawOffset();
+                    int offset2 = tz2.getRawOffset();
+                    if (offset1 != offset2) {
+                        System.err.println("Two timezones which have the same long display name \"" +
+                            name + "\" in non-DST have different DST offsets in " +
+                            locales[i] + " locale.\n\tTimezone 1=" +
+                            tz1.getID() + "(" + offset1 + ")\n\tTimezone 2=" +
+                            tz2.getID() + "(" + offset2 + ")");
+                    }
+
+                    String name1 = tz1.getDisplayName(false, TimeZone.SHORT, locales[i]);
+                    String name2 = tz2.getDisplayName(false, TimeZone.SHORT, locales[i]);
+                    if (!(name1.equals("GMT") && name2.equals("GMT")) &&
+                        !(name1.equals("CET") && name2.equals("MET")) &&
+                        !(name1.equals("MET") && name2.equals("CET"))) {
+                        if (!name1.equals(name2)) {
+                            System.err.println("Two timezones which have the same short display name \"" +
+                                name +
+                                "\" in non-DST have different short display names in non-DST in " +
+                                locales[i] + " locale.\n\tTimezone 1=" +
+                                tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" +
+                                tz2.getID() + "(" + name2 + ")");
+                        }
+
+                        name1 = tz1.getDisplayName(true, TimeZone.SHORT, locales[i]);
+                        name2 = tz2.getDisplayName(true, TimeZone.SHORT, locales[i]);
+                        if (!name1.equals(name2)) {
+                            System.err.println("Two timezones which have the same short display name \"" +
+                            name +
+                            "\" in non-DST have different short display names in DST in " +
+                            locales[i] + " locale.\n\tTimezone 1=" +
+                            tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" +
+                            tz2.getID() + "(" + name2 + ")");
+                        }
+
+                        name1 = tz1.getDisplayName(true, TimeZone.LONG, locales[i]);
+                        name2 = tz2.getDisplayName(true, TimeZone.LONG, locales[i]);
+                        if (!name1.equals(name2)) {
+                            System.err.println("Two timezones which have the same long display name \"" +
+                            name +
+                            "\" in non-DST have different long display names in DST in " +
+                            locales[i] + " locale.\n\tTimezone 1=" +
+                            tz1.getID() + "(" + name1 + ")\n\tTimezone 2=" +
+                            tz2.getID() + "(" + name2 + ")");
+                        }
+                    }
+                } else {
+                    map.put(name, tz1);
+                }
+            }
+        }
+    }
+
+    /*
+     * Compares three-letter timezones' display names with corresponding
+     * "popular" timezones.
+     */
+    private static void test118DisplayNames() {
+        System.out.println("Checking compatibility of Java 1.1.X's three-letter timezones");
+
+        for (int i = 0; i < zones_118.length; i+=2) {
+            String id_118 = zones_118[i];
+            String id_later = zones_118[i+1];
+            String zone_118, zone_later, localename;
+            TimeZone tz_118 = TimeZone.getTimeZone(id_118);
+            TimeZone tz_later = TimeZone.getTimeZone(id_later);
+
+            for (int j = 0; j < locales.length; j++) {
+                localename = locales[j].toString();
+                zone_118 = tz_118.getDisplayName(false, TimeZone.SHORT, locales[j]);
+                zone_later = tz_later.getDisplayName(false, TimeZone.SHORT, locales[j]);
+                check(id_118, id_later, zone_118, zone_later, "short", "non-DST", localename);
+
+                zone_118 = tz_118.getDisplayName(true, TimeZone.SHORT, locales[j]);
+                zone_later = tz_later.getDisplayName(true, TimeZone.SHORT, locales[j]);
+                check(id_118, id_later, zone_118, zone_later, "short", "DST", localename);
+
+                zone_118 = tz_118.getDisplayName(false, TimeZone.LONG, locales[j]);
+                zone_later = tz_later.getDisplayName(false, TimeZone.LONG, locales[j]);
+                check(id_118, id_later, zone_118, zone_later, "long", "non-DST", localename);
+
+                zone_118 = tz_118.getDisplayName(true, TimeZone.LONG, locales[j]);
+                zone_later = tz_later.getDisplayName(true, TimeZone.LONG, locales[j]);
+                check(id_118, id_later, zone_118, zone_later, "long", "DST", localename);
+            }
+        }
+    }
+
+    private static void check(String zoneID_118, String zoneID_later,
+                              String zonename_118, String zonename_later,
+                              String format, String dst, String loc) {
+        if (!zonename_118.equals(zonename_later)) {
+            System.err.println("JDK 118 TimeZone \"" + zoneID_118 +
+                "\" has a different " + format +
+                " display name from its equivalent timezone \"" +
+                zoneID_later + "\" in " + dst + " in " + loc + " locale.");
+            System.err.println("    Got: " + zonename_118 + ", Expected: " +
+                zonename_later);
+            err = true;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.html	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ 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.
+-->
+<!---->
+<html>
+  <head>
+    <title>Disable Auto-adjust Daylight Saving Time Test</title>
+  </head>
+
+  <body>
+This applet tests the platform time zone detection on all platforms (Part I)
+and on/off of DST adjustment on Windows (Part II).
+
+Part I:
+
+Observe the displayed Time zone ID and the local time. If you can change
+the platform time zone setting, try several time zones. If both the ID and
+the local time, including the time zone name and its time zone offset, are
+always correct, Part I passes. Note that some time zone IDs have their
+aliases that may be displayed.  For example, "US/Pacific" is an alias of
+"America/Los_Angeles".
+
+If you are running this applet in non-English locale, the time zone names
+can be displayed in the local language and English by pushing the
+English/Local button.
+
+If platform time zones are NOT detected correctly, press the Fail button
+to finish this applet.
+
+If this platform is Windows, proceed to Part II. Otherwise, press the Pass
+button to finish this applet.
+
+Part II:
+
+Note that Part II may require the Administrator privilege to change
+Windows setting.
+
+  1. Open the Date and Time control panel.
+  2. Select any time zone where daylight saving time is *currently* in effect,
+     such as "(GMT-08:00) Pacific Time (US & Canada); Tijuana",
+     "(GMT+10:00) Canberra, Melbourne, Sydney", and Apply.
+  3. Observe the local time on the control panel (Date&Time pane) and
+     the applet local time should be the same (daylight time).
+  4. Clear "Automatically adjust clock for daylight saving changes" and Apply.
+  5. Observe the two local times should be the same (standard time).
+  6. Select "Automatically adjust clock for daylight saving changes" and Apply.
+
+If the local time in the control panel and applet are always the same,
+then this test passes. Press the Pass or Fail button based on the Part II
+result and finish this applet.
+
+<applet code="DefaultTimeZoneTest.class" width=500 height=90></applet>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/DefaultTimeZoneTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4296930 5033603 7092679
+ * @summary Make sure that Java runtime detects the platform time zone
+ * correctly. Also make sure that the system time zone detection code
+ * detects the "Automatically adjust clock for daylight saving
+ * changes" setting correctly on Windows.
+ * @run applet/manual=yesno DefaultTimeZoneTest.html
+ */
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.text.*;
+import java.util.*;
+
+public class DefaultTimeZoneTest extends JApplet implements Runnable {
+    static final String FORMAT = "yyyy-MM-dd HH:mm:ss zzzz (XXX)";
+    JLabel tzid;
+    JLabel label;
+    SimpleDateFormat sdf = new SimpleDateFormat(FORMAT);
+    JButton button = new JButton("English");
+    Thread clock;
+    boolean english = false;
+
+    @Override
+    public void init() {
+        tzid = new JLabel("Time zone ID: " + sdf.getTimeZone().getID(), SwingConstants.CENTER);
+        tzid.setAlignmentX(Component.CENTER_ALIGNMENT);
+        label = new JLabel(sdf.format(new Date()), SwingConstants.CENTER);
+        label.setAlignmentX(Component.CENTER_ALIGNMENT);
+        button.addActionListener(new ActionListener() {
+                @Override
+                @SuppressWarnings("deprecation")
+                public void actionPerformed(ActionEvent e) {
+                    english = (english == false);
+                    Locale loc = english ? Locale.US : Locale.getDefault();
+                    sdf = new SimpleDateFormat(FORMAT, loc);
+                    button.setLabel(!english ? "English" : "Local");
+                }
+            });
+        button.setAlignmentX(Component.CENTER_ALIGNMENT);
+        JPanel panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+        panel.add(Box.createRigidArea(new Dimension(0, 10)));
+        panel.add(tzid);
+        panel.add(Box.createRigidArea(new Dimension(0, 5)));
+        panel.add(label);
+        panel.add(Box.createRigidArea(new Dimension(0, 10)));
+        panel.add(button);
+        getContentPane().add(panel);
+    }
+
+    @Override
+    public void start() {
+        clock = new Thread(this);
+        clock.start();
+    }
+
+    @Override
+    public void stop() {
+        clock = null;
+    }
+
+    @Override
+    public void run() {
+        Thread me = Thread.currentThread();
+
+        while (clock == me) {
+            // Reset the default time zone so that
+            // TimeZone.getDefault will detect the platform time zone
+            TimeZone.setDefault(null);
+            System.setProperty("user.timezone", "");
+            TimeZone tz = TimeZone.getDefault();
+            sdf.setTimeZone(tz);
+            tzid.setText("Time zone ID: " + tz.getID());
+            label.setText(sdf.format(new Date()));
+            repaint();
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/HongKong.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4487276 8008577
+ * @summary Verify that Hong Kong locale uses traditional Chinese names.
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI HongKong
+ */
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class HongKong {
+    public static void main(String[] args) {
+        Locale reservedLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("zh", "HK"));
+            checkCountry(Locale.GERMANY, "\u5fb7\u570b");
+            checkCountry(Locale.FRANCE, "\u6cd5\u570b");
+            checkCountry(Locale.ITALY, "\u7fa9\u5927\u5229");
+            checkTimeZone("Asia/Shanghai",
+                            "\u4e2d\u570b\u6a19\u6e96\u6642\u9593");
+        } finally {
+            // restore the reserved locale
+            Locale.setDefault(reservedLocale);
+        }
+    }
+
+    private static void checkCountry(Locale country, String expected) {
+        String actual = country.getDisplayCountry();
+        if (!expected.equals(actual)) {
+            throw new RuntimeException();
+        }
+    }
+
+    private static void checkTimeZone(String timeZoneID, String expected) {
+        TimeZone timeZone = TimeZone.getTimeZone(timeZoneID);
+        String actual = timeZone.getDisplayName();
+        if (!expected.equals(actual)) {
+            throw new RuntimeException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/IDTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4509255 5055567 6176318 7090844
+ * @summary Tests consistencies of time zone IDs.
+ */
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.TreeMap;
+
+public class IDTest {
+    public static void main(String[] args) {
+        Set<String> ids = new HashSet<>();
+        Map<Integer, Set<String>> tree = new TreeMap<>();
+
+        String[] tzs = TimeZone.getAvailableIDs();
+        String[] tzs2 = TimeZone.getAvailableIDs();
+        if (tzs.length != tzs2.length) {
+            throw new RuntimeException("tzs.length(" + tzs.length
+                                       + ") != tzs2.length(" + tzs2.length + ")");
+        }
+        for (int i = 0; i < tzs.length; i++) {
+            if (tzs[i] != tzs2[i]) {
+                throw new RuntimeException(i + ": " + tzs[i] + " != " + tzs2[i]);
+            }
+        }
+
+        System.out.println("Total: " + tzs.length + " time zone IDs");
+        for (String id : tzs) {
+            ids.add(id);
+            TimeZone tz = TimeZone.getTimeZone(id);
+            Integer offset = tz.getRawOffset();
+            Set<String> s = tree.get(offset);
+            if (s == null) {
+                s = new HashSet<>();
+                tree.put(offset, s);
+            }
+            s.add(id);
+        }
+
+        for (Integer key : tree.keySet()) {
+            Set<String> s1 = tree.get(key);
+
+            // Make sure no duplicates in the other sets
+            for (Integer k : tree.keySet()) {
+                if (k.equals(key)) {
+                    continue;
+                }
+                Set<String> s2 = new HashSet<>(tree.get(k));
+                s2.retainAll(s1);
+                if (!s2.isEmpty()) {
+                    throw new RuntimeException("s1 included in the subset for " + (k.intValue()/60000) +
+                                               " (" + s2 + " shouldn't be in s1)");
+                }
+            }
+
+            // Check the getAvailableIDs(int) call to return the same
+            // set of IDs
+            int offset = key.intValue();
+            tzs = TimeZone.getAvailableIDs(offset);
+            tzs2 = TimeZone.getAvailableIDs(offset);
+            if (!Arrays.equals(tzs, tzs2)) {
+                throw new RuntimeException("inconsistent tzs from getAvailableIDs("+offset+")");
+            }
+            Set<String> s2 = new HashSet<>();
+            s2.addAll(Arrays.asList(tzs));
+            if (!s1.equals(s2)) {
+                throw new RuntimeException("s1 != s2 for " + offset/60000 +
+                                           " (diff=" + getDiff(s1, s2) + ")");
+            }
+            if (!ids.containsAll(s2)) {
+                throw new RuntimeException("s2 isn't a subset of ids (" + getDiff(s2, ids) +
+                                           " not in ids)");
+            }
+        }
+
+        for (Integer key : tree.keySet()) {
+            Set<String> s1 = tree.get(key);
+            ids.removeAll(s1);
+        }
+        if (!ids.isEmpty()) {
+            throw new RuntimeException("ids didn't become empty. (" + ids + ")");
+        }
+    }
+
+    private static String getDiff(Set<String> set1, Set<String> set2) {
+        Set<String> s1 = new HashSet<>(set1);
+        s1.removeAll(set2);
+
+        Set<String> s2 = new HashSet<>(set2);
+        s2.removeAll(set1);
+        s2.addAll(s1);
+        return s2.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/TimeZoneBoundaryTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /java/text/testlib
+ * @summary test Time Zone Boundary
+ */
+
+import java.text.*;
+import java.util.*;
+
+/**
+ * A test which discovers the boundaries of DST programmatically and verifies
+ * that they are correct.
+ */
+public class TimeZoneBoundaryTest extends IntlTest
+{
+    static final int ONE_SECOND = 1000;
+    static final int ONE_MINUTE = 60*ONE_SECOND;
+    static final int ONE_HOUR = 60*ONE_MINUTE;
+    static final long ONE_DAY = 24*ONE_HOUR;
+    static final long ONE_YEAR = (long)(365.25 * ONE_DAY);
+    static final long SIX_MONTHS = ONE_YEAR / 2;
+
+    static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31};
+
+    // These values are empirically determined to be correct
+    static final long PST_1997_BEG  = 860320800000L;
+    static final long PST_1997_END  = 877856400000L;
+
+    // Minimum interval for binary searches in ms; should be no larger
+    // than 1000.
+    static final long INTERVAL = 10; // Milliseconds
+
+    static final String AUSTRALIA = "Australia/Adelaide";
+    static final long AUSTRALIA_1997_BEG = 877797000000L;
+    static final long AUSTRALIA_1997_END = 859653000000L;
+
+    public static void main(String[] args) throws Exception {
+        new TimeZoneBoundaryTest().run(args);
+    }
+
+    /**
+     * Date.toString().substring() Boundary Test
+     * Look for a DST changeover to occur within 6 months of the given Date.
+     * The initial Date.toString() should yield a string containing the
+     * startMode as a SUBSTRING.  The boundary will be tested to be
+     * at the expectedBoundary value.
+     */
+    void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary)
+    {
+        // Given a date with a year start, find the Daylight onset
+        // and end.  The given date should be 1/1/xx in some year.
+
+        if (d.toString().indexOf(startMode) == -1)
+        {
+            logln("Error: " + startMode + " not present in " + d);
+        }
+
+        // Use a binary search, assuming that we have a Standard
+        // time at the midpoint.
+        long min = d.getTime();
+        long max = min + SIX_MONTHS;
+
+        while ((max - min) >  INTERVAL)
+        {
+            long mid = (min + max) >> 1;
+            String s = new Date(mid).toString();
+            // logln(s);
+            if (s.indexOf(startMode) != -1)
+            {
+                min = mid;
+            }
+            else
+            {
+                max = mid;
+            }
+        }
+
+        logln("Date Before: " + showDate(min));
+        logln("Date After:  " + showDate(max));
+        long mindelta = expectedBoundary - min;
+        long maxdelta = max - expectedBoundary;
+        if (mindelta >= 0 && mindelta <= INTERVAL &&
+            mindelta >= 0 && mindelta <= INTERVAL)
+            logln("PASS: Expected boundary at " + expectedBoundary);
+        else
+            errln("FAIL: Expected boundary at " + expectedBoundary);
+    }
+
+    void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary)
+    {
+        findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary,
+                                          TimeZone.getDefault());
+    }
+
+    void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST,
+                                           long expectedBoundary, TimeZone tz)
+    {
+        // Given a date with a year start, find the Daylight onset
+        // and end.  The given date should be 1/1/xx in some year.
+
+        // Use a binary search, assuming that we have a Standard
+        // time at the midpoint.
+        long min = d.getTime();
+        long max = min + SIX_MONTHS;
+
+        if (tz.inDaylightTime(d) != startsInDST)
+        {
+            errln("FAIL: " + tz.getID() + " inDaylightTime(" +
+                  d + ") != " + startsInDST);
+            startsInDST = !startsInDST; // Flip over; find the apparent value
+        }
+
+        if (tz.inDaylightTime(new Date(max)) == startsInDST)
+        {
+            errln("FAIL: " + tz.getID() + " inDaylightTime(" +
+                  (new Date(max)) + ") != " + (!startsInDST));
+            return;
+        }
+
+        while ((max - min) >  INTERVAL)
+        {
+            long mid = (min + max) >> 1;
+            boolean isIn = tz.inDaylightTime(new Date(mid));
+            if (isIn == startsInDST)
+            {
+                min = mid;
+            }
+            else
+            {
+                max = mid;
+            }
+        }
+
+        logln(tz.getID() + " Before: " + showDate(min, tz));
+        logln(tz.getID() + " After:  " + showDate(max, tz));
+
+        long mindelta = expectedBoundary - min;
+        long maxdelta = max - expectedBoundary;
+        if (mindelta >= 0 && mindelta <= INTERVAL &&
+            mindelta >= 0 && mindelta <= INTERVAL)
+            logln("PASS: Expected boundary at " + expectedBoundary);
+        else
+            errln("FAIL: Expected boundary at " + expectedBoundary);
+    }
+
+    private static String showDate(long l)
+    {
+        return showDate(new Date(l));
+    }
+
+    @SuppressWarnings("deprecation")
+    private static String showDate(Date d)
+    {
+        return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) +
+            " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) +
+            " \"" + d + "\" = " +
+            d.getTime();
+    }
+
+    private static String showDate(long l, TimeZone z)
+    {
+        return showDate(new Date(l), z);
+    }
+
+    @SuppressWarnings("deprecation")
+    private static String showDate(Date d, TimeZone zone)
+    {
+        DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
+        fmt.setTimeZone(zone);
+        return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) +
+            " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) +
+            " \"" + d + "\" = " +
+            fmt.format(d);
+    }
+
+    private static String showNN(int n)
+    {
+        return ((n < 10) ? "0" : "") + n;
+    }
+
+    /**
+     * Given a date, a TimeZone, and expected values for inDaylightTime,
+     * useDaylightTime, zone and DST offset, verify that this is the case.
+     */
+    void verifyDST(Date d, TimeZone time_zone,
+                   boolean expUseDaylightTime, boolean expInDaylightTime,
+                   int expZoneOffset, int expDSTOffset)
+    {
+        logln("-- Verifying time " + d +
+              " in zone " + time_zone.getID());
+
+        if (time_zone.inDaylightTime(d) == expInDaylightTime)
+            logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d));
+        else
+            errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d));
+
+        if (time_zone.useDaylightTime() == expUseDaylightTime)
+            logln("PASS: useDaylightTime = " + time_zone.useDaylightTime());
+        else
+            errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime());
+
+        if (time_zone.getRawOffset() == expZoneOffset)
+            logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR);
+        else
+            errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR +
+                  "; expected " + expZoneOffset/(double)ONE_HOUR);
+
+        GregorianCalendar gc = new GregorianCalendar(time_zone);
+        gc.setTime(d);
+        int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH),
+                                         gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK),
+                                         ((gc.get(gc.HOUR_OF_DAY) * 60 +
+                                           gc.get(gc.MINUTE)) * 60 +
+                                          gc.get(gc.SECOND)) * 1000 +
+                                         gc.get(gc.MILLISECOND));
+        if (offset == expDSTOffset)
+            logln("PASS: getOffset() = " + offset/(double)ONE_HOUR);
+        else
+            errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR +
+                  "; expected " + expDSTOffset/(double)ONE_HOUR);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void TestBoundaries()
+    {
+        TimeZone pst = TimeZone.getTimeZone("PST");
+        TimeZone save = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(pst);
+
+            // DST changeover for PST is 4/6/1997 at 2 hours past midnight
+            Date d = new Date(97,Calendar.APRIL,6);
+
+            // i is minutes past midnight standard time
+            for (int i=60; i<=180; i+=15)
+            {
+                boolean inDST = (i >= 120);
+                Date e = new Date(d.getTime() + i*60*1000);
+                verifyDST(e, pst, true, inDST, -8*ONE_HOUR,
+                          inDST ? -7*ONE_HOUR : -8*ONE_HOUR);
+            }
+
+            logln("========================================");
+            findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG);
+            logln("========================================");
+            findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END);
+
+            // Southern hemisphere test
+            logln("========================================");
+            TimeZone z = TimeZone.getTimeZone(AUSTRALIA);
+            findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z);
+
+            logln("========================================");
+            findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG);
+            logln("========================================");
+            findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END);
+        } finally {
+            TimeZone.setDefault(save);
+        }
+    }
+
+    void testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary)
+    {
+        // Given a date with a year start, find the Daylight onset
+        // and end.  The given date should be 1/1/xx in some year.
+
+        // Use a binary search, assuming that we have a Standard
+        // time at the midpoint.
+        long min = d.getTime();
+        long max = min + (long)(365.25 / 2 * ONE_DAY);
+
+        // First check the boundaries
+        boolean startsInDST = tz.inDaylightTime(d);
+
+        if (tz.inDaylightTime(new Date(max)) == startsInDST)
+        {
+            logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST));
+        }
+
+        while ((max - min) >  INTERVAL)
+        {
+            long mid = (min + max) >> 1;
+            if (tz.inDaylightTime(new Date(mid)) == startsInDST)
+            {
+                min = mid;
+            }
+            else
+            {
+                max = mid;
+            }
+        }
+
+        logln("Binary Search Before: " + showDate(min));
+        logln("Binary Search After:  " + showDate(max));
+
+        long mindelta = expectedBoundary - min;
+        long maxdelta = max - expectedBoundary;
+        if (mindelta >= 0 && mindelta <= INTERVAL &&
+            mindelta >= 0 && mindelta <= INTERVAL)
+            logln("PASS: Expected boundary at " + expectedBoundary);
+        else
+            errln("FAIL: Expected boundary at " + expectedBoundary);
+    }
+
+    /*
+      static void testUsingMillis(Date d, boolean startsInDST)
+      {
+      long millis = d.getTime();
+      long max = millis + (long)(370 * ONE_DAY); // A year plus extra
+
+      boolean lastDST = startsInDST;
+      while (millis < max)
+      {
+      cal.setTime(new Date(millis));
+      boolean inDaylight = cal.inDaylightTime();
+
+      if (inDaylight != lastDST)
+      {
+      logln("Switch " + (inDaylight ? "into" : "out of")
+      + " DST at " + (new Date(millis)));
+      lastDST = inDaylight;
+      }
+
+      millis += 15*ONE_MINUTE;
+      }
+      }
+      */
+
+    /**
+     * Test new rule formats.
+     */
+    @SuppressWarnings("deprecation")
+    public void TestNewRules()
+    {
+        //logln(Locale.getDefault().getDisplayName());
+        //logln(TimeZone.getDefault().getID());
+        //logln(new Date(0));
+
+        if (true)
+        {
+            // Doesn't matter what the default TimeZone is here, since we
+            // are creating our own TimeZone objects.
+
+            SimpleTimeZone tz;
+
+            logln("-----------------------------------------------------------------");
+            logln("Aug 2ndTues .. Mar 15");
+            tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1",
+                                    Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR,
+                                    Calendar.MARCH, 15, 0, 2*ONE_HOUR);
+            //logln(tz.toString());
+            logln("========================================");
+            testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L);
+            logln("========================================");
+            testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L);
+
+            logln("-----------------------------------------------------------------");
+            logln("Apr Wed>=14 .. Sep Sun<=20");
+            tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2",
+                                    Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR,
+                                    Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR);
+            //logln(tz.toString());
+            logln("========================================");
+            testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L);
+            logln("========================================");
+            testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L);
+        }
+
+        /*
+          if (true)
+          {
+          logln("========================================");
+          logln("Stepping using millis");
+          testUsingMillis(new Date(97,0,1), false);
+          }
+
+          if (true)
+          {
+          logln("========================================");
+          logln("Stepping using fields");
+          testUsingFields(1997, false);
+          }
+
+          if (false)
+          {
+          cal.clear();
+          cal.set(1997, 3, 5, 10, 0);
+          //    cal.inDaylightTime();
+          logln("Date = " + cal.getTime());
+          logln("Millis = " + cal.getTime().getTime()/3600000);
+          }
+          */
+    }
+
+    //----------------------------------------------------------------------
+    //----------------------------------------------------------------------
+    //----------------------------------------------------------------------
+    // Long Bug
+    //----------------------------------------------------------------------
+    //----------------------------------------------------------------------
+    //----------------------------------------------------------------------
+
+    //public void Test3()
+    //{
+    //    findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true);
+    //}
+
+    /**
+     * Find boundaries by stepping.
+     */
+    @SuppressWarnings("deprecation")
+    void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges)
+    {
+        Date d = new Date(year - 1900, Calendar.JANUARY, 1);
+        long time = d.getTime(); // ms
+        long limit = time + ONE_YEAR + ONE_DAY;
+        boolean lastState = z.inDaylightTime(d);
+        int changes = 0;
+        logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState);
+        logln("useDaylightTime = " + z.useDaylightTime());
+        while (time < limit)
+        {
+            d.setTime(time);
+            boolean state = z.inDaylightTime(d);
+            if (state != lastState)
+            {
+                logln((state ? "Entry " : "Exit ") +
+                      "at " + d);
+                lastState = state;
+                ++changes;
+            }
+            time += interval;
+        }
+        if (changes == 0)
+        {
+            if (!lastState && !z.useDaylightTime()) logln("No DST");
+            else errln("FAIL: Timezone<" + z.getID() + "> DST all year, or no DST with true useDaylightTime");
+        }
+        else if (changes != 2)
+        {
+            errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; should see 0 or 2");
+        }
+        else if (!z.useDaylightTime())
+        {
+            errln("FAIL: Timezone<" + z.getID() + "> useDaylightTime false but 2 changes seen");
+        }
+        if (changes != expectedChanges)
+        {
+            errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; expected " + expectedChanges);
+        }
+    }
+
+    public void TestStepwise()
+    {
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0);
+        // "EST" is disabled because its behavior depends on the mapping property. (6466476).
+        //findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("HST"), 0);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST8PDT"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST"), 0);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST8PDT"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Japan"), 0);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Europe/Paris"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("America/Los_Angeles"), 2);
+        findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/TimeZoneRegression.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
+ * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
+ * 4966229 6433179 6851214 8007520 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.*;
+
+public class TimeZoneRegression extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new TimeZoneRegression().run(args);
+    }
+
+    public void Test4052967() {
+        logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
+        String id = TimeZone.getDefault().getID();
+        logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));
+        logln("TimeZone.getDefault().getID(): " + id);
+        logln(new Date().toString());
+        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
+    }
+
+    public void Test4073209() {
+        TimeZone z1 = TimeZone.getTimeZone("PST");
+        TimeZone z2 = TimeZone.getTimeZone("PST");
+        if (z1 == z2) {
+            errln("Fail: TimeZone should return clones");
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public void Test4073215() {
+        SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
+        if (z.useDaylightTime()) {
+            errln("Fail: Fix test to start with non-DST zone");
+        }
+        z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
+        z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
+        if (!z.useDaylightTime()) {
+            errln("Fail: DST not active");
+        }
+        if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) ||
+            !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) ||
+            z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) {
+            errln("Fail: DST not working as expected");
+        }
+    }
+
+    /**
+     * The expected behavior of TimeZone around the boundaries is:
+     * (Assume transition time of 2:00 AM)
+     *    day of onset 1:59 AM STD  = display name 1:59 AM ST
+     *                 2:00 AM STD  = display name 3:00 AM DT
+     *    day of end   0:59 AM STD  = display name 1:59 AM DT
+     *                 1:00 AM STD  = display name 1:00 AM ST
+     */
+    public void Test4084933() {
+        // test both SimpleTimeZone and ZoneInfo objects.
+        // @since 1.4
+        sub4084933(getPST());
+        sub4084933(TimeZone.getTimeZone("PST"));
+    }
+
+    private void sub4084933(TimeZone tz) {
+        long offset1 = tz.getOffset(1,
+            1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
+        long offset2 = tz.getOffset(1,
+            1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
+
+        long offset3 = tz.getOffset(1,
+            1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
+        long offset4 = tz.getOffset(1,
+            1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
+
+        /*
+         *  The following was added just for consistency.  It shows that going *to* Daylight
+         *  Savings Time (PDT) does work at 2am.
+         */
+
+        long offset5 = tz.getOffset(1,
+            1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
+        long offset6 = tz.getOffset(1,
+            1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
+
+        long offset7 = tz.getOffset(1,
+            1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
+        long offset8 = tz.getOffset(1,
+            1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
+
+        long SToffset = -8 * 60*60*1000L;
+        long DToffset = -7 * 60*60*1000L;
+        if (offset1 != SToffset || offset2 != SToffset ||
+            offset3 != SToffset || offset4 != DToffset ||
+            offset5 != DToffset || offset6 != SToffset ||
+            offset7 != SToffset || offset8 != SToffset)
+            errln("Fail: TimeZone misbehaving"); {
+        }
+    }
+
+    public void Test4096952() {
+        String[] ZONES = { "GMT", "MET", "IST" };
+        boolean pass = true;
+        try {
+            for (int i=0; i<ZONES.length; ++i) {
+                TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
+                if (!zone.getID().equals(ZONES[i]))
+                    errln("Fail: Test broken; zones not instantiating");
+
+                ByteArrayOutputStream baos;
+                ObjectOutputStream ostream =
+                    new ObjectOutputStream(baos = new
+                                           ByteArrayOutputStream());
+                ostream.writeObject(zone);
+                ostream.close();
+                baos.close();
+                ObjectInputStream istream =
+                    new ObjectInputStream(new
+                                          ByteArrayInputStream(baos.toByteArray()));
+                TimeZone frankenZone = (TimeZone) istream.readObject();
+                //logln("Zone:        " + zone);
+                //logln("FrankenZone: " + frankenZone);
+                if (!zone.equals(frankenZone)) {
+                    logln("TimeZone " + zone.getID() +
+                          " not equal to serialized/deserialized one");
+                    pass = false;
+                }
+            }
+            if (!pass) errln("Fail: TimeZone serialization/equality bug");
+        }
+        catch (IOException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+        catch (ClassNotFoundException e) {
+            errln("Fail: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public void Test4109314() {
+        // test both SimpleTimeZone and ZoneInfo objects.
+        // @since 1.4
+        if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+            return;
+        }
+        sub4109314(getPST());
+        sub4109314(TimeZone.getTimeZone("PST"));
+    }
+
+
+    @SuppressWarnings("deprecation")
+    private void sub4109314(TimeZone PST) {
+        GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
+        Object[] testData = {
+            PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
+            PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
+        };
+        boolean pass=true;
+        for (int i=0; i<testData.length; i+=3) {
+            testCal.setTimeZone((TimeZone) testData[i]);
+            long t = ((Date)testData[i+1]).getTime();
+            Date end = (Date) testData[i+2];
+            while (t < end.getTime()) {
+                testCal.setTime(new Date(t));
+                if (!checkCalendar314(testCal, (TimeZone) testData[i]))
+                    pass = false;
+                t += 60*60*1000L;
+            }
+        }
+        if (!pass) errln("Fail: TZ API inconsistent");
+    }
+
+    boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
+        // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
+
+        final int ONE_DAY = 24*60*60*1000;
+
+        int tzOffset, tzRawOffset;
+        Float tzOffsetFloat,tzRawOffsetFloat;
+        // Here is where the user made an error.  They were passing in the value of
+        // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
+        // time.
+        int millis = testCal.get(Calendar.MILLISECOND) +
+            1000 * (testCal.get(Calendar.SECOND) +
+                    60 * (testCal.get(Calendar.MINUTE) +
+                          60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
+            testCal.get(Calendar.DST_OFFSET);
+
+        /* Fix up millis to be in range.  ASSUME THAT WE ARE NOT AT THE
+         * BEGINNING OR END OF A MONTH.  We must add this code because
+         * getOffset() has been changed to be more strict about the parameters
+         * it receives -- it turns out that this test was passing in illegal
+         * values. */
+        int date = testCal.get(Calendar.DATE);
+        int dow  = testCal.get(Calendar.DAY_OF_WEEK);
+        while (millis < 0) {
+            millis += ONE_DAY;
+            --date;
+            dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7);
+        }
+        while (millis >= ONE_DAY) {
+            millis -= ONE_DAY;
+            ++date;
+            dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7);
+        }
+
+        tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA),
+                                    testCal.get(Calendar.YEAR),
+                                    testCal.get(Calendar.MONTH),
+                                    date,
+                                    dow,
+                                    millis);
+        tzRawOffset = testTZ.getRawOffset();
+        tzOffsetFloat = new Float((float)tzOffset/(float)3600000);
+        tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000);
+
+        Date testDate = testCal.getTime();
+
+        boolean inDaylightTime = testTZ.inDaylightTime(testDate);
+        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
+        sdf.setCalendar(testCal);
+        String inDaylightTimeString;
+
+        boolean passed;
+
+        if (inDaylightTime)
+        {
+            inDaylightTimeString = " DST ";
+            passed = (tzOffset == (tzRawOffset + 3600000));
+        }
+        else
+        {
+            inDaylightTimeString = "     ";
+            passed = (tzOffset == tzRawOffset);
+        }
+
+        String output = testTZ.getID() + " " + sdf.format(testDate) +
+            " Offset(" + tzOffsetFloat + ")" +
+            " RawOffset(" + tzRawOffsetFloat + ")" +
+            " " + millis/(float)3600000 + " " +
+            inDaylightTimeString;
+
+        if (passed)
+            output += "     ";
+        else
+            output += "ERROR";
+
+        if (passed) logln(output); else errln(output);
+        return passed;
+    }
+
+    /**
+     * CANNOT REPRODUDE
+     *
+     * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
+     * should have been made public.  It's simply too hard to use correctly.
+     *
+     * The original test code failed to do the following:
+     * (1) Call Calendar.setTime() before getting the fields!
+     * (2) Use the right millis (as usual) for getOffset(); they were passing
+     *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
+     * When you fix these two problems, the test passes, as expected.
+     */
+    public void Test4126678() {
+        // Note: this test depends on the PST time zone.
+        TimeZone initialZone = TimeZone.getDefault();
+
+        // test both SimpleTimeZone and ZoneInfo objects.
+        // @since 1.4
+        sub4126678(getPST());
+        sub4126678(TimeZone.getTimeZone("PST"));
+
+        // restore the initial time zone so that this test case
+        // doesn't affect the others.
+        TimeZone.setDefault(initialZone);
+    }
+
+    @SuppressWarnings("deprecation")
+    private void sub4126678(TimeZone tz) {
+        Calendar cal = Calendar.getInstance();
+        TimeZone.setDefault(tz);
+        cal.setTimeZone(tz);
+
+        Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0);
+        // the dt value is local time in PST.
+        if (!tz.inDaylightTime(dt))
+            errln("We're not in Daylight Savings Time and we should be.\n");
+
+        cal.setTime(dt);
+        int era = cal.get(Calendar.ERA);
+        int year = cal.get(Calendar.YEAR);
+        int month = cal.get(Calendar.MONTH);
+        int day = cal.get(Calendar.DATE);
+        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
+        int millis = cal.get(Calendar.MILLISECOND) +
+            (cal.get(Calendar.SECOND) +
+             (cal.get(Calendar.MINUTE) +
+              (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
+            cal.get(Calendar.DST_OFFSET);
+
+        long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
+        long raw_offset = tz.getRawOffset();
+        if (offset == raw_offset) {
+            errln("Offsets should not match when in DST");
+        }
+    }
+
+    /**
+     * TimeZone.getAvailableIDs(int) throws exception for certain values,
+     * due to a faulty constant in TimeZone.java.
+     */
+    public void Test4151406() {
+        int max = 0;
+        for (int h=-28; h<=30; ++h) {
+            // h is in half-hours from GMT; rawoffset is in millis
+            int rawoffset = h * 1800000;
+            int hh = (h<0) ? -h : h;
+            String hname = ((h<0) ? "GMT-" : "GMT+") +
+                ((hh/2 < 10) ? "0" : "") +
+                (hh/2) + ':' +
+                ((hh%2==0) ? "00" : "30");
+            try {
+                String[] ids = TimeZone.getAvailableIDs(rawoffset);
+                if (ids.length > max) max = ids.length;
+                logln(hname + ' ' + ids.length +
+                      ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
+            } catch (Exception e) {
+                errln(hname + ' ' + "Fail: " + e);
+            }
+        }
+        logln("Maximum zones per offset = " + max);
+    }
+
+    public void Test4151429() {
+        try {
+            TimeZone tz = TimeZone.getTimeZone("GMT");
+            String name = tz.getDisplayName(true, Integer.MAX_VALUE,
+                                            Locale.getDefault());
+            errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
+        } catch(IllegalArgumentException e) {}
+    }
+
+    /**
+     * SimpleTimeZone accepts illegal DST savings values.  These values
+     * must be non-zero.  There is no upper limit at this time.
+     */
+    public void Test4154525() {
+        final int GOOD = 1, BAD = 0;
+        int[] DATA = {
+            1, GOOD,
+            0, BAD,
+            -1, BAD,
+            60*60*1000, GOOD,
+            Integer.MIN_VALUE, BAD,
+            // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            int savings = DATA[i];
+            boolean valid = DATA[i+1] == GOOD;
+            String method = null;
+            for (int j=0; j<2; ++j) {
+                try {
+                    switch (j) {
+                    case 0:
+                        method = "constructor";
+                        SimpleTimeZone z = new SimpleTimeZone(0, "id",
+                            Calendar.JANUARY, 1, 0, 0,
+                            Calendar.MARCH, 1, 0, 0,
+                            savings); // <- what we're interested in
+                        break;
+                    case 1:
+                        method = "setDSTSavings()";
+                        z = new SimpleTimeZone(0, "GMT");
+                        z.setDSTSavings(savings);
+                        break;
+                    }
+                    if (valid) {
+                        logln("Pass: DST savings of " + savings + " accepted by " + method);
+                    } else {
+                        errln("Fail: DST savings of " + savings + " accepted by " + method);
+                    }
+                } catch (IllegalArgumentException e) {
+                    if (valid) {
+                        errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);
+                    } else {
+                        logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
+     * and different DST parameters.
+     */
+    public void Test4154537() {
+        // tz1 and tz2 have no DST and different rule parameters
+        SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
+        SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
+        // tza and tzA have the same rule params
+        SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
+        SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
+        // tzb differs from tza
+        SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
+        if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
+            !tza.useDaylightTime() || !tzA.useDaylightTime() ||
+            !tzb.useDaylightTime()) {
+            errln("Test is broken -- rewrite it");
+        }
+        if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
+            errln("Fail: hasSameRules() broken for zones with rules");
+        }
+        if (!tz1.hasSameRules(tz2)) {
+            errln("Fail: hasSameRules() returns false for zones without rules");
+            errln("zone 1 = " + tz1);
+            errln("zone 2 = " + tz2);
+        }
+    }
+
+    /**
+     * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
+     * check for out-of-range arguments.
+     */
+    public void Test4154542() {
+        final int GOOD = 1;
+        final int BAD  = 0;
+
+        final int GOOD_MONTH       = Calendar.JANUARY;
+        final int GOOD_DAY         = 1;
+        final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
+        final int GOOD_TIME        = 0;
+
+        int[] DATA = {
+            GOOD, Integer.MIN_VALUE,    0,  Integer.MAX_VALUE,   Integer.MIN_VALUE,
+            GOOD, Calendar.JANUARY,    -5,  Calendar.SUNDAY,     0,
+            GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000-1,
+            GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000,
+            BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000+1,
+            BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,  -1,
+            BAD,  Calendar.JANUARY,    -6,  Calendar.SUNDAY,     0,
+            BAD,  Calendar.DECEMBER,    6,  Calendar.SATURDAY,   24*60*60*1000,
+            GOOD, Calendar.DECEMBER,    1,  0,                   0,
+            GOOD, Calendar.DECEMBER,   31,  0,                   0,
+            BAD,  Calendar.APRIL,      31,  0,                   0,
+            BAD,  Calendar.DECEMBER,   32,  0,                   0,
+            BAD,  Calendar.JANUARY-1,   1,  Calendar.SUNDAY,     0,
+            BAD,  Calendar.DECEMBER+1,  1,  Calendar.SUNDAY,     0,
+            GOOD, Calendar.DECEMBER,   31, -Calendar.SUNDAY,     0,
+            GOOD, Calendar.DECEMBER,   31, -Calendar.SATURDAY,   0,
+            BAD,  Calendar.DECEMBER,   32, -Calendar.SATURDAY,   0,
+            BAD,  Calendar.DECEMBER,  -32, -Calendar.SATURDAY,   0,
+            BAD,  Calendar.DECEMBER,   31, -Calendar.SATURDAY-1, 0,
+        };
+        SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
+        for (int i=0; i<DATA.length; i+=5) {
+            boolean shouldBeGood = (DATA[i] == GOOD);
+            int month     = DATA[i+1];
+            int day       = DATA[i+2];
+            int dayOfWeek = DATA[i+3];
+            int time      = DATA[i+4];
+
+            Exception ex = null;
+            try {
+                zone.setStartRule(month, day, dayOfWeek, time);
+            } catch (IllegalArgumentException e) {
+                ex = e;
+            }
+            if ((ex == null) != shouldBeGood) {
+                errln("setStartRule(month=" + month + ", day=" + day +
+                      ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+                      (shouldBeGood ? (") should work but throws " + ex)
+                       : ") should fail but doesn't"));
+            }
+
+            ex = null;
+            try {
+                zone.setEndRule(month, day, dayOfWeek, time);
+            } catch (IllegalArgumentException e) {
+                ex = e;
+            }
+            if ((ex == null) != shouldBeGood) {
+                errln("setEndRule(month=" + month + ", day=" + day +
+                      ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+                      (shouldBeGood ? (") should work but throws " + ex)
+                       : ") should fail but doesn't"));
+            }
+
+            ex = null;
+            try {
+                SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
+                        month, day, dayOfWeek, time,
+                        GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
+            } catch (IllegalArgumentException e) {
+                ex = e;
+            }
+            if ((ex == null) != shouldBeGood) {
+                errln("SimpleTimeZone(month=" + month + ", day=" + day +
+                      ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+                      (shouldBeGood ? (", <end>) should work but throws " + ex)
+                       : ", <end>) should fail but doesn't"));
+            }
+
+            ex = null;
+            try {
+                SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
+                        GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
+                        month, day, dayOfWeek, time);
+            } catch (IllegalArgumentException e) {
+                ex = e;
+            }
+            if ((ex == null) != shouldBeGood) {
+                errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
+                      ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+                      (shouldBeGood ? (") should work but throws " + ex)
+                       : ") should fail but doesn't"));
+            }
+        }
+    }
+
+    /**
+     * SimpleTimeZone.getOffset accepts illegal arguments.
+     */
+    public void Test4154650() {
+        final int GOOD=1, BAD=0;
+        final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
+        final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
+        int[] DATA = {
+            GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+            GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            BAD,  GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            BAD,  GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+            GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+            GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
+            GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME,
+
+            GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME,
+            GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
+            BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
+
+            GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
+            GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
+            BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
+            BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
+        };
+
+        TimeZone tz = TimeZone.getDefault();
+        for (int i=0; i<DATA.length; i+=7) {
+            boolean good = DATA[i] == GOOD;
+            IllegalArgumentException e = null;
+            try {
+                int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
+                                          DATA[i+4], DATA[i+5], DATA[i+6]);
+           } catch (IllegalArgumentException ex) {
+                e = ex;
+            }
+            if (good != (e == null)) {
+                errln("Fail: getOffset(" +
+                      DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
+                      DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
+                      (good ? (") threw " + e) : ") accepts invalid args"));
+            }
+        }
+    }
+
+    /**
+     * TimeZone constructors allow null IDs.
+     */
+    public void Test4159922() {
+        TimeZone z = null;
+
+        // TimeZone API.  Only hasSameRules() and setDefault() should
+        // allow null.
+        try {
+            z = TimeZone.getTimeZone((String)null);
+            errln("FAIL: Null allowed in getTimeZone");
+        } catch (NullPointerException e) {}
+        z = TimeZone.getTimeZone("GMT");
+        try {
+            z.getDisplayName(false, TimeZone.SHORT, null);
+            errln("FAIL: Null allowed in getDisplayName(3)");
+        } catch (NullPointerException e) {}
+        try {
+            z.getDisplayName(null);
+            errln("FAIL: Null allowed in getDisplayName(1)");
+        } catch (NullPointerException e) {}
+        try {
+            if (z.hasSameRules(null)) {
+                errln("FAIL: hasSameRules returned true");
+            }
+        } catch (NullPointerException e) {
+            errln("FAIL: Null NOT allowed in hasSameRules");
+        }
+        try {
+            z.inDaylightTime(null);
+            errln("FAIL: Null allowed in inDaylightTime");
+        } catch (NullPointerException e) {}
+        try {
+            z.setID(null);
+            errln("FAIL: Null allowed in setID");
+        } catch (NullPointerException e) {}
+
+        TimeZone save = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(null);
+        } catch (NullPointerException e) {
+            errln("FAIL: Null NOT allowed in setDefault");
+        } finally {
+            TimeZone.setDefault(save);
+        }
+
+        // SimpleTimeZone API
+        SimpleTimeZone s = null;
+        try {
+            s = new SimpleTimeZone(0, null);
+            errln("FAIL: Null allowed in SimpleTimeZone(2)");
+        } catch (NullPointerException e) {}
+        try {
+            s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
+            errln("FAIL: Null allowed in SimpleTimeZone(10)");
+        } catch (NullPointerException e) {}
+        try {
+            s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
+            errln("FAIL: Null allowed in SimpleTimeZone(11)");
+        } catch (NullPointerException e) {}
+    }
+
+    /**
+     * TimeZone broken at midnight.  The TimeZone code fails to handle
+     * transitions at midnight correctly.
+     */
+    @SuppressWarnings("deprecation")
+    public void Test4162593() {
+        SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
+        final int ONE_HOUR = 60*60*1000;
+        TimeZone initialZone = TimeZone.getDefault();
+
+        SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
+            Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
+            Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
+
+        /* Zone
+         * Starting time
+         * Transition expected between start+1H and start+2H
+         */
+        Object[] DATA = {
+            new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
+                Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
+                Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
+            new int[] {98, Calendar.SEPTEMBER, 30, 22, 0},
+            Boolean.TRUE,
+
+            asuncion,
+            new int[] {100, Calendar.FEBRUARY, 28, 22, 0},
+            Boolean.FALSE,
+
+            asuncion,
+            new int[] {100, Calendar.FEBRUARY, 29, 22, 0},
+            Boolean.TRUE,
+        };
+
+        String[] zone = new String[4];
+
+        try {
+            for (int j=0; j<DATA.length; j+=3) {
+                TimeZone tz = (TimeZone)DATA[j];
+                TimeZone.setDefault(tz);
+                fmt.setTimeZone(tz);
+
+                // Must construct the Date object AFTER setting the default zone
+                int[] p = (int[])DATA[j+1];
+                Date d = new Date(p[0], p[1], p[2], p[3], p[4]);
+                boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
+
+                logln(tz.getID() + ":");
+                for (int i=0; i<4; ++i) {
+                    zone[i] = fmt.format(d);
+                    logln("" + i + ": " + d);
+                    d = new Date(d.getTime() + ONE_HOUR);
+                }
+                if (zone[0].equals(zone[1]) &&
+                    (zone[1].equals(zone[2]) != transitionExpected) &&
+                    zone[2].equals(zone[3])) {
+                    logln("Ok: transition " + transitionExpected);
+                } else {
+                    errln("Fail: boundary transition incorrect");
+                }
+            }
+        }
+        finally {
+            // restore the initial time zone so that this test case
+            // doesn't affect the others.
+            TimeZone.setDefault(initialZone);
+        }
+    }
+
+    /**
+     * TimeZone broken in last hour of year
+     */
+    public void Test4173604() {
+        // test both SimpleTimeZone and ZoneInfo objects.
+        // @since 1.4
+        sub4173604(getPST());
+        sub4173604(TimeZone.getTimeZone("PST"));
+    }
+
+    private void sub4173604(TimeZone pst) {
+        int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
+        int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
+        int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
+        if (o22 != o23 || o22 != o00) {
+            errln("Offsets should be the same (for PST), but got: " +
+                  "12/31 22:00 " + o22 +
+                  ", 12/31 23:00 " + o23 +
+                  ", 01/01 00:00 " + o00);
+        }
+
+        GregorianCalendar cal = new GregorianCalendar();
+        cal.setTimeZone(pst);
+        cal.clear();
+        cal.set(1998, Calendar.JANUARY, 1);
+        int lastDST = cal.get(Calendar.DST_OFFSET);
+        int transitions = 0;
+        int delta = 5;
+        while (cal.get(Calendar.YEAR) < 2000) {
+            cal.add(Calendar.MINUTE, delta);
+            if (cal.get(Calendar.DST_OFFSET) != lastDST) {
+                ++transitions;
+                Calendar t = (Calendar)cal.clone();
+                t.add(Calendar.MINUTE, -delta);
+                logln(t.getTime() + "  " + t.get(Calendar.DST_OFFSET));
+                logln(cal.getTime() + "  " + (lastDST=cal.get(Calendar.DST_OFFSET)));
+            }
+        }
+        if (transitions != 4) {
+            errln("Saw " + transitions + " transitions; should have seen 4");
+        }
+    }
+
+    /**
+     * getDisplayName doesn't work with unusual savings/offsets.
+     */
+    @SuppressWarnings("deprecation")
+    public void Test4176686() {
+        // Construct a zone that does not observe DST but
+        // that does have a DST savings (which should be ignored).
+        int offset = 90 * 60000; // 1:30
+        SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
+        z1.setDSTSavings(45 * 60000); // 0:45
+
+        // Construct a zone that observes DST for the first 6 months.
+        SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
+        z2.setDSTSavings(45 * 60000); // 0:45
+        z2.setStartRule(Calendar.JANUARY, 1, 0);
+        z2.setEndRule(Calendar.JULY, 1, 0);
+
+        // Also check DateFormat
+        DateFormat fmt1 = new SimpleDateFormat("z");
+        fmt1.setTimeZone(z1); // Format uses standard zone
+        DateFormat fmt2 = new SimpleDateFormat("z");
+        fmt2.setTimeZone(z2); // Format uses DST zone
+        Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST
+        Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard
+
+        // Description, Result, Expected Result
+        String[] DATA = {
+            "getDisplayName(false, SHORT)/std zone",
+            z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+            "getDisplayName(false, LONG)/std zone",
+            z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
+            "getDisplayName(true, SHORT)/std zone",
+            z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
+            "getDisplayName(true, LONG)/std zone",
+            z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
+            "getDisplayName(false, SHORT)/dst zone",
+            z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+            "getDisplayName(false, LONG)/dst zone",
+            z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
+            "getDisplayName(true, SHORT)/dst zone",
+            z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
+            "getDisplayName(true, LONG)/dst zone",
+            z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
+            "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
+            "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
+            "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
+            "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
+        };
+
+        for (int i=0; i<DATA.length; i+=3) {
+            if (!DATA[i+1].equals(DATA[i+2])) {
+                errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
+            }
+        }
+    }
+
+    /**
+     * SimpleTimeZone allows invalid DOM values.
+     */
+    public void Test4184229() {
+        SimpleTimeZone zone = null;
+        try {
+            zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
+            errln("Failed. No exception has been thrown for DOM -1 startDay");
+        } catch(IllegalArgumentException e) {
+            logln("(a) " + e.getMessage());
+        }
+        try {
+            zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
+            errln("Failed. No exception has been thrown for DOM -1 endDay");
+        } catch(IllegalArgumentException e) {
+            logln("(b) " + e.getMessage());
+        }
+        try {
+            zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
+            errln("Failed. No exception has been thrown for DOM -1 startDay +savings");
+        } catch(IllegalArgumentException e) {
+            logln("(c) " + e.getMessage());
+        }
+        try {
+            zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
+            errln("Failed. No exception has been thrown for DOM -1 endDay +savings");
+        } catch(IllegalArgumentException e) {
+            logln("(d) " + e.getMessage());
+        }
+        // Make a valid constructor call for subsequent tests.
+        zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
+        try {
+            zone.setStartRule(0, -1, 0, 0);
+            errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
+        } catch(IllegalArgumentException e) {
+            logln("(e) " + e.getMessage());
+        }
+        try {
+            zone.setStartRule(0, -1, 0);
+            errln("Failed. No exception has been thrown for DOM -1 setStartRule");
+        } catch(IllegalArgumentException e) {
+            logln("(f) " + e.getMessage());
+        }
+        try {
+            zone.setEndRule(0, -1, 0, 0);
+            errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
+        } catch(IllegalArgumentException e) {
+            logln("(g) " + e.getMessage());
+        }
+        try {
+            zone.setEndRule(0, -1, 0);
+            errln("Failed. No exception has been thrown for DOM -1 setEndRule");
+        } catch(IllegalArgumentException e) {
+            logln("(h) " + e.getMessage());
+        }
+    }
+
+    /**
+     * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
+     * of 2/29/1996 (leap day).
+     */
+    public void Test4208960 () {
+        // test both SimpleTimeZone and ZoneInfo objects.
+        // @since 1.4
+        sub4208960(getPST());
+        sub4208960(TimeZone.getTimeZone("PST"));
+    }
+
+    private void sub4208960(TimeZone tz) {
+        try {
+            int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
+                                      Calendar.THURSDAY, 0);
+        } catch (IllegalArgumentException e) {
+            errln("FAILED: to get TimeZone.getOffset(2/29/96)");
+        }
+        try {
+            int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
+                                      Calendar.THURSDAY, 0);
+            errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
+        } catch (IllegalArgumentException e) {
+            logln("got IllegalArgumentException");
+        }
+    }
+
+    /**
+     * 4966229: java.util.Date methods may works incorrect.
+     * sun.util.calendar.ZoneInfo doesn't clone properly.
+     */
+    @SuppressWarnings("deprecation")
+    public void Test4966229() {
+        TimeZone savedTZ = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Date d = new Date(2100-1900, 5, 1); // specify year >2037
+            TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+
+            Calendar cal = new GregorianCalendar(tz);
+            cal.setTime(d);
+
+            // Change the raw offset in tz
+            int offset = tz.getRawOffset();
+            tz.setRawOffset(0);
+
+            TimeZone tz2 = (TimeZone) tz.clone();
+            Calendar cal2 = new GregorianCalendar(tz2);
+            cal2.setTime(d);
+            int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY);
+
+            // Restore the GMT offset in tz which shouldn't affect tz2
+            tz.setRawOffset(offset);
+            cal2.setTime(d);
+            int hourOfDay = cal2.get(cal.HOUR_OF_DAY);
+            if (hourOfDay != expectedHourOfDay) {
+                errln("wrong hour of day: got: " + hourOfDay
+                      + ", expected: " + expectedHourOfDay);
+            }
+        } finally {
+            TimeZone.setDefault(savedTZ);
+        }
+    }
+
+    /**
+     * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+
+     */
+    public void Test6433179() {
+        // Use the old America/Winnipeg rule for testing. Note that
+        // startMode is WALL_TIME for testing. It's actually
+        // STANDARD_TIME, though.
+        //Rule  Winn    1966    2005    -       Oct     lastSun 2:00s   0       S
+        //Rule  Winn    1987    2005    -       Apr     Sun>=1  2:00s   1:00    D
+        TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg",
+          Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME,
+          Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME,
+          1*ONE_HOUR);
+        Calendar cal = Calendar.getInstance(tz, Locale.US);
+        cal.clear();
+        cal.set(2039, Calendar.OCTOBER, 1);
+        cal.getTime();
+        cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
+        cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1);
+        cal.add(Calendar.HOUR_OF_DAY, 2);
+        if (cal.get(cal.DST_OFFSET) == 0) {
+            errln("Should still be in DST.");
+        }
+    }
+
+    private static final int ONE_HOUR = 60 * 60 * 1000;
+    /**
+     * Returns an instance of SimpleTimeZone for
+     * "PST". (TimeZone.getTimeZone() no longer returns a
+     * SimpleTimeZone object.)
+     * @since 1.4
+     */
+    private SimpleTimeZone getPST() {
+        return new SimpleTimeZone(-8*ONE_HOUR, "PST",
+                                  Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR,
+                                  Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR,
+                                  1*ONE_HOUR);
+    }
+}
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/TimeZoneTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
+ *      8008577 8077685 8098547 8133321 8138716 8148446
+ * @modules java.base/sun.util.resources
+ * @library /java/text/testlib
+ * @summary test TimeZone
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+import sun.util.resources.LocaleData;
+
+public class TimeZoneTest extends IntlTest
+{
+    static final int millisPerHour = 3600000;
+
+    public static void main(String[] args) throws Exception {
+        new TimeZoneTest().run(args);
+    }
+
+    /**
+     * Bug 4130885
+     * Certain short zone IDs, used since 1.1.x, are incorrect.
+     *
+     * The worst of these is:
+     *
+     * "CAT" (Central African Time) should be GMT+2:00, but instead returns a
+     * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST,
+     * or AZOST, depending on which zone is meant, but in no case is it CAT.
+     *
+     * Other wrong zone IDs:
+     *
+     * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time,
+     * GMT-5:00. European Central time is abbreviated CEST.
+     *
+     * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time,
+     * GMT-11:00. Solomon Island time is SBT.
+     *
+     * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for
+     * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST.
+     *
+     * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in
+     * another bug.] It should be "AKST". AST is Atlantic Standard Time,
+     * GMT-4:00.
+     *
+     * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time,
+     * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct
+     * from MST with daylight savings.
+     *
+     * In addition to these problems, a number of zones are FAKE. That is, they
+     * don't match what people use in the real world.
+     *
+     * FAKE zones:
+     *
+     * EET (should be EEST)
+     * ART (should be EET)
+     * MET (should be IRST)
+     * NET (should be AMST)
+     * PLT (should be PKT)
+     * BST (should be BDT)
+     * VST (should be ICT)
+     * CTT (should be CST) +
+     * ACT (should be CST) +
+     * AET (should be EST) +
+     * MIT (should be WST) +
+     * IET (should be EST) +
+     * PRT (should be AST) +
+     * CNT (should be NST)
+     * AGT (should be ARST)
+     * BET (should be EST) +
+     *
+     * + A zone with the correct name already exists and means something
+     * else. E.g., EST usually indicates the US Eastern zone, so it cannot be
+     * used for Brazil (BET).
+     */
+    public void TestShortZoneIDs() throws Exception {
+
+        ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
+            new ZoneDescriptor("MIT", 780, true),
+            new ZoneDescriptor("HST", -600, false),
+            new ZoneDescriptor("AST", -540, true),
+            new ZoneDescriptor("PST", -480, true),
+            new ZoneDescriptor("PNT", -420, false),
+            new ZoneDescriptor("MST", -420, false),
+            new ZoneDescriptor("CST", -360, true),
+            new ZoneDescriptor("IET", -300, true),
+            new ZoneDescriptor("EST", -300, false),
+            new ZoneDescriptor("PRT", -240, false),
+            new ZoneDescriptor("CNT", -210, true),
+            new ZoneDescriptor("AGT", -180, false),
+            new ZoneDescriptor("BET", -180, true),
+            // new ZoneDescriptor("CAT", -60, false), // Wrong:
+            // As of bug 4130885, fix CAT (Central Africa)
+            new ZoneDescriptor("CAT", 120, false), // Africa/Harare
+            new ZoneDescriptor("GMT", 0, false),
+            new ZoneDescriptor("UTC", 0, false),
+            new ZoneDescriptor("ECT", 60, true),
+            new ZoneDescriptor("ART", 120, false),
+            new ZoneDescriptor("EET", 120, true),
+            new ZoneDescriptor("EAT", 180, false),
+            new ZoneDescriptor("MET", 60, true),
+            new ZoneDescriptor("NET", 240, false),
+            new ZoneDescriptor("PLT", 300, false),
+            new ZoneDescriptor("IST", 330, false),
+            new ZoneDescriptor("BST", 360, false),
+            new ZoneDescriptor("VST", 420, false),
+            new ZoneDescriptor("CTT", 480, false),
+            new ZoneDescriptor("JST", 540, false),
+            new ZoneDescriptor("ACT", 570, false),
+            new ZoneDescriptor("AET", 600, true),
+            new ZoneDescriptor("SST", 660, false),
+            // new ZoneDescriptor("NST", 720, false),
+            // As of bug 4130885, fix NST (New Zealand)
+            new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
+        };
+
+        Map<String, ZoneDescriptor> hash = new HashMap<>();
+
+        String[] ids = TimeZone.getAvailableIDs();
+        for (String id : ids) {
+            if (id.length() == 3) {
+                hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
+            }
+        }
+
+        for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) {
+            ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
+            ZoneDescriptor currentZone = hash.get(referenceZone.getID());
+            if (referenceZone.equals(currentZone)) {
+                logln("ok " + referenceZone);
+            }
+            else {
+                errln("Fail: Expected " + referenceZone +
+                      "; got " + currentZone);
+            }
+        }
+    }
+
+    /**
+     * A descriptor for a zone; used to regress the short zone IDs.
+     */
+    static class ZoneDescriptor {
+        String id;
+        int offset; // In minutes
+        boolean daylight;
+
+        ZoneDescriptor(TimeZone zone) {
+            this.id = zone.getID();
+            this.offset = zone.getRawOffset() / 60000;
+            this.daylight = zone.useDaylightTime();
+        }
+
+        ZoneDescriptor(String id, int offset, boolean daylight) {
+            this.id = id;
+            this.offset = offset;
+            this.daylight = daylight;
+        }
+
+        public String getID() { return id; }
+
+        @Override
+        public boolean equals(Object o) {
+            ZoneDescriptor that = (ZoneDescriptor)o;
+            return that != null &&
+                id.equals(that.id) &&
+                offset == that.offset &&
+                daylight == that.daylight;
+        }
+
+        @Override
+        public int hashCode() {
+            return id.hashCode() ^ offset | (daylight ? 1 : 0);
+        }
+
+        @Override
+        public String toString() {
+            int min = offset;
+            char sign = '+';
+            if (min < 0) { sign = '-'; min = -min; }
+
+            return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' +
+                (min%60<10?"0":"") + (min%60) + ", " +
+                (daylight ? "Daylight" : "Standard") + "]";
+        }
+
+        public static int compare(Object o1, Object o2) {
+            ZoneDescriptor i1 = (ZoneDescriptor)o1;
+            ZoneDescriptor i2 = (ZoneDescriptor)o2;
+            if (i1.offset > i2.offset) return 1;
+            if (i1.offset < i2.offset) return -1;
+            if (i1.daylight && !i2.daylight) return 1;
+            if (!i1.daylight && i2.daylight) return -1;
+            return i1.id.compareTo(i2.id);
+        }
+    }
+
+    static final String formatMinutes(int min) {
+        char sign = '+';
+        if (min < 0) { sign = '-'; min = -min; }
+        int h = min/60;
+        min = min%60;
+        return "" + sign + h + ":" + ((min<10) ? "0" : "") + min;
+    }
+    /**
+     * As part of the VM fix (see CCC approved RFE 4028006, bug
+     * 4044013), TimeZone.getTimeZone() has been modified to recognize
+     * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and
+     * GMT[+-]hh.  Test this behavior here.
+     *
+     * Bug 4044013
+     *
+     * ID "Custom" is no longer used for TimeZone objects created with
+     * a custom time zone ID, such as "GMT-8". See 4322313.
+     */
+    public void TestCustomParse() throws Exception {
+        Object[] DATA = {
+            // ID        Expected offset in minutes
+            "GMT",       null,
+            "GMT+0",     new Integer(0),
+            "GMT+1",     new Integer(60),
+            "GMT-0030",  new Integer(-30),
+            "GMT+15:99", null,
+            "GMT+",      null,
+            "GMT-",      null,
+            "GMT+0:",    null,
+            "GMT-:",     null,
+            "GMT+0010",  new Integer(10), // Interpret this as 00:10
+            "GMT-10",    new Integer(-10*60),
+            "GMT+30",    null,
+            "GMT-3:30",  new Integer(-(3*60+30)),
+            "GMT-230",   new Integer(-(2*60+30)),
+        };
+        for (int i=0; i<DATA.length; i+=2) {
+            String id = (String)DATA[i];
+            Integer exp = (Integer)DATA[i+1];
+            TimeZone zone = TimeZone.getTimeZone(id);
+            if (zone.getID().equals("GMT")) {
+                logln(id + " -> generic GMT");
+                // When TimeZone.getTimeZone() can't parse the id, it
+                // returns GMT -- a dubious practice, but required for
+                // backward compatibility.
+                if (exp != null) {
+                    throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) +
+                                        " for " + id + ", got parse failure");
+                }
+            }
+            else {
+                int ioffset = zone.getRawOffset()/60000;
+                String offset = formatMinutes(ioffset);
+                logln(id + " -> " + zone.getID() + " GMT" + offset);
+                if (exp == null) {
+                    throw new Exception("Expected parse failure for " + id +
+                                        ", got offset of " + offset +
+                                        ", id " + zone.getID());
+                }
+                else if (ioffset != exp.intValue()) {
+                    throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) +
+                                        ", id Custom, for " + id +
+                                        ", got offset of " + offset +
+                                        ", id " + zone.getID());
+                }
+            }
+        }
+    }
+
+    /**
+     * Test the basic functionality of the getDisplayName() API.
+     *
+     * Bug 4112869
+     * Bug 4028006
+     *
+     * See also API change request A41.
+     *
+     * 4/21/98 - make smarter, so the test works if the ext resources
+     * are present or not.
+     */
+    public void TestDisplayName() {
+        TimeZone zone = TimeZone.getTimeZone("PST");
+        String name = zone.getDisplayName(Locale.ENGLISH);
+        logln("PST->" + name);
+        if (!name.equals("Pacific Standard Time"))
+            errln("Fail: Expected \"Pacific Standard Time\"");
+
+        //*****************************************************************
+        // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        //*****************************************************************
+        Object[] DATA = {
+            new Boolean(false), new Integer(TimeZone.SHORT), "PST",
+            new Boolean(true),  new Integer(TimeZone.SHORT), "PDT",
+            new Boolean(false), new Integer(TimeZone.LONG),  "Pacific Standard Time",
+            new Boolean(true),  new Integer(TimeZone.LONG),  "Pacific Daylight Time",
+        };
+
+        for (int i=0; i<DATA.length; i+=3) {
+            name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(),
+                                       ((Integer)DATA[i+1]).intValue(),
+                                       Locale.ENGLISH);
+            if (!name.equals(DATA[i+2]))
+                errln("Fail: Expected " + DATA[i+2] + "; got " + name);
+        }
+
+        // Make sure that we don't display the DST name by constructing a fake
+        // PST zone that has DST all year long.
+        SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST");
+        zone2.setStartRule(Calendar.JANUARY, 1, 0);
+        zone2.setEndRule(Calendar.DECEMBER, 31, 0);
+        logln("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date()));
+        name = zone2.getDisplayName(Locale.ENGLISH);
+        logln("Modified PST->" + name);
+        if (!name.equals("Pacific Standard Time"))
+            errln("Fail: Expected \"Pacific Standard Time\"");
+
+        // Make sure we get the default display format for Locales
+        // with no display name data.
+        Locale zh_CN = Locale.SIMPLIFIED_CHINESE;
+        name = zone.getDisplayName(zh_CN);
+        //*****************************************************************
+        // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+        //*****************************************************************
+        logln("PST(zh_CN)->" + name);
+
+        // Now be smart -- check to see if zh resource is even present.
+        // If not, we expect the en fallback behavior.
+        ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
+                                                   Locale.ENGLISH);
+        ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
+                                                   zh_CN);
+
+        boolean noZH = enRB == zhRB;
+
+        if (noZH) {
+            logln("Warning: Not testing the zh_CN behavior because resource is absent");
+            if (!name.equals("Pacific Standard Time"))
+                errln("Fail: Expected Pacific Standard Time");
+        }
+        else if (!name.equals("Pacific Standard Time") &&
+                 !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
+                 !name.equals("GMT-08:00") &&
+                 !name.equals("GMT-8:00") &&
+                 !name.equals("GMT-0800") &&
+                 !name.equals("GMT-800")) {
+            errln("Fail: Expected GMT-08:00 or something similar");
+            errln("************************************************************");
+            errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED");
+            errln("************************************************************");
+        }
+
+        // Now try a non-existent zone
+        zone2 = new SimpleTimeZone(90*60*1000, "xyzzy");
+        name = zone2.getDisplayName(Locale.ENGLISH);
+        logln("GMT+90min->" + name);
+        if (!name.equals("GMT+01:30") &&
+            !name.equals("GMT+1:30") &&
+            !name.equals("GMT+0130") &&
+            !name.equals("GMT+130"))
+            errln("Fail: Expected GMT+01:30 or something similar");
+    }
+
+    public void TestGenericAPI() {
+        String id = "NewGMT";
+        int offset = 12345;
+
+        SimpleTimeZone zone = new SimpleTimeZone(offset, id);
+        if (zone.useDaylightTime()) {
+            errln("FAIL: useDaylightTime should return false");
+        }
+
+        TimeZone zoneclone = (TimeZone)zone.clone();
+        if (!zoneclone.equals(zone)) {
+            errln("FAIL: clone or operator== failed");
+        }
+        zoneclone.setID("abc");
+        if (zoneclone.equals(zone)) {
+            errln("FAIL: clone or operator!= failed");
+        }
+
+        zoneclone = (TimeZone)zone.clone();
+        if (!zoneclone.equals(zone)) {
+            errln("FAIL: clone or operator== failed");
+        }
+        zoneclone.setRawOffset(45678);
+        if (zoneclone.equals(zone)) {
+            errln("FAIL: clone or operator!= failed");
+        }
+
+        TimeZone saveDefault = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(zone);
+            TimeZone defaultzone = TimeZone.getDefault();
+            if (defaultzone == zone) {
+                errln("FAIL: Default object is identical, not clone");
+            }
+            if (!defaultzone.equals(zone)) {
+                errln("FAIL: Default object is not equal");
+            }
+        }
+        finally {
+            TimeZone.setDefault(saveDefault);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public void TestRuleAPI()
+    {
+        // ErrorCode status = ZERO_ERROR;
+
+        int offset = (int)(60*60*1000*1.75); // Pick a weird offset
+        SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone");
+        if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false");
+
+        // Establish our expected transition times.  Do this with a non-DST
+        // calendar with the (above) declared local offset.
+        GregorianCalendar gc = new GregorianCalendar(zone);
+        gc.clear();
+        gc.set(1990, Calendar.MARCH, 1);
+        long marchOneStd = gc.getTime().getTime(); // Local Std time midnight
+        gc.clear();
+        gc.set(1990, Calendar.JULY, 1);
+        long julyOneStd = gc.getTime().getTime(); // Local Std time midnight
+
+        // Starting and ending hours, WALL TIME
+        int startHour = (int)(2.25 * 3600000);
+        int endHour   = (int)(3.5  * 3600000);
+
+        zone.setStartRule(Calendar.MARCH, 1, 0, startHour);
+        zone.setEndRule  (Calendar.JULY,  1, 0, endHour);
+
+        gc = new GregorianCalendar(zone);
+        // if (failure(status, "new GregorianCalendar")) return;
+
+        long marchOne = marchOneStd + startHour;
+        long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time
+
+        long expMarchOne = 636251400000L;
+        if (marchOne != expMarchOne)
+        {
+            errln("FAIL: Expected start computed as " + marchOne +
+                  " = " + new Date(marchOne));
+            logln("      Should be                  " + expMarchOne +
+                  " = " + new Date(expMarchOne));
+        }
+
+        long expJulyOne = 646793100000L;
+        if (julyOne != expJulyOne)
+        {
+            errln("FAIL: Expected start computed as " + julyOne +
+                  " = " + new Date(julyOne));
+            logln("      Should be                  " + expJulyOne +
+                  " = " + new Date(expJulyOne));
+        }
+
+        testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(),
+                              new Date(90, Calendar.JUNE, 15).getTime(), marchOne);
+        testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(),
+                              new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne);
+
+        if (zone.inDaylightTime(new Date(marchOne - 1000)) ||
+            !zone.inDaylightTime(new Date(marchOne)))
+            errln("FAIL: Start rule broken");
+        if (!zone.inDaylightTime(new Date(julyOne - 1000)) ||
+            zone.inDaylightTime(new Date(julyOne)))
+            errln("FAIL: End rule broken");
+
+        zone.setStartYear(1991);
+        if (zone.inDaylightTime(new Date(marchOne)) ||
+            zone.inDaylightTime(new Date(julyOne - 1000)))
+            errln("FAIL: Start year broken");
+
+        // failure(status, "TestRuleAPI");
+        // delete gc;
+        // delete zone;
+    }
+
+    void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary)
+    {
+        // ErrorCode status = ZERO_ERROR;
+        boolean startsInDST = tz.inDaylightTime(new Date(min));
+        // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+        if (tz.inDaylightTime(new Date(max)) == startsInDST) {
+            logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST));
+            return;
+        }
+        // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+        while ((max - min) > INTERVAL) {
+            long mid = (min + max) / 2;
+            if (tz.inDaylightTime(new Date(mid)) == startsInDST) {
+                min = mid;
+            }
+            else {
+                max = mid;
+            }
+            // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+        }
+        logln("Binary Search Before: " + min + " = " + new Date(min));
+        logln("Binary Search After:  " + max + " = " + new Date(max));
+        long mindelta = expectedBoundary - min;
+        long maxdelta = max - expectedBoundary;
+        if (mindelta >= 0 &&
+            mindelta <= INTERVAL &&
+            mindelta >= 0 &&
+            mindelta <= INTERVAL)
+            logln("PASS: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
+        else
+            errln("FAIL: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
+    }
+
+    static final int INTERVAL = 100;
+
+    // Bug 006; verify the offset for a specific zone.
+    public void TestPRTOffset()
+    {
+        TimeZone tz = TimeZone.getTimeZone( "PRT" );
+        if( tz == null ) {
+            errln( "FAIL: TimeZone(PRT) is null" );
+        }
+        else{
+            if (tz.getRawOffset() != (-4*millisPerHour))
+                errln("FAIL: Offset for PRT should be -4");
+        }
+
+    }
+
+    // Test various calls
+    @SuppressWarnings("deprecation")
+    public void TestVariousAPI518()
+    {
+        TimeZone time_zone = TimeZone.getTimeZone("PST");
+        Date d = new Date(97, Calendar.APRIL, 30);
+
+        logln("The timezone is " + time_zone.getID());
+
+        if (time_zone.inDaylightTime(d) != true)
+            errln("FAIL: inDaylightTime returned false");
+
+        if (time_zone.useDaylightTime() != true)
+            errln("FAIL: useDaylightTime returned false");
+
+        if (time_zone.getRawOffset() != -8*millisPerHour)
+            errln( "FAIL: getRawOffset returned wrong value");
+
+        GregorianCalendar gc = new GregorianCalendar();
+        gc.setTime(d);
+        if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH),
+                                gc.get(gc.DAY_OF_MONTH),
+                                gc.get(gc.DAY_OF_WEEK), 0)
+            != -7*millisPerHour)
+            errln("FAIL: getOffset returned wrong value");
+    }
+
+    // Test getAvailableID API
+    public void TestGetAvailableIDs913()
+    {
+        StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { ");
+        String[] s = TimeZone.getAvailableIDs();
+        for (int i=0; i<s.length; ++i)
+        {
+            if (i > 0) buf.append(", ");
+            buf.append(s[i]);
+        }
+        buf.append(" };");
+        logln(buf.toString());
+
+        buf.setLength(0);
+        buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { ");
+        s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000);
+        for (int i=0; i<s.length; ++i)
+        {
+            if (i > 0) buf.append(", ");
+            buf.append(s[i]);
+        }
+        buf.append(" };");
+        logln(buf.toString());
+
+        TimeZone tz = TimeZone.getTimeZone("PST");
+        if (tz != null)
+            logln("getTimeZone(PST) = " + tz.getID());
+        else
+            errln("FAIL: getTimeZone(PST) = null");
+
+        tz = TimeZone.getTimeZone("America/Los_Angeles");
+        if (tz != null)
+            logln("getTimeZone(America/Los_Angeles) = " + tz.getID());
+        else
+            errln("FAIL: getTimeZone(PST) = null");
+
+        // Bug 4096694
+        tz = TimeZone.getTimeZone("NON_EXISTENT");
+        if (tz == null)
+            errln("FAIL: getTimeZone(NON_EXISTENT) = null");
+        else if (!tz.getID().equals("GMT"))
+            errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID());
+    }
+
+    /**
+     * Bug 4107276
+     */
+    public void TestDSTSavings() {
+        // It might be better to find a way to integrate this test into the main TimeZone
+        // tests above, but I don't have time to figure out how to do this (or if it's
+        // even really a good idea).  Let's consider that a future.  --rtg 1/27/98
+        SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest",
+                                               Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0,
+                                               (int)(0.5 * millisPerHour));
+
+        if (tz.getRawOffset() != -5 * millisPerHour)
+            errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) +
+                  " hours instead of -5 hours.");
+        if (!tz.useDaylightTime())
+            errln("Test time zone should use DST but claims it doesn't.");
+        if (tz.getDSTSavings() != 0.5 * millisPerHour)
+            errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() /
+                                                                 millisPerHour) + " hours instead.");
+
+        int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
+                                  Calendar.THURSDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
+                              10 * millisPerHour);
+        if (offset != -4.5 * millisPerHour)
+            errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        tz.setDSTSavings(millisPerHour);
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
+                              Calendar.THURSDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
+                              10 * millisPerHour);
+        if (offset != -4 * millisPerHour)
+            errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+    }
+
+    /**
+     * Bug 4107570
+     */
+    public void TestAlternateRules() {
+        // Like TestDSTSavings, this test should probably be integrated somehow with the main
+        // test at the top of this class, but I didn't have time to figure out how to do that.
+        //                      --rtg 1/28/98
+
+        SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest");
+
+        // test the day-of-month API
+        tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour);
+        tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour);
+
+        int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5,
+                                  Calendar.THURSDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15,
+                              Calendar.SUNDAY, 10 * millisPerHour);
+        if (offset != -4 * millisPerHour)
+            errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
+                              Calendar.THURSDAY, 10 * millisPerHour);
+        if (offset != -4 * millisPerHour)
+            errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25,
+                              Calendar.SUNDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        // test the day-of-week-after-day-in-month API
+        tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true);
+        tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false);
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11,
+                              Calendar.WEDNESDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14,
+                              Calendar.SATURDAY, 10 * millisPerHour);
+        if (offset != -4 * millisPerHour)
+            errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
+                              Calendar.THURSDAY, 10 * millisPerHour);
+        if (offset != -4 * millisPerHour)
+            errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+
+        offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17,
+                              Calendar.SATURDAY, 10 * millisPerHour);
+        if (offset != -5 * millisPerHour)
+            errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got "
+                  + (offset / millisPerHour) + " hours.");
+    }
+}
+
+//eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/TransitionTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4278609 4761696
+ * @library /java/text/testlib
+ * @summary Make sure to handle DST transition ending at 0:00 January 1.
+ */
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+public class TransitionTest extends IntlTest {
+
+    public static void main(String[] args) throws Exception {
+        new TransitionTest().run(args);
+    }
+
+    public void Test4278609() {
+        SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone",
+                               /* DST start day: August, 1, 0:00 */
+                               Calendar.AUGUST, 1, 0, 0,
+                               /* DST end day: January, 1, 0:00 (wall-clock)*/
+                               Calendar.JANUARY, 1, 0, 0,
+                               60 * 60 * 1000);
+
+        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+
+        // setting a date using GMT zone just after the end rule of tz zone
+        cal.clear();
+        cal.set(Calendar.ERA, GregorianCalendar.AD);
+        cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00);
+
+        Date date = cal.getTime();
+
+        int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000
+                     + cal.get(Calendar.MINUTE) * 60000
+                     + cal.get(Calendar.SECOND) * 1000
+                     + cal.get(Calendar.MILLISECOND);
+        /* we must use standard local time */
+        millis += tz.getRawOffset();
+
+        int offset = tz.getOffset(cal.get(Calendar.ERA),
+                                  cal.get(Calendar.YEAR),
+                                  cal.get(Calendar.MONTH),
+                                  cal.get(Calendar.DATE),
+                                  cal.get(Calendar.DAY_OF_WEEK),
+                                  millis);
+
+        if (offset != 0) {
+            SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz",
+                                                           Locale.US);
+            format.setTimeZone(tz);
+            errln("Wrong DST transition: " + tz
+                  + "\na date just after DST = " + format.format(date)
+                  + "\ngetOffset = " + offset);
+        }
+    }
+
+    /*
+     * 4761696: Rewrite SimpleTimeZone to support correct DST transitions
+     *
+     * Derived from JCK test cases some of which specify wrong day of week values.
+     */
+    public void Test4761696() {
+        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+
+        // test#1
+        int rawOffset = -43200000;
+        int saving = 1800000;
+        int timeOfDay = 84600001;
+        SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.JULY, 1, 0, 0,
+                                Calendar.JANUARY, 1, 0, 0,
+                                saving);
+        int year = Integer.MIN_VALUE;
+        tz.setStartYear(year);
+        int offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.DECEMBER,
+                              31,
+                              1, // should be SATURDAY
+                              timeOfDay);
+        int y = (int) mod((long)year, 28L); // 28-year cycle
+        cal.clear();
+        cal.set(cal.ERA, cal.AD);
+        cal.set(y, Calendar.DECEMBER, 31);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        long localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(cal.ERA, cal.AD);
+        cal.set(y + 1, Calendar.JANUARY, 1);
+        cal.set(cal.MILLISECOND, -saving);
+        long endTime = cal.getTimeInMillis() + rawOffset;
+        long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("test#1: wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+
+        // test#2
+        saving = 1;
+        timeOfDay = 0;
+        tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.JULY, 1, 0, 0,
+                                Calendar.JANUARY, 1, 0, 0,
+                                saving);
+        tz.setStartYear(year);
+        offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.AUGUST,
+                              15,
+                              1, // should be MONDAY
+                              timeOfDay);
+        y = (int) mod((long)year, 28L); // 28-year cycle
+        cal.clear();
+        cal.set(y, Calendar.AUGUST, 15);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(y + 1, Calendar.JANUARY, 1);
+        cal.set(cal.MILLISECOND, -saving);
+        endTime = cal.getTimeInMillis() + rawOffset;
+        expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("Wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+
+        rawOffset = 43200000;
+        saving = 1;
+        timeOfDay = 3599998;
+        tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.JULY, 1, 0, 3600000,
+                                Calendar.JANUARY, 1, 0, 3600000,
+                                saving);
+        tz.setStartYear(year);
+        offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.JANUARY,
+                              1,
+                              1,
+                              timeOfDay);
+        y = (int) mod((long)year, 28L); // 28-year cycle
+        cal.clear();
+        cal.set(y, Calendar.JANUARY, 1);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(y + 1, Calendar.JANUARY, 1);
+        cal.set(cal.MILLISECOND, 3600000-saving);
+        endTime = cal.getTimeInMillis() + rawOffset;
+        expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("test#2: wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+
+        // test#3
+        rawOffset = -43200000;
+        saving = 1800000;
+        timeOfDay = 84600001;
+        tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.SEPTEMBER, 1, 0, 0,
+                                Calendar.MARCH, 1, 0, 0,
+                                saving);
+        tz.setStartYear(year);
+        offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.FEBRUARY,
+                              28,
+                              1,
+                              timeOfDay);
+        y = (int) mod((long)year, 28L); // 28-year cycle
+        cal.clear();
+        cal.set(y, Calendar.FEBRUARY, 28);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(y, Calendar.MARCH, 1);
+        cal.set(cal.MILLISECOND, -saving);
+        endTime = cal.getTimeInMillis() + rawOffset;
+        expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("test#3: wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+
+        // test#4
+        rawOffset = -43200000;
+        saving = 1;
+        timeOfDay = 0;
+        tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.JANUARY, -4, 1, 3600000,
+                                Calendar.JULY, -4, 1, 3600000,
+                                saving);
+        tz.setStartYear(year);
+        offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.JANUARY,
+                              10,
+                              2, // should be 1 (SUNDAY)
+                              timeOfDay);
+        y = (int) mod((long)year, 28L); // 28-year cycle
+        cal.clear();
+        cal.set(y, Calendar.JANUARY, 10);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(cal.YEAR, y);
+        cal.set(cal.MONTH, Calendar.JANUARY);
+        cal.set(cal.DAY_OF_MONTH, 8);
+        cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1);
+        cal.set(cal.DAY_OF_WEEK, 1);
+        cal.set(cal.MILLISECOND, 3600000-saving);
+        long startTime = cal.getTimeInMillis() + rawOffset;
+        expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("test#4: wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+
+        // test#5
+        rawOffset = 0;
+        saving = 3600000;
+        timeOfDay = 7200000;
+        year = 1982;
+        tz = new SimpleTimeZone(rawOffset, "stz",
+                                Calendar.APRIL, 1, 0, 7200000,
+                                Calendar.OCTOBER, 10, 0, 7200000,
+                                saving);
+        offset = tz.getOffset(GregorianCalendar.AD,
+                              year,
+                              Calendar.OCTOBER,
+                              10,
+                              1,
+                              timeOfDay);
+        cal.clear();
+        cal.set(year, Calendar.OCTOBER, 10);
+        cal.set(cal.MILLISECOND, timeOfDay);
+        localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+        cal.clear();
+        cal.set(year, Calendar.OCTOBER, 10);
+        cal.set(cal.MILLISECOND, 7200000-saving);
+        endTime = cal.getTimeInMillis() + rawOffset;
+        expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+        if (offset != expectedOffset) {
+            errln("test#5: wrong offset: got "+offset+", expected="+expectedOffset);
+        }
+    }
+
+    public static final long floorDivide(long n, long d) {
+        return ((n >= 0) ?
+                (n / d) : (((n + 1L) / d) - 1L));
+    }
+
+    public static final long mod(long x, long y) {
+        return (x - y * floorDivide(x, y));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/UTCAliasTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6282072
+ * @summary Make sure that "UTC" is an alias of "Etc/UTC" as defined in the tzdata backward.
+ * @modules java.base/sun.util.calendar
+ * @compile -XDignore.symbol.file UTCAliasTest.java
+ */
+
+import java.util.*;
+import sun.util.calendar.ZoneInfo;
+
+public class UTCAliasTest {
+    public static void main(String[] args) {
+        Map<String,String> map = ZoneInfo.getAliasTable();
+        String alias = map.get("UTC");
+        if (!alias.equals("Etc/UTC")) {
+            throw new RuntimeException("got " + alias + ", expected Etc/UTC");
+        }
+        TimeZone GMT = TimeZone.getTimeZone("GMT");
+        TimeZone UTC = TimeZone.getTimeZone("UTC");
+        if (!GMT.hasSameRules(UTC)) {
+            throw new RuntimeException("GMT and UTC have different rules");
+        }
+        TimeZone EtcUTC = TimeZone.getTimeZone("Etc/UTC");
+        if (!UTC.hasSameRules(EtcUTC)) {
+            throw new RuntimeException("UTC and Etc/UTC have different rules");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/bug4096952.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4096952
+ * @summary simple serialization/deserialization test
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.TimeZone;
+
+public class bug4096952 {
+
+    public static void main(String[] args) {
+        int errors = 0;
+        String[] ZONES = { "GMT", "MET", "IST" };
+        for (String id : ZONES) {
+            TimeZone zone = TimeZone.getTimeZone(id);
+            try {
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                try (ObjectOutputStream ostream = new ObjectOutputStream(baos)) {
+                    ostream.writeObject(zone);
+                }
+                try (ObjectInputStream istream
+                        = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+                    if (!zone.equals(istream.readObject())) {
+                        errors++;
+                        System.out.println("Time zone " + id + " are not equal to serialized/deserialized one.");
+                    } else {
+                        System.out.println("Time zone " + id + " ok.");
+                    }
+                }
+            } catch (IOException | ClassNotFoundException e) {
+                errors++;
+                System.out.println(e);
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException("test failed");
+        }
+    }
+}
--- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java	Wed Jul 05 21:46:22 2017 +0200
@@ -25,13 +25,10 @@
  * @test
  * @bug 6503247 6574123
  * @summary Test resilience to tryAcquire methods that throw
- * @library /lib/testlibrary/
  * @author Martin Buchholz
  */
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -39,7 +36,6 @@
 import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
-import jdk.testlibrary.Utils;
 
 /**
  * This uses a variant of the standard Mutex demo, except with a
@@ -48,22 +44,10 @@
  */
 @SuppressWarnings("serial")
 public class FlakyMutex implements Lock {
-    static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
     static class MyError extends Error {}
     static class MyException extends Exception {}
     static class MyRuntimeException extends RuntimeException {}
 
-    static final Random rnd = new Random();
-
-    static void maybeThrow() {
-        switch (rnd.nextInt(10)) {
-        case 0: throw new MyError();
-        case 1: throw new MyRuntimeException();
-        case 2: FlakyMutex.<RuntimeException>uncheckedThrow(new MyException());
-        default: /* Do nothing */ break;
-        }
-    }
-
     static void checkThrowable(Throwable t) {
         check((t instanceof MyError) ||
               (t instanceof MyException) ||
@@ -72,31 +56,35 @@
 
     static void realMain(String[] args) throws Throwable {
         final int nThreads = 3;
-        final CyclicBarrier barrier = new CyclicBarrier(nThreads + 1);
-        final FlakyMutex m = new FlakyMutex();
+        final int iterations = 10_000;
+        final CyclicBarrier startingGate = new CyclicBarrier(nThreads);
+        final FlakyMutex mutex = new FlakyMutex();
         final ExecutorService es = Executors.newFixedThreadPool(nThreads);
-        for (int i = 0; i < nThreads; i++) {
-            es.submit(new Runnable() { public void run() {
-                try {
-                    barrier.await();
-                    for (int i = 0; i < 10000; i++) {
-                        for (;;) {
-                            try { m.lock(); break; }
-                            catch (Throwable t) { checkThrowable(t); }
-                        }
+        final Runnable task = () -> {
+            try {
+                startingGate.await();
+                for (int i = 0; i < iterations; i++) {
+                    for (;;) {
+                        try { mutex.lock(); break; }
+                        catch (Throwable t) { checkThrowable(t); }
+                    }
 
-                        try { check(! m.tryLock()); }
-                        catch (Throwable t) { checkThrowable(t); }
+                    try { check(! mutex.tryLock()); }
+                    catch (Throwable t) { checkThrowable(t); }
 
-                        try { check(! m.tryLock(1, TimeUnit.MICROSECONDS)); }
-                        catch (Throwable t) { checkThrowable(t); }
+                    try { check(! mutex.tryLock(1, TimeUnit.MICROSECONDS)); }
+                    catch (Throwable t) { checkThrowable(t); }
 
-                        m.unlock();
-                    }
-                } catch (Throwable t) { unexpected(t); }}});}
-        barrier.await();
+                    mutex.unlock();
+                }
+            } catch (Throwable t) { unexpected(t); }
+        };
+
+        for (int i = 0; i < nThreads; i++)
+            es.submit(task);
         es.shutdown();
-        check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+        // Let test harness handle timeout
+        check(es.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS));
     }
 
     private static class FlakySync extends AbstractQueuedLongSynchronizer {
@@ -116,8 +104,12 @@
                 do {} while (hasQueuedPredecessors() != hasQueuedThreads());
             }
 
-            maybeThrow();
-            return compareAndSetState(0, 1);
+            switch (ThreadLocalRandom.current().nextInt(10)) {
+            case 0: throw new MyError();
+            case 1: throw new MyRuntimeException();
+            case 2: FlakyMutex.<RuntimeException>uncheckedThrow(new MyException());
+            default: return compareAndSetState(0, 1);
+            }
         }
 
         public boolean tryRelease(long releases) {
--- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java	Wed Jul 05 21:46:22 2017 +0200
@@ -35,16 +35,10 @@
  * @test
  * @bug 8074773
  * @summary Stress test looks for lost unparks
- * @library /lib/testlibrary/
- * @modules java.management
- * @run main/timeout=1200 ParkLoops
  */
 
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
 import java.util.SplittableRandom;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
@@ -52,11 +46,8 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReferenceArray;
 import java.util.concurrent.locks.LockSupport;
-import jdk.testlibrary.Utils;
 
 public final class ParkLoops {
-    static final long TEST_TIMEOUT_SECONDS = Utils.adjustTimeout(1000);
-    static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
     static final int THREADS = 4;
     static final int ITERS = 30_000;
 
@@ -126,28 +117,13 @@
         final AtomicReferenceArray<Thread> threads
             = new AtomicReferenceArray<>(THREADS);
         final CountDownLatch done = new CountDownLatch(THREADS);
-        final Runnable parker = new Parker(threads, done, rnd.split());
-        final Runnable unparker = new Unparker(threads, done, rnd.split());
         for (int i = 0; i < THREADS; i++) {
-            pool.submit(parker);
-            pool.submit(unparker);
+            pool.submit(new Parker(threads, done, rnd.split()));
+            pool.submit(new Unparker(threads, done, rnd.split()));
         }
-        try {
-          if (!done.await(TEST_TIMEOUT_SECONDS, SECONDS)) {
-            dumpAllStacks();
-            throw new AssertionError("lost unpark");
-          }
-        } finally {
-          pool.shutdown();
-          pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
-        }
-    }
-
-    static void dumpAllStacks() {
-        ThreadInfo[] threadInfos =
-            ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
-        for (ThreadInfo threadInfo : threadInfos) {
-            System.err.print(threadInfo);
-        }
+        // Let test harness handle timeout
+        done.await();
+        pool.shutdown();
+        pool.awaitTermination(Long.MAX_VALUE, SECONDS);
     }
 }
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -3322,7 +3322,7 @@
             () -> f.obtrudeException(null),
 
             () -> CompletableFuture.delayedExecutor(1L, SECONDS, null),
-            () -> CompletableFuture.delayedExecutor(1L, null, new ThreadExecutor()),
+            () -> CompletableFuture.delayedExecutor(1L, null, exec),
             () -> CompletableFuture.delayedExecutor(1L, null),
 
             () -> f.orTimeout(1L, null),
@@ -3552,7 +3552,7 @@
         long timeoutMillis = timeoutMillis();
         CompletableFuture<Integer> f = new CompletableFuture<>();
         long startTime = System.nanoTime();
-        f.orTimeout(timeoutMillis, MILLISECONDS);
+        assertSame(f, f.orTimeout(timeoutMillis, MILLISECONDS));
         checkCompletedWithTimeoutException(f);
         assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
     }
@@ -3567,8 +3567,8 @@
         CompletableFuture<Integer> g = new CompletableFuture<>();
         long startTime = System.nanoTime();
         f.complete(v1);
-        f.orTimeout(LONG_DELAY_MS, MILLISECONDS);
-        g.orTimeout(LONG_DELAY_MS, MILLISECONDS);
+        assertSame(f, f.orTimeout(LONG_DELAY_MS, MILLISECONDS));
+        assertSame(g, g.orTimeout(LONG_DELAY_MS, MILLISECONDS));
         g.complete(v1);
         checkCompletedNormally(f, v1);
         checkCompletedNormally(g, v1);
@@ -3583,11 +3583,14 @@
                        () -> testCompleteOnTimeout_timesOut(null));
     }
 
+    /**
+     * completeOnTimeout completes with given value if not complete
+     */
     public void testCompleteOnTimeout_timesOut(Integer v) {
         long timeoutMillis = timeoutMillis();
         CompletableFuture<Integer> f = new CompletableFuture<>();
         long startTime = System.nanoTime();
-        f.completeOnTimeout(v, timeoutMillis, MILLISECONDS);
+        assertSame(f, f.completeOnTimeout(v, timeoutMillis, MILLISECONDS));
         assertSame(v, f.join());
         assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
         f.complete(99);         // should have no effect
@@ -3604,8 +3607,8 @@
         CompletableFuture<Integer> g = new CompletableFuture<>();
         long startTime = System.nanoTime();
         f.complete(v1);
-        f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
-        g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS);
+        assertSame(f, f.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS));
+        assertSame(g, g.completeOnTimeout(-1, LONG_DELAY_MS, MILLISECONDS));
         g.complete(v1);
         checkCompletedNormally(f, v1);
         checkCompletedNormally(g, v1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,137 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class ExecutorCompletionService9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(ExecutorCompletionService9Test.class);
+    }
+
+    void solveAll(Executor e,
+                  Collection<Callable<Integer>> solvers)
+        throws InterruptedException, ExecutionException {
+        CompletionService<Integer> cs
+            = new ExecutorCompletionService<>(e);
+        solvers.forEach(cs::submit);
+        for (int i = solvers.size(); i > 0; i--) {
+            Integer r = cs.take().get();
+            if (r != null)
+                use(r);
+        }
+    }
+
+    void solveAny(Executor e,
+                  Collection<Callable<Integer>> solvers)
+        throws InterruptedException {
+        CompletionService<Integer> cs
+            = new ExecutorCompletionService<>(e);
+        int n = solvers.size();
+        List<Future<Integer>> futures = new ArrayList<>(n);
+        Integer result = null;
+        try {
+            solvers.forEach((solver) -> futures.add(cs.submit(solver)));
+            for (int i = n; i > 0; i--) {
+                try {
+                    Integer r = cs.take().get();
+                    if (r != null) {
+                        result = r;
+                        break;
+                    }
+                } catch (ExecutionException ignore) {}
+            }
+        } finally {
+            futures.forEach((future) -> future.cancel(true));
+        }
+
+        if (result != null)
+            use(result);
+    }
+
+    HashSet<Integer> results;
+
+    void use(Integer x) {
+        if (results == null) results = new HashSet<Integer>();
+        results.add(x);
+    }
+
+    /**
+     * The first "solvers" sample code in the class javadoc works.
+     */
+    public void testSolveAll()
+        throws InterruptedException, ExecutionException {
+        Set<Callable<Integer>> solvers = Set.of(
+            () -> null,
+            () -> 1,
+            () -> 2,
+            () -> 3,
+            () -> null);
+        solveAll(cachedThreadPool, solvers);
+        assertEquals(Set.of(1, 2, 3), results);
+    }
+
+    /**
+     * The second "solvers" sample code in the class javadoc works.
+     */
+    public void testSolveAny()
+        throws InterruptedException {
+        Set<Callable<Integer>> solvers = Set.of(
+            () -> { throw new ArithmeticException(); },
+            () -> null,
+            () -> 1,
+            () -> 2);
+        solveAny(cachedThreadPool, solvers);
+        assertEquals(1, results.size());
+        Integer elt = results.iterator().next();
+        assertTrue(elt.equals(1) || elt.equals(2));
+    }
+
+}
--- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionServiceTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -37,8 +37,11 @@
 
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
@@ -59,7 +62,7 @@
     }
 
     /**
-     * Creating a new ECS with null Executor throw NPE
+     * new ExecutorCompletionService(null) throws NullPointerException
      */
     public void testConstructorNPE() {
         try {
@@ -69,111 +72,147 @@
     }
 
     /**
-     * Creating a new ECS with null queue throw NPE
+     * new ExecutorCompletionService(e, null) throws NullPointerException
      */
     public void testConstructorNPE2() {
         try {
-            ExecutorService e = Executors.newCachedThreadPool();
-            new ExecutorCompletionService(e, null);
+            new ExecutorCompletionService(cachedThreadPool, null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * ecs.submit(null) throws NullPointerException
+     */
+    public void testSubmitNullCallable() {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        try {
+            cs.submit((Callable) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
 
     /**
-     * Submitting a null callable throws NPE
+     * ecs.submit(null, val) throws NullPointerException
      */
-    public void testSubmitNPE() {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            Callable c = null;
-            try {
-                ecs.submit(c);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
-    }
-
-    /**
-     * Submitting a null runnable throws NPE
-     */
-    public void testSubmitNPE2() {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            Runnable r = null;
-            try {
-                ecs.submit(r, Boolean.TRUE);
-                shouldThrow();
-            } catch (NullPointerException success) {}
-        }
+    public void testSubmitNullRunnable() {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        try {
+            cs.submit((Runnable) null, Boolean.TRUE);
+            shouldThrow();
+        } catch (NullPointerException success) {}
     }
 
     /**
      * A taken submitted task is completed
      */
-    public void testTake() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            Callable c = new StringTask();
-            ecs.submit(c);
-            Future f = ecs.take();
-            assertTrue(f.isDone());
-        }
+    public void testTake()
+        throws InterruptedException, ExecutionException {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        cs.submit(new StringTask());
+        Future f = cs.take();
+        assertTrue(f.isDone());
+        assertSame(TEST_STRING, f.get());
     }
 
     /**
      * Take returns the same future object returned by submit
      */
     public void testTake2() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            Callable c = new StringTask();
-            Future f1 = ecs.submit(c);
-            Future f2 = ecs.take();
-            assertSame(f1, f2);
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        Future f1 = cs.submit(new StringTask());
+        Future f2 = cs.take();
+        assertSame(f1, f2);
+    }
+
+    /**
+     * poll returns non-null when the returned task is completed
+     */
+    public void testPoll1()
+        throws InterruptedException, ExecutionException {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        assertNull(cs.poll());
+        cs.submit(new StringTask());
+
+        long startTime = System.nanoTime();
+        Future f;
+        while ((f = cs.poll()) == null) {
+            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+                fail("timed out");
+            Thread.yield();
         }
+        assertTrue(f.isDone());
+        assertSame(TEST_STRING, f.get());
+    }
+
+    /**
+     * timed poll returns non-null when the returned task is completed
+     */
+    public void testPoll2()
+        throws InterruptedException, ExecutionException {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        assertNull(cs.poll());
+        cs.submit(new StringTask());
+
+        long startTime = System.nanoTime();
+        Future f;
+        while ((f = cs.poll(SHORT_DELAY_MS, MILLISECONDS)) == null) {
+            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
+                fail("timed out");
+            Thread.yield();
+        }
+        assertTrue(f.isDone());
+        assertSame(TEST_STRING, f.get());
     }
 
     /**
-     * If poll returns non-null, the returned task is completed
+     * poll returns null before the returned task is completed
      */
-    public void testPoll1() throws Exception {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            assertNull(ecs.poll());
-            Callable c = new StringTask();
-            ecs.submit(c);
-
-            long startTime = System.nanoTime();
-            Future f;
-            while ((f = ecs.poll()) == null) {
-                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
-                    fail("timed out");
-                Thread.yield();
-            }
-            assertTrue(f.isDone());
-            assertSame(TEST_STRING, f.get());
-        }
+    public void testPollReturnsNull()
+        throws InterruptedException, ExecutionException {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        final CountDownLatch proceed = new CountDownLatch(1);
+        cs.submit(new Callable() { public String call() throws Exception {
+            proceed.await();
+            return TEST_STRING;
+        }});
+        assertNull(cs.poll());
+        assertNull(cs.poll(0L, MILLISECONDS));
+        assertNull(cs.poll(Long.MIN_VALUE, MILLISECONDS));
+        long startTime = System.nanoTime();
+        assertNull(cs.poll(timeoutMillis(), MILLISECONDS));
+        assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
+        proceed.countDown();
+        assertSame(TEST_STRING, cs.take().get());
     }
 
     /**
-     * If timed poll returns non-null, the returned task is completed
+     * successful and failed tasks are both returned
      */
-    public void testPoll2() throws InterruptedException {
-        final ExecutorService e = Executors.newCachedThreadPool();
-        final ExecutorCompletionService ecs = new ExecutorCompletionService(e);
-        try (PoolCleaner cleaner = cleaner(e)) {
-            assertNull(ecs.poll());
-            Callable c = new StringTask();
-            ecs.submit(c);
-            Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS);
-            if (f != null)
-                assertTrue(f.isDone());
+    public void testTaskAssortment()
+        throws InterruptedException, ExecutionException {
+        CompletionService cs = new ExecutorCompletionService(cachedThreadPool);
+        ArithmeticException ex = new ArithmeticException();
+        for (int i = 0; i < 2; i++) {
+            cs.submit(new StringTask());
+            cs.submit(callableThrowing(ex));
+            cs.submit(runnableThrowing(ex), null);
         }
+        int normalCompletions = 0;
+        int exceptionalCompletions = 0;
+        for (int i = 0; i < 3 * 2; i++) {
+            try {
+                if (cs.take().get() == TEST_STRING)
+                    normalCompletions++;
+            }
+            catch (ExecutionException expected) {
+                assertTrue(expected.getCause() instanceof ArithmeticException);
+                exceptionalCompletions++;
+            }
+        }
+        assertEquals(2 * 1, normalCompletions);
+        assertEquals(2 * 2, exceptionalCompletions);
+        assertNull(cs.poll());
     }
 
     /**
@@ -184,7 +223,7 @@
         final AtomicBoolean done = new AtomicBoolean(false);
         class MyCallableFuture<V> extends FutureTask<V> {
             MyCallableFuture(Callable<V> c) { super(c); }
-            protected void done() { done.set(true); }
+            @Override protected void done() { done.set(true); }
         }
         final ExecutorService e =
             new ThreadPoolExecutor(1, 1,
@@ -193,15 +232,14 @@
                 protected <T> RunnableFuture<T> newTaskFor(Callable<T> c) {
                     return new MyCallableFuture<T>(c);
                 }};
-        ExecutorCompletionService<String> ecs =
-            new ExecutorCompletionService<String>(e);
+        CompletionService<String> cs = new ExecutorCompletionService<>(e);
         try (PoolCleaner cleaner = cleaner(e)) {
-            assertNull(ecs.poll());
+            assertNull(cs.poll());
             Callable<String> c = new StringTask();
-            Future f1 = ecs.submit(c);
+            Future f1 = cs.submit(c);
             assertTrue("submit must return MyCallableFuture",
                        f1 instanceof MyCallableFuture);
-            Future f2 = ecs.take();
+            Future f2 = cs.take();
             assertSame("submit and take must return same objects", f1, f2);
             assertTrue("completed task must have set done", done.get());
         }
@@ -215,7 +253,7 @@
         final AtomicBoolean done = new AtomicBoolean(false);
         class MyRunnableFuture<V> extends FutureTask<V> {
             MyRunnableFuture(Runnable t, V r) { super(t, r); }
-            protected void done() { done.set(true); }
+            @Override protected void done() { done.set(true); }
         }
         final ExecutorService e =
             new ThreadPoolExecutor(1, 1,
@@ -224,15 +262,14 @@
                 protected <T> RunnableFuture<T> newTaskFor(Runnable t, T r) {
                     return new MyRunnableFuture<T>(t, r);
                 }};
-        final ExecutorCompletionService<String> ecs =
-            new ExecutorCompletionService<String>(e);
+        CompletionService<String> cs = new ExecutorCompletionService<>(e);
         try (PoolCleaner cleaner = cleaner(e)) {
-            assertNull(ecs.poll());
+            assertNull(cs.poll());
             Runnable r = new NoOpRunnable();
-            Future f1 = ecs.submit(r, null);
+            Future f1 = cs.submit(r, null);
             assertTrue("submit must return MyRunnableFuture",
                        f1 instanceof MyRunnableFuture);
-            Future f2 = ecs.take();
+            Future f2 = cs.take();
             assertSame("submit and take must return same objects", f1, f2);
             assertTrue("completed task must have set done", done.get());
         }
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Wed Jul 05 21:46:22 2017 +0200
@@ -39,6 +39,7 @@
  * @modules java.management
  * @build *
  * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase
+ * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase
  */
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -85,6 +86,7 @@
 import java.util.concurrent.RecursiveTask;
 import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.Semaphore;
+import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeoutException;
@@ -546,7 +548,7 @@
         // Java9+ test classes
         if (atLeastJava9()) {
             String[] java9TestClassNames = {
-                // Currently empty, but expecting varhandle tests
+                "ExecutorCompletionService9Test",
             };
             addNamedTestClasses(suite, java9TestClassNames);
         }
@@ -1860,4 +1862,19 @@
         } catch (NoSuchElementException success) {}
         assertFalse(it.hasNext());
     }
+
+    public <T> Callable<T> callableThrowing(final Exception ex) {
+        return new Callable<T>() { public T call() throws Exception { throw ex; }};
+    }
+
+    public Runnable runnableThrowing(final RuntimeException ex) {
+        return new Runnable() { public void run() { throw ex; }};
+    }
+
+    /** A reusable thread pool to be shared by tests. */
+    static final ExecutorService cachedThreadPool =
+        new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+                               1000L, MILLISECONDS,
+                               new SynchronousQueue<Runnable>());
+
 }
--- a/jdk/test/java/util/logging/XMLFormatterDate.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/java/util/logging/XMLFormatterDate.java	Wed Jul 05 21:46:22 2017 +0200
@@ -21,10 +21,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-import java.util.Calendar;
-import java.util.GregorianCalendar;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.time.Month;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.util.Locale;
+import java.util.Properties;
+import java.util.function.Supplier;
 import java.util.logging.Level;
+import java.util.logging.LogManager;
 import java.util.logging.LogRecord;
 import java.util.logging.XMLFormatter;
 
@@ -33,9 +41,25 @@
  * @bug 8028185
  * @summary XMLFormatter.format emits incorrect year (year + 1900)
  * @author dfuchs
+ * @run main/othervm XMLFormatterDate
  */
 public class XMLFormatterDate {
 
+    static final class TimeStamp {
+
+        final ZonedDateTime zdt;
+        TimeStamp(ZoneId zoneId) {
+            zdt = ZonedDateTime.now(zoneId);
+        }
+        int getYear() {
+            return zdt.getYear();
+        }
+        boolean isJanuaryFirst() {
+            return zdt.getMonth() == Month.JANUARY && zdt.getDayOfMonth() == 1;
+        }
+    }
+
+
     /**
      * Before the fix, JDK8 prints: {@code
      * <record>
@@ -64,39 +88,62 @@
         try {
             Locale.setDefault(Locale.ENGLISH);
 
-            final GregorianCalendar cal1 = new GregorianCalendar();
-            final int year1 = cal1.get(Calendar.YEAR);
+            // Test with default format: by default date is in UTC.
+            System.out.println("Testing with UTC");
+            test(() -> new TimeStamp(ZoneOffset.UTC));
 
-            LogRecord record = new LogRecord(Level.INFO, "test");
-            XMLFormatter formatter = new XMLFormatter();
-            final String formatted = formatter.format(record);
-            System.out.println(formatted);
-
-            final GregorianCalendar cal2 = new GregorianCalendar();
-            final int year2 = cal2.get(Calendar.YEAR);
-            if (year2 < 1900) {
-                throw new Error("Invalid system year: " + year2);
+            // Change LogManager configuration so that new
+            // XMLFormatter prints date in the pre Java 9 local zone format
+            try {
+                Properties props = new Properties();
+                props.setProperty("java.util.logging.XMLFormatter.useInstant", "false");
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                props.store(baos, "");
+                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+                LogManager.getLogManager().updateConfiguration(bais, (k) -> (o,n) -> n!=null?n:o);
+            } catch (IOException io) {
+                throw new RuntimeException(io);
             }
 
-            StringBuilder buf2 = new StringBuilder()
-                    .append("<date>").append(year2).append("-");
-            if (!formatted.contains(buf2.toString())) {
-                StringBuilder buf1 = new StringBuilder()
-                        .append("<date>").append(year1).append("-");
-                if (formatted.contains(buf1)
-                        && year2 == year1 + 1
-                        && cal2.get(Calendar.MONTH) == Calendar.JANUARY
-                        && cal2.get(Calendar.DAY_OF_MONTH) == 1) {
-                    // Oh! The year just switched in the midst of the test...
-                    System.out.println("Happy new year!");
-                } else {
-                    throw new Error("Expected year " + year2
-                            + " not found in log:\n" + formatted);
-                }
-            }
+            // re test with the old format: date will be in the local time zone.
+            System.out.println("Testing with old format");
+            test(() -> new TimeStamp(ZoneId.systemDefault()));
+
         } finally {
             Locale.setDefault(locale);
         }
     }
 
+    static void test(Supplier<TimeStamp> timeStampSupplier) {
+
+        TimeStamp t1 = timeStampSupplier.get();
+        int year1 = t1.getYear();
+
+        LogRecord record = new LogRecord(Level.INFO, "test");
+        XMLFormatter formatter = new XMLFormatter();
+        final String formatted = formatter.format(record);
+        System.out.println(formatted);
+
+        final TimeStamp t2 = timeStampSupplier.get();
+        final int year2 = t2.getYear();
+        if (year2 < 1900) {
+            throw new Error("Invalid system year: " + year2);
+        }
+
+        final StringBuilder buf2 = new StringBuilder()
+                .append("<date>").append(year2).append("-");
+        if (!formatted.contains(buf2.toString())) {
+            StringBuilder buf1 = new StringBuilder()
+                    .append("<date>").append(year1).append("-");
+            if (formatted.contains(buf1) && year2 == year1 + 1
+                    && t2.isJanuaryFirst()) {
+                // Oh! The year just switched in the midst of the test...
+                System.out.println("Happy new year!");
+            } else {
+                throw new Error("Expected year " + year2
+                        + " not found in log:\n" + formatted);
+            }
+        }
+    }
+
 }
--- a/jdk/test/jdk/internal/jrtfs/Basic.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/internal/jrtfs/Basic.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -65,15 +65,31 @@
 
     private FileSystem theFileSystem;
     private FileSystem fs;
+    private boolean isExplodedBuild = false;
 
     @BeforeClass
     public void setup() {
+        theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
+        Path javaHomeDir = Paths.get(System.getProperty("java.home"));
+        Path jrtJarPath = javaHomeDir.resolve("jrt-fs.jar");
+        Path modulesPath = javaHomeDir.resolve("lib/modules");
+        isExplodedBuild = !Files.exists(jrtJarPath)
+                && !Files.exists(modulesPath);
+        if (Files.notExists(jrtJarPath)
+                && Files.notExists(modulesPath)) {
+            System.out.printf("Following files not exist: %s, %s",
+                    jrtJarPath.toString(), modulesPath.toString());
+            System.out.println();
+            System.out.println("It is most probably an exploded build."
+                    + " Skip non-default FileSystem testing.");
+            return;
+        }
+
+        Map<String, String> env = new HashMap<>();
+        // set java.home property to be underlying java.home
+        // so that jrt-fs.jar loading is exercised.
+        env.put("java.home", System.getProperty("java.home"));
         try {
-            theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
-            Map<String, String> env = new HashMap<>();
-            // set java.home property to be underlying java.home
-            // so that jrt-fs.jar loading is exercised.
-            env.put("java.home", System.getProperty("java.home"));
             fs = FileSystems.newFileSystem(URI.create("jrt:/"), env);
         } catch (IOException ioExp) {
             throw new RuntimeException(ioExp);
@@ -131,6 +147,12 @@
 
     @Test
     public void testNewFileSystemWithJavaHome() throws Exception {
+        if (isExplodedBuild) {
+            System.out.println("Skip testNewFileSystemWithJavaHome"
+                    + " since this is an exploded build");
+            return;
+        }
+
         Map<String, String> env = new HashMap<>();
         // set java.home property to be underlying java.home
         // so that jrt-fs.jar loading is exercised.
@@ -154,6 +176,11 @@
 
     @Test(dataProvider = "knownClassFiles")
     public void testKnownClassFiles(String path, boolean theDefault) throws Exception {
+        if (isExplodedBuild && !theDefault) {
+            System.out.println("Skip testKnownClassFiles with non-default FileSystem");
+            return;
+        }
+
         FileSystem fs = selectFileSystem(theDefault);
         Path classFile = fs.getPath(path);
 
@@ -201,6 +228,11 @@
 
     @Test(dataProvider = "knownDirectories")
     public void testKnownDirectories(String path, boolean theDefault) throws Exception {
+        if (isExplodedBuild && !theDefault) {
+            System.out.println("Skip testKnownDirectories with non-default FileSystem");
+            return;
+        }
+
         FileSystem fs = selectFileSystem(theDefault);
         Path dir = fs.getPath(path);
 
@@ -684,3 +716,4 @@
         assertEquals(dirPrefixOkayCount, childCount);
     }
 }
+
--- a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java	Wed Jul 05 21:46:22 2017 +0200
@@ -25,6 +25,7 @@
  * @test
  * @bug 8765432
  * @summary Basic test for SocketFlow API
+ * @modules jdk.net
  * @run testng SocketFlowBasic
  */
 
--- a/jdk/test/jdk/net/Sockets/SupportedOptions.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/net/Sockets/SupportedOptions.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 8062744
+ * @modules jdk.net
  * @run main SupportedOptions
  */
 
--- a/jdk/test/jdk/net/Sockets/Test.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/net/Sockets/Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -25,24 +25,35 @@
  * @test
  * @bug 8032808 8044773
  * @modules jdk.net
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
  * @run main/othervm -Xcheck:jni Test success
  * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
  * @run main/othervm/policy=policy.success -Xcheck:jni Test success
  */
 
-import java.net.*;
+import jdk.net.ExtendedSocketOptions;
+import jdk.net.SocketFlow;
+import jdk.net.Sockets;
+import jdk.testlibrary.OSInfo;
+
 import java.io.IOException;
-import java.nio.channels.*;
-import java.util.concurrent.*;
-import java.util.Set;
-import jdk.net.*;
+import java.net.*;
+import java.nio.channels.AsynchronousSocketChannel;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.Future;
+
 import static java.lang.System.out;
+import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA;
 
 public class Test {
 
     interface Runner { void run() throws Exception; }
 
     static boolean expectSuccess;
+    private static final boolean expectSupport = checkExpectedOptionSupport();
+    private static final double solarisVersionToCheck = 11.2;
 
     public static void main(String[] args) throws Exception {
 
@@ -54,9 +65,8 @@
         expectSuccess = args[0].equals("success");
 
         // Main thing is to check for JNI problems
-        // Doesn't matter if current system does not support the option
-        // and currently setting the option with the loopback interface
-        // doesn't work either
+        // Doesn't matter if currently setting the option with the loopback
+        // interface doesn't work
 
         boolean sm = System.getSecurityManager() != null;
         out.println("Security Manager enabled: " + sm);
@@ -75,56 +85,70 @@
 
             final int udp_port = dg.getLocalPort();
 
-            // If option not available, end test
-            Set<SocketOption<?>> options = dg.supportedOptions();
-            if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
-                System.out.println("SO_FLOW_SLA not supported");
-                return;
-            }
-
             final Socket s = new Socket("127.0.0.1", tcp_port);
             final SocketChannel sc = SocketChannel.open();
             sc.connect(new InetSocketAddress("127.0.0.1", tcp_port));
 
             doTest("Sockets.setOption Socket", () -> {
                 out.println(flowIn);
-                Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                if (s.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                    throw new RuntimeException("Unexpected supportedOptions()");
+                }
+                Sockets.setOption(s, SO_FLOW_SLA, flowIn);
                 out.println(flowIn);
             });
-            doTest("Sockets.getOption Socket",() -> {
-                Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
+
+            doTest("Sockets.getOption Socket", () -> {
+                Sockets.getOption(s, SO_FLOW_SLA);
                 out.println(flowIn);
             });
-            doTest("Sockets.setOption SocketChannel",() ->
-                sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn)
+
+            doTest("Sockets.setOption SocketChannel", () -> {
+                if (sc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                    throw new RuntimeException("Unexpected supportedOptions()");
+                }
+                sc.setOption(SO_FLOW_SLA, flowIn);
+            });
+            doTest("Sockets.getOption SocketChannel", () ->
+                    sc.getOption(SO_FLOW_SLA)
             );
-            doTest("Sockets.getOption SocketChannel",() ->
-                sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA)
-            );
-            doTest("Sockets.setOption DatagramSocket",() -> {
+            doTest("Sockets.setOption DatagramSocket", () -> {
                 try (DatagramSocket dg1 = new DatagramSocket(0)) {
+                    if (dg1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                        throw new RuntimeException("Unexpected supportedOptions()");
+                    }
+
                     dg1.connect(loop, udp_port);
-                    Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                    Sockets.setOption(dg1, SO_FLOW_SLA, flowIn);
                 }
             });
             doTest("Sockets.setOption DatagramSocket 2", () -> {
                 try (DatagramChannel dg2 = DatagramChannel.open()) {
+                    if (dg2.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                        throw new RuntimeException("Unexpected supportedOptions()");
+                    }
                     dg2.bind(new InetSocketAddress(loop, 0));
                     dg2.connect(new InetSocketAddress(loop, udp_port));
-                    dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                    dg2.setOption(SO_FLOW_SLA, flowIn);
                 }
             });
             doTest("Sockets.setOption MulticastSocket", () -> {
                 try (MulticastSocket mc1 = new MulticastSocket(0)) {
+                    if (mc1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                        throw new RuntimeException("Unexpected supportedOptions()");
+                    }
                     mc1.connect(loop, udp_port);
-                    Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                    Sockets.setOption(mc1, SO_FLOW_SLA, flowIn);
                 }
             });
             doTest("Sockets.setOption AsynchronousSocketChannel", () -> {
                 try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
+                    if (asc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
+                        throw new RuntimeException("Unexpected supportedOptions()");
+                    }
                     Future<Void> f = asc.connect(loopad);
                     f.get();
-                    asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                    asc.setOption(SO_FLOW_SLA, flowIn);
                 }
             });
         }
@@ -144,14 +168,43 @@
                 throw new RuntimeException("Unexpected SecurityException", e);
             } else {
                 out.println("Caught expected: " + e);
+                return;
             }
         } catch (UnsupportedOperationException e) {
-            System.out.println(e);
+            if (expectSupport) {
+                throw new RuntimeException("Test failed: " +
+                        "unexpected UnsupportedOperationException");
+            }
+            out.println("UnsupportedOperationException as expected");
+            return;
         } catch (IOException e) {
             // Probably a permission error, but we're not
             // going to check unless a specific permission exception
             // is defined.
             System.out.println(e);
         }
+        if (!expectSupport) {
+            throw new RuntimeException("Test failed: " +
+                    "UnsupportedOperationException was not thrown");
+        }
     }
+
+    private static boolean checkExpectedOptionSupport() {
+        if (OSInfo.getOSType().equals(OSInfo.OSType.SOLARIS)) {
+            double solarisVersion = OSInfo.getSolarisVersion();
+            if (solarisVersion >= solarisVersionToCheck) {
+                System.out.println("This Solaris version (" + solarisVersion
+                        + ") should support SO_FLOW_SLA option");
+                return true;
+            } else {
+                System.out.println("This Solaris version (" + solarisVersion
+                        + ") should not support SO_FLOW_SLA option");
+            }
+        } else {
+            System.out.println("Not Solaris, SO_FLOW_SLA should not be " +
+                    "supported");
+        }
+        return false;
+    }
+
 }
--- a/jdk/test/jdk/net/Sockets/policy.fail	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/net/Sockets/policy.fail	Wed Jul 05 21:46:22 2017 +0200
@@ -1,4 +1,8 @@
 grant {
+    permission java.util.PropertyPermission "os.name", "read";
+    permission java.io.FilePermission "<<ALL FILES>>", "execute";
+    permission java.util.PropertyPermission "line.separator", "read";
+    permission java.io.FilePermission "/etc/release", "read";
     permission java.net.SocketPermission "127.0.0.1", "connect,accept" ;
     permission java.net.SocketPermission "localhost", "listen" ;
 };
--- a/jdk/test/jdk/net/Sockets/policy.success	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/net/Sockets/policy.success	Wed Jul 05 21:46:22 2017 +0200
@@ -1,4 +1,8 @@
 grant {
+    permission java.util.PropertyPermission "os.name", "read";
+    permission java.io.FilePermission "<<ALL FILES>>", "execute";
+    permission java.util.PropertyPermission "line.separator", "read";
+    permission java.io.FilePermission "/etc/release", "read";
     permission java.net.SocketPermission "127.0.0.1", "connect,accept" ;
     permission java.net.SocketPermission "localhost", "listen" ;
     permission jdk.net.NetworkPermission "setOption.SO_FLOW_SLA";
--- a/jdk/test/jdk/nio/zipfs/Basic.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/Basic.java	Wed Jul 05 21:46:22 2017 +0200
@@ -31,6 +31,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.ProviderMismatchException;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.BasicFileAttributes;
@@ -39,14 +40,15 @@
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Map;
-
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
 /**
  * @test
- * @bug 8038500 8040059 8150366 8150496
+ * @bug 8038500 8040059 8150366 8150496 8147539
  * @summary Basic test for zip provider
  *
  * @run main Basic
  * @run main/othervm/java.security.policy=test.policy Basic
+ * @modules jdk.zipfs
  */
 
 public class Basic {
@@ -89,7 +91,7 @@
         found = false;
         try (DirectoryStream<Path> stream = Files.newDirectoryStream(fs.getPath("/"))) {
             for (Path entry: stream) {
-                found = entry.toString().equals("/META-INF/");
+                found = entry.toString().equals("/META-INF");
                 if (found) break;
             }
         }
@@ -117,6 +119,13 @@
         if (!store.supportsFileAttributeView("basic"))
             throw new RuntimeException("BasicFileAttributeView should be supported");
 
+        // Test: watch register should throw PME
+        try {
+            fs.getPath("/")
+              .register(FileSystems.getDefault().newWatchService(), ENTRY_CREATE);
+            throw new RuntimeException("watch service is not supported");
+        } catch (ProviderMismatchException x) { }
+
         // Test: ClosedFileSystemException
         fs.close();
         if (fs.isOpen())
--- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -28,6 +28,9 @@
  * @library /lib/testlibrary/java/util/jar
  * @build Compiler JarBuilder CreateMultiReleaseTestJars
  * @run testng MultiReleaseJarTest
+ * @modules java.compiler
+ *          jdk.jartool
+ *          jdk.zipfs
  */
 
 import java.io.IOException;
--- a/jdk/test/jdk/nio/zipfs/PathOps.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/PathOps.java	Wed Jul 05 21:46:22 2017 +0200
@@ -31,11 +31,12 @@
 /**
  *
  * @test
- * @bug 8038500 8040059
+ * @bug 8038500 8040059 8139956 8146754
  * @summary Tests path operations for zip provider.
  *
  * @run main PathOps
  * @run main/othervm/java.security.policy=test.policy PathOps
+ * @modules jdk.zipfs
  */
 
 public class PathOps {
@@ -424,6 +425,11 @@
         test("/")
             .relativize("/a", "a")
             .relativize("/a/c", "a/c");
+        // 8146754
+        test("/tmp/path")
+            .relativize("/tmp/path/a.txt", "a.txt");
+        test("/tmp/path/")
+            .relativize("/tmp/path/a.txt", "a.txt");
 
         // normalize
         test("/")
@@ -486,7 +492,16 @@
         // isSameFile
         test("/fileDoesNotExist")
             .isSameFile("/fileDoesNotExist");
-    }
+
+        // 8139956
+        out.println("check getNameCount");
+        int nc = fs.getPath("/").relativize(fs.getPath("/")).getNameCount();
+        if (nc != 1) {
+            out.format("\tExpected: 1\n");
+            out.format("\tActual: %d\n",  nc);
+            throw new RuntimeException("getNameCount of empty path failed");
+        }
+     }
 
     static void npes() {
         header("NullPointerException");
--- a/jdk/test/jdk/nio/zipfs/ZFSTests.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZFSTests.java	Wed Jul 05 21:46:22 2017 +0200
@@ -22,11 +22,12 @@
  */
 
 /* @test
- * @bug 7156873 8040059 8028480 8034773
+ * @bug 7156873 8040059 8028480 8034773 8153248
  * @summary ZipFileSystem regression tests
  *
  * @run main ZFSTests
  * @run main/othervm/java.security.policy=test.policy ZFSTests
+ * @modules jdk.zipfs
  */
 
 
@@ -42,7 +43,7 @@
 
     public static void main(String[] args) throws Throwable {
         test7156873();
-        testOpenOptions();
+        tests();
     }
 
     static void test7156873() throws Throwable {
@@ -61,7 +62,7 @@
         }
     }
 
-    static void testOpenOptions() throws Throwable {
+    static void tests() throws Throwable {
         Path path = Paths.get("file.zip");
         try {
             URI uri = URI.create("jar:" + path.toUri());
@@ -95,6 +96,18 @@
                 } catch (IllegalArgumentException x) {
                     // expected x.printStackTrace();
                 }
+
+                //8153248
+                Path dir = fs.getPath("/dir");
+                Path subdir = fs.getPath("/dir/subdir");
+                Files.createDirectory(dir);
+                Files.createDirectory(subdir);
+                Files.list(dir)
+                     .forEach( child -> {
+                             System.out.println("child:" + child);
+                             if (child.toString().endsWith("/"))
+                                 throw new RuntimeException("subdir names ends with /");
+                          });
             }
         } finally {
             Files.deleteIfExists(path);
--- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java	Wed Jul 05 21:46:22 2017 +0200
@@ -74,6 +74,7 @@
  * @summary Test Zip filesystem provider
  * @run main ZipFSTester
  * @run main/othervm/java.security.policy=test.policy ZipFSTester
+ * @modules jdk.zipfs
  */
 
 public class ZipFSTester {
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OSInfo.java	Wed Jul 05 21:46:22 2017 +0200
@@ -28,6 +28,9 @@
 import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.InputStreamReader;
 
 import static jdk.testlibrary.OSInfo.OSType.*;
 
@@ -147,6 +150,28 @@
         }
     }
 
+    public static double getSolarisVersion() {
+        try {
+            OutputAnalyzer output = ProcessTools.executeProcess("uname", "-v");
+            System.out.println("'uname -v' finished with code "
+                    + output.getExitValue());
+            return Double.parseDouble(output.getOutput());
+        } catch (Exception e) {
+            System.out.println("First attempt failed with: " + e.getMessage());
+        }
+
+        //Try to get Solaris version from /etc/release
+        try (BufferedReader in =
+                     new BufferedReader(new FileReader("/etc/release"))) {
+            String line = in.readLine().trim().split(" ")[2];
+            return Double.parseDouble(line);
+        } catch (Exception e) {
+            System.out.println("Second attempt failed with: " + e.getMessage());
+        }
+
+        throw new RuntimeException("Unable to get Solaris version");
+    }
+
     public static class WindowsVersion implements Comparable<WindowsVersion> {
         private final int major;
 
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java	Wed Jul 05 21:46:22 2017 +0200
@@ -423,7 +423,7 @@
      * @param cmds The command line to execute.
      * @return The output from the process.
      */
-    public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
+    public static OutputAnalyzer executeProcess(String... cmds) throws Exception {
         return executeProcess(new ProcessBuilder(cmds));
     }
 
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,6 @@
 
 package jdk.testlibrary;
 
-import com.sun.net.httpserver.*;
-
 import java.util.*;
 import java.util.concurrent.*;
 import java.io.*;
@@ -54,7 +52,7 @@
      * loads default keystore from SimpleSSLContext
      * source directory
      */
-    public SimpleSSLContext () throws IOException {
+    public SimpleSSLContext() throws IOException {
         String paths = System.getProperty("test.src.path");
         StringTokenizer st = new StringTokenizer(paths, File.pathSeparator);
         boolean securityExceptions = false;
@@ -63,8 +61,10 @@
             try {
                 File f = new File(path, "jdk/testlibrary/testkeys");
                 if (f.exists()) {
-                    init (new FileInputStream(f));
-                    return;
+                    try (FileInputStream fis = new FileInputStream(f)) {
+                        init(fis);
+                        return;
+                    }
                 }
             } catch (SecurityException e) {
                 // catch and ignore because permission only required
@@ -80,13 +80,14 @@
     /**
      * loads default keystore from given directory
      */
-    public SimpleSSLContext (String dir) throws IOException {
+    public SimpleSSLContext(String dir) throws IOException {
         String file = dir+"/testkeys";
-        FileInputStream fis = new FileInputStream(file);
-        init(fis);
+        try (FileInputStream fis = new FileInputStream(file)) {
+            init(fis);
+        }
     }
 
-    private void init (InputStream i) throws IOException {
+    private void init(InputStream i) throws IOException {
         try {
             char[] passphrase = "passphrase".toCharArray();
             KeyStore ks = KeyStore.getInstance("JKS");
@@ -98,22 +99,22 @@
             TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
             tmf.init(ks);
 
-            ssl = SSLContext.getInstance ("TLS");
+            ssl = SSLContext.getInstance("TLS");
             ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
         } catch (KeyManagementException e) {
-            throw new RuntimeException (e.getMessage());
+            throw new RuntimeException(e.getMessage());
         } catch (KeyStoreException e) {
-            throw new RuntimeException (e.getMessage());
+            throw new RuntimeException(e.getMessage());
         } catch (UnrecoverableKeyException e) {
-            throw new RuntimeException (e.getMessage());
+            throw new RuntimeException(e.getMessage());
         } catch (CertificateException e) {
-            throw new RuntimeException (e.getMessage());
+            throw new RuntimeException(e.getMessage());
         } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException (e.getMessage());
+            throw new RuntimeException(e.getMessage());
         }
     }
 
-    public SSLContext get () {
+    public SSLContext get() {
         return ssl;
     }
 }
--- a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh	Wed Jul 05 21:46:22 2017 +0200
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 # @test
 # @bug 4763315
+# @modules java.naming
 # @build CanonicalName Lookup
 # @run shell/timeout=120 cname.sh
 # @summary Test DNS provider's handling of CNAME records
--- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 4333920
+ * @modules jdk.httpserver
  * @run main ChunkedEncodingTest
  * @summary ChunkedEncodingTest unit test
  */
--- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2012, 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
@@ -26,6 +26,7 @@
  * @bug 4333920 4994372
  * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem
  * @modules java.base/sun.net
+ *          jdk.httpserver
  * @run main ChunkedEncodingWithProgressMonitorTest
  */
 
--- a/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/ChunkedInputStream/TestAvailable.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6446990
+ * @modules jdk.httpserver
  * @run main/othervm TestAvailable
  * @summary HttpURLConnection#available() reads more and more data into memory
  */
--- a/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/ChunkedOutputStream/Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 5026745 6631048
+ * @modules jdk.httpserver
  * @run main/othervm/timeout=500 Test
  * @summary Cannot flush output stream when writing to an HttpUrlConnection
  */
--- a/jdk/test/sun/net/www/http/HttpClient/B7025238.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/HttpClient/B7025238.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -30,6 +30,7 @@
 /*
  * @test
  * @bug 7025238
+ * @modules jdk.httpserver
  * @summary HttpURLConnection does not handle URLs with an empty path component
  */
 public class B7025238 {
--- a/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/HttpURLConnection/DigestAuth.java	Wed Jul 05 21:46:22 2017 +0200
@@ -41,6 +41,7 @@
  * @summary Tests for HTTP Digest auth
  *          The impl maintains a cache for auth info,
  *          the testcases run in a separate JVM to avoid cache hits
+ * @modules jdk.httpserver
  * @run main/othervm DigestAuth good
  * @run main/othervm DigestAuth only_nonce
  * @run main/othervm DigestAuth sha1
--- a/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/HttpURLConnection/NTLMAuthWithSM.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -40,6 +40,7 @@
  * @test
  * @bug 8137174
  * @modules java.base/sun.net.www.protocol.http.ntlm
+ *          jdk.httpserver
  * @summary Checks if NTLM auth works fine if security manager set
  * @run main/othervm/java.security.policy=NTLMAuthWithSM.policy NTLMAuthWithSM
  */
--- a/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/http/HttpURLConnection/PostOnDelete.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -30,6 +30,7 @@
 /*
  * @test
  * @bug 7157360
+ * @modules jdk.httpserver
  * @summary HttpURLConnection: HTTP method DELETE doesn't support output
  */
 public class PostOnDelete {
--- a/jdk/test/sun/net/www/protocol/http/6550798/test.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/6550798/test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -25,6 +25,7 @@
  * @test
  * @bug 6550798
  * @summary Using InputStream.skip with ResponseCache will cause partial data to be cached
+ * @modules jdk.httpserver
  * @run main/othervm test
  */
 
--- a/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/AsyncDisconnect.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6358532
+ * @modules jdk.httpserver
  * @run main/othervm AsyncDisconnect
  * @summary HttpURLConnection.disconnect doesn't really do the job
  */
--- a/jdk/test/sun/net/www/protocol/http/B5017051.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B5017051.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 5017051 6360774
+ * @modules jdk.httpserver
  * @run main/othervm B5017051
  * @summary Tests CR 5017051 & 6360774
  */
--- a/jdk/test/sun/net/www/protocol/http/B6299712.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B6299712.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6299712 7150552
+ * @modules jdk.httpserver
  * @run main/othervm B6299712
  * @summary  NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect
  */
--- a/jdk/test/sun/net/www/protocol/http/B6369510.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B6369510.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6369510
+ * @modules jdk.httpserver
  * @run main/othervm B6369510
  * @summary HttpURLConnection sets Content-Type to application/x-www-form-urlencoded
  */
--- a/jdk/test/sun/net/www/protocol/http/B6518816.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B6518816.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6518816
+ * @modules jdk.httpserver
  * @run main/othervm B6518816
  */
 
--- a/jdk/test/sun/net/www/protocol/http/B6641309.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B6641309.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6641309
+ * @modules jdk.httpserver
  * @summary Wrong Cookie separator used in HttpURLConnection
  */
 
--- a/jdk/test/sun/net/www/protocol/http/B6660405.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B6660405.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6660405
+ * @modules jdk.httpserver
  * @summary HttpURLConnection returns the wrong InputStream
  */
 
--- a/jdk/test/sun/net/www/protocol/http/B8012625.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/B8012625.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 8012625
+ * @modules jdk.httpserver
  * @run main B8012625
  */
 
--- a/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/BasicLongCredentials.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 6947917
+ * @modules jdk.httpserver
  * @summary  Error in basic authentication when user name and password are long
  */
 
--- a/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/ChunkedErrorStream.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6488669 6595324 6993490
+ * @modules jdk.httpserver
  * @run main/othervm ChunkedErrorStream
  * @summary Chunked ErrorStream tests
  */
--- a/jdk/test/sun/net/www/protocol/http/HttpOnly.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/HttpOnly.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -23,6 +23,7 @@
 /**
  * @test
  * @bug 7095980 8007315
+ * @modules jdk.httpserver
  * @summary Ensure HttpURLConnection (and supporting APIs) don't expose
  *          HttpOnly cookies
  */
--- a/jdk/test/sun/net/www/protocol/http/HttpStreams.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/HttpStreams.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @bug 8011719
+ * @modules jdk.httpserver
  * @summary Basic checks to verify behavior of returned input streams
  */
 
--- a/jdk/test/sun/net/www/protocol/http/NoCache.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/NoCache.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 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
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 7133367
+ * @modules jdk.httpserver
  * @summary ResponseCache.put should not be called when setUseCaches(false)
  */
 
--- a/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/RedirectOnPost.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -24,6 +24,7 @@
 /**
  * @test
  * @library /lib/testlibrary/
+ * @modules jdk.httpserver
  * @build jdk.testlibrary.SimpleSSLContext
  * @compile RedirectOnPost.java
  * @run main/othervm RedirectOnPost
--- a/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/StreamingOutputStream.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6472250
+ * @modules jdk.httpserver
  * @run main/othervm StreamingOutputStream
  * @summary HttpURLConnection.getOutputStream streaming mode bug when called multiple times
  */
--- a/jdk/test/sun/net/www/protocol/http/UserAuth.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/UserAuth.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6421122
+ * @modules jdk.httpserver
  * @run main/othervm UserAuth
  * @summary Authorization header removed for preemptive authentication by user code
  */
--- a/jdk/test/sun/net/www/protocol/http/UserCookie.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/UserCookie.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6439651
+ * @modules jdk.httpserver
  * @run main/othervm UserAuth
  * @summary Sending "Cookie" header with JRE 1.5.0_07 doesn't work anymore
  */
--- a/jdk/test/sun/net/www/protocol/http/ZoneId.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/http/ZoneId.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -26,6 +26,7 @@
  * @bug 8027308
  * @key intermittent
  * @modules java.base/sun.net.www.protocol.http
+ *          jdk.httpserver
  * @summary  verifies that HttpURLConnection does not send the zone id in the
  *           'Host' field of the header:
  *              Host: [fe80::a00:27ff:aaaa:aaaa] instead of
--- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 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
@@ -26,6 +26,7 @@
  * @bug 6771432
  * @summary createSocket() - smpatch fails using 1.6.0_10 because of
  *     "Unconnected sockets not implemented"
+ * @modules jdk.httpserver
  * @run main/othervm HttpsCreateSockTest
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
--- a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 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
@@ -25,6 +25,7 @@
  * @test
  * @bug 6614957
  * @summary HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets
+ * @modules jdk.httpserver
  * @run main/othervm HttpsSocketFacTest
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
--- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java	Wed Jul 05 21:46:22 2017 +0200
@@ -26,6 +26,9 @@
  * @bug 8132734 8144062
  * @summary Test that URL connections to multi-release jars can be runtime versioned
  * @library /lib/testlibrary/java/util/jar
+ * @modules java.compiler
+ *          jdk.httpserver
+ *          jdk.jartool
  * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer
  * @run testng MultiReleaseJarURLConnection
  */
--- a/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/nio/ch/TestMaxCachedBufferSize.java	Wed Jul 05 21:46:22 2017 +0200
@@ -43,6 +43,7 @@
 /*
  * @test
  * @requires sun.arch.data.model == "64"
+ * @modules java.management
  * @build TestMaxCachedBufferSize
  * @run main/othervm TestMaxCachedBufferSize
  * @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize
--- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java	Wed Jul 05 21:46:22 2017 +0200
@@ -33,6 +33,7 @@
 import java.security.spec.InvalidParameterSpecException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /*
  * @test
@@ -41,26 +42,15 @@
  * @summary Verify that DSAGenParameterSpec can and can only be used to generate
  *          DSA within some certain range of key sizes as described in the class
  *          specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and
- *          (3072, 256) should be OK for DSAGenParameterSpec. But the real
- *          implementation SUN doesn't support (3072, 256).
- * @run main TestDSAGenParameterSpec
+ *          (3072, 256) should be OK for DSAGenParameterSpec.
+ * @run main TestDSAGenParameterSpec 2048,256,true 2048,224,true 1024,160,true 4096,256 3072,224 2048,160 1024,224 512,160
+ * @run main TestDSAGenParameterSpec 3072,256,true
  */
 public class TestDSAGenParameterSpec {
 
     private static final String ALGORITHM_NAME = "DSA";
     private static final String PROVIDER_NAME = "SUN";
 
-    private static final List<DataTuple> DATA = Arrays.asList(
-            new DataTuple(1024, 160, true, true),
-            new DataTuple(2048, 224, true, true),
-            new DataTuple(2048, 256, true, true),
-            new DataTuple(3072, 256, true, false),
-            new DataTuple(1024, 224),
-            new DataTuple(2048, 160),
-            new DataTuple(4096, 256),
-            new DataTuple(512, 160),
-            new DataTuple(3072, 224));
-
     private static void testDSAGenParameterSpec(DataTuple dataTuple)
             throws NoSuchAlgorithmException, NoSuchProviderException,
             InvalidParameterSpecException, InvalidAlgorithmParameterException {
@@ -84,14 +74,7 @@
             checkParam(param, genParamSpec);
             System.out.println("Test case passed");
         } catch (InvalidParameterException ipe) {
-            // The DSAGenParameterSpec API support this, but the real
-            // implementation in SUN doesn't
-            if (!dataTuple.isSunProviderSupported) {
-                System.out.println("Test case passed: expected "
-                        + "InvalidParameterException is caught");
-            } else {
-                throw new RuntimeException("Test case failed.", ipe);
-            }
+            throw new RuntimeException("Test case failed.", ipe);
         }
     }
 
@@ -127,11 +110,9 @@
             throw new RuntimeException("Wrong seed length");
         }
 
-        // use the parameters to generate real DSA keys
         KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM_NAME,
                 PROVIDER_NAME);
         keyGen.initialize(spec);
-        keyGen.generateKeyPair();
     }
 
     private static DSAGenParameterSpec createGenParameterSpec(
@@ -158,10 +139,21 @@
     }
 
     public static void main(String[] args) throws Exception {
-        for (DataTuple dataTuple : DATA) {
+        List<DataTuple> dataTuples = Arrays.stream(args)
+                .map(arg -> arg.split(",")).map(params -> {
+                    int primePLen = Integer.valueOf(params[0]);
+                    int subprimeQLen = Integer.valueOf(params[1]);
+                    boolean isDSASpecSupported = false;
+                    if (params.length == 3) {
+                        isDSASpecSupported = Boolean.valueOf(params[2]);
+                    }
+                    return new DataTuple(primePLen, subprimeQLen,
+                            isDSASpecSupported);
+                }).collect(Collectors.toList());
+
+        for (DataTuple dataTuple : dataTuples) {
             testDSAGenParameterSpec(dataTuple);
         }
-        System.out.println("All tests passed");
     }
 
     private static class DataTuple {
@@ -169,18 +161,13 @@
         private int primePLen;
         private int subprimeQLen;
         private boolean isDSASpecSupported;
-        private boolean isSunProviderSupported;
 
         private DataTuple(int primePLen, int subprimeQLen,
-                boolean isDSASpecSupported, boolean isSunProviderSupported) {
+                boolean isDSASpecSupported) {
             this.primePLen = primePLen;
             this.subprimeQLen = subprimeQLen;
             this.isDSASpecSupported = isDSASpecSupported;
-            this.isSunProviderSupported = isSunProviderSupported;
-        }
-
-        private DataTuple(int primePLen, int subprimeQLen) {
-            this(primePLen, subprimeQLen, false, false);
         }
     }
 }
+
--- a/jdk/test/sun/security/provider/PolicyFile/Modules.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/security/provider/PolicyFile/Modules.java	Wed Jul 05 21:46:22 2017 +0200
@@ -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
@@ -25,6 +25,19 @@
  * @test
  * @bug 8047771
  * @summary check permissions and principals from various modules
+ * @modules java.desktop
+ *          java.logging
+ *          java.management
+ *          java.security.jgss
+ *          java.smartcardio
+ *          java.sql
+ *          java.xml
+ *          java.xml.bind
+ *          jdk.attach
+ *          jdk.jdi
+ *          jdk.net
+ *          jdk.security.auth
+ *          jdk.security.jgss
  * @compile -addmods java.xml.ws,java.smartcardio Modules.java
  * @run main/othervm/java.security.policy==modules.policy
  *     -addmods java.xml.ws,java.smartcardio Modules
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+    (this test doesn't have an at-test tag because it's run by a shell
+    script instead of directly by the test harness)
+*/
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * 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.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+package java.text;
+import sun.text.IntHashtable;
+
+
+/**
+ * This class tests some internal hashCode() functions.
+ * Bug #4170614 complained that we had two iternal classes that
+ * break the invariant that if a.equals(b) than a.hashCode() ==
+ * b.hashCode().  This is because these classes overrode equals()
+ * but not hashCode().  These are both purely internal classes, and
+ * the library itself doesn't actually call hashCode(), so this isn't
+ * actually causing anyone problems yet.  But if these classes are
+ * ever exposed in the API, their hashCode() methods need to work right.
+ * PatternEntry will never be exposed in the API, but IntHashtable
+ * might be.  This is a shell test to allow us to access classes that
+ * are declared package private.
+ * @author Richard Gillam
+ */
+public class Bug4170614Test {
+    public static void main(String[] args) throws Exception {
+        testIntHashtable();
+        testPatternEntry();
+    }
+
+
+    public static void testIntHashtable() throws Exception {
+        IntHashtable fred = new IntHashtable();
+        fred.put(1, 10);
+        fred.put(2, 20);
+        fred.put(3, 30);
+
+        IntHashtable barney = new IntHashtable();
+        barney.put(1, 10);
+        barney.put(3, 30);
+        barney.put(2, 20);
+
+        IntHashtable homer = new IntHashtable();
+        homer.put(3, 30);
+        homer.put(1, 10);
+        homer.put(7, 900);
+
+        if (fred.equals(barney)) {
+            System.out.println("fred.equals(barney)");
+        }
+        else {
+            System.out.println("!fred.equals(barney)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("barney.hashCode() == " + barney.hashCode());
+
+        if (!fred.equals(barney)) {
+            throw new Exception("equals() failed on two hashtables that are equal");
+        }
+
+        if (fred.hashCode() != barney.hashCode()) {
+           throw new Exception("hashCode() failed on two hashtables that are equal");
+        }
+
+        System.out.println();
+        if (fred.equals(homer)) {
+            System.out.println("fred.equals(homer)");
+        }
+        else {
+            System.out.println("!fred.equals(homer)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("homer.hashCode() == " + homer.hashCode());
+
+        if (fred.equals(homer)) {
+            throw new Exception("equals() failed on two hashtables that are not equal");
+        }
+
+        if (fred.hashCode() == homer.hashCode()) {
+            throw new Exception("hashCode() failed on two hashtables that are not equal");
+        }
+
+        System.out.println();
+        System.out.println("testIntHashtable() passed.\n");
+    }
+
+    public static void testPatternEntry() throws Exception {
+        PatternEntry fred = new PatternEntry(1,
+                                             new StringBuffer("hello"),
+                                             new StringBuffer("up"));
+        PatternEntry barney = new PatternEntry(1,
+                                               new StringBuffer("hello"),
+                                               new StringBuffer("down"));
+        // (equals() only considers the "chars" field, so fred and barney are equal)
+        PatternEntry homer = new PatternEntry(1,
+                                              new StringBuffer("goodbye"),
+                                              new StringBuffer("up"));
+
+        if (fred.equals(barney)) {
+            System.out.println("fred.equals(barney)");
+        }
+        else {
+            System.out.println("!fred.equals(barney)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("barney.hashCode() == " + barney.hashCode());
+
+        if (!fred.equals(barney)) {
+            throw new Exception("equals() failed on two hashtables that are equal");
+        }
+
+        if (fred.hashCode() != barney.hashCode()) {
+           throw new Exception("hashCode() failed on two hashtables that are equal");
+        }
+
+        System.out.println();
+        if (fred.equals(homer)) {
+            System.out.println("fred.equals(homer)");
+        }
+        else {
+            System.out.println("!fred.equals(homer)");
+        }
+        System.out.println("fred.hashCode() == " + fred.hashCode());
+        System.out.println("homer.hashCode() == " + homer.hashCode());
+
+        if (fred.equals(homer)) {
+            throw new Exception("equals() failed on two hashtables that are not equal");
+        }
+
+        if (fred.hashCode() == homer.hashCode()) {
+            throw new Exception("hashCode() failed on two hashtables that are not equal");
+        }
+
+        System.out.println();
+        System.out.println("testPatternEntry() passed.\n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/text/IntHashtable/Bug4170614Test.sh	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+#
+# 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.
+#
+# 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 4170614
+# @summary Test internal hashCode() functions
+#
+
+set -x
+if [ "${TESTSRC}" = "" ]
+then
+  echo "TESTSRC not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+echo "TESTSRC=${TESTSRC}"
+if [ "${TESTJAVA}" = "" ]
+then
+  echo "TESTJAVA not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+if [ "${COMPILEJAVA}" = "" ]; then
+   COMPILEJAVA="${TESTJAVA}"
+fi
+echo "COMPILEJAVA=${COMPILEJAVA}"
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+echo "TESTCLASSES=${TESTCLASSES}"
+
+goback=`pwd`
+
+cd ${TESTSRC}
+
+TEST_JAVABASE=${TESTCLASSES}/java.base
+mkdir -p ${TEST_JAVABASE}
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+    -Xmodule:java.base \
+    -d ${TEST_JAVABASE} Bug4170614Test.java
+
+${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.base=${TEST_JAVABASE} java.text.Bug4170614Test
+
+result=$?
+
+cd ${goback}
+
+if [ $result -eq 0 ]
+then
+  echo "Passed"
+else
+  echo "Failed"
+fi
+exit $result
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/text/IntHashtable/Bug4705389.java	Wed Jul 05 21:46:22 2017 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 4705389
+ * @summary Make sure to find removed slots, which test case will be timed out without the fix.
+ * @modules java.base/sun.text
+ * @run main/timeout=10 Bug4705389
+ */
+
+import sun.text.IntHashtable;
+
+public class Bug4705389 {
+   public static void main(String args[]) {
+      IntHashtable table = new IntHashtable();
+      for (int i = 1; i < 132; ++i) {
+         table.put(i, 0);
+         table.remove(i);
+      }
+      table.put(132, 0);
+   }
+}
--- a/jdk/test/sun/util/logging/SourceClassName.java	Thu May 26 17:19:03 2016 +0000
+++ b/jdk/test/sun/util/logging/SourceClassName.java	Wed Jul 05 21:46:22 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 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
@@ -28,6 +28,7 @@
  *          logger.
  *
  * @modules java.base/sun.util.logging
+ *          java.logging
  * @compile -XDignore.symbol.file SourceClassName.java
  * @run main/othervm SourceClassName
  */
--- a/make/Images.gmk	Thu May 26 17:19:03 2016 +0000
+++ b/make/Images.gmk	Wed Jul 05 21:46:22 2017 +0200
@@ -115,9 +115,12 @@
 # Use this file inside the image as target for make rule
 JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX)
 
-JLINK_ORDER_RESOURCES := \
-    *module-info.class* \
-    @$(SUPPORT_OUTPUTDIR)/classlist/classlist,/java.base/java/* \
+JLINK_ORDER_RESOURCES := *module-info.class*
+ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
+  JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/classlist/classlist
+endif
+JLINK_ORDER_RESOURCES += \
+    /java.base/java/* \
     /java.base/jdk/* \
     /java.base/sun/* \
     /java.base/com/* \
@@ -125,9 +128,10 @@
     #
 
 JLINK_TOOL := $(JLINK) --modulepath $(IMAGES_OUTPUTDIR)/jmods \
-              --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
-              --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
-              --release-info $(BASE_RELEASE_FILE)
+    --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
+    --release-info $(BASE_RELEASE_FILE) \
+    --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
+    #
 
 ifeq ($(JLINK_KEEP_PACKAGED_MODULES), true)
   JLINK_EXTRA_OPTS := --keep-packaged-modules $(JDK_IMAGE_DIR)/jmods
@@ -369,19 +373,21 @@
 ################################################################################
 # classlist
 
-$(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \
-    FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
-    DEST := $(JDK_IMAGE_DIR)/lib, \
-))
+ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
+  $(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \
+      FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
+      DEST := $(JDK_IMAGE_DIR)/lib, \
+  ))
 
-JDK_TARGETS += $(JDK_COPY_CLASSLIST)
+  JDK_TARGETS += $(JDK_COPY_CLASSLIST)
 
-$(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \
-    FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
-    DEST := $(JRE_IMAGE_DIR)/lib, \
-))
+  $(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \
+      FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
+      DEST := $(JRE_IMAGE_DIR)/lib, \
+  ))
 
-JRE_TARGETS += $(JRE_COPY_CLASSLIST)
+  JRE_TARGETS += $(JRE_COPY_CLASSLIST)
+endif
 
 ################################################################################
 # /demo dir
--- a/make/Main.gmk	Thu May 26 17:19:03 2016 +0000
+++ b/make/Main.gmk	Wed Jul 05 21:46:22 2017 +0200
@@ -373,8 +373,10 @@
 interim-image:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f InterimImage.gmk)
 
-generate-classlist:
+ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
+  generate-classlist:
 	+($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f GenerateClasslist.gmk)
+endif
 
 ALL_TARGETS += interim-image generate-classlist
 
@@ -640,18 +642,22 @@
 
   jrtfs-jar: interim-langtools
 
-  ifeq ($(CREATE_BUILDJDK), true)
-    # If creating a buildjdk, the interim image needs to be based on that.
-    generate-classlist: create-buildjdk
-  else ifeq ($(EXTERNAL_BUILDJDK), false)
-    # If an external buildjdk has been provided, we skip generating an
-    # interim-image and just use the external buildjdk for generating
-    # classlist.
-    generate-classlist: interim-image
+  ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
+    ifeq ($(CREATE_BUILDJDK), true)
+      # If creating a buildjdk, the interim image needs to be based on that.
+      generate-classlist: create-buildjdk
+    else ifeq ($(EXTERNAL_BUILDJDK), false)
+      # If an external buildjdk has been provided, we skip generating an
+      # interim-image and just use the external buildjdk for generating
+      # classlist.
+      generate-classlist: interim-image
+    endif
+    generate-classlist: buildtools-jdk
+
+    jimages: generate-classlist
   endif
-  generate-classlist: buildtools-jdk
 
-  jimages: jmods zip-source source-tips demos samples jrtfs-jar generate-classlist
+  jimages: jmods zip-source source-tips demos samples jrtfs-jar
 
   profiles: jmods zip-source source-tips jrtfs-jar