changeset 6443:57561ea851d2

Merge
author lana
date Sat, 26 Jan 2013 19:22:51 -0800
parents ef592aceb40e e96577d82cbb
children a1a55db02f34
files test/java/rmi/activation/ActivationSystem/unregisterGroup/CallbackInterface.java test/java/rmi/activation/ActivationSystem/unregisterGroup/Callback_Stub.java test/java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup_Stub.java test/sun/text/resources/LocaleData test/sun/text/resources/LocaleDataTest.java
diffstat 566 files changed, 120920 insertions(+), 2677 deletions(-) [+]
line wrap: on
line diff
--- a/make/docs/CORE_PKGS.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/docs/CORE_PKGS.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -127,6 +127,11 @@
   java.sql                                       \
   java.text                                      \
   java.text.spi                                  \
+  java.time                                      \
+  java.time.temporal                             \
+  java.time.calendar                             \
+  java.time.format                               \
+  java.time.zone                                 \
   java.util                                      \
   java.util.concurrent                           \
   java.util.concurrent.atomic                    \
--- a/make/docs/Makefile	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/docs/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -207,6 +207,7 @@
 		-quiet					\
                 -use					\
                 -keywords				\
+		-Xdoclint:none				\
 		$(ADDITIONAL_JAVADOCFLAGS)
 
 ifdef OPENJDK
--- a/make/java/Makefile	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/java/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -39,7 +39,7 @@
 # Others
 #    Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk
 
-SUBDIRS += security math util text net nio jar
+SUBDIRS += security math util text net nio jar time
 
 SUBDIRS_desktop    = awt applet beans
 SUBDIRS_management = management
--- a/make/java/java/Exportedfiles.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/java/java/Exportedfiles.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
     java/lang/reflect/Constructor.java \
     java/lang/reflect/InvocationTargetException.java \
     java/lang/reflect/Array.java \
+    java/lang/reflect/Executable.java \
     java/lang/reflect/Proxy.java \
     java/security/AccessController.java \
     java/util/Date.java \
@@ -129,6 +130,7 @@
     java/lang/reflect/Constructor.java \
     java/lang/reflect/InvocationTargetException.java \
     java/lang/reflect/Array.java \
+    java/lang/reflect/Executable.java \
     java/lang/reflect/Proxy.java \
     java/lang/ref/Reference.java \
     java/lang/ref/Finalizer.java \
--- a/make/java/java/FILES_c.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/java/java/FILES_c.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 	Compiler.c \
 	Console_md.c \
 	Double.c \
+	Executable.c \
 	FileDescriptor_md.c \
 	FileInputStream.c \
 	FileInputStream_md.c \
--- a/make/java/java/FILES_java.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/java/java/FILES_java.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -137,6 +137,7 @@
     java/lang/Appendable.java \
     java/lang/Comparable.java \
     java/lang/Readable.java \
+    java/lang/FunctionalInterface.java \
     java/lang/Override.java \
     java/lang/SafeVarargs.java \
     java/lang/SuppressWarnings.java \
@@ -227,6 +228,7 @@
             sun/util/locale/provider/LocaleResources.java \
             sun/util/locale/provider/NumberFormatProviderImpl.java \
             sun/util/locale/provider/RuleBasedBreakIterator.java \
+            sun/util/locale/provider/ResourceBundleBasedAdapter.java \
             sun/util/locale/provider/SPILocaleProviderAdapter.java \
             sun/util/locale/provider/TimeZoneNameProviderImpl.java \
             sun/util/locale/provider/TimeZoneNameUtility.java \
@@ -372,6 +374,11 @@
     java/util/concurrent/atomic/AtomicReferenceArray.java \
     java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java \
     java/util/concurrent/atomic/AtomicStampedReference.java \
+    java/util/concurrent/atomic/DoubleAccumulator.java \
+    java/util/concurrent/atomic/DoubleAdder.java \
+    java/util/concurrent/atomic/LongAccumulator.java \
+    java/util/concurrent/atomic/LongAdder.java \
+    java/util/concurrent/atomic/Striped64.java \
     java/util/concurrent/locks/AbstractOwnableSynchronizer.java \
     java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java \
     java/util/concurrent/locks/AbstractQueuedSynchronizer.java \
--- a/make/java/java/mapfile-vers	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/java/java/mapfile-vers	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
 		Java_java_lang_reflect_Array_setInt;
 		Java_java_lang_reflect_Array_setLong;
 		Java_java_lang_reflect_Array_setShort;
+		Java_java_lang_reflect_Executable_getParameters0;
 		Java_java_lang_Runtime_freeMemory;
                 Java_java_lang_Runtime_maxMemory;
 		Java_java_lang_Runtime_gc;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/java/time/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#
+# Makefile for building jar utility.
+#
+
+BUILDDIR = ../../
+PACKAGE = java.time
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files
+#
+AUTO_FILES_JAVA_DIRS = java/time
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
--- a/make/jprt.properties	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/jprt.properties	Sat Jan 26 19:22:51 2013 -0800
@@ -87,6 +87,7 @@
     ${jprt.my.test.target.set:TESTNAME=jdk_text},               \
     ${jprt.my.test.target.set:TESTNAME=jdk_tools},              \
     ${jprt.my.test.target.set:TESTNAME=jdk_jfr},                \
+    ${jprt.my.test.target.set:TESTNAME=jdk_time},               \
     ${jprt.my.test.target.set:TESTNAME=jdk_other}
 
 # All vm test targets (testset=all)
--- a/make/sun/Makefile	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/sun/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -70,7 +70,7 @@
 endif
 
 # nio need to be compiled before awt to have all charsets ready
-SUBDIRS            = jar security javazic misc net nio text util launcher cldr
+SUBDIRS            = jar security javazic misc net nio text util launcher cldr tzdb
 
 ifdef BUILD_HEADLESS_ONLY
   DISPLAY_LIBS = awt $(HEADLESS_SUBDIR)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/tzdb/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#
+# Makefile for building tzdb compiler utility.
+#
+
+BUILDDIR = ../..
+PACKAGE = sun.tzdb
+PRODUCT = sun
+include $(BUILDDIR)/common/Defs.gmk
+
+# This program must contain a manifest that defines the execution level
+# needed to follow standard Vista User Access Control Guidelines
+# This must be set before Program.gmk is included
+#
+BUILD_MANIFEST=true
+
+#
+# Time zone data file creation
+#
+TZDATA_DIR := ../javazic/tzdata
+TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
+TZFILE := africa antarctica asia australasia europe northamerica southamerica backward etcetera
+TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZFILE))
+
+TZDB_JAR = tzdb.jar
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
+
+#
+# Add to the build rule
+#
+build: $(LIBDIR)/$(TZDB_JAR)
+
+$(LIBDIR)/$(TZDB_JAR): $(TZFILES)
+	$(prep-target)
+	echo build tzdb from version $(TZDATA_VER)
+	$(BOOT_JAVA_CMD) -jar $(BUILDTOOLJARDIR)/tzdb.jar -verbose \
+	  -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(LIBDIR) $(TZFILE)
+
+clean clobber::
+	$(RM) $(LIBDIR)/$(TZDB_JAR)
--- a/make/tools/Makefile	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/tools/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -53,6 +53,7 @@
   makeclasslist             \
   strip_properties          \
   spp                       \
+  tzdb                      \
   CharsetMapping
 
 ifndef DISABLE_NIMBUS
--- a/make/tools/src/build/tools/cldrconverter/Bundle.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/tools/src/build/tools/cldrconverter/Bundle.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -274,7 +274,7 @@
             handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns");
         }
 
-        // if myMap has any empty timezone or metazone names, weed out them.
+        // First, weed out any empty timezone or metazone names from myMap.
         // Fill in any missing abbreviations if locale is "en".
         for (Iterator<String> it = myMap.keySet().iterator(); it.hasNext();) {
             String key = it.next();
@@ -426,7 +426,7 @@
 
     /*
      * Adjusts String[] for era names because JRE's Calendars use different
-     * ERA value indexes in the Buddhist and Japanese Imperial calendars.
+     * ERA value indexes in the Buddhist, Japanese Imperial, and Islamic calendars.
      */
     private void adjustEraNames(Map<String, Object> map, CalendarType type) {
         String[][] eraNames = new String[ERA_KEYS.length][];
@@ -458,6 +458,11 @@
                     // Replace the value
                     value = new String[] {"BC", value[0]};
                     break;
+
+                case ISLAMIC:
+                    // Replace the value
+                    value = new String[] {"", value[0]};
+                    break;
                 }
                 if (!key.equals(realKey)) {
                     map.put(realKey, value);
@@ -479,6 +484,7 @@
         for (String k : patternKeys) {
             if (myMap.containsKey(calendarPrefix + k)) {
                 int len = patternKeys.length;
+                List<String> rawPatterns = new ArrayList<>();
                 List<String> patterns = new ArrayList<>();
                 for (int i = 0; i < len; i++) {
                     String key = calendarPrefix + patternKeys[i];
@@ -487,6 +493,7 @@
                         pattern = (String) parentsMap.remove(key);
                     }
                     if (pattern != null) {
+                        rawPatterns.add(i, pattern);
                         patterns.add(i, translateDateFormatLetters(calendarType, pattern));
                     }
                 }
@@ -494,6 +501,9 @@
                     return;
                 }
                 String key = calendarPrefix + name;
+                if (!rawPatterns.equals(patterns)) {
+                    myMap.put("cldr." + key, rawPatterns.toArray(new String[len]));
+                }
                 myMap.put(key, patterns.toArray(new String[len]));
                 break;
             }
--- a/make/tools/src/build/tools/cldrconverter/CLDRConverter.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/tools/src/build/tools/cldrconverter/CLDRConverter.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,7 @@
     static final String LOCALE_NAME_PREFIX = "locale.displayname.";
     static final String CURRENCY_SYMBOL_PREFIX = "currency.symbol.";
     static final String CURRENCY_NAME_PREFIX = "currency.displayname.";
+    static final String CALENDAR_NAME_PREFIX = "calendarname.";
     static final String TIMEZONE_ID_PREFIX = "timezone.id.";
     static final String ZONE_NAME_PREFIX = "timezone.displayname.";
     static final String METAZONE_ID_PREFIX = "metazone.id.";
@@ -519,35 +520,70 @@
         return calendarData;
     }
 
+    static final String[] FORMAT_DATA_ELEMENTS = {
+        "MonthNames",
+        "standalone.MonthNames",
+        "MonthAbbreviations",
+        "standalone.MonthAbbreviations",
+        "MonthNarrow",
+        "standalone.MonthNarrows",
+        "DayNames",
+        "standalone.DayNames",
+        "DayAbbreviations",
+        "standalone.DayAbbreviations",
+        "DayNarrows",
+        "standalone.DayNarrows",
+        "AmPmMarkers",
+        "narrow.AmPmMarkers",
+        "long.Eras",
+        "Eras",
+        "narrow.Eras",
+        "field.era",
+        "field.year",
+        "field.month",
+        "field.week",
+        "field.weekday",
+        "field.dayperiod",
+        "field.hour",
+        "field.minute",
+        "field.second",
+        "field.zone",
+        "TimePatterns",
+        "DatePatterns",
+        "DateTimePatterns",
+        "DateTimePatternChars"
+    };
+
     private static Map<String, Object> extractFormatData(Map<String, Object> map, String id) {
         Map<String, Object> formatData = new LinkedHashMap<>();
         for (CalendarType calendarType : CalendarType.values()) {
             String prefix = calendarType.keyElementName();
-            copyIfPresent(map, prefix + "MonthNames", formatData); // default FORMAT since JDK8
-            copyIfPresent(map, prefix + "standalone.MonthNames", formatData);
-            copyIfPresent(map, prefix + "MonthAbbreviations", formatData);
-            copyIfPresent(map, prefix + "standalone.MonthAbbreviations", formatData);
-            copyIfPresent(map, prefix + "MonthNarrow", formatData);
-            copyIfPresent(map, prefix + "standalone.MonthNarrows", formatData);
-            copyIfPresent(map, prefix + "DayNames", formatData);
-            copyIfPresent(map, prefix + "standalone.DayNames", formatData);
-            copyIfPresent(map, prefix + "DayAbbreviations", formatData);
-            copyIfPresent(map, prefix + "standalone.DayAbbreviations", formatData);
-            copyIfPresent(map, prefix + "DayNarrows", formatData);
-            copyIfPresent(map, prefix + "standalone.DayNarrows", formatData);
-            copyIfPresent(map, prefix + "AmPmMarkers", formatData);
-            copyIfPresent(map, prefix + "narrow.AmPmMarkers", formatData);
-            copyIfPresent(map, prefix + "long.Eras", formatData);
-            copyIfPresent(map, prefix + "Eras", formatData);
-            copyIfPresent(map, prefix + "narrow.Eras", formatData);
-            copyIfPresent(map, prefix + "TimePatterns", formatData);
-            copyIfPresent(map, prefix + "DatePatterns", formatData);
-            copyIfPresent(map, prefix + "DateTimePatterns", formatData);
-            copyIfPresent(map, prefix + "DateTimePatternChars", formatData);
+            for (String element : FORMAT_DATA_ELEMENTS) {
+                String key = prefix + element;
+                copyIfPresent(map, "cldr." + key, formatData);
+                copyIfPresent(map, key, formatData);
+            }
+        }
+
+        // Copy available calendar names
+        for (String key : map.keySet()) {
+            if (key.startsWith(CLDRConverter.CALENDAR_NAME_PREFIX)) {
+                String type = key.substring(CLDRConverter.CALENDAR_NAME_PREFIX.length());
+                for (CalendarType calendarType : CalendarType.values()) {
+                    if (type.equals(calendarType.lname())) {
+                        Object value = map.get(key);
+                        formatData.put(key, value);
+                        String ukey = CLDRConverter.CALENDAR_NAME_PREFIX + calendarType.uname();
+                        if (!key.equals(ukey)) {
+                            formatData.put(ukey, value);
+                        }
+                    }
+                }
+            }
         }
 
         copyIfPresent(map, "DefaultNumberingSystem", formatData);
-        String defaultScript = (String) map.get("DefaultNumberingSystem");
+
         @SuppressWarnings("unchecked")
         List<String> numberingScripts = (List<String>) map.remove("numberingScripts");
         if (numberingScripts != null) {
--- a/make/tools/src/build/tools/cldrconverter/CalendarType.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/tools/src/build/tools/cldrconverter/CalendarType.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,26 +31,42 @@
  * Constants for the Calendars supported by JRE.
  */
 enum CalendarType {
-
-    GREGORIAN, BUDDHIST, JAPANESE;
+    GREGORIAN("gregory"), BUDDHIST, JAPANESE, ROC, ISLAMIC, ISLAMIC_CIVIL("islamicc");
 
     private static final int[][] ERA_DATA = {
         // start index, array length
         {0,   2},   // gregorian
         {0,   1},   // buddhist
         {232, 4},   // japanese (eras from Meiji)
+        {0,   2},   // roc (Minguo)
+        {0,   1},   // islamic (Hijrah)
+        {0,   1},   // islamicc (same as islamic)
     };
 
     private final String lname; // lowercase name
+    private final String uname; // unicode key name (e.g., "gregory" for GREGORIAN)
 
     private CalendarType() {
-        lname = name().toLowerCase(Locale.ROOT);
+        this(null);
+    }
+
+    private CalendarType(String uname) {
+        String lname = name().toLowerCase(Locale.ROOT);
+        if (lname.equals("islamic_civil")) {
+            lname = "islamic-civil";
+        }
+        this.lname = lname;
+        this.uname = (uname != null) ? uname : lname;
     }
 
     String lname() {
         return lname;
     }
 
+    String uname() {
+        return uname;
+    }
+
     String keyElementName() {
         return (this == GREGORIAN) ? "" : lname + ".";
     }
--- a/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,6 +71,13 @@
             // ignore this element - it has language and territory elements that aren't locale data
             pushIgnoredContainer(qName);
             break;
+        case "type":
+            if ("calendar".equals(attributes.getValue("key"))) {
+                pushStringEntry(qName, attributes, CLDRConverter.CALENDAR_NAME_PREFIX + attributes.getValue("type"));
+            } else {
+                pushIgnoredContainer(qName);
+            }
+            break;
         case "language":
             // for LocaleNames
             // copy string
@@ -98,19 +105,30 @@
         case "symbol":
             // for CurrencyNames
             // need to get the key from the containing <currency> element
-            pushStringEntry(qName, attributes, CLDRConverter.CURRENCY_SYMBOL_PREFIX + getContainerKey());
+            pushStringEntry(qName, attributes, CLDRConverter.CURRENCY_SYMBOL_PREFIX
+                                               + getContainerKey());
             break;
+
+        // Calendar or currency
         case "displayName":
-            // for CurrencyNames
-            // need to get the key from the containing <currency> element
-            // ignore if is has "count" attribute
-            String containerKey = getContainerKey();
-            if (containerKey != null && attributes.getValue("count") == null) {
-                pushStringEntry(qName, attributes,
-                                CLDRConverter.CURRENCY_NAME_PREFIX + containerKey.toLowerCase(Locale.ROOT),
-                                attributes.getValue("type"));
-            } else {
-                pushIgnoredContainer(qName);
+            {
+                if (currentCalendarType != null) {
+                    pushStringEntry(qName, attributes,
+                            currentCalendarType.keyElementName() + "field." + getContainerKey());
+                } else {
+                    // for CurrencyNames
+                    // need to get the key from the containing <currency> element
+                    // ignore if is has "count" attribute
+                    String containerKey = getContainerKey();
+                    if (containerKey != null && attributes.getValue("count") == null) {
+                        pushStringEntry(qName, attributes,
+                                        CLDRConverter.CURRENCY_NAME_PREFIX
+                                        + containerKey.toLowerCase(Locale.ROOT),
+                                        attributes.getValue("type"));
+                    } else {
+                        pushIgnoredContainer(qName);
+                    }
+                }
             }
             break;
 
@@ -130,6 +148,35 @@
                 }
             }
             break;
+        case "fields":
+            if (currentCalendarType != null) {
+                pushContainer(qName, attributes);
+            } else {
+                pushIgnoredContainer(qName);
+            }
+            break;
+        case "field":
+            {
+                String type = attributes.getValue("type");
+                switch (type) {
+                case "era":
+                case "year":
+                case "month":
+                case "week":
+                case "weekday":
+                case "dayperiod":
+                case "hour":
+                case "minute":
+                case "second":
+                case "zone":
+                    pushKeyContainer(qName, attributes, type);
+                    break;
+                default:
+                    pushIgnoredContainer(qName);
+                    break;
+                }
+            }
+            break;
         case "monthContext":
             {
                 // for FormatData
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ChronoField.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package build.tools.tzdb;
+
+/**
+ * A standard set of date/time fields.
+ *
+ * @since 1.8
+ */
+enum ChronoField {
+
+    /**
+     * The second-of-minute.
+     * <p>
+     * This counts the second within the minute, from 0 to 59.
+     * This field has the same meaning for all calendar systems.
+     */
+    SECOND_OF_MINUTE("SecondOfMinute", 0, 59),
+
+    /**
+     * The second-of-day.
+     * <p>
+     * This counts the second within the day, from 0 to (24 * 60 * 60) - 1.
+     * This field has the same meaning for all calendar systems.
+     */
+    SECOND_OF_DAY("SecondOfDay", 0, 86400 - 1),
+
+    /**
+     * The minute-of-hour.
+     * <p>
+     * This counts the minute within the hour, from 0 to 59.
+     * This field has the same meaning for all calendar systems.
+     */
+    MINUTE_OF_HOUR("MinuteOfHour", 0, 59),
+
+    /**
+     * The hour-of-day.
+     * <p>
+     * This counts the hour within the day, from 0 to 23.
+     * This is the hour that would be observed on a standard 24-hour digital clock.
+     * This field has the same meaning for all calendar systems.
+     */
+    HOUR_OF_DAY("HourOfDay", 0, 23),
+
+
+    /**
+     * The day-of-month.
+     * <p>
+     * This represents the concept of the day within the month.
+     * In the default ISO calendar system, this has values from 1 to 31 in most months.
+     * April, June, September, November have days from 1 to 30, while February has days
+     * from 1 to 28, or 29 in a leap year.
+     * <p>
+     * Non-ISO calendar systems should implement this field using the most recognized
+     * day-of-month values for users of the calendar system.
+     * Normally, this is a count of days from 1 to the length of the month.
+     */
+    DAY_OF_MONTH("DayOfMonth", 1, 31),
+
+    /**
+     * The month-of-year, such as March.
+     * <p>
+     * This represents the concept of the month within the year.
+     * In the default ISO calendar system, this has values from January (1) to December (12).
+     * <p>
+     * Non-ISO calendar systems should implement this field using the most recognized
+     * month-of-year values for users of the calendar system.
+     * Normally, this is a count of months starting from 1.
+     */
+    MONTH_OF_YEAR("MonthOfYear", 1, 12),
+
+    /**
+     * The proleptic year, such as 2012.
+     * <p>
+     * This represents the concept of the year, counting sequentially and using negative numbers.
+     * The proleptic year is not interpreted in terms of the era.
+     * See {@link #YEAR_OF_ERA} for an example showing the mapping from proleptic year to year-of-era.
+     * <p>
+     * The standard mental model for a date is based on three concepts - year, month and day.
+     * These map onto the {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
+     * Note that there is no reference to eras.
+     * The full model for a date requires four concepts - era, year, month and day. These map onto
+     * the {@code ERA}, {@code YEAR_OF_ERA}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
+     * Whether this field or {@code YEAR_OF_ERA} is used depends on which mental model is being used.
+     * See {@link ChronoLocalDate} for more discussion on this topic.
+     * <p>
+     * Non-ISO calendar systems should implement this field as follows.
+     * If the calendar system has only two eras, before and after a fixed date, then the
+     * proleptic-year value must be the same as the year-of-era value for the later era,
+     * and increasingly negative for the earlier era.
+     * If the calendar system has more than two eras, then the proleptic-year value may be
+     * defined with any appropriate value, although defining it to be the same as ISO may be
+     * the best option.
+     */
+    YEAR("Year", -999_999_999, 999_999_999);
+
+    private final String name;
+    private final int min;
+    private final int max;
+
+    private ChronoField(String name, int min, int max) {
+        this.name = name;
+        this.min= min;
+        this.max= max;
+    }
+
+    /**
+     * Checks that the specified value is valid for this field.
+     * <p>
+     *
+     * @param value  the value to check
+     * @return the value that was passed in
+     */
+    public int checkValidValue(int value) {
+        if (value >= min && value <= max) {
+            return value;
+        }
+        throw new DateTimeException("Invalid value for " + name + " value: " + value);
+    }
+
+    public String toString() {
+        return name;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/DateTimeException.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+/**
+ * Exception used to indicate a problem while calculating a date-time.
+ * <p>
+ * This exception is used to indicate problems with creating, querying
+ * and manipulating date-time objects.
+ *
+ * @since 1.8
+ */
+class DateTimeException extends RuntimeException {
+
+    /**
+     * Serialization version.
+     */
+    private static final long serialVersionUID = -1632418723876261839L;
+
+    /**
+     * Constructs a new date-time exception with the specified message.
+     *
+     * @param message  the message to use for this exception, may be null
+     */
+    public DateTimeException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new date-time exception with the specified message and cause.
+     *
+     * @param message  the message to use for this exception, may be null
+     * @param cause  the cause of the exception, may be null
+     */
+    public DateTimeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/LocalDate.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.Utils.*;
+import static build.tools.tzdb.LocalTime.SECONDS_PER_DAY;
+import static build.tools.tzdb.ChronoField.DAY_OF_MONTH;
+import static build.tools.tzdb.ChronoField.MONTH_OF_YEAR;
+import static build.tools.tzdb.ChronoField.YEAR;
+
+import java.util.Objects;
+
+/**
+ * A date without a time-zone in the ISO-8601 calendar system,
+ * such as {@code 2007-12-03}.
+ *
+ * @since 1.8
+ */
+final class LocalDate {
+
+    /**
+     * The minimum supported {@code LocalDate}, '-999999999-01-01'.
+     * This could be used by an application as a "far past" date.
+     */
+    public static final LocalDate MIN = new LocalDate(YEAR_MIN_VALUE, 1, 1);
+    /**
+     * The maximum supported {@code LocalDate}, '+999999999-12-31'.
+     * This could be used by an application as a "far future" date.
+     */
+    public static final LocalDate MAX = new LocalDate(YEAR_MAX_VALUE, 12, 31);
+
+    /**
+     * The number of days in a 400 year cycle.
+     */
+    private static final int DAYS_PER_CYCLE = 146097;
+    /**
+     * The number of days from year zero to year 1970.
+     * There are five 400 year cycles from year zero to 2000.
+     * There are 7 leap years from 1970 to 2000.
+     */
+    static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
+
+    /**
+     * The year.
+     */
+    private final int year;
+    /**
+     * The month-of-year.
+     */
+    private final short month;
+    /**
+     * The day-of-month.
+     */
+    private final short day;
+
+    /**
+     * Obtains an instance of {@code LocalDate} from a year, month and day.
+     * <p>
+     * The day must be valid for the year and month, otherwise an exception will be thrown.
+     *
+     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
+     * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
+     * @param dayOfMonth  the day-of-month to represent, from 1 to 31
+     * @return the local date, not null
+     * @throws DateTimeException if the value of any field is out of range
+     * @throws DateTimeException if the day-of-month is invalid for the month-year
+     */
+    public static LocalDate of(int year, int month, int dayOfMonth) {
+        YEAR.checkValidValue(year);
+        MONTH_OF_YEAR.checkValidValue(month);
+        DAY_OF_MONTH.checkValidValue(dayOfMonth);
+        if (dayOfMonth > 28 && dayOfMonth > lengthOfMonth(month, isLeapYear(year))) {
+            if (dayOfMonth == 29) {
+                throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
+            } else {
+                throw new DateTimeException("Invalid date '" + month + " " + dayOfMonth + "'");
+            }
+        }
+        return new LocalDate(year, month, dayOfMonth);
+    }
+
+    /**
+     * Constructor, previously validated.
+     *
+     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
+     * @param month  the month-of-year to represent, not null
+     * @param dayOfMonth  the day-of-month to represent, valid for year-month, from 1 to 31
+     */
+    private LocalDate(int year, int month, int dayOfMonth) {
+        this.year = year;
+        this.month = (short) month;
+        this.day = (short) dayOfMonth;
+    }
+
+    /**
+     * Gets the year field.
+     * <p>
+     * This method returns the primitive {@code int} value for the year.
+     * <p>
+     * The year returned by this method is proleptic as per {@code get(YEAR)}.
+     * To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
+     *
+     * @return the year, from MIN_YEAR to MAX_YEAR
+     */
+    public int getYear() {
+        return year;
+    }
+
+    /**
+     * Gets the month-of-year field as an int from 1 to 12.
+     *
+     * @return the month-of-year
+     */
+    public int getMonth() {
+        return month;
+    }
+
+    /**
+     * Gets the day-of-month field.
+     * <p>
+     * This method returns the primitive {@code int} value for the day-of-month.
+     *
+     * @return the day-of-month, from 1 to 31
+     */
+    public int getDayOfMonth() {
+        return day;
+    }
+
+    /**
+     * Gets the day-of-week field, which is an int from 1 to 7.
+     *
+     * @return the day-of-week
+     */
+    public int getDayOfWeek() {
+        return (int)floorMod(toEpochDay() + 3, 7) + 1;
+    }
+
+    /**
+     * Returns a copy of this {@code LocalDate} with the specified number of days added.
+     * <p>
+     * This method adds the specified amount to the days field incrementing the
+     * month and year fields as necessary to ensure the result remains valid.
+     * The result is only invalid if the maximum/minimum year is exceeded.
+     * <p>
+     * For example, 2008-12-31 plus one day would result in 2009-01-01.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param daysToAdd  the days to add, may be negative
+     * @return a {@code LocalDate} based on this date with the days added, not null
+     * @throws DateTimeException if the result exceeds the supported date range
+     */
+    public LocalDate plusDays(long daysToAdd) {
+        if (daysToAdd == 0) {
+            return this;
+        }
+        long mjDay = addExact(toEpochDay(), daysToAdd);
+        return LocalDate.ofEpochDay(mjDay);
+    }
+
+    /**
+     * Returns a copy of this {@code LocalDate} with the specified number of days subtracted.
+     * <p>
+     * This method subtracts the specified amount from the days field decrementing the
+     * month and year fields as necessary to ensure the result remains valid.
+     * The result is only invalid if the maximum/minimum year is exceeded.
+     * <p>
+     * For example, 2009-01-01 minus one day would result in 2008-12-31.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param daysToSubtract  the days to subtract, may be negative
+     * @return a {@code LocalDate} based on this date with the days subtracted, not null
+     * @throws DateTimeException if the result exceeds the supported date range
+     */
+    public LocalDate minusDays(long daysToSubtract) {
+        return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
+    }
+
+    /**
+     * Obtains an instance of {@code LocalDate} from the epoch day count.
+     * <p>
+     * The Epoch Day count is a simple incrementing count of days
+     * where day 0 is 1970-01-01. Negative numbers represent earlier days.
+     *
+     * @param epochDay  the Epoch Day to convert, based on the epoch 1970-01-01
+     * @return the local date, not null
+     * @throws DateTimeException if the epoch days exceeds the supported date range
+     */
+    public static LocalDate ofEpochDay(long epochDay) {
+        long zeroDay = epochDay + DAYS_0000_TO_1970;
+        // find the march-based year
+        zeroDay -= 60;  // adjust to 0000-03-01 so leap day is at end of four year cycle
+        long adjust = 0;
+        if (zeroDay < 0) {
+            // adjust negative years to positive for calculation
+            long adjustCycles = (zeroDay + 1) / DAYS_PER_CYCLE - 1;
+            adjust = adjustCycles * 400;
+            zeroDay += -adjustCycles * DAYS_PER_CYCLE;
+        }
+        long yearEst = (400 * zeroDay + 591) / DAYS_PER_CYCLE;
+        long doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
+        if (doyEst < 0) {
+            // fix estimate
+            yearEst--;
+            doyEst = zeroDay - (365 * yearEst + yearEst / 4 - yearEst / 100 + yearEst / 400);
+        }
+        yearEst += adjust;  // reset any negative year
+        int marchDoy0 = (int) doyEst;
+
+        // convert march-based values back to january-based
+        int marchMonth0 = (marchDoy0 * 5 + 2) / 153;
+        int month = (marchMonth0 + 2) % 12 + 1;
+        int dom = marchDoy0 - (marchMonth0 * 306 + 5) / 10 + 1;
+        yearEst += marchMonth0 / 10;
+
+        // check year now we are certain it is correct
+        int year = YEAR.checkValidValue((int)yearEst);
+        return new LocalDate(year, month, dom);
+    }
+
+    public long toEpochDay() {
+        long y = year;
+        long m = month;
+        long total = 0;
+        total += 365 * y;
+        if (y >= 0) {
+            total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
+        } else {
+            total -= y / -4 - y / -100 + y / -400;
+        }
+        total += ((367 * m - 362) / 12);
+        total += day - 1;
+        if (m > 2) {
+            total--;
+            if (isLeapYear(year) == false) {
+                total--;
+            }
+        }
+        return total - DAYS_0000_TO_1970;
+    }
+
+    /**
+     * Compares this date to another date.
+     * <p>
+     * The comparison is primarily based on the date, from earliest to latest.
+     * It is "consistent with equals", as defined by {@link Comparable}.
+     * <p>
+     * If all the dates being compared are instances of {@code LocalDate},
+     * then the comparison will be entirely based on the date.
+     * If some dates being compared are in different chronologies, then the
+     * chronology is also considered, see {@link java.time.temporal.ChronoLocalDate#compareTo}.
+     *
+     * @param other  the other date to compare to, not null
+     * @return the comparator value, negative if less, positive if greater
+     */
+    public int compareTo(LocalDate otherDate) {
+        int cmp = (year - otherDate.year);
+        if (cmp == 0) {
+            cmp = (month - otherDate.month);
+            if (cmp == 0) {
+                cmp = (day - otherDate.day);
+            }
+        }
+        return cmp;
+    }
+
+    /**
+     * Checks if this date is equal to another date.
+     * <p>
+     * Compares this {@code LocalDate} with another ensuring that the date is the same.
+     * <p>
+     * Only objects of type {@code LocalDate} are compared, other types return false.
+     * To compare the dates of two {@code TemporalAccessor} instances, including dates
+     * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
+     *
+     * @param obj  the object to check, null returns false
+     * @return true if this is equal to the other date
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LocalDate) {
+            return compareTo((LocalDate) obj) == 0;
+        }
+        return false;
+    }
+
+    /**
+     * A hash code for this date.
+     *
+     * @return a suitable hash code
+     */
+    @Override
+    public int hashCode() {
+        int yearValue = year;
+        int monthValue = month;
+        int dayValue = day;
+        return (yearValue & 0xFFFFF800) ^ ((yearValue << 11) + (monthValue << 6) + (dayValue));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/LocalDateTime.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.Utils.*;
+import static build.tools.tzdb.LocalTime.HOURS_PER_DAY;
+import static build.tools.tzdb.LocalTime.MICROS_PER_DAY;
+import static build.tools.tzdb.LocalTime.MILLIS_PER_DAY;
+import static build.tools.tzdb.LocalTime.MINUTES_PER_DAY;
+import static build.tools.tzdb.LocalTime.SECONDS_PER_DAY;
+import static build.tools.tzdb.LocalTime.SECONDS_PER_MINUTE;
+import static build.tools.tzdb.LocalTime.SECONDS_PER_HOUR;
+
+import java.util.Objects;
+
+/**
+ * A date-time without a time-zone in the ISO-8601 calendar system,
+ * such as {@code 2007-12-03T10:15:30}.
+ *
+ * @since 1.8
+ */
+final class LocalDateTime {
+
+    /**
+     * The minimum supported {@code LocalDateTime}, '-999999999-01-01T00:00:00'.
+     * This is the local date-time of midnight at the start of the minimum date.
+     * This combines {@link LocalDate#MIN} and {@link LocalTime#MIN}.
+     * This could be used by an application as a "far past" date-time.
+     */
+    public static final LocalDateTime MIN = LocalDateTime.of(LocalDate.MIN, LocalTime.MIN);
+    /**
+     * The maximum supported {@code LocalDateTime}, '+999999999-12-31T23:59:59.999999999'.
+     * This is the local date-time just before midnight at the end of the maximum date.
+     * This combines {@link LocalDate#MAX} and {@link LocalTime#MAX}.
+     * This could be used by an application as a "far future" date-time.
+     */
+    public static final LocalDateTime MAX = LocalDateTime.of(LocalDate.MAX, LocalTime.MAX);
+
+    /**
+     * The date part.
+     */
+    private final LocalDate date;
+    /**
+     * The time part.
+     */
+    private final LocalTime time;
+
+    /**
+     * Obtains an instance of {@code LocalDateTime} from year, month,
+     * day, hour and minute, setting the second and nanosecond to zero.
+     * <p>
+     * The day must be valid for the year and month, otherwise an exception will be thrown.
+     * The second and nanosecond fields will be set to zero.
+     *
+     * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
+     * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
+     * @param dayOfMonth  the day-of-month to represent, from 1 to 31
+     * @param hour  the hour-of-day to represent, from 0 to 23
+     * @param minute  the minute-of-hour to represent, from 0 to 59
+     * @return the local date-time, not null
+     * @throws DateTimeException if the value of any field is out of range
+     * @throws DateTimeException if the day-of-month is invalid for the month-year
+     */
+    public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) {
+        LocalDate date = LocalDate.of(year, month, dayOfMonth);
+        LocalTime time = LocalTime.of(hour, minute);
+        return new LocalDateTime(date, time);
+    }
+
+    /**
+     * Obtains an instance of {@code LocalDateTime} from a date and time.
+     *
+     * @param date  the local date, not null
+     * @param time  the local time, not null
+     * @return the local date-time, not null
+     */
+    public static LocalDateTime of(LocalDate date, LocalTime time) {
+        Objects.requireNonNull(date, "date");
+        Objects.requireNonNull(time, "time");
+        return new LocalDateTime(date, time);
+    }
+
+    /**
+     * Obtains an instance of {@code LocalDateTime} using seconds from the
+     * epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * This allows the {@link ChronoField#INSTANT_SECONDS epoch-second} field
+     * to be converted to a local date-time. This is primarily intended for
+     * low-level conversions rather than general application usage.
+     *
+     * @param epochSecond  the number of seconds from the epoch of 1970-01-01T00:00:00Z
+     * @param nanoOfSecond  the nanosecond within the second, from 0 to 999,999,999
+     * @param offset  the zone offset, not null
+     * @return the local date-time, not null
+     * @throws DateTimeException if the result exceeds the supported range
+     */
+    public static LocalDateTime ofEpochSecond(long epochSecond, int nanoOfSecond, ZoneOffset offset) {
+        Objects.requireNonNull(offset, "offset");
+        long localSecond = epochSecond + offset.getTotalSeconds();  // overflow caught later
+        long localEpochDay = floorDiv(localSecond, SECONDS_PER_DAY);
+        int secsOfDay = (int)floorMod(localSecond, SECONDS_PER_DAY);
+        LocalDate date = LocalDate.ofEpochDay(localEpochDay);
+        LocalTime time = LocalTime.ofSecondOfDay(secsOfDay);  // ignore nano
+        return new LocalDateTime(date, time);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param date  the date part of the date-time, validated not null
+     * @param time  the time part of the date-time, validated not null
+     */
+    private LocalDateTime(LocalDate date, LocalTime time) {
+        this.date = date;
+        this.time = time;
+    }
+
+    /**
+     * Returns a copy of this date-time with the new date and time, checking
+     * to see if a new object is in fact required.
+     *
+     * @param newDate  the date of the new date-time, not null
+     * @param newTime  the time of the new date-time, not null
+     * @return the date-time, not null
+     */
+    private LocalDateTime with(LocalDate newDate, LocalTime newTime) {
+        if (date == newDate && time == newTime) {
+            return this;
+        }
+        return new LocalDateTime(newDate, newTime);
+    }
+
+    /**
+     * Gets the {@code LocalDate} part of this date-time.
+     * <p>
+     * This returns a {@code LocalDate} with the same year, month and day
+     * as this date-time.
+     *
+     * @return the date part of this date-time, not null
+     */
+    public LocalDate getDate() {
+        return date;
+    }
+
+    /**
+     * Gets the year field.
+     * <p>
+     * This method returns the primitive {@code int} value for the year.
+     * <p>
+     * The year returned by this method is proleptic as per {@code get(YEAR)}.
+     * To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
+     *
+     * @return the year, from MIN_YEAR to MAX_YEAR
+     */
+    public int getYear() {
+        return date.getYear();
+    }
+
+    /**
+     * Gets the month-of-year field as an int from 1 to 12.
+     *
+     * @return the month-of-year
+     */
+    public int getMonth() {
+        return date.getMonth();
+    }
+
+    /**
+     * Gets the day-of-month field.
+     * <p>
+     * This method returns the primitive {@code int} value for the day-of-month.
+     *
+     * @return the day-of-month, from 1 to 31
+     */
+    public int getDayOfMonth() {
+        return date.getDayOfMonth();
+    }
+
+    /**
+     * Gets the day-of-week field, which is an integer from 1 to 7.
+     *
+     * @return the day-of-week, from 1 to 7
+     */
+    public int getDayOfWeek() {
+        return date.getDayOfWeek();
+    }
+
+    /**
+     * Gets the {@code LocalTime} part of this date-time.
+     * <p>
+     * This returns a {@code LocalTime} with the same hour, minute, second and
+     * nanosecond as this date-time.
+     *
+     * @return the time part of this date-time, not null
+     */
+    public LocalTime getTime() {
+        return time;
+    }
+
+    /**
+     * Gets the hour-of-day field.
+     *
+     * @return the hour-of-day, from 0 to 23
+     */
+    public int getHour() {
+        return time.getHour();
+    }
+
+    /**
+     * Gets the minute-of-hour field.
+     *
+     * @return the minute-of-hour, from 0 to 59
+     */
+    public int getMinute() {
+        return time.getMinute();
+    }
+
+    /**
+     * Gets the second-of-minute field.
+     *
+     * @return the second-of-minute, from 0 to 59
+     */
+    public int getSecond() {
+        return time.getSecond();
+    }
+
+    /**
+     * Converts this date-time to the number of seconds from the epoch
+     * of 1970-01-01T00:00:00Z.
+     * <p>
+     * This combines this local date-time and the specified offset to calculate the
+     * epoch-second value, which is the number of elapsed seconds from 1970-01-01T00:00:00Z.
+     * Instants on the time-line after the epoch are positive, earlier are negative.
+     * <p>
+     * This default implementation calculates from the epoch-day of the date and the
+     * second-of-day of the time.
+     *
+     * @param offset  the offset to use for the conversion, not null
+     * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
+     */
+    public long toEpochSecond(ZoneOffset offset) {
+        Objects.requireNonNull(offset, "offset");
+        long epochDay = getDate().toEpochDay();
+        long secs = epochDay * 86400 + getTime().toSecondOfDay();
+        secs -= offset.getTotalSeconds();
+        return secs;
+    }
+
+    /**
+     * Returns a copy of this {@code LocalDateTime} with the specified period in days added.
+     * <p>
+     * This method adds the specified amount to the days field incrementing the
+     * month and year fields as necessary to ensure the result remains valid.
+     * The result is only invalid if the maximum/minimum year is exceeded.
+     * <p>
+     * For example, 2008-12-31 plus one day would result in 2009-01-01.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param days  the days to add, may be negative
+     * @return a {@code LocalDateTime} based on this date-time with the days added, not null
+     * @throws DateTimeException if the result exceeds the supported date range
+     */
+    public LocalDateTime plusDays(long days) {
+        LocalDate newDate = date.plusDays(days);
+        return with(newDate, time);
+    }
+
+    /**
+     * Returns a copy of this {@code LocalDateTime} with the specified period in seconds added.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param seconds  the seconds to add, may be negative
+     * @return a {@code LocalDateTime} based on this date-time with the seconds added, not null
+     * @throws DateTimeException if the result exceeds the supported date range
+     */
+    public LocalDateTime plusSeconds(long seconds) {
+        return plusWithOverflow(date, 0, 0, seconds, 1);
+    }
+
+    /**
+     * Returns a copy of this {@code LocalDateTime} with the specified period added.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param newDate  the new date to base the calculation on, not null
+     * @param hours  the hours to add, may be negative
+     * @param minutes the minutes to add, may be negative
+     * @param seconds the seconds to add, may be negative
+     * @param nanos the nanos to add, may be negative
+     * @param sign  the sign to determine add or subtract
+     * @return the combined result, not null
+     */
+    private LocalDateTime plusWithOverflow(LocalDate newDate, long hours, long minutes, long seconds, int sign) {
+        if ((hours | minutes | seconds) == 0) {
+            return with(newDate, time);
+        }
+        long totDays = seconds / SECONDS_PER_DAY +                //   max/24*60*60
+                       minutes / MINUTES_PER_DAY +                //   max/24*60
+                       hours / HOURS_PER_DAY;                     //   max/24
+        totDays *= sign;                                          // total max*0.4237...
+        long totSecs = (seconds % SECONDS_PER_DAY) +
+                       (minutes % MINUTES_PER_DAY) * SECONDS_PER_MINUTE +
+                       (hours % HOURS_PER_DAY) * SECONDS_PER_HOUR;
+        long curSoD = time.toSecondOfDay();
+        totSecs = totSecs * sign + curSoD;                    // total 432000000000000
+        totDays += floorDiv(totSecs, SECONDS_PER_DAY);
+
+        int newSoD = (int)floorMod(totSecs, SECONDS_PER_DAY);
+        LocalTime newTime = (newSoD == curSoD ? time : LocalTime.ofSecondOfDay(newSoD));
+        return with(newDate.plusDays(totDays), newTime);
+    }
+
+    /**
+     * Compares this date-time to another date-time.
+     * <p>
+     * The comparison is primarily based on the date-time, from earliest to latest.
+     * It is "consistent with equals", as defined by {@link Comparable}.
+     * <p>
+     * If all the date-times being compared are instances of {@code LocalDateTime},
+     * then the comparison will be entirely based on the date-time.
+     * If some dates being compared are in different chronologies, then the
+     * chronology is also considered, see {@link ChronoLocalDateTime#compareTo}.
+     *
+     * @param other  the other date-time to compare to, not null
+     * @return the comparator value, negative if less, positive if greater
+     */
+    public int compareTo(LocalDateTime other) {
+        int cmp = date.compareTo(other.getDate());
+        if (cmp == 0) {
+            cmp = time.compareTo(other.getTime());
+        }
+        return cmp;
+    }
+
+    /**
+     * Checks if this date-time is equal to another date-time.
+     * <p>
+     * Compares this {@code LocalDateTime} with another ensuring that the date-time is the same.
+     * Only objects of type {@code LocalDateTime} are compared, other types return false.
+     *
+     * @param obj  the object to check, null returns false
+     * @return true if this is equal to the other date-time
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LocalDateTime) {
+            LocalDateTime other = (LocalDateTime) obj;
+            return date.equals(other.date) && time.equals(other.time);
+        }
+        return false;
+    }
+
+    /**
+     * A hash code for this date-time.
+     *
+     * @return a suitable hash code
+     */
+    @Override
+    public int hashCode() {
+        return date.hashCode() ^ time.hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/LocalTime.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.ChronoField.HOUR_OF_DAY;
+import static build.tools.tzdb.ChronoField.MINUTE_OF_HOUR;
+import static build.tools.tzdb.ChronoField.SECOND_OF_MINUTE;
+import static build.tools.tzdb.ChronoField.SECOND_OF_DAY;
+
+import java.util.Objects;
+
+/**
+ * A time without time-zone in the ISO-8601 calendar system,
+ * such as {@code 10:15:30}.
+ *
+ */
+final class LocalTime {
+
+    /**
+     * The minimum supported {@code LocalTime}, '00:00'.
+     * This is the time of midnight at the start of the day.
+     */
+    public static final LocalTime MIN;
+    /**
+     * The minimum supported {@code LocalTime}, '23:59:59.999999999'.
+     * This is the time just before midnight at the end of the day.
+     */
+    public static final LocalTime MAX;
+    /**
+     * The time of midnight at the start of the day, '00:00'.
+     */
+    public static final LocalTime MIDNIGHT;
+    /**
+     * The time of noon in the middle of the day, '12:00'.
+     */
+    public static final LocalTime NOON;
+    /**
+     * Constants for the local time of each hour.
+     */
+    private static final LocalTime[] HOURS = new LocalTime[24];
+    static {
+        for (int i = 0; i < HOURS.length; i++) {
+            HOURS[i] = new LocalTime(i, 0, 0);
+        }
+        MIDNIGHT = HOURS[0];
+        NOON = HOURS[12];
+        MIN = HOURS[0];
+        MAX = new LocalTime(23, 59, 59);
+    }
+
+    /**
+     * Hours per day.
+     */
+    static final int HOURS_PER_DAY = 24;
+    /**
+     * Minutes per hour.
+     */
+    static final int MINUTES_PER_HOUR = 60;
+    /**
+     * Minutes per day.
+     */
+    static final int MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY;
+    /**
+     * Seconds per minute.
+     */
+    static final int SECONDS_PER_MINUTE = 60;
+    /**
+     * Seconds per hour.
+     */
+    static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;
+    /**
+     * Seconds per day.
+     */
+    static final int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
+    /**
+     * Milliseconds per day.
+     */
+    static final long MILLIS_PER_DAY = SECONDS_PER_DAY * 1000L;
+    /**
+     * Microseconds per day.
+     */
+    static final long MICROS_PER_DAY = SECONDS_PER_DAY * 1000_000L;
+
+    /**
+     * The hour.
+     */
+    private final byte hour;
+    /**
+     * The minute.
+     */
+    private final byte minute;
+    /**
+     * The second.
+     */
+    private final byte second;
+
+    /**
+     * Obtains an instance of {@code LocalTime} from an hour and minute.
+     * <p>
+     * The second and nanosecond fields will be set to zero by this factory method.
+     * <p>
+     * This factory may return a cached value, but applications must not rely on this.
+     *
+     * @param hour  the hour-of-day to represent, from 0 to 23
+     * @param minute  the minute-of-hour to represent, from 0 to 59
+     * @return the local time, not null
+     * @throws DateTimeException if the value of any field is out of range
+     */
+    public static LocalTime of(int hour, int minute) {
+        HOUR_OF_DAY.checkValidValue(hour);
+        if (minute == 0) {
+            return HOURS[hour];  // for performance
+        }
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        return new LocalTime(hour, minute, 0);
+    }
+
+    /**
+     * Obtains an instance of {@code LocalTime} from an hour, minute and second.
+     * <p>
+     * The nanosecond field will be set to zero by this factory method.
+     * <p>
+     * This factory may return a cached value, but applications must not rely on this.
+     *
+     * @param hour  the hour-of-day to represent, from 0 to 23
+     * @param minute  the minute-of-hour to represent, from 0 to 59
+     * @param second  the second-of-minute to represent, from 0 to 59
+     * @return the local time, not null
+     * @throws DateTimeException if the value of any field is out of range
+     */
+    public static LocalTime of(int hour, int minute, int second) {
+        HOUR_OF_DAY.checkValidValue(hour);
+        if ((minute | second) == 0) {
+            return HOURS[hour];  // for performance
+        }
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        SECOND_OF_MINUTE.checkValidValue(second);
+        return new LocalTime(hour, minute, second);
+    }
+
+    /**
+     * Obtains an instance of {@code LocalTime} from a second-of-day value.
+     * <p>
+     * This factory may return a cached value, but applications must not rely on this.
+     *
+     * @param secondOfDay  the second-of-day, from {@code 0} to {@code 24 * 60 * 60 - 1}
+     * @return the local time, not null
+     * @throws DateTimeException if the second-of-day value is invalid
+     */
+    public static LocalTime ofSecondOfDay(int secondOfDay) {
+        SECOND_OF_DAY.checkValidValue(secondOfDay);
+        int hours = secondOfDay / SECONDS_PER_HOUR;
+        secondOfDay -= hours * SECONDS_PER_HOUR;
+        int minutes = secondOfDay / SECONDS_PER_MINUTE;
+        secondOfDay -= minutes * SECONDS_PER_MINUTE;
+        return create(hours, minutes, secondOfDay);
+    }
+
+
+    /**
+     * Creates a local time from the hour, minute, second and nanosecond fields.
+     * <p>
+     * This factory may return a cached value, but applications must not rely on this.
+     *
+     * @param hour  the hour-of-day to represent, validated from 0 to 23
+     * @param minute  the minute-of-hour to represent, validated from 0 to 59
+     * @param second  the second-of-minute to represent, validated from 0 to 59
+     * @return the local time, not null
+     */
+    private static LocalTime create(int hour, int minute, int second) {
+        if ((minute | second) == 0) {
+            return HOURS[hour];
+        }
+        return new LocalTime(hour, minute, second);
+    }
+
+    /**
+     * Constructor, previously validated.
+     *
+     * @param hour  the hour-of-day to represent, validated from 0 to 23
+     * @param minute  the minute-of-hour to represent, validated from 0 to 59
+     * @param second  the second-of-minute to represent, validated from 0 to 59
+     */
+    private LocalTime(int hour, int minute, int second) {
+        this.hour = (byte) hour;
+        this.minute = (byte) minute;
+        this.second = (byte) second;
+    }
+
+    /**
+     * Gets the hour-of-day field.
+     *
+     * @return the hour-of-day, from 0 to 23
+     */
+    public int getHour() {
+        return hour;
+    }
+
+    /**
+     * Gets the minute-of-hour field.
+     *
+     * @return the minute-of-hour, from 0 to 59
+     */
+    public int getMinute() {
+        return minute;
+    }
+
+    /**
+     * Gets the second-of-minute field.
+     *
+     * @return the second-of-minute, from 0 to 59
+     */
+    public int getSecond() {
+        return second;
+    }
+
+    /**
+     * Returns a copy of this {@code LocalTime} with the specified period in seconds added.
+     * <p>
+     * This adds the specified number of seconds to this time, returning a new time.
+     * The calculation wraps around midnight.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param secondstoAdd  the seconds to add, may be negative
+     * @return a {@code LocalTime} based on this time with the seconds added, not null
+     */
+    public LocalTime plusSeconds(long secondstoAdd) {
+        if (secondstoAdd == 0) {
+            return this;
+        }
+        int sofd = hour * SECONDS_PER_HOUR +
+                    minute * SECONDS_PER_MINUTE + second;
+        int newSofd = ((int) (secondstoAdd % SECONDS_PER_DAY) + sofd + SECONDS_PER_DAY) % SECONDS_PER_DAY;
+        if (sofd == newSofd) {
+            return this;
+        }
+        int newHour = newSofd / SECONDS_PER_HOUR;
+        int newMinute = (newSofd / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
+        int newSecond = newSofd % SECONDS_PER_MINUTE;
+        return create(newHour, newMinute, newSecond);
+    }
+
+    /**
+     * Returns a copy of this {@code LocalTime} with the specified period in seconds subtracted.
+     * <p>
+     * This subtracts the specified number of seconds from this time, returning a new time.
+     * The calculation wraps around midnight.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param secondsToSubtract  the seconds to subtract, may be negative
+     * @return a {@code LocalTime} based on this time with the seconds subtracted, not null
+     */
+    public LocalTime minusSeconds(long secondsToSubtract) {
+        return plusSeconds(-(secondsToSubtract % SECONDS_PER_DAY));
+    }
+
+    /**
+     * Extracts the time as seconds of day,
+     * from {@code 0} to {@code 24 * 60 * 60 - 1}.
+     *
+     * @return the second-of-day equivalent to this time
+     */
+    public int toSecondOfDay() {
+        int total = hour * SECONDS_PER_HOUR;
+        total += minute * SECONDS_PER_MINUTE;
+        total += second;
+        return total;
+    }
+
+     /**
+     * Compares this {@code LocalTime} to another time.
+     * <p>
+     * The comparison is based on the time-line position of the local times within a day.
+     * It is "consistent with equals", as defined by {@link Comparable}.
+     *
+     * @param other  the other time to compare to, not null
+     * @return the comparator value, negative if less, positive if greater
+     * @throws NullPointerException if {@code other} is null
+     */
+    public int compareTo(LocalTime other) {
+        int cmp = Integer.compare(hour, other.hour);
+        if (cmp == 0) {
+            cmp = Integer.compare(minute, other.minute);
+            if (cmp == 0) {
+                cmp = Integer.compare(second, other.second);
+             }
+        }
+        return cmp;
+    }
+
+    /**
+     * Checks if this time is equal to another time.
+     * <p>
+     * The comparison is based on the time-line position of the time within a day.
+     * <p>
+     * Only objects of type {@code LocalTime} are compared, other types return false.
+     * To compare the date of two {@code TemporalAccessor} instances, use
+     * {@link ChronoField#NANO_OF_DAY} as a comparator.
+     *
+     * @param obj  the object to check, null returns false
+     * @return true if this is equal to the other time
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LocalTime) {
+            LocalTime other = (LocalTime) obj;
+            return hour == other.hour && minute == other.minute &&
+                    second == other.second;
+        }
+        return false;
+    }
+
+    /**
+     * A hash code for this time.
+     *
+     * @return a suitable hash code
+     */
+    @Override
+    public int hashCode() {
+        long sod = toSecondOfDay();
+        return (int) (sod ^ (sod >>> 32));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/TimeDefinition.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import java.util.Objects;
+
+/**
+ * A definition of the way a local time can be converted to the actual
+ * transition date-time.
+ * <p>
+ * Time zone rules are expressed in one of three ways:
+ * <p><ul>
+ * <li>Relative to UTC</li>
+ * <li>Relative to the standard offset in force</li>
+ * <li>Relative to the wall offset (what you would see on a clock on the wall)</li>
+ * </ul><p>
+ */
+public enum TimeDefinition {
+    /** The local date-time is expressed in terms of the UTC offset. */
+    UTC,
+    /** The local date-time is expressed in terms of the wall offset. */
+    WALL,
+    /** The local date-time is expressed in terms of the standard offset. */
+    STANDARD;
+
+    /**
+     * Converts the specified local date-time to the local date-time actually
+     * seen on a wall clock.
+     * <p>
+     * This method converts using the type of this enum.
+     * The output is defined relative to the 'before' offset of the transition.
+     * <p>
+     * The UTC type uses the UTC offset.
+     * The STANDARD type uses the standard offset.
+     * The WALL type returns the input date-time.
+     * The result is intended for use with the wall-offset.
+     *
+     * @param dateTime  the local date-time, not null
+     * @param standardOffset  the standard offset, not null
+     * @param wallOffset  the wall offset, not null
+     * @return the date-time relative to the wall/before offset, not null
+     */
+    public LocalDateTime createDateTime(LocalDateTime dateTime, ZoneOffset standardOffset, ZoneOffset wallOffset) {
+        switch (this) {
+            case UTC: {
+                int difference = wallOffset.getTotalSeconds() - ZoneOffset.UTC.getTotalSeconds();
+                return dateTime.plusSeconds(difference);
+            }
+            case STANDARD: {
+                int difference = wallOffset.getTotalSeconds() - standardOffset.getTotalSeconds();
+                return dateTime.plusSeconds(difference);
+            }
+            default:  // WALL
+                return dateTime;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.Utils.*;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.text.ParsePosition;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A builder that can read the TZDB time-zone files and build {@code ZoneRules} instances.
+ *
+ * @since 1.8
+ */
+public final class TzdbZoneRulesCompiler {
+
+    private static final Matcher YEAR = Pattern.compile("(?i)(?<min>min)|(?<max>max)|(?<only>only)|(?<year>[0-9]+)").matcher("");
+    private static final Matcher MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)").matcher("");
+    private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher("");
+    private static final Matcher TIME = Pattern.compile("(?<neg>-)?+(?<hour>[0-9]{1,2})(:(?<minute>[0-5][0-9]))?+(:(?<second>[0-5][0-9]))?+").matcher("");
+
+    /**
+     * Constant for MJD 1972-01-01.
+     */
+    private static final long MJD_1972_01_01 = 41317L;
+
+    /**
+     * Reads a set of TZDB files and builds a single combined data file.
+     *
+     * @param args  the arguments
+     */
+    public static void main(String[] args) {
+        if (args.length < 2) {
+            outputHelp();
+            return;
+        }
+
+        // parse args
+        String version = null;
+        File baseSrcDir = null;
+        File dstDir = null;
+        boolean verbose = false;
+
+        // parse options
+        int i;
+        for (i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.startsWith("-") == false) {
+                break;
+            }
+            if ("-srcdir".equals(arg)) {
+                if (baseSrcDir == null && ++i < args.length) {
+                    baseSrcDir = new File(args[i]);
+                    continue;
+                }
+            } else if ("-dstdir".equals(arg)) {
+                if (dstDir == null && ++i < args.length) {
+                    dstDir = new File(args[i]);
+                    continue;
+                }
+            } else if ("-version".equals(arg)) {
+                if (version == null && ++i < args.length) {
+                    version = args[i];
+                    continue;
+                }
+            } else if ("-verbose".equals(arg)) {
+                if (verbose == false) {
+                    verbose = true;
+                    continue;
+                }
+            } else if ("-help".equals(arg) == false) {
+                System.out.println("Unrecognised option: " + arg);
+            }
+            outputHelp();
+            return;
+        }
+
+        // check source directory
+        if (baseSrcDir == null) {
+            System.out.println("Source directory must be specified using -srcdir: " + baseSrcDir);
+            return;
+        }
+        if (baseSrcDir.isDirectory() == false) {
+            System.out.println("Source does not exist or is not a directory: " + baseSrcDir);
+            return;
+        }
+        dstDir = (dstDir != null ? dstDir : baseSrcDir);
+
+        // parse source file names
+        List<String> srcFileNames = Arrays.asList(Arrays.copyOfRange(args, i, args.length));
+        if (srcFileNames.isEmpty()) {
+            System.out.println("Source filenames not specified, using default set");
+            System.out.println("(africa antarctica asia australasia backward etcetera europe northamerica southamerica)");
+            srcFileNames = Arrays.asList("africa", "antarctica", "asia", "australasia", "backward",
+                    "etcetera", "europe", "northamerica", "southamerica");
+        }
+
+        // find source directories to process
+        List<File> srcDirs = new ArrayList<>();
+        if (version != null) {
+            //  if the "version" specified, as in jdk repo, the "baseSrcDir" is
+            //  the "srcDir" that contains the tzdb data.
+            srcDirs.add(baseSrcDir);
+        } else {
+            File[] dirs = baseSrcDir.listFiles();
+            for (File dir : dirs) {
+                if (dir.isDirectory() && dir.getName().matches("[12][0-9]{3}[A-Za-z0-9._-]+")) {
+                    srcDirs.add(dir);
+                }
+            }
+        }
+        if (srcDirs.isEmpty()) {
+            System.out.println("Source directory contains no valid source folders: " + baseSrcDir);
+            return;
+        }
+        // check destination directory
+        if (dstDir.exists() == false && dstDir.mkdirs() == false) {
+            System.out.println("Destination directory could not be created: " + dstDir);
+            return;
+        }
+        if (dstDir.isDirectory() == false) {
+            System.out.println("Destination is not a directory: " + dstDir);
+            return;
+        }
+        process(srcDirs, srcFileNames, dstDir, version, verbose);
+        System.exit(0);
+    }
+
+    /**
+     * Output usage text for the command line.
+     */
+    private static void outputHelp() {
+        System.out.println("Usage: TzdbZoneRulesCompiler <options> <tzdb source filenames>");
+        System.out.println("where options include:");
+        System.out.println("   -srcdir <directory>   Where to find source directories (required)");
+        System.out.println("   -dstdir <directory>   Where to output generated files (default srcdir)");
+        System.out.println("   -version <version>    Specify the version, such as 2009a (optional)");
+        System.out.println("   -help                 Print this usage message");
+        System.out.println("   -verbose              Output verbose information during compilation");
+        System.out.println(" There must be one directory for each version in srcdir");
+        System.out.println(" Each directory must have the name of the version, such as 2009a");
+        System.out.println(" Each directory must contain the unpacked tzdb files, such as asia or europe");
+        System.out.println(" Directories must match the regex [12][0-9][0-9][0-9][A-Za-z0-9._-]+");
+        System.out.println(" There will be one jar file for each version and one combined jar in dstdir");
+        System.out.println(" If the version is specified, only that version is processed");
+    }
+
+    /**
+     * Process to create the jar files.
+     */
+    private static void process(List<File> srcDirs, List<String> srcFileNames, File dstDir, String version, boolean verbose) {
+        // build actual jar files
+        Map<String, SortedMap<String, ZoneRules>> allBuiltZones = new TreeMap<>();
+        Set<String> allRegionIds = new TreeSet<String>();
+        Set<ZoneRules> allRules = new HashSet<ZoneRules>();
+
+        for (File srcDir : srcDirs) {
+            // source files in this directory
+            List<File> srcFiles = new ArrayList<>();
+            for (String srcFileName : srcFileNames) {
+                File file = new File(srcDir, srcFileName);
+                if (file.exists()) {
+                    srcFiles.add(file);
+                }
+            }
+            if (srcFiles.isEmpty()) {
+                continue;  // nothing to process
+            }
+
+            // compile
+            String loopVersion = srcDir.getName();
+            TzdbZoneRulesCompiler compiler = new TzdbZoneRulesCompiler(loopVersion, srcFiles, verbose);
+            try {
+                // compile
+                compiler.compile();
+                SortedMap<String, ZoneRules> builtZones = compiler.getZones();
+
+                // output version-specific file
+                File dstFile = version == null ? new File(dstDir, "tzdb" + loopVersion + ".jar")
+                                               : new File(dstDir, "tzdb.jar");
+                if (verbose) {
+                    System.out.println("Outputting file: " + dstFile);
+                }
+                outputFile(dstFile, loopVersion, builtZones);
+
+                // create totals
+                allBuiltZones.put(loopVersion, builtZones);
+                allRegionIds.addAll(builtZones.keySet());
+                allRules.addAll(builtZones.values());
+            } catch (Exception ex) {
+                System.out.println("Failed: " + ex.toString());
+                ex.printStackTrace();
+                System.exit(1);
+            }
+        }
+
+        // output merged file
+        if (version == null) {
+            File dstFile = new File(dstDir, "tzdb-all.jar");
+            if (verbose) {
+                System.out.println("Outputting combined file: " + dstFile);
+            }
+            outputFile(dstFile, allBuiltZones, allRegionIds, allRules);
+        }
+    }
+
+    /**
+     * Outputs the file.
+     */
+    private static void outputFile(File dstFile,
+                                   String version,
+                                   SortedMap<String, ZoneRules> builtZones) {
+        Map<String, SortedMap<String, ZoneRules>> loopAllBuiltZones = new TreeMap<>();
+        loopAllBuiltZones.put(version, builtZones);
+        Set<String> loopAllRegionIds = new TreeSet<String>(builtZones.keySet());
+        Set<ZoneRules> loopAllRules = new HashSet<ZoneRules>(builtZones.values());
+        outputFile(dstFile, loopAllBuiltZones, loopAllRegionIds, loopAllRules);
+    }
+
+    /**
+     * Outputs the file.
+     */
+    private static void outputFile(File dstFile,
+                                   Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
+                                   Set<String> allRegionIds,
+                                   Set<ZoneRules> allRules)
+    {
+        try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(dstFile))) {
+            outputTZEntry(jos, allBuiltZones, allRegionIds, allRules);
+        } catch (Exception ex) {
+            System.out.println("Failed: " + ex.toString());
+            ex.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Outputs the timezone entry in the JAR file.
+     */
+    private static void outputTZEntry(JarOutputStream jos,
+                                      Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
+                                      Set<String> allRegionIds,
+                                      Set<ZoneRules> allRules) {
+        // this format is not publicly specified
+        try {
+            jos.putNextEntry(new ZipEntry("TZDB.dat"));
+            DataOutputStream out = new DataOutputStream(jos);
+
+            // file version
+            out.writeByte(1);
+            // group
+            out.writeUTF("TZDB");
+            // versions
+            String[] versionArray = allBuiltZones.keySet().toArray(new String[allBuiltZones.size()]);
+            out.writeShort(versionArray.length);
+            for (String version : versionArray) {
+                out.writeUTF(version);
+            }
+            // regions
+            String[] regionArray = allRegionIds.toArray(new String[allRegionIds.size()]);
+            out.writeShort(regionArray.length);
+            for (String regionId : regionArray) {
+                out.writeUTF(regionId);
+            }
+            // rules
+            List<ZoneRules> rulesList = new ArrayList<>(allRules);
+            out.writeShort(rulesList.size());
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+            for (ZoneRules rules : rulesList) {
+                baos.reset();
+                DataOutputStream dataos = new DataOutputStream(baos);
+                rules.writeExternal(dataos);
+                dataos.close();
+                byte[] bytes = baos.toByteArray();
+                out.writeShort(bytes.length);
+                out.write(bytes);
+            }
+            // link version-region-rules
+            for (String version : allBuiltZones.keySet()) {
+                out.writeShort(allBuiltZones.get(version).size());
+                for (Map.Entry<String, ZoneRules> entry : allBuiltZones.get(version).entrySet()) {
+                     int regionIndex = Arrays.binarySearch(regionArray, entry.getKey());
+                     int rulesIndex = rulesList.indexOf(entry.getValue());
+                     out.writeShort(regionIndex);
+                     out.writeShort(rulesIndex);
+                }
+            }
+            out.flush();
+            jos.closeEntry();
+        } catch (Exception ex) {
+            System.out.println("Failed: " + ex.toString());
+            ex.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /** The TZDB rules. */
+    private final Map<String, List<TZDBRule>> rules = new HashMap<>();
+
+    /** The TZDB zones. */
+    private final Map<String, List<TZDBZone>> zones = new HashMap<>();
+    /** The TZDB links. */
+
+    private final Map<String, String> links = new HashMap<>();
+
+    /** The built zones. */
+    private final SortedMap<String, ZoneRules> builtZones = new TreeMap<>();
+
+
+    /** The version to produce. */
+    private final String version;
+
+    /** The source files. */
+
+    private final List<File> sourceFiles;
+
+    /** The version to produce. */
+    private final boolean verbose;
+
+    /**
+     * Creates an instance if you want to invoke the compiler manually.
+     *
+     * @param version  the version, such as 2009a, not null
+     * @param sourceFiles  the list of source files, not empty, not null
+     * @param verbose  whether to output verbose messages
+     */
+    public TzdbZoneRulesCompiler(String version, List<File> sourceFiles, boolean verbose) {
+        this.version = version;
+        this.sourceFiles = sourceFiles;
+        this.verbose = verbose;
+    }
+
+    /**
+     * Compile the rules file.
+     * <p>
+     * Use {@link #getZones()} to retrieve the parsed data.
+     *
+     * @throws Exception if an error occurs
+     */
+    public void compile() throws Exception {
+        printVerbose("Compiling TZDB version " + version);
+        parseFiles();
+        buildZoneRules();
+        printVerbose("Compiled TZDB version " + version);
+    }
+
+    /**
+     * Gets the parsed zone rules.
+     *
+     * @return the parsed zone rules, not null
+     */
+    public SortedMap<String, ZoneRules> getZones() {
+        return builtZones;
+    }
+
+    /**
+     * Parses the source files.
+     *
+     * @throws Exception if an error occurs
+     */
+    private void parseFiles() throws Exception {
+        for (File file : sourceFiles) {
+            printVerbose("Parsing file: " + file);
+            parseFile(file);
+        }
+    }
+
+    /**
+     * Parses a source file.
+     *
+     * @param file  the file being read, not null
+     * @throws Exception if an error occurs
+     */
+    private void parseFile(File file) throws Exception {
+        int lineNumber = 1;
+        String line = null;
+        BufferedReader in = null;
+        try {
+            in = new BufferedReader(new FileReader(file));
+            List<TZDBZone> openZone = null;
+            for ( ; (line = in.readLine()) != null; lineNumber++) {
+                int index = line.indexOf('#');  // remove comments (doesn't handle # in quotes)
+                if (index >= 0) {
+                    line = line.substring(0, index);
+                }
+                if (line.trim().length() == 0) {  // ignore blank lines
+                    continue;
+                }
+                StringTokenizer st = new StringTokenizer(line, " \t");
+                if (openZone != null && Character.isWhitespace(line.charAt(0)) && st.hasMoreTokens()) {
+                    if (parseZoneLine(st, openZone)) {
+                        openZone = null;
+                    }
+                } else {
+                    if (st.hasMoreTokens()) {
+                        String first = st.nextToken();
+                        if (first.equals("Zone")) {
+                            if (st.countTokens() < 3) {
+                                printVerbose("Invalid Zone line in file: " + file + ", line: " + line);
+                                throw new IllegalArgumentException("Invalid Zone line");
+                            }
+                            openZone = new ArrayList<>();
+                            zones.put(st.nextToken(), openZone);
+                            if (parseZoneLine(st, openZone)) {
+                                openZone = null;
+                            }
+                        } else {
+                            openZone = null;
+                            if (first.equals("Rule")) {
+                                if (st.countTokens() < 9) {
+                                    printVerbose("Invalid Rule line in file: " + file + ", line: " + line);
+                                    throw new IllegalArgumentException("Invalid Rule line");
+                                }
+                                parseRuleLine(st);
+
+                            } else if (first.equals("Link")) {
+                                if (st.countTokens() < 2) {
+                                    printVerbose("Invalid Link line in file: " + file + ", line: " + line);
+                                    throw new IllegalArgumentException("Invalid Link line");
+                                }
+                                String realId = st.nextToken();
+                                String aliasId = st.nextToken();
+                                links.put(aliasId, realId);
+
+                            } else {
+                                throw new IllegalArgumentException("Unknown line");
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            throw new Exception("Failed while processing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex);
+        } finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (Exception ex) {
+                // ignore NPE and IOE
+            }
+        }
+    }
+
+    /**
+     * Parses a Rule line.
+     *
+     * @param st  the tokenizer, not null
+     */
+    private void parseRuleLine(StringTokenizer st) {
+        TZDBRule rule = new TZDBRule();
+        String name = st.nextToken();
+        if (rules.containsKey(name) == false) {
+            rules.put(name, new ArrayList<TZDBRule>());
+        }
+        rules.get(name).add(rule);
+        rule.startYear = parseYear(st.nextToken(), 0);
+        rule.endYear = parseYear(st.nextToken(), rule.startYear);
+        if (rule.startYear > rule.endYear) {
+            throw new IllegalArgumentException("Year order invalid: " + rule.startYear + " > " + rule.endYear);
+        }
+        parseOptional(st.nextToken());  // type is unused
+        parseMonthDayTime(st, rule);
+        rule.savingsAmount = parsePeriod(st.nextToken());
+        rule.text = parseOptional(st.nextToken());
+    }
+
+    /**
+     * Parses a Zone line.
+     *
+     * @param st  the tokenizer, not null
+     * @return true if the zone is complete
+     */
+    private boolean parseZoneLine(StringTokenizer st, List<TZDBZone> zoneList) {
+        TZDBZone zone = new TZDBZone();
+        zoneList.add(zone);
+        zone.standardOffset = parseOffset(st.nextToken());
+        String savingsRule = parseOptional(st.nextToken());
+        if (savingsRule == null) {
+            zone.fixedSavingsSecs = 0;
+            zone.savingsRule = null;
+        } else {
+            try {
+                zone.fixedSavingsSecs = parsePeriod(savingsRule);
+                zone.savingsRule = null;
+            } catch (Exception ex) {
+                zone.fixedSavingsSecs = null;
+                zone.savingsRule = savingsRule;
+            }
+        }
+        zone.text = st.nextToken();
+        if (st.hasMoreTokens()) {
+            zone.year = Integer.parseInt(st.nextToken());
+            if (st.hasMoreTokens()) {
+                parseMonthDayTime(st, zone);
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Parses a Rule line.
+     *
+     * @param st  the tokenizer, not null
+     * @param mdt  the object to parse into, not null
+     */
+    private void parseMonthDayTime(StringTokenizer st, TZDBMonthDayTime mdt) {
+        mdt.month = parseMonth(st.nextToken());
+        if (st.hasMoreTokens()) {
+            String dayRule = st.nextToken();
+            if (dayRule.startsWith("last")) {
+                mdt.dayOfMonth = -1;
+                mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(4));
+                mdt.adjustForwards = false;
+            } else {
+                int index = dayRule.indexOf(">=");
+                if (index > 0) {
+                    mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
+                    dayRule = dayRule.substring(index + 2);
+                } else {
+                    index = dayRule.indexOf("<=");
+                    if (index > 0) {
+                        mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(0, index));
+                        mdt.adjustForwards = false;
+                        dayRule = dayRule.substring(index + 2);
+                    }
+                }
+                mdt.dayOfMonth = Integer.parseInt(dayRule);
+            }
+            if (st.hasMoreTokens()) {
+                String timeStr = st.nextToken();
+                int secsOfDay = parseSecs(timeStr);
+                if (secsOfDay == 86400) {
+                    mdt.endOfDay = true;
+                    secsOfDay = 0;
+                }
+                LocalTime time = LocalTime.ofSecondOfDay(secsOfDay);
+                mdt.time = time;
+                mdt.timeDefinition = parseTimeDefinition(timeStr.charAt(timeStr.length() - 1));
+            }
+        }
+    }
+
+    private int parseYear(String str, int defaultYear) {
+        if (YEAR.reset(str).matches()) {
+            if (YEAR.group("min") != null) {
+                return YEAR_MIN_VALUE;
+            } else if (YEAR.group("max") != null) {
+                return YEAR_MAX_VALUE;
+            } else if (YEAR.group("only") != null) {
+                return defaultYear;
+            }
+            return Integer.parseInt(YEAR.group("year"));
+        }
+        throw new IllegalArgumentException("Unknown year: " + str);
+    }
+
+    private int parseMonth(String str) {
+        if (MONTH.reset(str).matches()) {
+            for (int moy = 1; moy < 13; moy++) {
+                if (MONTH.group(moy) != null) {
+                    return moy;
+                }
+            }
+        }
+        throw new IllegalArgumentException("Unknown month: " + str);
+    }
+
+    private int parseDayOfWeek(String str) {
+        if (DOW.reset(str).matches()) {
+            for (int dow = 1; dow < 8; dow++) {
+                if (DOW.group(dow) != null) {
+                    return dow;
+                }
+            }
+        }
+        throw new IllegalArgumentException("Unknown day-of-week: " + str);
+    }
+
+    private String parseOptional(String str) {
+        return str.equals("-") ? null : str;
+    }
+
+    private int parseSecs(String str) {
+        if (str.equals("-")) {
+            return 0;
+        }
+        try {
+            if (TIME.reset(str).find()) {
+                int secs = Integer.parseInt(TIME.group("hour")) * 60 * 60;
+                if (TIME.group("minute") != null) {
+                    secs += Integer.parseInt(TIME.group("minute")) * 60;
+                }
+                if (TIME.group("second") != null) {
+                    secs += Integer.parseInt(TIME.group("second"));
+                }
+                if (TIME.group("neg") != null) {
+                    secs = -secs;
+                }
+                return secs;
+            }
+        } catch (NumberFormatException x) {}
+        throw new IllegalArgumentException(str);
+    }
+
+    private ZoneOffset parseOffset(String str) {
+        int secs = parseSecs(str);
+        return ZoneOffset.ofTotalSeconds(secs);
+    }
+
+    private int parsePeriod(String str) {
+        return parseSecs(str);
+    }
+
+    private TimeDefinition parseTimeDefinition(char c) {
+        switch (c) {
+            case 's':
+            case 'S':
+                // standard time
+                return TimeDefinition.STANDARD;
+            case 'u':
+            case 'U':
+            case 'g':
+            case 'G':
+            case 'z':
+            case 'Z':
+                // UTC
+                return TimeDefinition.UTC;
+            case 'w':
+            case 'W':
+            default:
+                // wall time
+                return TimeDefinition.WALL;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Build the rules, zones and links into real zones.
+     *
+     * @throws Exception if an error occurs
+     */
+    private void buildZoneRules() throws Exception {
+        // build zones
+        for (String zoneId : zones.keySet()) {
+            printVerbose("Building zone " + zoneId);
+            List<TZDBZone> tzdbZones = zones.get(zoneId);
+            ZoneRulesBuilder bld = new ZoneRulesBuilder();
+            for (TZDBZone tzdbZone : tzdbZones) {
+                bld = tzdbZone.addToBuilder(bld, rules);
+            }
+            ZoneRules buildRules = bld.toRules(zoneId);
+            builtZones.put(zoneId, buildRules);
+        }
+
+        // build aliases
+        for (String aliasId : links.keySet()) {
+            String realId = links.get(aliasId);
+            printVerbose("Linking alias " + aliasId + " to " + realId);
+            ZoneRules realRules = builtZones.get(realId);
+            if (realRules == null) {
+                realId = links.get(realId);  // try again (handle alias liked to alias)
+                printVerbose("Relinking alias " + aliasId + " to " + realId);
+                realRules = builtZones.get(realId);
+                if (realRules == null) {
+                    throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId + "' for '" + version + "'");
+                }
+            }
+            builtZones.put(aliasId, realRules);
+        }
+
+        // remove UTC and GMT
+        builtZones.remove("UTC");
+        builtZones.remove("GMT");
+        builtZones.remove("GMT0");
+        builtZones.remove("GMT+0");
+        builtZones.remove("GMT-0");
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Prints a verbose message.
+     *
+     * @param message  the message, not null
+     */
+    private void printVerbose(String message) {
+        if (verbose) {
+            System.out.println(message);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Class representing a month-day-time in the TZDB file.
+     */
+    abstract class TZDBMonthDayTime {
+        /** The month of the cutover. */
+        int month = 1;
+        /** The day-of-month of the cutover. */
+        int dayOfMonth = 1;
+        /** Whether to adjust forwards. */
+        boolean adjustForwards = true;
+        /** The day-of-week of the cutover. */
+        int dayOfWeek = -1;
+        /** The time of the cutover. */
+        LocalTime time = LocalTime.MIDNIGHT;
+        /** Whether this is midnight end of day. */
+        boolean endOfDay;
+        /** The time of the cutover. */
+        TimeDefinition timeDefinition = TimeDefinition.WALL;
+
+        void adjustToFowards(int year) {
+            if (adjustForwards == false && dayOfMonth > 0) {
+                LocalDate adjustedDate = LocalDate.of(year, month, dayOfMonth).minusDays(6);
+                dayOfMonth = adjustedDate.getDayOfMonth();
+                month = adjustedDate.getMonth();
+                adjustForwards = true;
+            }
+        }
+    }
+
+    /**
+     * Class representing a rule line in the TZDB file.
+     */
+    final class TZDBRule extends TZDBMonthDayTime {
+        /** The start year. */
+        int startYear;
+        /** The end year. */
+        int endYear;
+        /** The amount of savings. */
+        int savingsAmount;
+        /** The text name of the zone. */
+        String text;
+
+        void addToBuilder(ZoneRulesBuilder bld) {
+            adjustToFowards(2004);  // irrelevant, treat as leap year
+            bld.addRuleToWindow(startYear, endYear, month, dayOfMonth, dayOfWeek, time, endOfDay, timeDefinition, savingsAmount);
+        }
+    }
+
+    /**
+     * Class representing a linked set of zone lines in the TZDB file.
+     */
+    final class TZDBZone extends TZDBMonthDayTime {
+        /** The standard offset. */
+        ZoneOffset standardOffset;
+        /** The fixed savings amount. */
+        Integer fixedSavingsSecs;
+        /** The savings rule. */
+        String savingsRule;
+        /** The text name of the zone. */
+        String text;
+        /** The year of the cutover. */
+        int year = YEAR_MAX_VALUE;
+
+        ZoneRulesBuilder addToBuilder(ZoneRulesBuilder bld, Map<String, List<TZDBRule>> rules) {
+            if (year != YEAR_MAX_VALUE) {
+                bld.addWindow(standardOffset, toDateTime(year), timeDefinition);
+            } else {
+                bld.addWindowForever(standardOffset);
+            }
+            if (fixedSavingsSecs != null) {
+                bld.setFixedSavingsToWindow(fixedSavingsSecs);
+            } else {
+                List<TZDBRule> tzdbRules = rules.get(savingsRule);
+                if (tzdbRules == null) {
+                    throw new IllegalArgumentException("Rule not found: " + savingsRule);
+                }
+                for (TZDBRule tzdbRule : tzdbRules) {
+                    tzdbRule.addToBuilder(bld);
+                }
+            }
+            return bld;
+        }
+
+        private LocalDateTime toDateTime(int year) {
+            adjustToFowards(year);
+            LocalDate date;
+            if (dayOfMonth == -1) {
+                dayOfMonth = lengthOfMonth(month, isLeapYear(year));
+                date = LocalDate.of(year, month, dayOfMonth);
+                if (dayOfWeek != -1) {
+                    date = previousOrSame(date, dayOfWeek);
+                }
+            } else {
+                date = LocalDate.of(year, month, dayOfMonth);
+                if (dayOfWeek != -1) {
+                    date = nextOrSame(date, dayOfWeek);
+                }
+            }
+            LocalDateTime ldt = LocalDateTime.of(date, time);
+            if (endOfDay) {
+                ldt = ldt.plusDays(1);
+            }
+            return ldt;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/Utils.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,176 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import java.util.Objects;
+
+class Utils {
+
+    // Returns the largest (closest to positive infinity)
+    public static long floorDiv(long x, long y) {
+        long r = x / y;
+        // if the signs are different and modulo not zero, round down
+        if ((x ^ y) < 0 && (r * y != x)) {
+            r--;
+        }
+        return r;
+    }
+
+    // Returns the floor modulus of the {@code long} arguments.
+    public static long floorMod(long x, long y) {
+        return x - floorDiv(x, y) * y;
+    }
+
+    // Returns the sum of its arguments,
+    public static long addExact(long x, long y) {
+        long r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    // Year
+
+    // Returns true if the specified year is a leap year.
+    public static boolean isLeapYear(int year) {
+        return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0);
+    }
+
+    // The minimum supported year, '-999,999,999'.
+    public static final int YEAR_MIN_VALUE = -999_999_999;
+
+    // The maximum supported year, '+999,999,999'.
+    public static final int YEAR_MAX_VALUE = 999_999_999;
+
+
+    // Gets the length of the specified month in days.
+    public static int lengthOfMonth(int month, boolean leapYear) {
+        switch (month) {
+            case 2:        //FEBRUARY:
+                return (leapYear ? 29 : 28);
+            case 4:        //APRIL:
+            case 6:        //JUNE:
+            case 9:        //SEPTEMBER:
+            case 11:       //NOVEMBER:
+                return 30;
+            default:
+                return 31;
+        }
+    }
+
+    // Gets the maximum length of the specified month in days.
+    public static int maxLengthOfMonth(int month) {
+        switch (month) {
+            case 2:           //FEBRUARY:
+                return 29;
+            case 4:           //APRIL:
+            case 6:           //JUNE:
+            case 9:           //SEPTEMBER:
+            case 11:          //NOVEMBER:
+                return 30;
+            default:
+                return 31;
+        }
+    }
+
+    // DayOfWeek
+
+    // Returns the day-of-week that is the specified number of days after
+    // this one, from 1 to 7 for Monday to Sunday.
+    public static int plusDayOfWeek(int dow, long days) {
+        int amount = (int) (days % 7);
+        return (dow - 1 + (amount + 7)) % 7 + 1;
+    }
+
+    // Returns the day-of-week that is the specified number of days before
+    // this one, from 1 to 7 for Monday to Sunday.
+    public static int minusDayOfWeek(int dow, long days) {
+        return plusDayOfWeek(dow, -(days % 7));
+    }
+
+    // Adjusts the date to the first occurrence of the specified day-of-week
+    // before the date being adjusted unless it is already on that day in
+    // which case the same object is returned.
+    public static LocalDate previousOrSame(LocalDate date, int dayOfWeek) {
+        return adjust(date, dayOfWeek, 1);
+    }
+
+    // Adjusts the date to the first occurrence of the specified day-of-week
+    // after the date being adjusted unless it is already on that day in
+    // which case the same object is returned.
+    public static LocalDate nextOrSame(LocalDate date, int dayOfWeek) {
+        return adjust(date, dayOfWeek, 0);
+    }
+
+    // Implementation of next, previous or current day-of-week.
+    // @param relative  whether the current date is a valid answer
+    private static final LocalDate adjust(LocalDate date, int dow, int relative) {
+        int calDow = date.getDayOfWeek();
+        if (relative < 2 && calDow == dow) {
+            return date;
+        }
+        if ((relative & 1) == 0) {
+            int daysDiff = calDow - dow;
+            return date.plusDays(daysDiff >= 0 ? 7 - daysDiff : -daysDiff);
+        } else {
+            int daysDiff = dow - calDow;
+            return date.minusDays(daysDiff >= 0 ? 7 - daysDiff : -daysDiff);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ZoneOffset.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A time-zone offset from Greenwich/UTC, such as {@code +02:00}.
+ * <p>
+ * A time-zone offset is the period of time that a time-zone differs from Greenwich/UTC.
+ * This is usually a fixed number of hours and minutes.
+ *
+ * @since 1.8
+ */
+final class ZoneOffset implements Comparable<ZoneOffset> {
+
+    /** Cache of time-zone offset by offset in seconds. */
+    private static final ConcurrentMap<Integer, ZoneOffset> SECONDS_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
+    /** Cache of time-zone offset by ID. */
+    private static final ConcurrentMap<String, ZoneOffset> ID_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
+
+    /**
+     * The number of seconds per hour.
+     */
+    private static final int SECONDS_PER_HOUR = 60 * 60;
+    /**
+     * The number of seconds per minute.
+     */
+    private static final int SECONDS_PER_MINUTE = 60;
+    /**
+     * The number of minutes per hour.
+     */
+    private static final int MINUTES_PER_HOUR = 60;
+    /**
+     * The abs maximum seconds.
+     */
+    private static final int MAX_SECONDS = 18 * SECONDS_PER_HOUR;
+    /**
+     * Serialization version.
+     */
+    private static final long serialVersionUID = 2357656521762053153L;
+
+    /**
+     * The time-zone offset for UTC, with an ID of 'Z'.
+     */
+    public static final ZoneOffset UTC = ZoneOffset.ofTotalSeconds(0);
+    /**
+     * Constant for the maximum supported offset.
+     */
+    public static final ZoneOffset MIN = ZoneOffset.ofTotalSeconds(-MAX_SECONDS);
+    /**
+     * Constant for the maximum supported offset.
+     */
+    public static final ZoneOffset MAX = ZoneOffset.ofTotalSeconds(MAX_SECONDS);
+
+    /**
+     * The total offset in seconds.
+     */
+    private final int totalSeconds;
+    /**
+     * The string form of the time-zone offset.
+     */
+    private final transient String id;
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ZoneOffset} using the ID.
+     * <p>
+     * This method parses the string ID of a {@code ZoneOffset} to
+     * return an instance. The parsing accepts all the formats generated by
+     * {@link #getId()}, plus some additional formats:
+     * <p><ul>
+     * <li>{@code Z} - for UTC
+     * <li>{@code +h}
+     * <li>{@code +hh}
+     * <li>{@code +hh:mm}
+     * <li>{@code -hh:mm}
+     * <li>{@code +hhmm}
+     * <li>{@code -hhmm}
+     * <li>{@code +hh:mm:ss}
+     * <li>{@code -hh:mm:ss}
+     * <li>{@code +hhmmss}
+     * <li>{@code -hhmmss}
+     * </ul><p>
+     * Note that &plusmn; means either the plus or minus symbol.
+     * <p>
+     * The ID of the returned offset will be normalized to one of the formats
+     * described by {@link #getId()}.
+     * <p>
+     * The maximum supported range is from +18:00 to -18:00 inclusive.
+     *
+     * @param offsetId  the offset ID, not null
+     * @return the zone-offset, not null
+     * @throws DateTimeException if the offset ID is invalid
+     */
+    @SuppressWarnings("fallthrough")
+    public static ZoneOffset of(String offsetId) {
+        Objects.requireNonNull(offsetId, "offsetId");
+        // "Z" is always in the cache
+        ZoneOffset offset = ID_CACHE.get(offsetId);
+        if (offset != null) {
+            return offset;
+        }
+
+        // parse - +h, +hh, +hhmm, +hh:mm, +hhmmss, +hh:mm:ss
+        final int hours, minutes, seconds;
+        switch (offsetId.length()) {
+            case 2:
+                offsetId = offsetId.charAt(0) + "0" + offsetId.charAt(1);  // fallthru
+            case 3:
+                hours = parseNumber(offsetId, 1, false);
+                minutes = 0;
+                seconds = 0;
+                break;
+            case 5:
+                hours = parseNumber(offsetId, 1, false);
+                minutes = parseNumber(offsetId, 3, false);
+                seconds = 0;
+                break;
+            case 6:
+                hours = parseNumber(offsetId, 1, false);
+                minutes = parseNumber(offsetId, 4, true);
+                seconds = 0;
+                break;
+            case 7:
+                hours = parseNumber(offsetId, 1, false);
+                minutes = parseNumber(offsetId, 3, false);
+                seconds = parseNumber(offsetId, 5, false);
+                break;
+            case 9:
+                hours = parseNumber(offsetId, 1, false);
+                minutes = parseNumber(offsetId, 4, true);
+                seconds = parseNumber(offsetId, 7, true);
+                break;
+            default:
+                throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid");
+        }
+        char first = offsetId.charAt(0);
+        if (first != '+' && first != '-') {
+            throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Plus/minus not found when expected");
+        }
+        if (first == '-') {
+            return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
+        } else {
+            return ofHoursMinutesSeconds(hours, minutes, seconds);
+        }
+    }
+
+    /**
+     * Parse a two digit zero-prefixed number.
+     *
+     * @param offsetId  the offset ID, not null
+     * @param pos  the position to parse, valid
+     * @param precededByColon  should this number be prefixed by a precededByColon
+     * @return the parsed number, from 0 to 99
+     */
+    private static int parseNumber(CharSequence offsetId, int pos, boolean precededByColon) {
+        if (precededByColon && offsetId.charAt(pos - 1) != ':') {
+            throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Colon not found when expected");
+        }
+        char ch1 = offsetId.charAt(pos);
+        char ch2 = offsetId.charAt(pos + 1);
+        if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
+            throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Non numeric characters found");
+        }
+        return (ch1 - 48) * 10 + (ch2 - 48);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ZoneOffset} using an offset in hours.
+     *
+     * @param hours  the time-zone offset in hours, from -18 to +18
+     * @return the zone-offset, not null
+     * @throws DateTimeException if the offset is not in the required range
+     */
+    public static ZoneOffset ofHours(int hours) {
+        return ofHoursMinutesSeconds(hours, 0, 0);
+    }
+
+    /**
+     * Obtains an instance of {@code ZoneOffset} using an offset in
+     * hours and minutes.
+     * <p>
+     * The sign of the hours and minutes components must match.
+     * Thus, if the hours is negative, the minutes must be negative or zero.
+     * If the hours is zero, the minutes may be positive, negative or zero.
+     *
+     * @param hours  the time-zone offset in hours, from -18 to +18
+     * @param minutes  the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours
+     * @return the zone-offset, not null
+     * @throws DateTimeException if the offset is not in the required range
+     */
+    public static ZoneOffset ofHoursMinutes(int hours, int minutes) {
+        return ofHoursMinutesSeconds(hours, minutes, 0);
+    }
+
+    /**
+     * Obtains an instance of {@code ZoneOffset} using an offset in
+     * hours, minutes and seconds.
+     * <p>
+     * The sign of the hours, minutes and seconds components must match.
+     * Thus, if the hours is negative, the minutes and seconds must be negative or zero.
+     *
+     * @param hours  the time-zone offset in hours, from -18 to +18
+     * @param minutes  the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours and seconds
+     * @param seconds  the time-zone offset in seconds, from 0 to &plusmn;59, sign matches hours and minutes
+     * @return the zone-offset, not null
+     * @throws DateTimeException if the offset is not in the required range
+     */
+    public static ZoneOffset ofHoursMinutesSeconds(int hours, int minutes, int seconds) {
+        validate(hours, minutes, seconds);
+        int totalSeconds = totalSeconds(hours, minutes, seconds);
+        return ofTotalSeconds(totalSeconds);
+    }
+
+    /**
+     * Validates the offset fields.
+     *
+     * @param hours  the time-zone offset in hours, from -18 to +18
+     * @param minutes  the time-zone offset in minutes, from 0 to &plusmn;59
+     * @param seconds  the time-zone offset in seconds, from 0 to &plusmn;59
+     * @throws DateTimeException if the offset is not in the required range
+     */
+    private static void validate(int hours, int minutes, int seconds) {
+        if (hours < -18 || hours > 18) {
+            throw new DateTimeException("Zone offset hours not in valid range: value " + hours +
+                    " is not in the range -18 to 18");
+        }
+        if (hours > 0) {
+            if (minutes < 0 || seconds < 0) {
+                throw new DateTimeException("Zone offset minutes and seconds must be positive because hours is positive");
+            }
+        } else if (hours < 0) {
+            if (minutes > 0 || seconds > 0) {
+                throw new DateTimeException("Zone offset minutes and seconds must be negative because hours is negative");
+            }
+        } else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) {
+            throw new DateTimeException("Zone offset minutes and seconds must have the same sign");
+        }
+        if (Math.abs(minutes) > 59) {
+            throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " +
+                    Math.abs(minutes) + " is not in the range 0 to 59");
+        }
+        if (Math.abs(seconds) > 59) {
+            throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " +
+                    Math.abs(seconds) + " is not in the range 0 to 59");
+        }
+        if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) {
+            throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
+        }
+    }
+
+    /**
+     * Calculates the total offset in seconds.
+     *
+     * @param hours  the time-zone offset in hours, from -18 to +18
+     * @param minutes  the time-zone offset in minutes, from 0 to &plusmn;59, sign matches hours and seconds
+     * @param seconds  the time-zone offset in seconds, from 0 to &plusmn;59, sign matches hours and minutes
+     * @return the total in seconds
+     */
+    private static int totalSeconds(int hours, int minutes, int seconds) {
+        return hours * SECONDS_PER_HOUR + minutes * SECONDS_PER_MINUTE + seconds;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ZoneOffset} specifying the total offset in seconds
+     * <p>
+     * The offset must be in the range {@code -18:00} to {@code +18:00}, which corresponds to -64800 to +64800.
+     *
+     * @param totalSeconds  the total time-zone offset in seconds, from -64800 to +64800
+     * @return the ZoneOffset, not null
+     * @throws DateTimeException if the offset is not in the required range
+     */
+    public static ZoneOffset ofTotalSeconds(int totalSeconds) {
+        if (Math.abs(totalSeconds) > MAX_SECONDS) {
+            throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
+        }
+        if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
+            Integer totalSecs = totalSeconds;
+            ZoneOffset result = SECONDS_CACHE.get(totalSecs);
+            if (result == null) {
+                result = new ZoneOffset(totalSeconds);
+                SECONDS_CACHE.putIfAbsent(totalSecs, result);
+                result = SECONDS_CACHE.get(totalSecs);
+                ID_CACHE.putIfAbsent(result.getId(), result);
+            }
+            return result;
+        } else {
+            return new ZoneOffset(totalSeconds);
+        }
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param totalSeconds  the total time-zone offset in seconds, from -64800 to +64800
+     */
+    private ZoneOffset(int totalSeconds) {
+        super();
+        this.totalSeconds = totalSeconds;
+        id = buildId(totalSeconds);
+    }
+
+    private static String buildId(int totalSeconds) {
+        if (totalSeconds == 0) {
+            return "Z";
+        } else {
+            int absTotalSeconds = Math.abs(totalSeconds);
+            StringBuilder buf = new StringBuilder();
+            int absHours = absTotalSeconds / SECONDS_PER_HOUR;
+            int absMinutes = (absTotalSeconds / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR;
+            buf.append(totalSeconds < 0 ? "-" : "+")
+                .append(absHours < 10 ? "0" : "").append(absHours)
+                .append(absMinutes < 10 ? ":0" : ":").append(absMinutes);
+            int absSeconds = absTotalSeconds % SECONDS_PER_MINUTE;
+            if (absSeconds != 0) {
+                buf.append(absSeconds < 10 ? ":0" : ":").append(absSeconds);
+            }
+            return buf.toString();
+        }
+    }
+
+    /**
+     * Gets the total zone offset in seconds.
+     * <p>
+     * This is the primary way to access the offset amount.
+     * It returns the total of the hours, minutes and seconds fields as a
+     * single offset that can be added to a time.
+     *
+     * @return the total zone offset amount in seconds
+     */
+    public int getTotalSeconds() {
+        return totalSeconds;
+    }
+
+    /**
+     * Gets the normalized zone offset ID.
+     * <p>
+     * The ID is minor variation to the standard ISO-8601 formatted string
+     * for the offset. There are three formats:
+     * <p><ul>
+     * <li>{@code Z} - for UTC (ISO-8601)
+     * <li>{@code +hh:mm} or {@code -hh:mm} - if the seconds are zero (ISO-8601)
+     * <li>{@code +hh:mm:ss} or {@code -hh:mm:ss} - if the seconds are non-zero (not ISO-8601)
+     * </ul><p>
+     *
+     * @return the zone offset ID, not null
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * Compares this offset to another offset in descending order.
+     * <p>
+     * The offsets are compared in the order that they occur for the same time
+     * of day around the world. Thus, an offset of {@code +10:00} comes before an
+     * offset of {@code +09:00} and so on down to {@code -18:00}.
+     * <p>
+     * The comparison is "consistent with equals", as defined by {@link Comparable}.
+     *
+     * @param other  the other date to compare to, not null
+     * @return the comparator value, negative if less, postive if greater
+     * @throws NullPointerException if {@code other} is null
+     */
+    @Override
+    public int compareTo(ZoneOffset other) {
+        return other.totalSeconds - totalSeconds;
+    }
+
+    /**
+     * Checks if this offset is equal to another offset.
+     * <p>
+     * The comparison is based on the amount of the offset in seconds.
+     * This is equivalent to a comparison by ID.
+     *
+     * @param obj  the object to check, null returns false
+     * @return true if this is equal to the other offset
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+           return true;
+        }
+        if (obj instanceof ZoneOffset) {
+            return totalSeconds == ((ZoneOffset) obj).totalSeconds;
+        }
+        return false;
+    }
+
+    /**
+     * A hash code for this offset.
+     *
+     * @return a suitable hash code
+     */
+    @Override
+    public int hashCode() {
+        return totalSeconds;
+    }
+
+    /**
+     * Outputs this offset as a {@code String}, using the normalized ID.
+     *
+     * @return a string representation of this offset, not null
+     */
+    @Override
+    public String toString() {
+        return id;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ZoneOffsetTransition.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A transition between two offsets caused by a discontinuity in the local time-line.
+ *
+ * @since 1.8
+ */
+final class ZoneOffsetTransition implements Comparable<ZoneOffsetTransition> {
+
+    /**
+     * The local transition date-time at the transition.
+     */
+    private final LocalDateTime transition;
+    /**
+     * The offset before transition.
+     */
+    private final ZoneOffset offsetBefore;
+    /**
+     * The offset after transition.
+     */
+    private final ZoneOffset offsetAfter;
+
+    /**
+     * Creates an instance defining a transition between two offsets.
+     *
+     * @param transition  the transition date-time with the offset before the transition, not null
+     * @param offsetBefore  the offset before the transition, not null
+     * @param offsetAfter  the offset at and after the transition, not null
+     */
+    ZoneOffsetTransition(LocalDateTime transition, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
+        Objects.requireNonNull(transition, "transition");
+        Objects.requireNonNull(offsetBefore, "offsetBefore");
+        Objects.requireNonNull(offsetAfter, "offsetAfter");
+        if (offsetBefore.equals(offsetAfter)) {
+            throw new IllegalArgumentException("Offsets must not be equal");
+        }
+        this.transition = transition;
+        this.offsetBefore = offsetBefore;
+        this.offsetAfter = offsetAfter;
+    }
+
+    /**
+     * Creates an instance from epoch-second and offsets.
+     *
+     * @param epochSecond  the transition epoch-second
+     * @param offsetBefore  the offset before the transition, not null
+     * @param offsetAfter  the offset at and after the transition, not null
+     */
+    ZoneOffsetTransition(long epochSecond, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
+        this.transition = LocalDateTime.ofEpochSecond(epochSecond, 0, offsetBefore);
+        this.offsetBefore = offsetBefore;
+        this.offsetAfter = offsetAfter;
+    }
+
+    /**
+     * Gets the transition instant as an epoch second.
+     *
+     * @return the transition epoch second
+     */
+    public long toEpochSecond() {
+        return transition.toEpochSecond(offsetBefore);
+    }
+
+    /**
+     * Gets the local transition date-time, as would be expressed with the 'before' offset.
+     * <p>
+     * This is the date-time where the discontinuity begins expressed with the 'before' offset.
+     * At this instant, the 'after' offset is actually used, therefore the combination of this
+     * date-time and the 'before' offset will never occur.
+     * <p>
+     * The combination of the 'before' date-time and offset represents the same instant
+     * as the 'after' date-time and offset.
+     *
+     * @return the transition date-time expressed with the before offset, not null
+     */
+    public LocalDateTime getDateTimeBefore() {
+        return transition;
+    }
+
+    /**
+     * Gets the local transition date-time, as would be expressed with the 'after' offset.
+     * <p>
+     * This is the first date-time after the discontinuity, when the new offset applies.
+     * <p>
+     * The combination of the 'before' date-time and offset represents the same instant
+     * as the 'after' date-time and offset.
+     *
+     * @return the transition date-time expressed with the after offset, not null
+     */
+    public LocalDateTime getDateTimeAfter() {
+        return transition.plusSeconds(getDurationSeconds());
+    }
+
+    /**
+     * Gets the offset before the transition.
+     * <p>
+     * This is the offset in use before the instant of the transition.
+     *
+     * @return the offset before the transition, not null
+     */
+    public ZoneOffset getOffsetBefore() {
+        return offsetBefore;
+    }
+
+    /**
+     * Gets the offset after the transition.
+     * <p>
+     * This is the offset in use on and after the instant of the transition.
+     *
+     * @return the offset after the transition, not null
+     */
+    public ZoneOffset getOffsetAfter() {
+        return offsetAfter;
+    }
+
+    /**
+     * Gets the duration of the transition in seconds.
+     *
+     * @return the duration in seconds
+     */
+    private int getDurationSeconds() {
+        return getOffsetAfter().getTotalSeconds() - getOffsetBefore().getTotalSeconds();
+    }
+
+    /**
+     * Does this transition represent a gap in the local time-line.
+     * <p>
+     * Gaps occur where there are local date-times that simply do not not exist.
+     * An example would be when the offset changes from {@code +01:00} to {@code +02:00}.
+     * This might be described as 'the clocks will move forward one hour tonight at 1am'.
+     *
+     * @return true if this transition is a gap, false if it is an overlap
+     */
+    public boolean isGap() {
+        return getOffsetAfter().getTotalSeconds() > getOffsetBefore().getTotalSeconds();
+    }
+
+    /**
+     * Does this transition represent a gap in the local time-line.
+     * <p>
+     * Overlaps occur where there are local date-times that exist twice.
+     * An example would be when the offset changes from {@code +02:00} to {@code +01:00}.
+     * This might be described as 'the clocks will move back one hour tonight at 2am'.
+     *
+     * @return true if this transition is an overlap, false if it is a gap
+     */
+    public boolean isOverlap() {
+        return getOffsetAfter().getTotalSeconds() < getOffsetBefore().getTotalSeconds();
+    }
+
+    /**
+     * Checks if the specified offset is valid during this transition.
+     * <p>
+     * This checks to see if the given offset will be valid at some point in the transition.
+     * A gap will always return false.
+     * An overlap will return true if the offset is either the before or after offset.
+     *
+     * @param offset  the offset to check, null returns false
+     * @return true if the offset is valid during the transition
+     */
+    public boolean isValidOffset(ZoneOffset offset) {
+        return isGap() ? false : (getOffsetBefore().equals(offset) || getOffsetAfter().equals(offset));
+    }
+
+    /**
+     * Gets the valid offsets during this transition.
+     * <p>
+     * A gap will return an empty list, while an overlap will return both offsets.
+     *
+     * @return the list of valid offsets
+     */
+    List<ZoneOffset> getValidOffsets() {
+        if (isGap()) {
+            return Collections.emptyList();
+        }
+        return Arrays.asList(getOffsetBefore(), getOffsetAfter());
+    }
+
+    /**
+     * Compares this transition to another based on the transition instant.
+     * <p>
+     * This compares the instants of each transition.
+     * The offsets are ignored, making this order inconsistent with equals.
+     *
+     * @param transition  the transition to compare to, not null
+     * @return the comparator value, negative if less, positive if greater
+     */
+    @Override
+    public int compareTo(ZoneOffsetTransition transition) {
+        return Long.compare(this.toEpochSecond(), transition.toEpochSecond());
+    }
+
+    /**
+     * Checks if this object equals another.
+     * <p>
+     * The entire state of the object is compared.
+     *
+     * @param other  the other object to compare to, null returns false
+     * @return true if equal
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+        if (other instanceof ZoneOffsetTransition) {
+            ZoneOffsetTransition d = (ZoneOffsetTransition) other;
+            return transition.equals(d.transition) &&
+                offsetBefore.equals(d.offsetBefore) && offsetAfter.equals(d.offsetAfter);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a suitable hash code.
+     *
+     * @return the hash code
+     */
+    @Override
+    public int hashCode() {
+        return transition.hashCode() ^ offsetBefore.hashCode() ^ Integer.rotateLeft(offsetAfter.hashCode(), 16);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ZoneOffsetTransitionRule.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.Utils.*;
+import java.util.Objects;
+
+/**
+ * A rule expressing how to create a transition.
+ * <p>
+ * This class allows rules for identifying future transitions to be expressed.
+ * A rule might be written in many forms:
+ * <p><ul>
+ * <li>the 16th March
+ * <li>the Sunday on or after the 16th March
+ * <li>the Sunday on or before the 16th March
+ * <li>the last Sunday in February
+ * </ul><p>
+ * These different rule types can be expressed and queried.
+ *
+ * <h3>Specification for implementors</h3>
+ * This class is immutable and thread-safe.
+ *
+ * @since 1.8
+ */
+final class ZoneOffsetTransitionRule {
+
+    /**
+     * The month of the month-day of the first day of the cutover week.
+     * The actual date will be adjusted by the dowChange field.
+     */
+    final int month;
+    /**
+     * The day-of-month of the month-day of the cutover week.
+     * If positive, it is the start of the week where the cutover can occur.
+     * If negative, it represents the end of the week where cutover can occur.
+     * The value is the number of days from the end of the month, such that
+     * {@code -1} is the last day of the month, {@code -2} is the second
+     * to last day, and so on.
+     */
+    final byte dom;
+    /**
+     * The cutover day-of-week, -1 to retain the day-of-month.
+     */
+    final int dow;
+    /**
+     * The cutover time in the 'before' offset.
+     */
+    final LocalTime time;
+    /**
+     * Whether the cutover time is midnight at the end of day.
+     */
+    final boolean timeEndOfDay;
+    /**
+     * The definition of how the local time should be interpreted.
+     */
+    final TimeDefinition timeDefinition;
+    /**
+     * The standard offset at the cutover.
+     */
+    final ZoneOffset standardOffset;
+    /**
+     * The offset before the cutover.
+     */
+    final ZoneOffset offsetBefore;
+    /**
+     * The offset after the cutover.
+     */
+    final ZoneOffset offsetAfter;
+
+    /**
+     * Creates an instance defining the yearly rule to create transitions between two offsets.
+     *
+     * @param month  the month of the month-day of the first day of the cutover week, from 1 to 12
+     * @param dayOfMonthIndicator  the day of the month-day of the cutover week, positive if the week is that
+     *  day or later, negative if the week is that day or earlier, counting from the last day of the month,
+     *  from -28 to 31 excluding 0
+     * @param dayOfWeek  the required day-of-week, -1 if the month-day should not be changed
+     * @param time  the cutover time in the 'before' offset, not null
+     * @param timeEndOfDay  whether the time is midnight at the end of day
+     * @param timeDefnition  how to interpret the cutover
+     * @param standardOffset  the standard offset in force at the cutover, not null
+     * @param offsetBefore  the offset before the cutover, not null
+     * @param offsetAfter  the offset after the cutover, not null
+     * @throws IllegalArgumentException if the day of month indicator is invalid
+     * @throws IllegalArgumentException if the end of day flag is true when the time is not midnight
+     */
+    ZoneOffsetTransitionRule(
+            int month,
+            int dayOfMonthIndicator,
+            int dayOfWeek,
+            LocalTime time,
+            boolean timeEndOfDay,
+            TimeDefinition timeDefnition,
+            ZoneOffset standardOffset,
+            ZoneOffset offsetBefore,
+            ZoneOffset offsetAfter) {
+        Objects.requireNonNull(time, "time");
+        Objects.requireNonNull(timeDefnition, "timeDefnition");
+        Objects.requireNonNull(standardOffset, "standardOffset");
+        Objects.requireNonNull(offsetBefore, "offsetBefore");
+        Objects.requireNonNull(offsetAfter, "offsetAfter");
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("month must be between 1 and 12");
+        }
+        if (dayOfMonthIndicator < -28 || dayOfMonthIndicator > 31 || dayOfMonthIndicator == 0) {
+            throw new IllegalArgumentException("Day of month indicator must be between -28 and 31 inclusive excluding zero");
+        }
+        if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
+            throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
+        }
+        this.month = month;
+        this.dom = (byte) dayOfMonthIndicator;
+        this.dow = dayOfWeek;
+        this.time = time;
+        this.timeEndOfDay = timeEndOfDay;
+        this.timeDefinition = timeDefnition;
+        this.standardOffset = standardOffset;
+        this.offsetBefore = offsetBefore;
+        this.offsetAfter = offsetAfter;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if this object equals another.
+     * <p>
+     * The entire state of the object is compared.
+     *
+     * @param otherRule  the other object to compare to, null returns false
+     * @return true if equal
+     */
+    @Override
+    public boolean equals(Object otherRule) {
+        if (otherRule == this) {
+            return true;
+        }
+        if (otherRule instanceof ZoneOffsetTransitionRule) {
+            ZoneOffsetTransitionRule other = (ZoneOffsetTransitionRule) otherRule;
+            return month == other.month && dom == other.dom && dow == other.dow &&
+                timeDefinition == other.timeDefinition &&
+                time.equals(other.time) &&
+                timeEndOfDay == other.timeEndOfDay &&
+                standardOffset.equals(other.standardOffset) &&
+                offsetBefore.equals(other.offsetBefore) &&
+                offsetAfter.equals(other.offsetAfter);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a suitable hash code.
+     *
+     * @return the hash code
+     */
+    @Override
+    public int hashCode() {
+        int hash = ((time.toSecondOfDay() + (timeEndOfDay ? 1 : 0)) << 15) +
+                (month << 11) + ((dom + 32) << 5) +
+                ((dow == -1 ? 8 : dow) << 2) + (timeDefinition.ordinal());
+        return hash ^ standardOffset.hashCode() ^
+                offsetBefore.hashCode() ^ offsetAfter.hashCode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ZoneRules.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Duplicated code of javax.time.zone.ZoneRules, ZoneOffsetTransitionRule
+ * and Ser to generate the serialization form output of ZoneRules for
+ * tzdb.jar.
+ *
+ * Implementation here is the copy/paste of ZoneRules, ZoneOffsetTransitionRule
+ * and Ser in javax.time.zone package. Make sure the code here is synchrionozed
+ * with the serialization implementation there.
+ *
+ * @since 1.8
+ */
+
+final class ZoneRules {
+
+    /**
+     * The transitions between standard offsets (epoch seconds), sorted.
+     */
+    private final long[] standardTransitions;
+    /**
+     * The standard offsets.
+     */
+    private final ZoneOffset[] standardOffsets;
+    /**
+     * The transitions between instants (epoch seconds), sorted.
+     */
+    private final long[] savingsInstantTransitions;
+
+    /**
+     * The wall offsets.
+     */
+    private final ZoneOffset[] wallOffsets;
+    /**
+     * The last rule.
+     */
+    private final ZoneOffsetTransitionRule[] lastRules;
+
+    /**
+     * Creates an instance.
+     *
+     * @param baseStandardOffset  the standard offset to use before legal rules were set, not null
+     * @param baseWallOffset  the wall offset to use before legal rules were set, not null
+     * @param standardOffsetTransitionList  the list of changes to the standard offset, not null
+     * @param transitionList  the list of transitions, not null
+     * @param lastRules  the recurring last rules, size 16 or less, not null
+     */
+    ZoneRules(ZoneOffset baseStandardOffset,
+              ZoneOffset baseWallOffset,
+              List<ZoneOffsetTransition> standardOffsetTransitionList,
+              List<ZoneOffsetTransition> transitionList,
+              List<ZoneOffsetTransitionRule> lastRules) {
+
+        this.standardTransitions = new long[standardOffsetTransitionList.size()];
+
+        this.standardOffsets = new ZoneOffset[standardOffsetTransitionList.size() + 1];
+        this.standardOffsets[0] = baseStandardOffset;
+        for (int i = 0; i < standardOffsetTransitionList.size(); i++) {
+            this.standardTransitions[i] = standardOffsetTransitionList.get(i).toEpochSecond();
+            this.standardOffsets[i + 1] = standardOffsetTransitionList.get(i).getOffsetAfter();
+        }
+
+        // convert savings transitions to locals
+        List<ZoneOffset> localTransitionOffsetList = new ArrayList<>();
+        localTransitionOffsetList.add(baseWallOffset);
+        for (ZoneOffsetTransition trans : transitionList) {
+            localTransitionOffsetList.add(trans.getOffsetAfter());
+        }
+
+        this.wallOffsets = localTransitionOffsetList.toArray(new ZoneOffset[localTransitionOffsetList.size()]);
+
+        // convert savings transitions to instants
+        this.savingsInstantTransitions = new long[transitionList.size()];
+        for (int i = 0; i < transitionList.size(); i++) {
+            this.savingsInstantTransitions[i] = transitionList.get(i).toEpochSecond();
+        }
+
+        // last rules
+        if (lastRules.size() > 16) {
+            throw new IllegalArgumentException("Too many transition rules");
+        }
+        this.lastRules = lastRules.toArray(new ZoneOffsetTransitionRule[lastRules.size()]);
+    }
+
+    /** Type for ZoneRules. */
+    static final byte ZRULES = 1;
+
+    /**
+     * Writes the state to the stream.
+     *
+     * @param out  the output stream, not null
+     * @throws IOException if an error occurs
+     */
+    void writeExternal(DataOutput out) throws IOException {
+        out.writeByte(ZRULES);
+        out.writeInt(standardTransitions.length);
+        for (long trans : standardTransitions) {
+            writeEpochSec(trans, out);
+        }
+        for (ZoneOffset offset : standardOffsets) {
+            writeOffset(offset, out);
+        }
+        out.writeInt(savingsInstantTransitions.length);
+        for (long trans : savingsInstantTransitions) {
+            writeEpochSec(trans, out);
+        }
+        for (ZoneOffset offset : wallOffsets) {
+            writeOffset(offset, out);
+        }
+        out.writeByte(lastRules.length);
+        for (ZoneOffsetTransitionRule rule : lastRules) {
+            writeRule(rule, out);
+        }
+    }
+
+    /**
+     * Writes the state the ZoneOffset to the stream.
+     *
+     * @param offset  the offset, not null
+     * @param out  the output stream, not null
+     * @throws IOException if an error occurs
+     */
+    static void writeOffset(ZoneOffset offset, DataOutput out) throws IOException {
+        final int offsetSecs = offset.getTotalSeconds();
+        int offsetByte = offsetSecs % 900 == 0 ? offsetSecs / 900 : 127;  // compress to -72 to +72
+        out.writeByte(offsetByte);
+        if (offsetByte == 127) {
+            out.writeInt(offsetSecs);
+        }
+    }
+
+    /**
+     * Writes the epoch seconds to the stream.
+     *
+     * @param epochSec  the epoch seconds, not null
+     * @param out  the output stream, not null
+     * @throws IOException if an error occurs
+     */
+    static void writeEpochSec(long epochSec, DataOutput out) throws IOException {
+        if (epochSec >= -4575744000L && epochSec < 10413792000L && epochSec % 900 == 0) {  // quarter hours between 1825 and 2300
+            int store = (int) ((epochSec + 4575744000L) / 900);
+            out.writeByte((store >>> 16) & 255);
+            out.writeByte((store >>> 8) & 255);
+            out.writeByte(store & 255);
+        } else {
+            out.writeByte(255);
+            out.writeLong(epochSec);
+        }
+    }
+
+    /**
+     * Writes the state of the transition rule to the stream.
+     *
+     * @param rule  the transition rule, not null
+     * @param out  the output stream, not null
+     * @throws IOException if an error occurs
+     */
+    static void writeRule(ZoneOffsetTransitionRule rule, DataOutput out) throws IOException {
+        int month = rule.month;
+        byte dom = rule.dom;
+        int dow = rule.dow;
+        LocalTime time = rule.time;
+        boolean timeEndOfDay = rule.timeEndOfDay;
+        TimeDefinition timeDefinition = rule.timeDefinition;
+        ZoneOffset standardOffset = rule.standardOffset;
+        ZoneOffset offsetBefore = rule.offsetBefore;
+        ZoneOffset offsetAfter = rule.offsetAfter;
+
+        int timeSecs = (timeEndOfDay ? 86400 : time.toSecondOfDay());
+        int stdOffset = standardOffset.getTotalSeconds();
+        int beforeDiff = offsetBefore.getTotalSeconds() - stdOffset;
+        int afterDiff = offsetAfter.getTotalSeconds() - stdOffset;
+        int timeByte = (timeSecs % 3600 == 0 ? (timeEndOfDay ? 24 : time.getHour()) : 31);
+        int stdOffsetByte = (stdOffset % 900 == 0 ? stdOffset / 900 + 128 : 255);
+        int beforeByte = (beforeDiff == 0 || beforeDiff == 1800 || beforeDiff == 3600 ? beforeDiff / 1800 : 3);
+        int afterByte = (afterDiff == 0 || afterDiff == 1800 || afterDiff == 3600 ? afterDiff / 1800 : 3);
+        int dowByte = (dow == -1 ? 0 : dow);
+        int b = (month << 28) +                     // 4 bytes
+                ((dom + 32) << 22) +                // 6 bytes
+                (dowByte << 19) +                   // 3 bytes
+                (timeByte << 14) +                  // 5 bytes
+                (timeDefinition.ordinal() << 12) +  // 2 bytes
+                (stdOffsetByte << 4) +              // 8 bytes
+                (beforeByte << 2) +                 // 2 bytes
+                afterByte;                          // 2 bytes
+        out.writeInt(b);
+        if (timeByte == 31) {
+            out.writeInt(timeSecs);
+        }
+        if (stdOffsetByte == 255) {
+            out.writeInt(stdOffset);
+        }
+        if (beforeByte == 3) {
+            out.writeInt(offsetBefore.getTotalSeconds());
+        }
+        if (afterByte == 3) {
+            out.writeInt(offsetAfter.getTotalSeconds());
+        }
+    }
+
+    /**
+     * Checks if this set of rules equals another.
+     * <p>
+     * Two rule sets are equal if they will always result in the same output
+     * for any given input instant or local date-time.
+     * Rules from two different groups may return false even if they are in fact the same.
+     * <p>
+     * This definition should result in implementations comparing their entire state.
+     *
+     * @param otherRules  the other rules, null returns false
+     * @return true if this rules is the same as that specified
+     */
+    @Override
+    public boolean equals(Object otherRules) {
+        if (this == otherRules) {
+           return true;
+        }
+        if (otherRules instanceof ZoneRules) {
+            ZoneRules other = (ZoneRules) otherRules;
+            return Arrays.equals(standardTransitions, other.standardTransitions) &&
+                    Arrays.equals(standardOffsets, other.standardOffsets) &&
+                    Arrays.equals(savingsInstantTransitions, other.savingsInstantTransitions) &&
+                    Arrays.equals(wallOffsets, other.wallOffsets) &&
+                    Arrays.equals(lastRules, other.lastRules);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a suitable hash code given the definition of {@code #equals}.
+     *
+     * @return the hash code
+     */
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(standardTransitions) ^
+                Arrays.hashCode(standardOffsets) ^
+                Arrays.hashCode(savingsInstantTransitions) ^
+                Arrays.hashCode(wallOffsets) ^
+                Arrays.hashCode(lastRules);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/src/build/tools/tzdb/ZoneRulesBuilder.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * 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:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package build.tools.tzdb;
+
+import static build.tools.tzdb.Utils.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A mutable builder used to create all the rules for a historic time-zone.
+ * <p>
+ * The rules of a time-zone describe how the offset changes over time.
+ * The rules are created by building windows on the time-line within which
+ * the different rules apply. The rules may be one of two kinds:
+ * <p><ul>
+ * <li>Fixed savings - A single fixed amount of savings from the standard offset will apply.</li>
+ * <li>Rules - A set of one or more rules describe how daylight savings changes during the window.</li>
+ * </ul><p>
+ *
+ * <h4>Implementation notes</h4>
+ * This class is a mutable builder used to create zone instances.
+ * It must only be used from a single thread.
+ * The created instances are immutable and thread-safe.
+ *
+ * @since 1.8
+ */
+public class ZoneRulesBuilder {
+
+    /**
+     * The list of windows.
+     */
+    private List<TZWindow> windowList = new ArrayList<>();
+
+    //-----------------------------------------------------------------------
+    /**
+     * Constructs an instance of the builder that can be used to create zone rules.
+     * <p>
+     * The builder is used by adding one or more windows representing portions
+     * of the time-line. The standard offset from UTC/Greenwich will be constant
+     * within a window, although two adjacent windows can have the same standard offset.
+     * <p>
+     * Within each window, there can either be a
+     * {@link #setFixedSavingsToWindow fixed savings amount} or a
+     * {@link #addRuleToWindow list of rules}.
+     */
+    public ZoneRulesBuilder() {
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Adds a window to the builder that can be used to filter a set of rules.
+     * <p>
+     * This method defines and adds a window to the zone where the standard offset is specified.
+     * The window limits the effect of subsequent additions of transition rules
+     * or fixed savings. If neither rules or fixed savings are added to the window
+     * then the window will default to no savings.
+     * <p>
+     * Each window must be added sequentially, as the start instant of the window
+     * is derived from the until instant of the previous window.
+     *
+     * @param standardOffset  the standard offset, not null
+     * @param until  the date-time that the offset applies until, not null
+     * @param untilDefinition  the time type for the until date-time, not null
+     * @return this, for chaining
+     * @throws IllegalStateException if the window order is invalid
+     */
+    public ZoneRulesBuilder addWindow(
+            ZoneOffset standardOffset,
+            LocalDateTime until,
+            TimeDefinition untilDefinition) {
+        Objects.requireNonNull(standardOffset, "standardOffset");
+        Objects.requireNonNull(until, "until");
+        Objects.requireNonNull(untilDefinition, "untilDefinition");
+        TZWindow window = new TZWindow(standardOffset, until, untilDefinition);
+        if (windowList.size() > 0) {
+            TZWindow previous = windowList.get(windowList.size() - 1);
+            window.validateWindowOrder(previous);
+        }
+        windowList.add(window);
+        return this;
+    }
+
+    /**
+     * Adds a window that applies until the end of time to the builder that can be
+     * used to filter a set of rules.
+     * <p>
+     * This method defines and adds a window to the zone where the standard offset is specified.
+     * The window limits the effect of subsequent additions of transition rules
+     * or fixed savings. If neither rules or fixed savings are added to the window
+     * then the window will default to no savings.
+     * <p>
+     * This must be added after all other windows.
+     * No more windows can be added after this one.
+     *
+     * @param standardOffset  the standard offset, not null
+     * @return this, for chaining
+     * @throws IllegalStateException if a forever window has already been added
+     */
+    public ZoneRulesBuilder addWindowForever(ZoneOffset standardOffset) {
+        return addWindow(standardOffset, LocalDateTime.MAX, TimeDefinition.WALL);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Sets the previously added window to have fixed savings.
+     * <p>
+     * Setting a window to have fixed savings simply means that a single daylight
+     * savings amount applies throughout the window. The window could be small,
+     * such as a single summer, or large, such as a multi-year daylight savings.
+     * <p>
+     * A window can either have fixed savings or rules but not both.
+     *
+     * @param fixedSavingAmountSecs  the amount of saving to use for the whole window, not null
+     * @return this, for chaining
+     * @throws IllegalStateException if no window has yet been added
+     * @throws IllegalStateException if the window already has rules
+     */
+    public ZoneRulesBuilder setFixedSavingsToWindow(int fixedSavingAmountSecs) {
+        if (windowList.isEmpty()) {
+            throw new IllegalStateException("Must add a window before setting the fixed savings");
+        }
+        TZWindow window = windowList.get(windowList.size() - 1);
+        window.setFixedSavings(fixedSavingAmountSecs);
+        return this;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Adds a single transition rule to the current window.
+     * <p>
+     * This adds a rule such that the offset, expressed as a daylight savings amount,
+     * changes at the specified date-time.
+     *
+     * @param transitionDateTime  the date-time that the transition occurs as defined by timeDefintion, not null
+     * @param timeDefinition  the definition of how to convert local to actual time, not null
+     * @param savingAmountSecs  the amount of saving from the standard offset after the transition in seconds
+     * @return this, for chaining
+     * @throws IllegalStateException if no window has yet been added
+     * @throws IllegalStateException if the window already has fixed savings
+     * @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
+     */
+    public ZoneRulesBuilder addRuleToWindow(
+            LocalDateTime transitionDateTime,
+            TimeDefinition timeDefinition,
+            int savingAmountSecs) {
+        Objects.requireNonNull(transitionDateTime, "transitionDateTime");
+        return addRuleToWindow(
+                transitionDateTime.getYear(), transitionDateTime.getYear(),
+                transitionDateTime.getMonth(), transitionDateTime.getDayOfMonth(),
+                -1, transitionDateTime.getTime(), false, timeDefinition, savingAmountSecs);
+    }
+
+    /**
+     * Adds a single transition rule to the current window.
+     * <p>
+     * This adds a rule such that the offset, expressed as a daylight savings amount,
+     * changes at the specified date-time.
+     *
+     * @param year  the year of the transition, from MIN_YEAR to MAX_YEAR
+     * @param month  the month of the transition, not null
+     * @param dayOfMonthIndicator  the day-of-month of the transition, adjusted by dayOfWeek,
+     *   from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
+     * @param time  the time that the transition occurs as defined by timeDefintion, not null
+     * @param timeEndOfDay  whether midnight is at the end of day
+     * @param timeDefinition  the definition of how to convert local to actual time, not null
+     * @param savingAmountSecs  the amount of saving from the standard offset after the transition in seconds
+     * @return this, for chaining
+     * @throws DateTimeException if a date-time field is out of range
+     * @throws IllegalStateException if no window has yet been added
+     * @throws IllegalStateException if the window already has fixed savings
+     * @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
+     */
+    public ZoneRulesBuilder addRuleToWindow(
+            int year,
+            int month,
+            int dayOfMonthIndicator,
+            LocalTime time,
+            boolean timeEndOfDay,
+            TimeDefinition timeDefinition,
+            int savingAmountSecs) {
+        return addRuleToWindow(year, year, month, dayOfMonthIndicator, -1, time, timeEndOfDay, timeDefinition, savingAmountSecs);
+    }
+
+    /**
+     * Adds a multi-year transition rule to the current window.
+     * <p>
+     * This adds a rule such that the offset, expressed as a daylight savings amount,
+     * changes at the specified date-time for each year in the range.
+     *
+     * @param startYear  the start year of the rule, from MIN_YEAR to MAX_YEAR
+     * @param endYear  the end year of the rule, from MIN_YEAR to MAX_YEAR
+     * @param month  the month of the transition, from 1 to 12
+     * @param dayOfMonthIndicator  the day-of-month of the transition, adjusted by dayOfWeek,
+     *   from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
+     * @param dayOfWeek  the day-of-week to adjust to, -1 if day-of-month should not be adjusted
+     * @param time  the time that the transition occurs as defined by timeDefintion, not null
+     * @param timeEndOfDay  whether midnight is at the end of day
+     * @param timeDefinition  the definition of how to convert local to actual time, not null
+     * @param savingAmountSecs  the amount of saving from the standard offset after the transition in seconds
+     * @return this, for chaining
+     * @throws DateTimeException if a date-time field is out of range
+     * @throws IllegalArgumentException if the day of month indicator is invalid
+     * @throws IllegalArgumentException if the end of day midnight flag does not match the time
+     * @throws IllegalStateException if no window has yet been added
+     * @throws IllegalStateException if the window already has fixed savings
+     * @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
+     */
+    public ZoneRulesBuilder addRuleToWindow(
+            int startYear,
+            int endYear,
+            int month,
+            int dayOfMonthIndicator,
+            int dayOfWeek,
+            LocalTime time,
+            boolean timeEndOfDay,
+            TimeDefinition timeDefinition,
+            int savingAmountSecs) {
+        Objects.requireNonNull(time, "time");
+        Objects.requireNonNull(timeDefinition, "timeDefinition");
+        if (dayOfMonthIndicator < -28 || dayOfMonthIndicator > 31 || dayOfMonthIndicator == 0) {
+            throw new IllegalArgumentException("Day of month indicator must be between -28 and 31 inclusive excluding zero");
+        }
+        if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
+            throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
+        }
+        if (windowList.isEmpty()) {
+            throw new IllegalStateException("Must add a window before adding a rule");
+        }
+        TZWindow window = windowList.get(windowList.size() - 1);
+        window.addRule(startYear, endYear, month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, savingAmountSecs);
+        return this;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Completes the build converting the builder to a set of time-zone rules.
+     * <p>
+     * Calling this method alters the state of the builder.
+     * Further rules should not be added to this builder once this method is called.
+     *
+     * @param zoneId  the time-zone ID, not null
+     * @return the zone rules, not null
+     * @throws IllegalStateException if no windows have been added
+     * @throws IllegalStateException if there is only one rule defined as being forever for any given window
+     */
+    public ZoneRules toRules(String zoneId) {
+        Objects.requireNonNull(zoneId, "zoneId");
+        if (windowList.isEmpty()) {
+            throw new IllegalStateException("No windows have been added to the builder");
+        }
+
+        final List<ZoneOffsetTransition> standardTransitionList = new ArrayList<>(4);
+        final List<ZoneOffsetTransition> transitionList = new ArrayList<>(256);
+        final List<ZoneOffsetTransitionRule> lastTransitionRuleList = new ArrayList<>(2);
+
+        // initialize the standard offset calculation
+        final TZWindow firstWindow = windowList.get(0);
+        ZoneOffset loopStandardOffset = firstWindow.standardOffset;
+        int loopSavings = 0;
+        if (firstWindow.fixedSavingAmountSecs != null) {
+            loopSavings = firstWindow.fixedSavingAmountSecs;
+        }
+        final ZoneOffset firstWallOffset = ZoneOffset.ofTotalSeconds(loopStandardOffset.getTotalSeconds() + loopSavings);
+        LocalDateTime loopWindowStart = LocalDateTime.of(YEAR_MIN_VALUE, 1, 1, 0, 0);
+        ZoneOffset loopWindowOffset = firstWallOffset;
+
+        // build the windows and rules to interesting data
+        for (TZWindow window : windowList) {
+            // tidy the state
+            window.tidy(loopWindowStart.getYear());
+
+            // calculate effective savings at the start of the window
+            Integer effectiveSavings = window.fixedSavingAmountSecs;
+            if (effectiveSavings == null) {
+                // apply rules from this window together with the standard offset and
+                // savings from the last window to find the savings amount applicable
+                // at start of this window
+                effectiveSavings = 0;
+                for (TZRule rule : window.ruleList) {
+                    if (rule.toEpochSecond(loopStandardOffset, loopSavings) > loopWindowStart.toEpochSecond(loopWindowOffset)) {
+                        // previous savings amount found, which could be the savings amount at
+                        // the instant that the window starts (hence isAfter)
+                        break;
+                    }
+                    effectiveSavings = rule.savingAmountSecs;
+                }
+            }
+
+            // check if standard offset changed, and update it
+            if (loopStandardOffset.equals(window.standardOffset) == false) {
+                standardTransitionList.add(
+                    new ZoneOffsetTransition(
+                        LocalDateTime.ofEpochSecond(loopWindowStart.toEpochSecond(loopWindowOffset), 0, loopStandardOffset),
+                        loopStandardOffset, window.standardOffset));
+                loopStandardOffset = window.standardOffset;
+            }
+
+            // check if the start of the window represents a transition
+            ZoneOffset effectiveWallOffset = ZoneOffset.ofTotalSeconds(loopStandardOffset.getTotalSeconds() + effectiveSavings);
+            if (loopWindowOffset.equals(effectiveWallOffset) == false) {
+                transitionList.add(new ZoneOffsetTransition(loopWindowStart, loopWindowOffset, effectiveWallOffset));
+            }
+            loopSavings = effectiveSavings;
+
+            // apply rules within the window
+            for (TZRule rule : window.ruleList) {
+                if (rule.isTransition(loopSavings)) {
+                    ZoneOffsetTransition trans = rule.toTransition(loopStandardOffset, loopSavings);
+                    if (trans.toEpochSecond() < loopWindowStart.toEpochSecond(loopWindowOffset) == false &&
+                        trans.toEpochSecond() < window.createDateTimeEpochSecond(loopSavings)) {
+                        transitionList.add(trans);
+                        loopSavings = rule.savingAmountSecs;
+                    }
+                }
+            }
+
+            // calculate last rules
+            for (TZRule lastRule : window.lastRuleList) {
+                lastTransitionRuleList.add(lastRule.toTransitionRule(loopStandardOffset, loopSavings));
+                loopSavings = lastRule.savingAmountSecs;
+            }
+
+            // finally we can calculate the true end of the window, passing it to the next window
+            loopWindowOffset = window.createWallOffset(loopSavings);
+            loopWindowStart = LocalDateTime.ofEpochSecond(
+                    window.createDateTimeEpochSecond(loopSavings), 0, loopWindowOffset);
+        }
+
+        return new ZoneRules(
+                firstWindow.standardOffset, firstWallOffset, standardTransitionList,
+                transitionList, lastTransitionRuleList);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * A definition of a window in the time-line.
+     * The window will have one standard offset and will either have a
+     * fixed DST savings or a set of rules.
+     */
+    class TZWindow {
+        /** The standard offset during the window, not null. */
+        private final ZoneOffset standardOffset;
+        /** The end local time, not null. */
+        private final LocalDateTime windowEnd;
+        /** The type of the end time, not null. */
+        private final TimeDefinition timeDefinition;
+
+        /** The fixed amount of the saving to be applied during this window. */
+        private Integer fixedSavingAmountSecs;
+        /** The rules for the current window. */
+        private List<TZRule> ruleList = new ArrayList<>();
+        /** The latest year that the last year starts at. */
+        private int maxLastRuleStartYear = YEAR_MIN_VALUE;
+        /** The last rules. */
+        private List<TZRule> lastRuleList = new ArrayList<>();
+
+        /**
+         * Constructor.
+         *
+         * @param standardOffset  the standard offset applicable during the window, not null
+         * @param windowEnd  the end of the window, relative to the time definition, null if forever
+         * @param timeDefinition  the time definition for calculating the true end, not null
+         */
+        TZWindow(
+                ZoneOffset standardOffset,
+                LocalDateTime windowEnd,
+                TimeDefinition timeDefinition) {
+            super();
+            this.windowEnd = windowEnd;
+            this.timeDefinition = timeDefinition;
+            this.standardOffset = standardOffset;
+        }
+
+        /**
+         * Sets the fixed savings amount for the window.
+         *
+         * @param fixedSavingAmount  the amount of daylight saving to apply throughout the window, may be null
+         * @throws IllegalStateException if the window already has rules
+         */
+        void setFixedSavings(int fixedSavingAmount) {
+            if (ruleList.size() > 0 || lastRuleList.size() > 0) {
+                throw new IllegalStateException("Window has DST rules, so cannot have fixed savings");
+            }
+            this.fixedSavingAmountSecs = fixedSavingAmount;
+        }
+
+        /**
+         * Adds a rule to the current window.
+         *
+         * @param startYear  the start year of the rule, from MIN_YEAR to MAX_YEAR
+         * @param endYear  the end year of the rule, from MIN_YEAR to MAX_YEAR
+         * @param month  the month of the transition, not null
+         * @param dayOfMonthIndicator  the day-of-month of the transition, adjusted by dayOfWeek,
+         *   from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
+         * @param dayOfWeek  the day-of-week to adjust to, null if day-of-month should not be adjusted
+         * @param time  the time that the transition occurs as defined by timeDefintion, not null
+         * @param timeEndOfDay  whether midnight is at the end of day
+         * @param timeDefinition  the definition of how to convert local to actual time, not null
+         * @param savingAmountSecs  the amount of saving from the standard offset in seconds
+         * @throws IllegalStateException if the window already has fixed savings
+         * @throws IllegalStateException if the window has reached the maximum capacity of 2000 rules
+         */
+        void addRule(
+                int startYear,
+                int endYear,
+                int month,
+                int dayOfMonthIndicator,
+                int dayOfWeek,
+                LocalTime time,
+                boolean timeEndOfDay,
+                TimeDefinition timeDefinition,
+                int savingAmountSecs) {
+
+            if (fixedSavingAmountSecs != null) {
+                throw new IllegalStateException("Window has a fixed DST saving, so cannot have DST rules");
+            }
+            if (ruleList.size() >= 2000) {
+                throw new IllegalStateException("Window has reached the maximum number of allowed rules");
+            }
+            boolean lastRule = false;
+            if (endYear == YEAR_MAX_VALUE) {
+                lastRule = true;
+                endYear = startYear;
+            }
+            int year = startYear;
+            while (year <= endYear) {
+                TZRule rule = new TZRule(year, month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition, savingAmountSecs);
+                if (lastRule) {
+                    lastRuleList.add(rule);
+                    maxLastRuleStartYear = Math.max(startYear, maxLastRuleStartYear);
+                } else {
+                    ruleList.add(rule);
+                }
+                year++;
+            }
+        }
+
+        /**
+         * Validates that this window is after the previous one.
+         *
+         * @param previous  the previous window, not null
+         * @throws IllegalStateException if the window order is invalid
+         */
+        void validateWindowOrder(TZWindow previous) {
+            if (windowEnd.compareTo(previous.windowEnd) < 0) {
+                throw new IllegalStateException("Windows must be added in date-time order: " +
+                        windowEnd + " < " + previous.windowEnd);
+            }
+        }
+
+        /**
+         * Adds rules to make the last rules all start from the same year.
+         * Also add one more year to avoid weird case where penultimate year has odd offset.
+         *
+         * @param windowStartYear  the window start year
+         * @throws IllegalStateException if there is only one rule defined as being forever
+         */
+        void tidy(int windowStartYear) {
+            if (lastRuleList.size() == 1) {
+                throw new IllegalStateException("Cannot have only one rule defined as being forever");
+            }
+
+            // handle last rules
+            if (windowEnd.equals(LocalDateTime.MAX)) {
+                // setup at least one real rule, which closes off other windows nicely
+                maxLastRuleStartYear = Math.max(maxLastRuleStartYear, windowStartYear) + 1;
+                for (TZRule lastRule : lastRuleList) {
+                    addRule(lastRule.year, maxLastRuleStartYear, lastRule.month, lastRule.dayOfMonthIndicator,
+                        lastRule.dayOfWeek, lastRule.time, lastRule.timeEndOfDay, lastRule.timeDefinition, lastRule.savingAmountSecs);
+                    lastRule.year = maxLastRuleStartYear + 1;
+                }
+                if (maxLastRuleStartYear == YEAR_MAX_VALUE) {
+                    lastRuleList.clear();
+                } else {
+                    maxLastRuleStartYear++;
+                }
+            } else {
+                // convert all within the endYear limit
+                int endYear = windowEnd.getYear();
+                for (TZRule lastRule : lastRuleList) {
+                    addRule(lastRule.year, endYear + 1, lastRule.month, lastRule.dayOfMonthIndicator,
+                        lastRule.dayOfWeek, lastRule.time, lastRule.timeEndOfDay, lastRule.timeDefinition, lastRule.savingAmountSecs);
+                }
+                lastRuleList.clear();
+                maxLastRuleStartYear = YEAR_MAX_VALUE;
+            }
+
+            // ensure lists are sorted
+            Collections.sort(ruleList);
+            Collections.sort(lastRuleList);
+
+            // default fixed savings to zero
+            if (ruleList.size() == 0 && fixedSavingAmountSecs == null) {
+                fixedSavingAmountSecs = 0;
+            }
+        }
+
+        /**
+         * Checks if the window is empty.
+         *
+         * @return true if the window is only a standard offset
+         */
+        boolean isSingleWindowStandardOffset() {
+            return windowEnd.equals(LocalDateTime.MAX) && timeDefinition == TimeDefinition.WALL &&
+                    fixedSavingAmountSecs == null && lastRuleList.isEmpty() && ruleList.isEmpty();
+        }
+
+        /**
+         * Creates the wall offset for the local date-time at the end of the window.
+         *
+         * @param savingsSecs  the amount of savings in use in seconds
+         * @return the created date-time epoch second in the wall offset, not null
+         */
+        ZoneOffset createWallOffset(int savingsSecs) {
+            return ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsSecs);
+        }
+
+        /**
+         * Creates the offset date-time for the local date-time at the end of the window.
+         *
+         * @param savingsSecs  the amount of savings in use in seconds
+         * @return the created date-time epoch second in the wall offset, not null
+         */
+        long createDateTimeEpochSecond(int savingsSecs) {
+            ZoneOffset wallOffset = createWallOffset(savingsSecs);
+            LocalDateTime ldt = timeDefinition.createDateTime(windowEnd, standardOffset, wallOffset);
+            return ldt.toEpochSecond(wallOffset);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * A definition of the way a local time can be converted to an offset time.
+     */
+    class TZRule implements Comparable<TZRule> {
+        private int year;
+        private int month;
+        private int dayOfMonthIndicator;
+        private int dayOfWeek;
+        private LocalTime time;
+        private boolean timeEndOfDay; // Whether the local time is end of day.
+        private TimeDefinition timeDefinition; // The type of the time.
+        private int savingAmountSecs; // The amount of the saving to be applied after this point.
+
+        /**
+         * Constructor.
+         *
+         * @param year  the year
+         * @param month  the month, value from 1 to 12
+         * @param dayOfMonthIndicator  the day-of-month of the transition, adjusted by dayOfWeek,
+         *   from 1 to 31 adjusted later, or -1 to -28 adjusted earlier from the last day of the month
+         * @param dayOfWeek  the day-of-week, -1 if day-of-month is exact
+         * @param time  the time, not null
+         * @param timeEndOfDay  whether midnight is at the end of day
+         * @param timeDefinition  the time definition, not null
+         * @param savingAfterSecs  the savings amount in seconds
+         */
+        TZRule(int year, int month, int dayOfMonthIndicator,
+                int dayOfWeek, LocalTime time, boolean timeEndOfDay,
+                TimeDefinition timeDefinition, int savingAfterSecs) {
+            this.year = year;
+            this.month = month;
+            this.dayOfMonthIndicator = dayOfMonthIndicator;
+            this.dayOfWeek = dayOfWeek;
+            this.time = time;
+            this.timeEndOfDay = timeEndOfDay;
+            this.timeDefinition = timeDefinition;
+            this.savingAmountSecs = savingAfterSecs;
+        }
+
+        /**
+         * Converts this to a transition.
+         *
+         * @param standardOffset  the active standard offset, not null
+         * @param savingsBeforeSecs  the active savings in seconds
+         * @return the transition, not null
+         */
+        ZoneOffsetTransition toTransition(ZoneOffset standardOffset, int savingsBeforeSecs) {
+            // copy of code in ZoneOffsetTransitionRule to avoid infinite loop
+            LocalDate date = toLocalDate();
+            LocalDateTime ldt = LocalDateTime.of(date, time);
+            ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs);
+            LocalDateTime dt = timeDefinition.createDateTime(ldt, standardOffset, wallOffset);
+            ZoneOffset offsetAfter = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingAmountSecs);
+            return new ZoneOffsetTransition(dt, wallOffset, offsetAfter);
+        }
+
+        /**
+         * Returns the apoch second of this rules with the specified
+         * active standard offset and active savings
+         *
+         * @param standardOffset  the active standard offset, not null
+         * @param savingsBeforeSecs  the active savings in seconds
+         * @return the transition epoch second
+         */
+        long toEpochSecond(ZoneOffset standardOffset, int savingsBeforeSecs) {
+            LocalDateTime ldt = LocalDateTime.of(toLocalDate(), time);
+            ZoneOffset wallOffset = ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs);
+            return timeDefinition.createDateTime(ldt, standardOffset, wallOffset)
+                                 .toEpochSecond(wallOffset);
+        }
+
+        /**
+         * Tests if this a real transition with the active savings in seconds
+         *
+         * @param savingsBeforeSecs  the active savings in seconds
+         * @return true, if savings in seconds changes
+         */
+        boolean isTransition(int savingsBeforeSecs) {
+            return savingAmountSecs != savingsBeforeSecs;
+        }
+
+        /**
+         * Converts this to a transition rule.
+         *
+         * @param standardOffset  the active standard offset, not null
+         * @param savingsBeforeSecs  the active savings before the transition in seconds
+         * @return the transition, not null
+         */
+        ZoneOffsetTransitionRule toTransitionRule(ZoneOffset standardOffset, int savingsBeforeSecs) {
+            // optimize stored format
+            if (dayOfMonthIndicator < 0) {
+                if (month != 2) {    // not Month.FEBRUARY
+                    dayOfMonthIndicator = maxLengthOfMonth(month) - 6;
+                }
+            }
+            if (timeEndOfDay && dayOfMonthIndicator > 0 &&
+                (dayOfMonthIndicator == 28 && month == 2) == false) {
+                LocalDate date = LocalDate.of(2004, month, dayOfMonthIndicator).plusDays(1);  // leap-year
+                month = date.getMonth();
+                dayOfMonthIndicator = date.getDayOfMonth();
+                if (dayOfWeek != -1) {
+                    dayOfWeek = plusDayOfWeek(dayOfWeek, 1);
+                }
+                timeEndOfDay = false;
+            }
+            // build rule
+            return new ZoneOffsetTransitionRule(
+                    month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefinition,
+                    standardOffset,
+                    ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingsBeforeSecs),
+                    ZoneOffset.ofTotalSeconds(standardOffset.getTotalSeconds() + savingAmountSecs));
+        }
+
+        public int compareTo(TZRule other) {
+            int cmp = year - other.year;
+            cmp = (cmp == 0 ? month - other.month : cmp);
+            if (cmp == 0) {
+                // convert to date to handle dow/domIndicator/timeEndOfDay
+                LocalDate thisDate = toLocalDate();
+                LocalDate otherDate = other.toLocalDate();
+                cmp = thisDate.compareTo(otherDate);
+            }
+            cmp = (cmp == 0 ? time.compareTo(other.time) : cmp);
+            return cmp;
+        }
+
+        private LocalDate toLocalDate() {
+            LocalDate date;
+            if (dayOfMonthIndicator < 0) {
+                int monthLen = lengthOfMonth(month, isLeapYear(year));
+                date = LocalDate.of(year, month, monthLen + 1 + dayOfMonthIndicator);
+                if (dayOfWeek != -1) {
+                    date = previousOrSame(date, dayOfWeek);
+                }
+            } else {
+                date = LocalDate.of(year, month, dayOfMonthIndicator);
+                if (dayOfWeek != -1) {
+                    date = nextOrSame(date, dayOfWeek);
+                }
+            }
+            if (timeEndOfDay) {
+                date = date.plusDays(1);
+            }
+            return date;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/tools/tzdb/Makefile	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#
+# Makefile for building the tzdb compiler tool
+#
+
+BUILDDIR = ../..
+PACKAGE = build.tools.tzdb
+PRODUCT = tzdb
+PROGRAM = tzdb
+include $(BUILDDIR)/common/Defs.gmk
+
+BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src
+BUILDTOOL_MAIN        = $(PKGDIR)/TzdbZoneRulesCompiler.java
+
+#
+# Build tool jar rules.
+#
+include $(BUILDDIR)/common/BuildToolJar.gmk
+
--- a/makefiles/CreateJars.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/makefiles/CreateJars.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -72,6 +72,13 @@
 
 ##########################################################################################
 
+$(IMAGES_OUTPUTDIR)/lib/tzdb.jar: $(JDK_OUTPUTDIR)/lib/tzdb.jar
+	$(install-file)
+
+JARS += $(IMAGES_OUTPUTDIR)/lib/tzdb.jar 
+
+##########################################################################################
+
 LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in is it \
                               iw ja ko lt lv mk ms mt nl no pl pt ro ru sk sl sq sr sv \
                               th tr uk vi zh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefiles/GendataTZDB.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+GENDATA_TZDB :=
+
+#
+# Time zone data file creation
+#
+TZDATA_DIR := $(JDK_TOPDIR)/make/sun/javazic/tzdata
+TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
+TZDATA_TZFILE := africa antarctica asia australasia europe northamerica southamerica backward etcetera
+TZDATA_TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZDATA_TZFILE))
+
+GENDATA_TZDB_DST := $(JDK_OUTPUTDIR)/lib
+GENDATA_TZDB_JAR := tzdb.jar
+
+$(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) : $(TZDATA_TZFILES)
+	$(RM) $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
+	echo building tzdb from version $(TZDATA_VER)
+	$(TOOL_TZDB) -verbose -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(GENDATA_TZDB_DST) $(TZDATA_TZFILE)
+
+GENDATA_TZDB += $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
--- a/makefiles/GenerateData.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/makefiles/GenerateData.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -47,6 +47,9 @@
 include GendataTimeZone.gmk
 GENDATA += $(GENDATA_TIMEZONE)
 
+include GendataTZDB.gmk
+GENDATA += $(GENDATA_TZDB)
+
 include GendataHtml32dtd.gmk
 GENDATA += $(GENDATA_HTML32DTD)
 
--- a/makefiles/Tools.gmk	Thu Jan 24 16:49:20 2013 -0800
+++ b/makefiles/Tools.gmk	Sat Jan 26 19:22:51 2013 -0800
@@ -106,6 +106,10 @@
 TOOL_JAVAZIC=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
 	build.tools.javazic.Main
 
+TOOL_TZDB=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
+	build.tools.tzdb.TzdbZoneRulesCompiler
+
+
 # TODO: There are references to the jdwpgen.jar in jdk/make/netbeans/jdwpgen/build.xml 
 # and nbproject/project.properties in the same dir. Needs to be looked at.
 TOOL_JDWPGEN=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses build.tools.jdwpgen.Main
--- a/makefiles/mapfiles/libjava/mapfile-vers	Thu Jan 24 16:49:20 2013 -0800
+++ b/makefiles/mapfiles/libjava/mapfile-vers	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
 		Java_java_lang_reflect_Array_setInt;
 		Java_java_lang_reflect_Array_setLong;
 		Java_java_lang_reflect_Array_setShort;
+		Java_java_lang_reflect_Executable_getParameters0;
 		Java_java_lang_Runtime_freeMemory;
                 Java_java_lang_Runtime_maxMemory;
 		Java_java_lang_Runtime_gc;
--- a/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/java/util/jar/pack/Attribute.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -177,6 +177,7 @@
         define(sd, ATTR_CONTEXT_METHOD, "Synthetic", "");
         define(sd, ATTR_CONTEXT_METHOD, "Deprecated", "");
         define(sd, ATTR_CONTEXT_METHOD, "Exceptions", "NH[RCH]");
+        define(sd, ATTR_CONTEXT_METHOD, "MethodParameters", "NB[RUNHI]");
         //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]");
 
         define(sd, ATTR_CONTEXT_CODE, "StackMapTable",
--- a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1502,6 +1502,10 @@
     CPRefBand method_Exceptions_RC = method_attr_bands.newCPRefBand("method_Exceptions_RC", CONSTANT_Class);
     CPRefBand method_Signature_RS = method_attr_bands.newCPRefBand("method_Signature_RS", CONSTANT_Signature);
     MultiBand method_metadata_bands = method_attr_bands.newMultiBand("(method_metadata_bands)", UNSIGNED5);
+    // band for predefine method parameters
+    IntBand  method_MethodParameters_NB = method_attr_bands.newIntBand("method_MethodParameters_NB", BYTE1);
+    CPRefBand method_MethodParameters_name_RUN = method_attr_bands.newCPRefBand("method_MethodParameters_name_RUN", UNSIGNED5, CONSTANT_Utf8, NULL_IS_OK);
+    IntBand   method_MethodParameters_flag_I = method_attr_bands.newIntBand("method_MethodParameters_flag_I");
 
     MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5);
     IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi");
@@ -1768,6 +1772,13 @@
                                method_Exceptions_RC
                            },
                            "Exceptions", "NH[RCH]");
+        predefineAttribute(METHOD_ATTR_MethodParameters, ATTR_CONTEXT_METHOD,
+                           new Band[]{
+                                method_MethodParameters_NB,
+                                method_MethodParameters_name_RUN,
+                                method_MethodParameters_flag_I
+                           },
+                           "MethodParameters", "NB[RUNHI]");
         assert(attrCodeEmpty == Package.attrCodeEmpty);
         predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD,
                            new Band[] { method_Signature_RS },
--- a/src/share/classes/com/sun/java/util/jar/pack/Constants.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/java/util/jar/pack/Constants.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,6 +73,9 @@
     public final static Package.Version JAVA7_PACKAGE_VERSION =
             Package.Version.of(170, 1);
 
+    public final static Package.Version JAVA8_PACKAGE_VERSION =
+            Package.Version.of(171, 0);
+
     // upper limit, should point to the latest class version
     public final static Package.Version JAVA_MAX_CLASS_VERSION =
             JAVA8_MAX_CLASS_VERSION;
@@ -158,6 +161,7 @@
         METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
         CLASS_ATTR_ClassFile_version = 24,
         METHOD_ATTR_AnnotationDefault = 25,
+        METHOD_ATTR_MethodParameters = 26,
         CODE_ATTR_StackMapTable = 0,  // new in Java 6
         CODE_ATTR_LineNumberTable = 1,
         CODE_ATTR_LocalVariableTable = 2,
--- a/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -242,6 +242,7 @@
     void checkArchiveVersion() throws IOException {
         Package.Version versionFound = null;
         for (Package.Version v : new Package.Version[] {
+                JAVA8_PACKAGE_VERSION,
                 JAVA7_PACKAGE_VERSION,
                 JAVA6_PACKAGE_VERSION,
                 JAVA5_PACKAGE_VERSION
@@ -252,7 +253,9 @@
             }
         }
         if (versionFound == null) {
-            String expVer = JAVA7_PACKAGE_VERSION.toString()
+            String expVer =   JAVA8_PACKAGE_VERSION.toString()
+                            + "OR"
+                            + JAVA7_PACKAGE_VERSION.toString()
                             + " OR "
                             + JAVA6_PACKAGE_VERSION.toString()
                             + " OR "
@@ -1516,6 +1519,9 @@
         //        method_metadata_bands
         //        *method_Exceptions_N :UNSIGNED5
         //        *method_Exceptions_RC :UNSIGNED5  (cp_Class)
+        //        *method_MethodParameters_NB: BYTE1
+        //        *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8)
+        //        *method_MethodParameters_I:  UNSIGNED5 (flag)
         //
         //  code_attr_bands:
         //        *code_flags :UNSIGNED5
--- a/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -142,12 +142,14 @@
         } else if (highV.equals(JAVA6_MAX_CLASS_VERSION) ||
                 (highV.equals(JAVA7_MAX_CLASS_VERSION) && !pkg.cp.haveExtraTags())) {
             // force down the package version if we have jdk7 classes without
-            // any Indy references, this is because jdk7 class file (52.0) without
-            // Indy is identical to jdk6 class file (51.0).
+            // any Indy references, this is because jdk7 class file (51.0) without
+            // Indy is identical to jdk6 class file (50.0).
             packageVersion = JAVA6_PACKAGE_VERSION;
+        } else if (highV.equals(JAVA7_MAX_CLASS_VERSION)) {
+            packageVersion = JAVA7_PACKAGE_VERSION;
         } else {
             // Normal case.  Use the newest archive format, when available
-            packageVersion = JAVA7_PACKAGE_VERSION;
+            packageVersion = JAVA8_PACKAGE_VERSION;
         }
 
         if (verbose > 0) {
--- a/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/com/sun/net/httpserver/BasicAuthenticator.java	Sat Jan 26 19:22:51 2013 -0800
@@ -25,6 +25,8 @@
 
 package com.sun.net.httpserver;
 
+import java.util.Base64;
+
 /**
  * BasicAuthenticator provides an implementation of HTTP Basic
  * authentication. It is an abstract class and must be extended
@@ -68,7 +70,7 @@
         if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) {
             return new Authenticator.Failure (401);
         }
-        byte[] b = Base64.base64ToByteArray (auth.substring(sp+1));
+        byte[] b = Base64.getDecoder().decode(auth.substring(sp+1));
         String userpass = new String (b);
         int colon = userpass.indexOf (':');
         String uname = userpass.substring (0, colon);
@@ -102,208 +104,3 @@
     public abstract boolean checkCredentials (String username, String password);
 }
 
-class Base64 {
-
-    /**
-     * Translates the specified byte array into a Base64 string as per
-     * Preferences.put(byte[]).
-     */
-    static String byteArrayToBase64(byte[] a) {
-        return byteArrayToBase64(a, false);
-    }
-
-    /**
-     * Translates the specified byte array into an "aternate representation"
-     * Base64 string.  This non-standard variant uses an alphabet that does
-     * not contain the uppercase alphabetic characters, which makes it
-     * suitable for use in situations where case-folding occurs.
-     */
-    static String byteArrayToAltBase64(byte[] a) {
-        return byteArrayToBase64(a, true);
-    }
-
-    private static String byteArrayToBase64(byte[] a, boolean alternate) {
-        int aLen = a.length;
-        int numFullGroups = aLen/3;
-        int numBytesInPartialGroup = aLen - 3*numFullGroups;
-        int resultLen = 4*((aLen + 2)/3);
-        StringBuffer result = new StringBuffer(resultLen);
-        char[] intToAlpha = (alternate ? intToAltBase64 : intToBase64);
-
-        // Translate all full groups from byte array elements to Base64
-        int inCursor = 0;
-        for (int i=0; i<numFullGroups; i++) {
-            int byte0 = a[inCursor++] & 0xff;
-            int byte1 = a[inCursor++] & 0xff;
-            int byte2 = a[inCursor++] & 0xff;
-            result.append(intToAlpha[byte0 >> 2]);
-            result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
-            result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
-            result.append(intToAlpha[byte2 & 0x3f]);
-        }
-
-        // Translate partial group if present
-        if (numBytesInPartialGroup != 0) {
-            int byte0 = a[inCursor++] & 0xff;
-            result.append(intToAlpha[byte0 >> 2]);
-            if (numBytesInPartialGroup == 1) {
-                result.append(intToAlpha[(byte0 << 4) & 0x3f]);
-                result.append("==");
-            } else {
-                // assert numBytesInPartialGroup == 2;
-                int byte1 = a[inCursor++] & 0xff;
-                result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
-                result.append(intToAlpha[(byte1 << 2)&0x3f]);
-                result.append('=');
-            }
-        }
-        // assert inCursor == a.length;
-        // assert result.length() == resultLen;
-        return result.toString();
-    }
-
-    /**
-     * This array is a lookup table that translates 6-bit positive integer
-     * index values into their "Base64 Alphabet" equivalents as specified
-     * in Table 1 of RFC 2045.
-     */
-    private static final char intToBase64[] = {
-        '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',
-        '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',
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-    };
-
-    /**
-     * This array is a lookup table that translates 6-bit positive integer
-     * index values into their "Alternate Base64 Alphabet" equivalents.
-     * This is NOT the real Base64 Alphabet as per in Table 1 of RFC 2045.
-     * This alternate alphabet does not use the capital letters.  It is
-     * designed for use in environments where "case folding" occurs.
-     */
-    private static final char intToAltBase64[] = {
-        '!', '"', '#', '$', '%', '&', '\'', '(', ')', ',', '-', '.', ':',
-        ';', '<', '>', '@', '[', ']', '^',  '`', '_', '{', '|', '}', '~',
-        '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',
-        '0', '1', '2', '3', '4', '5', '6',  '7', '8', '9', '+', '?'
-    };
-
-    /**
-     * Translates the specified Base64 string (as per Preferences.get(byte[]))
-     * into a byte array.
-     *
-     * @throw IllegalArgumentException if <tt>s</tt> is not a valid Base64
-     *        string.
-     */
-    static byte[] base64ToByteArray(String s) {
-        return base64ToByteArray(s, false);
-    }
-
-    /**
-     * Translates the specified "aternate representation" Base64 string
-     * into a byte array.
-     *
-     * @throw IllegalArgumentException or ArrayOutOfBoundsException
-     *        if <tt>s</tt> is not a valid alternate representation
-     *        Base64 string.
-     */
-    static byte[] altBase64ToByteArray(String s) {
-        return base64ToByteArray(s, true);
-    }
-
-    private static byte[] base64ToByteArray(String s, boolean alternate) {
-        byte[] alphaToInt = (alternate ?  altBase64ToInt : base64ToInt);
-        int sLen = s.length();
-        int numGroups = sLen/4;
-        if (4*numGroups != sLen)
-            throw new IllegalArgumentException(
-                "String length must be a multiple of four.");
-        int missingBytesInLastGroup = 0;
-        int numFullGroups = numGroups;
-        if (sLen != 0) {
-            if (s.charAt(sLen-1) == '=') {
-                missingBytesInLastGroup++;
-                numFullGroups--;
-            }
-            if (s.charAt(sLen-2) == '=')
-                missingBytesInLastGroup++;
-        }
-        byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
-
-        // Translate all full groups from base64 to byte array elements
-        int inCursor = 0, outCursor = 0;
-        for (int i=0; i<numFullGroups; i++) {
-            int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            int ch3 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
-            result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
-            result[outCursor++] = (byte) ((ch2 << 6) | ch3);
-        }
-
-        // Translate partial group, if present
-        if (missingBytesInLastGroup != 0) {
-            int ch0 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            int ch1 = base64toInt(s.charAt(inCursor++), alphaToInt);
-            result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
-
-            if (missingBytesInLastGroup == 1) {
-                int ch2 = base64toInt(s.charAt(inCursor++), alphaToInt);
-                result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
-            }
-        }
-        // assert inCursor == s.length()-missingBytesInLastGroup;
-        // assert outCursor == result.length;
-        return result;
-    }
-
-    /**
-     * Translates the specified character, which is assumed to be in the
-     * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
-     *
-     * @throw IllegalArgumentException or ArrayOutOfBoundsException if
-     *        c is not in the Base64 Alphabet.
-     */
-    private static int base64toInt(char c, byte[] alphaToInt) {
-        int result = alphaToInt[c];
-        if (result < 0)
-            throw new IllegalArgumentException("Illegal character " + c);
-        return result;
-    }
-
-    /**
-     * This array is a lookup table that translates unicode characters
-     * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
-     * into their 6-bit positive integer equivalents.  Characters that
-     * are not in the Base64 alphabet but fall within the bounds of the
-     * array are translated to -1.
-     */
-    private static final byte base64ToInt[] = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54,
-        55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
-    };
-
-    /**
-     * This array is the analogue of base64ToInt, but for the nonstandard
-     * variant that avoids the use of uppercase alphabetic characters.
-     */
-    private static final byte altBase64ToInt[] = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
-        2, 3, 4, 5, 6, 7, 8, -1, 62, 9, 10, 11, -1 , 52, 53, 54, 55, 56, 57,
-        58, 59, 60, 61, 12, 13, 14, -1, 15, 63, 16, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, 17, -1, 18, 19, 21, 20, 26, 27, 28, 29, 30, 31, 32, 33,
-        34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-        51, 22, 23, 24, 25
-    };
-
-}
--- a/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,11 +56,6 @@
  * by the data transfer subsystem to transfer data between Java and native
  * applications, and between Java applications in separate VMs.
  * <p>
- * In the Sun reference implementation, the default SystemFlavorMap is
- * initialized by the file <code>jre/lib/flavormap.properties</code> and the
- * contents of the URL referenced by the AWT property
- * <code>AWT.DnD.flavorMapFileURL</code>. See <code>flavormap.properties</code>
- * for details.
  *
  * @since 1.2
  */
@@ -1213,7 +1208,7 @@
      * are equal according to <code>String.equals(Object)</code>.</li>
      * </ul>
      * <p>
-     * Sun's reference implementation of this method returns the specified MIME
+     * The reference implementation of this method returns the specified MIME
      * type <code>String</code> prefixed with <code>JAVA_DATAFLAVOR:</code>.
      *
      * @param mimeType the MIME type to encode
@@ -1241,7 +1236,7 @@
      * according to <code>String.equals(Object)</code>.</li>
      * </ul>
      * <p>
-     * Sun's reference implementation of this method returns the MIME type
+     * The reference implementation of this method returns the MIME type
      * <code>String</code> of the specified <code>DataFlavor</code> prefixed
      * with <code>JAVA_DATAFLAVOR:</code>.
      *
--- a/src/share/classes/java/lang/AbstractStringBuilder.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java	Sat Jan 26 19:22:51 2013 -0800
@@ -35,6 +35,10 @@
  * particular sequence of characters, but the length and content of the
  * sequence can be changed through certain method calls.
  *
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
  * @author      Michael McCloskey
  * @author      Martin Buchholz
  * @author      Ulf Zibis
@@ -334,8 +338,6 @@
      * @param      srcEnd     stop copying at this offset.
      * @param      dst        the array to copy the data into.
      * @param      dstBegin   offset into {@code dst}.
-     * @throws     NullPointerException if {@code dst} is
-     *             {@code null}.
      * @throws     IndexOutOfBoundsException  if any of the following is true:
      *             <ul>
      *             <li>{@code srcBegin} is negative
@@ -1282,8 +1284,6 @@
      *          object, then the index of the first character of the first
      *          such substring is returned; if it does not occur as a
      *          substring, {@code -1} is returned.
-     * @throws  java.lang.NullPointerException if {@code str} is
-     *          {@code null}.
      */
     public int indexOf(String str) {
         return indexOf(str, 0);
@@ -1303,8 +1303,6 @@
      * @param   fromIndex   the index from which to start the search.
      * @return  the index within this string of the first occurrence of the
      *          specified substring, starting at the specified index.
-     * @throws  java.lang.NullPointerException if {@code str} is
-     *            {@code null}.
      */
     public int indexOf(String str, int fromIndex) {
         return String.indexOf(value, 0, count, str, fromIndex);
@@ -1325,8 +1323,6 @@
      *          within this object, then the index of the first character of
      *          the last such substring is returned. If it does not occur as
      *          a substring, {@code -1} is returned.
-     * @throws  java.lang.NullPointerException  if {@code str} is
-     *          {@code null}.
      */
     public int lastIndexOf(String str) {
         return lastIndexOf(str, count);
@@ -1346,8 +1342,6 @@
      * @param   fromIndex   the index to start the search from.
      * @return  the index within this sequence of the last occurrence of the
      *          specified substring.
-     * @throws  java.lang.NullPointerException if {@code str} is
-     *          {@code null}.
      */
     public int lastIndexOf(String str, int fromIndex) {
         return String.lastIndexOf(value, 0, count, str, fromIndex);
--- a/src/share/classes/java/lang/Boolean.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Boolean.java	Sat Jan 26 19:22:51 2013 -0800
@@ -290,4 +290,46 @@
     public static int compare(boolean x, boolean y) {
         return (x == y) ? 0 : (x ? 1 : -1);
     }
+
+    /**
+     * Returns the result of applying the logical AND operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the logical AND of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalAnd(boolean a, boolean b) {
+        return a && b;
+    }
+
+    /**
+     * Returns the result of applying the logical OR operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the logical OR of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalOr(boolean a, boolean b) {
+        return a || b;
+    }
+
+    /**
+     * Returns the result of applying the logical XOR operator to the
+     * specified {@code boolean} operands.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return  the logical XOR of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static boolean logicalXor(boolean a, boolean b) {
+        return a ^ b;
+    }
 }
--- a/src/share/classes/java/lang/Class.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Class.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2214,39 +2214,89 @@
 
     // Caches for certain reflective results
     private static boolean useCaches = true;
-    private volatile transient SoftReference<Field[]> declaredFields;
-    private volatile transient SoftReference<Field[]> publicFields;
-    private volatile transient SoftReference<Method[]> declaredMethods;
-    private volatile transient SoftReference<Method[]> publicMethods;
-    private volatile transient SoftReference<Constructor<T>[]> declaredConstructors;
-    private volatile transient SoftReference<Constructor<T>[]> publicConstructors;
-    // Intermediate results for getFields and getMethods
-    private volatile transient SoftReference<Field[]> declaredPublicFields;
-    private volatile transient SoftReference<Method[]> declaredPublicMethods;
+
+    // reflection data that might get invalidated when JVM TI RedefineClasses() is called
+    static class ReflectionData<T> {
+        volatile Field[] declaredFields;
+        volatile Field[] publicFields;
+        volatile Method[] declaredMethods;
+        volatile Method[] publicMethods;
+        volatile Constructor<T>[] declaredConstructors;
+        volatile Constructor<T>[] publicConstructors;
+        // Intermediate results for getFields and getMethods
+        volatile Field[] declaredPublicFields;
+        volatile Method[] declaredPublicMethods;
+        // Value of classRedefinedCount when we created this ReflectionData instance
+        final int redefinedCount;
+
+        ReflectionData(int redefinedCount) {
+            this.redefinedCount = redefinedCount;
+        }
+
+        // initialize Unsafe machinery here, since we need to call Class.class instance method
+        // and have to avoid calling it in the static initializer of the Class class...
+        private static final Unsafe unsafe;
+        // offset of Class.reflectionData instance field
+        private static final long reflectionDataOffset;
+
+        static {
+            unsafe = Unsafe.getUnsafe();
+            // bypass caches
+            Field reflectionDataField = searchFields(Class.class.getDeclaredFields0(false),
+                                                     "reflectionData");
+            if (reflectionDataField == null) {
+                throw new Error("No reflectionData field found in java.lang.Class");
+            }
+            reflectionDataOffset = unsafe.objectFieldOffset(reflectionDataField);
+        }
+
+        static <T> boolean compareAndSwap(Class<?> clazz,
+                                          SoftReference<ReflectionData<T>> oldData,
+                                          SoftReference<ReflectionData<T>> newData) {
+            return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData);
+        }
+    }
+
+    private volatile transient SoftReference<ReflectionData<T>> reflectionData;
 
     // Incremented by the VM on each call to JVM TI RedefineClasses()
     // that redefines this class or a superclass.
     private volatile transient int classRedefinedCount = 0;
 
-    // Value of classRedefinedCount when we last cleared the cached values
-    // that are sensitive to class redefinition.
-    private volatile transient int lastRedefinedCount = 0;
+    // Lazily create and cache ReflectionData
+    private ReflectionData<T> reflectionData() {
+        SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
+        int classRedefinedCount = this.classRedefinedCount;
+        ReflectionData<T> rd;
+        if (useCaches &&
+            reflectionData != null &&
+            (rd = reflectionData.get()) != null &&
+            rd.redefinedCount == classRedefinedCount) {
+            return rd;
+        }
+        // else no SoftReference or cleared SoftReference or stale ReflectionData
+        // -> create and replace new instance
+        return newReflectionData(reflectionData, classRedefinedCount);
+    }
 
-    // Clears cached values that might possibly have been obsoleted by
-    // a class redefinition.
-    private void clearCachesOnClassRedefinition() {
-        if (lastRedefinedCount != classRedefinedCount) {
-            declaredFields = publicFields = declaredPublicFields = null;
-            declaredMethods = publicMethods = declaredPublicMethods = null;
-            declaredConstructors = publicConstructors = null;
-            annotations = declaredAnnotations = null;
+    private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
+                                                int classRedefinedCount) {
+        if (!useCaches) return null;
 
-            // Use of "volatile" (and synchronization by caller in the case
-            // of annotations) ensures that no thread sees the update to
-            // lastRedefinedCount before seeing the caches cleared.
-            // We do not guard against brief windows during which multiple
-            // threads might redundantly work to fill an empty cache.
-            lastRedefinedCount = classRedefinedCount;
+        while (true) {
+            ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
+            // try to CAS it...
+            if (ReflectionData.compareAndSwap(this, oldReflectionData, new SoftReference<>(rd))) {
+                return rd;
+            }
+            // else retry
+            oldReflectionData = this.reflectionData;
+            classRedefinedCount = this.classRedefinedCount;
+            if (oldReflectionData != null &&
+                (rd = oldReflectionData.get()) != null &&
+                rd.redefinedCount == classRedefinedCount) {
+                return rd;
+            }
         }
     }
 
@@ -2289,27 +2339,19 @@
     // via ReflectionFactory.copyField.
     private Field[] privateGetDeclaredFields(boolean publicOnly) {
         checkInitted();
-        Field[] res = null;
-        if (useCaches) {
-            clearCachesOnClassRedefinition();
-            if (publicOnly) {
-                if (declaredPublicFields != null) {
-                    res = declaredPublicFields.get();
-                }
-            } else {
-                if (declaredFields != null) {
-                    res = declaredFields.get();
-                }
-            }
+        Field[] res;
+        ReflectionData<T> rd = reflectionData();
+        if (rd != null) {
+            res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
             if (res != null) return res;
         }
         // No cached value available; request value from VM
         res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
-        if (useCaches) {
+        if (rd != null) {
             if (publicOnly) {
-                declaredPublicFields = new SoftReference<>(res);
+                rd.declaredPublicFields = res;
             } else {
-                declaredFields = new SoftReference<>(res);
+                rd.declaredFields = res;
             }
         }
         return res;
@@ -2320,12 +2362,10 @@
     // via ReflectionFactory.copyField.
     private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
         checkInitted();
-        Field[] res = null;
-        if (useCaches) {
-            clearCachesOnClassRedefinition();
-            if (publicFields != null) {
-                res = publicFields.get();
-            }
+        Field[] res;
+        ReflectionData<T> rd = reflectionData();
+        if (rd != null) {
+            res = rd.publicFields;
             if (res != null) return res;
         }
 
@@ -2358,8 +2398,8 @@
 
         res = new Field[fields.size()];
         fields.toArray(res);
-        if (useCaches) {
-            publicFields = new SoftReference<>(res);
+        if (rd != null) {
+            rd.publicFields = res;
         }
         return res;
     }
@@ -2382,18 +2422,10 @@
     // instead be copied via ReflectionFactory.copyConstructor.
     private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
         checkInitted();
-        Constructor<T>[] res = null;
-        if (useCaches) {
-            clearCachesOnClassRedefinition();
-            if (publicOnly) {
-                if (publicConstructors != null) {
-                    res = publicConstructors.get();
-                }
-            } else {
-                if (declaredConstructors != null) {
-                    res = declaredConstructors.get();
-                }
-            }
+        Constructor<T>[] res;
+        ReflectionData<T> rd = reflectionData();
+        if (rd != null) {
+            res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
             if (res != null) return res;
         }
         // No cached value available; request value from VM
@@ -2404,11 +2436,11 @@
         } else {
             res = getDeclaredConstructors0(publicOnly);
         }
-        if (useCaches) {
+        if (rd != null) {
             if (publicOnly) {
-                publicConstructors = new SoftReference<>(res);
+                rd.publicConstructors = res;
             } else {
-                declaredConstructors = new SoftReference<>(res);
+                rd.declaredConstructors = res;
             }
         }
         return res;
@@ -2425,27 +2457,19 @@
     // via ReflectionFactory.copyMethod.
     private Method[] privateGetDeclaredMethods(boolean publicOnly) {
         checkInitted();
-        Method[] res = null;
-        if (useCaches) {
-            clearCachesOnClassRedefinition();
-            if (publicOnly) {
-                if (declaredPublicMethods != null) {
-                    res = declaredPublicMethods.get();
-                }
-            } else {
-                if (declaredMethods != null) {
-                    res = declaredMethods.get();
-                }
-            }
+        Method[] res;
+        ReflectionData<T> rd = reflectionData();
+        if (rd != null) {
+            res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
             if (res != null) return res;
         }
         // No cached value available; request value from VM
         res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
-        if (useCaches) {
+        if (rd != null) {
             if (publicOnly) {
-                declaredPublicMethods = new SoftReference<>(res);
+                rd.declaredPublicMethods = res;
             } else {
-                declaredMethods = new SoftReference<>(res);
+                rd.declaredMethods = res;
             }
         }
         return res;
@@ -2547,12 +2571,10 @@
     // via ReflectionFactory.copyMethod.
     private Method[] privateGetPublicMethods() {
         checkInitted();
-        Method[] res = null;
-        if (useCaches) {
-            clearCachesOnClassRedefinition();
-            if (publicMethods != null) {
-                res = publicMethods.get();
-            }
+        Method[] res;
+        ReflectionData<T> rd = reflectionData();
+        if (rd != null) {
+            res = rd.publicMethods;
             if (res != null) return res;
         }
 
@@ -2560,7 +2582,7 @@
         // Start by fetching public declared methods
         MethodArray methods = new MethodArray();
         {
-                Method[] tmp = privateGetDeclaredMethods(true);
+            Method[] tmp = privateGetDeclaredMethods(true);
             methods.addAll(tmp);
         }
         // Now recur over superclass and direct superinterfaces.
@@ -2600,8 +2622,8 @@
         methods.addAllIfNotPresent(inheritedMethods);
         methods.compactAndTrim();
         res = methods.getArray();
-        if (useCaches) {
-            publicMethods = new SoftReference<>(res);
+        if (rd != null) {
+            rd.publicMethods = res;
         }
         return res;
     }
@@ -2611,7 +2633,7 @@
     // Helpers for fetchers of one field, method, or constructor
     //
 
-    private Field searchFields(Field[] fields, String name) {
+    private static Field searchFields(Field[] fields, String name) {
         String internedName = name.intern();
         for (int i = 0; i < fields.length; i++) {
             if (fields[i].getName() == internedName) {
@@ -2629,7 +2651,7 @@
         // of Field objects which have to be created for the common
         // case where the field being requested is declared in the
         // class which is being queried.
-        Field res = null;
+        Field res;
         // Search declared public fields
         if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) {
             return res;
@@ -2681,7 +2703,7 @@
         // number of Method objects which have to be created for the
         // common case where the method being requested is declared in
         // the class which is being queried.
-        Method res = null;
+        Method res;
         // Search declared public methods
         if ((res = searchMethods(privateGetDeclaredMethods(true),
                                  name,
@@ -3125,9 +3147,20 @@
     // Annotations cache
     private transient Map<Class<? extends Annotation>, Annotation> annotations;
     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+    // Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields
+    private  transient int lastAnnotationsRedefinedCount = 0;
+
+    // Clears cached values that might possibly have been obsoleted by
+    // a class redefinition.
+    private void clearAnnotationCachesOnClassRedefinition() {
+        if (lastAnnotationsRedefinedCount != classRedefinedCount) {
+            annotations = declaredAnnotations = null;
+            lastAnnotationsRedefinedCount = classRedefinedCount;
+        }
+    }
 
     private synchronized void initAnnotationsIfNecessary() {
-        clearCachesOnClassRedefinition();
+        clearAnnotationCachesOnClassRedefinition();
         if (annotations != null)
             return;
         declaredAnnotations = AnnotationParser.parseAnnotations(
--- a/src/share/classes/java/lang/Double.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Double.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1021,6 +1021,48 @@
                  1));                          // (0.0, -0.0) or (NaN, !NaN)
     }
 
+    /**
+     * Adds two {@code double} values together as per the + operator.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the sum of {@code a} and {@code b}
+     * @jls 4.2.4 Floating-Point Operations
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static double sum(double a, double b) {
+        return a + b;
+    }
+
+    /**
+     * Returns the greater of two {@code double} values
+     * as if by calling {@link Math#max(double, double) Math.max}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the greater of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static double max(double a, double b) {
+        return Math.max(a, b);
+    }
+
+    /**
+     * Returns the smaller of two {@code double} values
+     * as if by calling {@link Math#min(double, double) Math.min}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the smaller of {@code a} and {@code b}.
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static double min(double a, double b) {
+        return Math.min(a, b);
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -9172774392245257468L;
 }
--- a/src/share/classes/java/lang/Float.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Float.java	Sat Jan 26 19:22:51 2013 -0800
@@ -926,6 +926,48 @@
                  1));                          // (0.0, -0.0) or (NaN, !NaN)
     }
 
+    /**
+     * Adds two {@code float} values together as per the + operator.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the sum of {@code a} and {@code b}
+     * @jls 4.2.4 Floating-Point Operations
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float sum(float a, float b) {
+        return a + b;
+    }
+
+    /**
+     * Returns the greater of two {@code float} values
+     * as if by calling {@link Math#max(float, float) Math.max}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the greater of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float max(float a, float b) {
+        return Math.max(a, b);
+    }
+
+    /**
+     * Returns the smaller of two {@code float} values
+     * as if by calling {@link Math#min(float, float) Math.min}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the smaller of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float min(float a, float b) {
+        return Math.min(a, b);
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -2671257302660747028L;
 }
--- a/src/share/classes/java/lang/FunctionalInterface.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/FunctionalInterface.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,9 @@
 import java.lang.annotation.*;
 
 /**
- * Indicates that an interface type declaration is intended to be a
- * <i>functional interface</i> as defined by the Java Language
- * Specification.
+ * An informative annotation type used to indicate that an interface
+ * type declaration is intended to be a <i>functional interface</i> as
+ * defined by the Java Language Specification.
  *
  * Conceptually, a functional interface has exactly one abstract
  * method.  Since {@linkplain java.lang.reflect.Method#isDefault()
@@ -52,6 +52,11 @@
  * <li> The annotated type satisfies the requirements of a functional interface.
  * </ul>
  *
+ * <p>However, the compiler will treat any interface meeting the
+ * definition of a functional interface as a functional interface
+ * regardless of whether or not a {@code FunctionalInterface}
+ * annotation is present on the interface declaration.
+ *
  * @jls 4.3.2. The Class Object
  * @jls 9.8 Functional Interfaces
  * @jls 9.4.3 Interface Method Body
--- a/src/share/classes/java/lang/Integer.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Integer.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1513,6 +1513,47 @@
                ((i << 24));
     }
 
+    /**
+     * Adds two integers together as per the + operator.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the sum of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static int sum(int a, int b) {
+        return a + b;
+    }
+
+    /**
+     * Returns the greater of two {@code int} values
+     * as if by calling {@link Math#max(int, int) Math.max}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the greater of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static int max(int a, int b) {
+        return Math.max(a, b);
+    }
+
+    /**
+     * Returns the smaller of two {@code int} values
+     * as if by calling {@link Math#min(int, int) Math.min}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the smaller of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static int min(int a, int b) {
+        return Math.min(a, b);
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     @Native private static final long serialVersionUID = 1360826667806852920L;
 }
--- a/src/share/classes/java/lang/Long.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Long.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1540,6 +1540,47 @@
             ((i >>> 16) & 0xffff0000L) | (i >>> 48);
     }
 
+    /**
+     * Adds two {@code long} values together as per the + operator.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the sum of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static long sum(long a, long b) {
+        return a + b;
+    }
+
+    /**
+     * Returns the greater of two {@code long} values
+     * as if by calling {@link Math#max(long, long) Math.max}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the greater of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static long max(long a, long b) {
+        return Math.max(a, b);
+    }
+
+    /**
+     * Returns the smaller of two {@code long} values
+     * as if by calling {@link Math#min(long, long) Math.min}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the smaller of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static long min(long a, long b) {
+        return Math.min(a, b);
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     @Native private static final long serialVersionUID = 4290774380558885855L;
 }
--- a/src/share/classes/java/lang/String.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/String.java	Sat Jan 26 19:22:51 2013 -0800
@@ -33,6 +33,7 @@
 import java.util.Comparator;
 import java.util.Formatter;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -871,6 +872,8 @@
         if (srcBegin > srcEnd) {
             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
         }
+        Objects.requireNonNull(dst);
+
         int j = dstBegin;
         int n = srcEnd;
         int i = srcBegin;
@@ -2112,7 +2115,6 @@
      *
      * @param s the sequence to search for
      * @return true if this string contains {@code s}, false otherwise
-     * @throws NullPointerException if {@code s} is {@code null}
      * @since 1.5
      */
     public boolean contains(CharSequence s) {
@@ -2219,8 +2221,6 @@
      * @param  target The sequence of char values to be replaced
      * @param  replacement The replacement sequence of char values
      * @return  The resulting string
-     * @throws NullPointerException if {@code target} or
-     *         {@code replacement} is {@code null}.
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
@@ -2833,9 +2833,6 @@
      *          href="../util/Formatter.html#detail">Details</a> section of the
      *          formatter class specification.
      *
-     * @throws  NullPointerException
-     *          If the {@code format} is {@code null}
-     *
      * @return  A formatted string
      *
      * @see  java.util.Formatter
@@ -2865,8 +2862,8 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         {@code null} argument depends on the <a
-     *         href="../util/Formatter.html#syntax">conversion</a>.
+     *         {@code null} argument depends on the
+     *         <a href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
      *          If a format string contains an illegal syntax, a format
@@ -2877,9 +2874,6 @@
      *          href="../util/Formatter.html#detail">Details</a> section of the
      *          formatter class specification
      *
-     * @throws  NullPointerException
-     *          If the {@code format} is {@code null}
-     *
      * @return  A formatted string
      *
      * @see  java.util.Formatter
--- a/src/share/classes/java/lang/StringBuffer.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/StringBuffer.java	Sat Jan 26 19:22:51 2013 -0800
@@ -77,7 +77,11 @@
  * the capacity, it is not necessary to allocate a new internal
  * buffer array. If the internal buffer overflows, it is
  * automatically made larger.
- *
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ * <p>
  * As of  release JDK 5, this class has been supplemented with an equivalent
  * class designed for use by a single thread, {@link StringBuilder}.  The
  * {@code StringBuilder} class should generally be used in preference to
@@ -123,7 +127,6 @@
      * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @exception NullPointerException if {@code str} is {@code null}
      */
     public StringBuffer(String str) {
         super(str.length() + 16);
@@ -141,7 +144,6 @@
      * {@code 16} is returned.
      *
      * @param      seq   the sequence to copy.
-     * @exception NullPointerException if {@code seq} is {@code null}
      * @since 1.5
      */
     public StringBuffer(CharSequence seq) {
@@ -228,7 +230,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     @Override
@@ -584,7 +585,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
     @Override
@@ -594,7 +594,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
     @Override
@@ -603,7 +602,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
     @Override
@@ -613,7 +611,6 @@
     }
 
     /**
-     * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
     @Override
--- a/src/share/classes/java/lang/StringBuilder.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/StringBuilder.java	Sat Jan 26 19:22:51 2013 -0800
@@ -64,6 +64,10 @@
  * use by multiple threads. If such synchronization is required then it is
  * recommended that {@link java.lang.StringBuffer} be used.
  *
+ * <p>Unless otherwise noted, passing a {@code null} argument to a constructor
+ * or method in this class will cause a {@link NullPointerException} to be
+ * thrown.
+ *
  * @author      Michael McCloskey
  * @see         java.lang.StringBuffer
  * @see         java.lang.String
@@ -103,7 +107,6 @@
      * {@code 16} plus the length of the string argument.
      *
      * @param   str   the initial contents of the buffer.
-     * @throws    NullPointerException if {@code str} is {@code null}
      */
     public StringBuilder(String str) {
         super(str.length() + 16);
@@ -117,7 +120,6 @@
      * {@code CharSequence} argument.
      *
      * @param      seq   the sequence to copy.
-     * @throws    NullPointerException if {@code seq} is {@code null}
      */
     public StringBuilder(CharSequence seq) {
         this(seq.length() + 16);
@@ -373,33 +375,21 @@
         return this;
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
     @Override
     public int indexOf(String str) {
         return super.indexOf(str);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
     @Override
     public int indexOf(String str, int fromIndex) {
         return super.indexOf(str, fromIndex);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
     @Override
     public int lastIndexOf(String str) {
         return super.lastIndexOf(str);
     }
 
-    /**
-     * @throws NullPointerException {@inheritDoc}
-     */
     @Override
     public int lastIndexOf(String str, int fromIndex) {
         return super.lastIndexOf(str, fromIndex);
--- a/src/share/classes/java/lang/Thread.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/Thread.java	Sat Jan 26 19:22:51 2013 -0800
@@ -2028,6 +2028,16 @@
         }
     }
 
+
+    // The following three initially uninitialized fields are exclusively
+    // managed by class java.util.concurrent.ThreadLocalRandom.
+    /** The current seed for a ThreadLocalRandom */
+    long threadLocalRandomSeed;
+    /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
+    int threadLocalRandomProbe;
+    /** Secondary seed isolated from public ThreadLocalRandom sequence */
+    int threadLocalRandomSecondarySeed;
+
     /* Some private helper methods */
     private native void setPriority0(int newPriority);
     private native void stop0(Object o);
--- a/src/share/classes/java/lang/instrument/package.html	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/instrument/package.html	Sat Jan 26 19:22:51 2013 -0800
@@ -53,8 +53,10 @@
 <h3>Command-Line Interface</h3>
 
 <P> 
-On implementations with a command-line interface, an agent is started by
-adding this option to the command-line:
+An implementation is not required to provide a way to start agents from the
+command-line interface. On implementations that do provide a way to start agents
+from the command-line interface, an agent is started by adding this option to
+the command-line:
 <blockquote>
 <code><b>-javaagent:</b></code><i>jarpath[</i><code><b>=</b></code><i>options]</i>
 </blockquote>
--- a/src/share/classes/java/lang/reflect/Constructor.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/reflect/Constructor.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -205,6 +205,11 @@
 
     /**
      * {@inheritDoc}
+     */
+    public int getParameterCount() { return parameterTypes.length; }
+
+    /**
+     * {@inheritDoc}
      * @throws GenericSignatureFormatError {@inheritDoc}
      * @throws TypeNotPresentException {@inheritDoc}
      * @throws MalformedParameterizedTypeException {@inheritDoc}
--- a/src/share/classes/java/lang/reflect/Executable.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/reflect/Executable.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -226,6 +226,18 @@
     public abstract Class<?>[] getParameterTypes();
 
     /**
+     * Returns the number of formal parameters (including any
+     * synthetic or synthesized parameters) for the executable
+     * represented by this object.
+     *
+     * @return The number of formal parameters for the executable this
+     * object represents
+     */
+    public int getParameterCount() {
+        throw new AbstractMethodError();
+    }
+
+    /**
      * Returns an array of {@code Type} objects that represent the formal
      * parameter types, in declaration order, of the executable represented by
      * this object. Returns an array of length 0 if the
@@ -259,6 +271,60 @@
     }
 
     /**
+     * Returns an array of {@code Parameter} objects that represent
+     * all the parameters to the underlying executable represented by
+     * this object.  Returns an array of length 0 if the executable
+     * has no parameters.
+     *
+     * @return an array of {@code Parameter} objects representing all
+     * the parameters to the executable this object represents
+     */
+    public Parameter[] getParameters() {
+        // TODO: This may eventually need to be guarded by security
+        // mechanisms similar to those in Field, Method, etc.
+        //
+        // Need to copy the cached array to prevent users from messing
+        // with it.  Since parameters are immutable, we can
+        // shallow-copy.
+        return privateGetParameters().clone();
+    }
+
+    private Parameter[] synthesizeAllParams() {
+        final int realparams = getParameterCount();
+        final Parameter[] out = new Parameter[realparams];
+        for (int i = 0; i < realparams; i++)
+            // TODO: is there a way to synthetically derive the
+            // modifiers?  Probably not in the general case, since
+            // we'd have no way of knowing about them, but there
+            // may be specific cases.
+            out[i] = new Parameter("arg" + i, 0, this, i);
+        return out;
+    }
+
+    private Parameter[] privateGetParameters() {
+        // Use tmp to avoid multiple writes to a volatile.
+        Parameter[] tmp = parameters;
+
+        if (tmp == null) {
+
+            // Otherwise, go to the JVM to get them
+            tmp = getParameters0();
+
+            // If we get back nothing, then synthesize parameters
+            if (tmp == null)
+                tmp = synthesizeAllParams();
+
+            parameters = tmp;
+        }
+
+        return tmp;
+    }
+
+    private transient volatile Parameter[] parameters;
+
+    private native Parameter[] getParameters0();
+
+    /**
      * Returns an array of {@code Class} objects that represent the
      * types of exceptions declared to be thrown by the underlying
      * executable represented by this object.  Returns an array of
@@ -403,4 +469,5 @@
         }
         return declaredAnnotations;
     }
+
 }
--- a/src/share/classes/java/lang/reflect/Method.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/reflect/Method.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -255,6 +255,12 @@
 
     /**
      * {@inheritDoc}
+     */
+    public int getParameterCount() { return parameterTypes.length; }
+
+
+    /**
+     * {@inheritDoc}
      * @throws GenericSignatureFormatError {@inheritDoc}
      * @throws TypeNotPresentException {@inheritDoc}
      * @throws MalformedParameterizedTypeException {@inheritDoc}
--- a/src/share/classes/java/lang/reflect/Modifier.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/lang/reflect/Modifier.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -340,12 +340,17 @@
     static final int BRIDGE    = 0x00000040;
     static final int VARARGS   = 0x00000080;
     static final int SYNTHETIC = 0x00001000;
-    static final int ANNOTATION= 0x00002000;
+    static final int ANNOTATION  = 0x00002000;
     static final int ENUM      = 0x00004000;
+    static final int SYNTHESIZED = 0x00010000;
     static boolean isSynthetic(int mod) {
       return (mod & SYNTHETIC) != 0;
     }
 
+    static boolean isSynthesized(int mod) {
+      return (mod & SYNTHESIZED) != 0;
+    }
+
     /**
      * See JLSv3 section 8.1.1.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/lang/reflect/Parameter.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.reflect;
+
+import java.lang.annotation.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import sun.reflect.annotation.AnnotationSupport;
+
+/**
+ * Information about method parameters.
+ *
+ * A {@code Parameter} provides information about method parameters,
+ * including its name and modifiers.  It also provides an alternate
+ * means of obtaining attributes for the parameter.
+ *
+ * @since 1.8
+ */
+public final class Parameter implements AnnotatedElement {
+
+    private final String name;
+    private final int modifiers;
+    private final Executable executable;
+    private int index;
+
+    /**
+     * Package-private constructor for {@code Parameter}.
+     *
+     * If method parameter data is present in the classfile, then the
+     * JVM creates {@code Parameter} objects directly.  If it is
+     * absent, however, then {@code Executable} uses this constructor
+     * to synthesize them.
+     *
+     * @param name The name of the parameter.
+     * @param modifiers The modifier flags for the parameter.
+     * @param executable The executable which defines this parameter.
+     * @param index The index of the parameter.
+     */
+    Parameter(String name,
+              int modifiers,
+              Executable executable,
+              int index) {
+        this.name = name;
+        this.modifiers = modifiers;
+        this.executable = executable;
+        this.index = index;
+    }
+
+    /**
+     * Compares based on the executable and the index.
+     *
+     * @param obj The object to compare.
+     * @return Whether or not this is equal to the argument.
+     */
+    public boolean equals(Object obj) {
+        if(obj instanceof Parameter) {
+            Parameter other = (Parameter)obj;
+            return (other.executable.equals(executable) &&
+                    other.index == index);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code based on the executable's hash code and the
+     * index.
+     *
+     * @return A hash code based on the executable's hash code.
+     */
+    public int hashCode() {
+        return executable.hashCode() ^ index;
+    }
+
+    /**
+     * Returns a string representation of the parameter's modifiers,
+     * its attributes, its type, its name, and a trailing ... if it is
+     * a variadic parameter.
+     *
+     * @return A string representation of the parameter and associated
+     * information.
+     */
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        final Type type = getParameterizedType();
+        final String typename = (type instanceof Class)?
+            Field.getTypeName((Class)type):
+            (type.toString());
+
+        sb.append(Modifier.toString(getModifiers()));
+        sb.append(" ");
+
+        if(isVarArgs())
+            sb.append(typename.replaceFirst("\\[\\]$", "..."));
+        else
+            sb.append(typename);
+
+        sb.append(" ");
+        sb.append(name);
+
+        return sb.toString();
+    }
+
+    /**
+     * Return the {@code Executable} which declares this parameter.
+     *
+     * @return The {@code Executable} declaring this parameter.
+     */
+    public Executable getDeclaringExecutable() {
+        return executable;
+    }
+
+    /**
+     * Get the modifier flags for this the parameter represented by
+     * this {@code Parameter} object.
+     *
+     * @return The modifier flags for this parameter.
+     */
+    public int getModifiers() {
+        return modifiers;
+    }
+
+    /**
+     * Returns the name of the parameter represented by this
+     * {@code Parameter} object.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns a {@code Type} object that identifies the parameterized
+     * type for the parameter represented by this {@code Parameter}
+     * object.
+     *
+     * @return a {@code Type} object identifying the parameterized
+     * type of the parameter represented by this object
+     */
+    public Type getParameterizedType() {
+        Type tmp = parameterTypeCache;
+        if (null == tmp) {
+            tmp = executable.getGenericParameterTypes()[index];
+            parameterTypeCache = tmp;
+        }
+
+        return tmp;
+    }
+
+    private transient volatile Type parameterTypeCache = null;
+
+    /**
+     * Returns a {@code Class} object that identifies the
+     * declared type for the parameter represented by this
+     * {@code Parameter} object.
+     *
+     * @return a {@code Class} object identifying the declared
+     * type of the parameter represented by this object
+     */
+    public Class<?> getType() {
+        Class<?> tmp = parameterClassCache;
+        if (null == tmp) {
+            tmp = executable.getParameterTypes()[index];
+            parameterClassCache = tmp;
+        }
+        return tmp;
+    }
+
+    private transient volatile Class<?> parameterClassCache = null;
+
+    /**
+     * Returns {@code true} if this parameter is a synthesized
+     * construct; returns {@code false} otherwise.
+     *
+     * @return true if and only if this parameter is a synthesized
+     * construct as defined by
+     * <cite>The Java&trade; Language Specification</cite>.
+     */
+    public boolean isSynthesized() {
+        return Modifier.isSynthesized(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter is a synthetic
+     * construct; returns {@code false} otherwise.
+     *
+     * @jls 13.1 The Form of a Binary
+     * @return true if and only if this parameter is a synthetic
+     * construct as defined by
+     * <cite>The Java&trade; Language Specification</cite>.
+     */
+    public boolean isSynthetic() {
+        return Modifier.isSynthetic(getModifiers());
+    }
+
+    /**
+     * Returns {@code true} if this parameter represents a variable
+     * argument list; returns {@code false} otherwise.
+     *
+     * @return {@code true} if an only if this parameter represents a
+     * variable argument list.
+     */
+    public boolean isVarArgs() {
+        return executable.isVarArgs() &&
+            index == executable.getParameterCount() - 1;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+
+        return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getDeclaredAnnotations() {
+        return executable.getParameterAnnotations()[index];
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotation is the same as
+        // getAnnotation.
+        return getAnnotation(annotationClass);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+        // Only annotations on classes are inherited, for all other
+        // objects getDeclaredAnnotations is the same as
+        // getAnnotations.
+        return getAnnotations(annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Annotation[] getAnnotations() {
+        return getDeclaredAnnotations();
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean isAnnotationPresent(
+        Class<? extends Annotation> annotationClass) {
+        return getAnnotation(annotationClass) != null;
+    }
+
+    private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+
+    private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+        if(null == declaredAnnotations) {
+            declaredAnnotations =
+                new HashMap<Class<? extends Annotation>, Annotation>();
+            Annotation[] ann = getDeclaredAnnotations();
+            for(int i = 0; i < ann.length; i++)
+                declaredAnnotations.put(ann[i].annotationType(), ann[i]);
+        }
+        return declaredAnnotations;
+    }
+
+}
--- a/src/share/classes/java/net/URI.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/net/URI.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1694,6 +1694,13 @@
         return c;
     }
 
+    // US-ASCII only
+    private static int toUpper(char c) {
+        if ((c >= 'a') && (c <= 'z'))
+            return c - ('a' - 'A');
+        return c;
+    }
+
     private static boolean equal(String s, String t) {
         if (s == t) return true;
         if ((s != null) && (t != null)) {
@@ -1744,7 +1751,26 @@
 
     private static int hash(int hash, String s) {
         if (s == null) return hash;
-        return hash * 127 + s.hashCode();
+        return s.indexOf('%') < 0 ? hash * 127 + s.hashCode()
+                                  : normalizedHash(hash, s);
+    }
+
+
+    private static int normalizedHash(int hash, String s) {
+        int h = 0;
+        for (int index = 0; index < s.length(); index++) {
+            char ch = s.charAt(index);
+            h = 31 * h + ch;
+            if (ch == '%') {
+                /*
+                 * Process the next two encoded characters
+                 */
+                for (int i = index + 1; i < index + 3; i++)
+                    h = 31 * h + toUpper(s.charAt(i));
+                index += 2;
+            }
+        }
+        return hash * 127 + h;
     }
 
     // US-ASCII only
--- a/src/share/classes/java/net/URL.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/net/URL.java	Sat Jan 26 19:22:51 2013 -0800
@@ -38,17 +38,21 @@
  * directory, or it can be a reference to a more complicated object,
  * such as a query to a database or to a search engine. More
  * information on the types of URLs and their formats can be found at:
- * <blockquote>
- *     <a href="http://www.socs.uts.edu.au/MosaicDocs-old/url-primer.html">
- *    <i>http://www.socs.uts.edu.au/MosaicDocs-old/url-primer.html</i></a>
- * </blockquote>
+ * <a href=
+ * "http://web.archive.org/web/20051219043731/http://archive.ncsa.uiuc.edu/SDG/Software/Mosaic/Demo/url-primer.html">
+ * <i>Types of URL</i></a>
  * <p>
- * In general, a URL can be broken into several parts. The previous
- * example of a URL indicates that the protocol to use is
+ * In general, a URL can be broken into several parts. Consider the
+ * following example:
+ * <blockquote><pre>
+ *     http://www.example.com/docs/resource1.html
+ * </pre></blockquote>
+ * <p>
+ * The URL above indicates that the protocol to use is
  * <code>http</code> (HyperText Transfer Protocol) and that the
  * information resides on a host machine named
- * <code>www.socs.uts.edu.au</code>. The information on that host
- * machine is named <code>/MosaicDocs-old/url-primer.html</code>. The exact
+ * <code>www.example.com</code>. The information on that host
+ * machine is named <code>/docs/resource1.html</code>. The exact
  * meaning of this name on the host machine is both protocol
  * dependent and host dependent. The information normally resides in
  * a file, but it could be generated on the fly. This component of
@@ -61,7 +65,7 @@
  * <code>http</code> is <code>80</code>. An alternative port could be
  * specified as:
  * <blockquote><pre>
- *     http://www.socs.uts.edu.au:80/MosaicDocs-old/url-primer.html
+ *     http://www.example.com:1080/docs/resource1.html
  * </pre></blockquote>
  * <p>
  * The syntax of <code>URL</code> is defined by  <a
--- a/src/share/classes/java/security/KeyStore.java	Thu Jan 24 16:49:20 2013 -0800
+++ b/src/share/classes/java/security/KeyStore.java	Sat Jan 26 19:22:51 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,11 @@
 package java.security;
 
 import java.io.*;
+import java.net.URI;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
+import java.security.spec.AlgorithmParameterSpec;
 import java.util.*;
 import javax.crypto.SecretKey;
 
@@ -239,6 +241,8 @@
                 ProtectionParameter, javax.security.auth.Destroyable {
 
         private final char[] password;
+        private final String protectionAlgorithm;
+        private final AlgorithmParameterSpec protectionParameters;
         private volatile boolean destroyed = false;
 
         /**
@@ -251,6 +255,72 @@
          */
         public PasswordProtection(char[] password) {
             this.password = (password == null) ? null : password.clone();
+            this.protectionAlgorithm = null;
+            this.protectionParameters = null;
+        }
+
+        /**
+         * Creates a password parameter and specifies the protection algorithm
+         * and associated parameters to use when encrypting a keystore entry.
+         * <p>
+         * The specified {@code password} is cloned before it is stored in the
+         * new {@code PasswordProtection} object.
+         *
+         * @param password the password, which may be {@code null}
+         * @param protectionAlgorithm the encryption algorithm name, for
+         *     example, {@code PBEWithHmacSHA256AndAES_256}.
+         *     See the Cipher section in the <a href=
+         * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
+         * Java Cryptography Architecture Standard Algorithm Name
+         * Documentation</a>
+         *     for information about standard encryption algorithm names.
+         * @param protectionParameters the encryption algorithm parameter
+         *     specification, which may be {@code null}
+         * @exception NullPointerException if {@code protectionAlgorithm} is
+         *     {@code null}
+         *
+         * @since 1.8
+         */
+        public PasswordProtection(char[] password, String protectionAlgorithm,
+            AlgorithmParameterSpec protectionParameters) {
+            if (protectionAlgorithm == null) {
+                throw new NullPointerException("invalid null input");
+            }
+            this.password = (password == null) ? null : password.clone();
+            this.protectionAlgorithm = protectionAlgorithm;
+            this.protectionParameters = protectionParameters;
+        }
+
+        /**
+         * Gets the name of the protection algorithm.
+         * If none was set then the keystore provider will use its default
+         * protection algorithm. The name of the default protection algorithm
+         * for a given keystore type is set using the
+         * {@code 'keystore.<type>.keyProtectionAlgorithm'} security property.
+         * For example, the
+         * {@code keystore.PKCS12.keyProtectionAlgorithm} property stores the
+         * name of the default key protection algorithm used for PKCS12
+         * keystores. If the security property is not set, an
+         * implementation-specific algorithm will be used.
+         *
+         * @return the algorithm name, or {@code null} if none was set
+         *
+         * @since 1.8
+         */
+        public String getProtectionAlgorithm() {
+            return protectionAlgorithm;
+        }
+
+        /**
+         * Gets the parameters supplied for the protection algorithm.
+         *
+         * @return the algorithm parameter specification, or {@code  null},
+         *     if none was set
+         *
+         * @since 1.8
+         */
+        public AlgorithmParameterSpec getProtectionParameters() {
+            return protectionParameters;
         }
 
         /**
@@ -336,7 +406,44 @@
      *
      * @since 1.5
      */
-    public static interface Entry { }
+    public static interface Entry {
+
+        /**
+         * Retrieves the attributes associated with an entry.
+         * <p>
+         * The default implementation returns an empty {@code Set}.
+         *
+         * @return an unmodifiable {@code Set} of attributes, possibly empty
+         *
+         * @since 1.8
+         */
+        public default Set<Attribute> getAttributes() {
+            return Collections.<Attribute>emptySet();
+        }
+
+        /**
+         * An attribute associated with a keystore entry.
+         * It comprises a name and one or more values.
+         *
+         * @since 1.8
+         */
+        public interface Attribute {
+            /**
+             * Returns the attribute's name.
+             *
+             * @return the attribute name
+             */
+            public String getName();
+
+            /**
+             * Returns the attribute's value.
+             * Multi-valued attributes encode their values as a single string.
+             *
+             * @return the attribute value
+             */
+            public String getValue();
+        }
+    }
 
     /**
      * A <code>KeyStore</code> entry that holds a <code>PrivateKey</code>
@@ -348,6 +455,7 @@
 
         private final PrivateKey privKey;
         private final Certificate[] chain;
+        private final Set<Attribute> attributes;
 
         /**
          * Constructs a <code>PrivateKeyEntry</code> with a
@@ -374,7 +482,39 @@
          *      in the end entity <code>Certificate</code> (at index 0)
          */
         public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
-            if (privateKey == null || chain == null) {
+            this(privateKey, chain, Collections.<Attribute>emptySet());
+        }
+
+        /**
+         * Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
+         * corresponding certificate chain and associated entry attributes.
+         *
+         * <p> The specified {@code chain} and {@code attributes} are cloned
+         * before they are stored in the new {@code PrivateKeyEntry} object.
+         *
+         * @param privateKey the {@code PrivateKey}
+         * @param chain an array of {@code Certificate}s
+         *      representing the certificate chain.
+         *      The chain must be ordered and contain a
+         *      {@code Certificate} at index 0
+         *      corresponding to the private key.
+         * @param attributes the attributes
+         *
+         * @exception NullPointerException if {@code privateKey}, {@code chain}
+         *      or {@code attributes} is {@code null}
+         * @exception IllegalArgumentException if the specified chain has a
+         *      length of 0, if the specified chain does not contain
+         *      {@code Certificate}s of the same type,
+         *      or if the {@code PrivateKey} algorithm
+         *      does not match the algorithm of the {@code PublicKey}
+         *      in the end entity {@code Certificate} (at index 0)
+         *
+         * @since 1.8
+         */
+        public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
+           Set<Attribute> attributes) {
+
+            if (privateKey == null || chain == null || attributes == null) {
                 throw new NullPointerException("invalid null input");
             }
             if (chain.length == 0) {
@@ -409,6 +549,9 @@
             } else {
                 this.chain = clonedChain;
             }
+
+            this.attributes =
+                Collections.unmodifiableSet(new HashSet<>(attributes));
         }
 
         /**
@@ -450,6 +593,19 @@
         }
 
         /**
+         * Retrieves the attributes associated with an entry.
+         * <p>
+         *
+         * @return an unmodifiable {@code Set} of attributes, possibly empty
+         *
+         * @since 1.8
+         */
+        @Override
+        public Set<Attribute> getAttributes() {
+            return attributes;
+        }
+
+        /**
          * Returns a string representation of this PrivateKeyEntry.
          * @return a string representation of this PrivateKeyEntry.
          */
@@ -474,6 +630,7 @@
     public static final class SecretKeyEntry implements Entry {
 
         private final SecretKey sKey;
+        private final Set<Attribute> attributes;
 
         /**
          * Constructs a <code>SecretKeyEntry</code> with a
@@ -489,6 +646,32 @@
                 throw new NullPointerException("invalid null input");
             }
             this.sKey = secretKey;
+            this.attributes = Collections.<Attribute>emptySet();
+        }
+
+        /**
+         * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
+         * associated entry attributes.
+         *
+         * <p> The specified {@code attributes} is cloned before it is stored
+         * in the new {@code SecretKeyEntry} object.
+         *
+         * @param secretKey the {@code SecretKey}
+         * @param attributes the attributes
+         *
+         * @exception NullPointerException if {@code secretKey} or
+         *     {@code attributes} is {@code null}
+         *
+         * @since 1.8
+         */
+        public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {
+
+            if (secretKey == null || attributes == null) {
+                throw new NullPointerException("invalid null input");
+            }
+            this.sKey = secretKey;
+            this.attributes =
+                Collections.unmodifiableSet(new HashSet<>(attributes));
         }
 
         /**
@@ -501,6 +684,19 @@
         }
 
         /**
+         * Retrieves the attributes associated with an entry.
+         * <p>
+         *
+         * @return an unmodifiable {@code Set} of attributes, possibly empty
+         *
+         * @since 1.8
+         */
+        @Override
+        public Set<Attribute> getAttributes() {
+            return attributes;
+        }
+
+        /**
          * Returns a string representation of this SecretKeyEntry.
          * @return a string representation of this SecretKeyEntry.
          */
@@ -518,6 +714,7 @@
     public static final class TrustedCertificateEntry implements Entry {
 
         private final Certificate cert;
+        private final Set<Attribute> attributes;
 
         /**
          * Constructs a <code>TrustedCertificateEntry</code> with a
@@ -533,6 +730,32 @@
                 throw new NullPointerException("invalid null input");
             }
             this.cert = trustedCert;
+            this.attributes = Collections.<Attribute>emptySet();
+        }
+
+        /**
+         * Constructs a {@code TrustedCertificateEntry} with a
+         * trusted {@code Certificate} and associated entry attributes.
+         *
+         * <p> The specified {@code attributes} is cloned before it is stored
+         * in the new {@code TrustedCertificateEntry} object.
+         *
+         * @param trustedCert the trusted {@code Certificate}
+         * @param attributes the attributes
+         *
+         * @exception NullPointerException if {@code trustedCert} or
+         *     {@code attributes} is {@code null}
+         *
+         * @since 1.8
+         */
+        public TrustedCertificateEntry(Certificate trustedCert,
+           Set<Attribute> attributes) {
+            if (trustedCert == null || attributes == null) {
+                throw new NullPointerException("invalid null input");
+            }
+            this.cert = trustedCert;
+            this.attributes =
+                Collections.unmodifiableSet(new HashSet<>(attributes));
         }
 
         /**
@@ -545,6 +768,19 @@
         }
 
         /**
+         * Retrieves the attributes associated with an entry.
+         * <p>
+         *
+         * @return an unmodifiable {@code Set} of attributes, possibly empty
+         *
+         * @since 1.8
+         */
+        @Override
+        public Set<Attribute> getAttributes() {
+            return attributes;
+        }
+
+        /**
          * Returns a string representation of this TrustedCertificateEntry.
          * @return a string representation of this TrustedCertificateEntry.
          */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/security/PKCS12Attribute.java	Sat Jan 26 19:22:51 2013 -0800
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.regex.Pattern;
+import sun.security.util.*;
+
+/**
+ * An attribute associated with a PKCS12 keystore entry.
+ * The attribute name is an ASN.1 Object Identifier and the attribute
+ * value is a set of ASN.1 types.
+ *
+ * @since 1.8
+ */
+public final class PKCS12Attribute implements KeyStore.Entry.Attribute {
+
+    private static final Pattern COLON_SEPARATED_HEX_PAIRS =
+        Pattern.compile("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2})+$");
+    private String name;
+    private String value;
+    private byte[] encoded;
+    private int hashValue = -1;
+
+    /**
+     * Constructs a PKCS12 attribute from its name and value.
+     * The name is an ASN.1 Object Identifier represented as a list of
+     * dot-separated integers.
+     * A string value is represented as the string itself.
+     * A binary value is represented as a string of colon-separated
+     * pairs of hexadecimal digits.
+     * Multi-valued attributes are represented as a comma-separated
+     * list of values, enclosed in square brackets. See
+     * {@link Arrays#toString(java.lang.Object[])}.
+     * <p>
+     * A string value will be DER-encoded as an ASN.1 UTF8String and a
+     * binary value will be DER-encoded as an ASN.1 Octet String.
+     *
+     * @param name the attribute's identifier
+     * @param value the attribute's value
+     *
+     * @exception NullPointerException if {@code name} or {@code value}
+     *     is {@code null}
+     * @exception IllegalArgumentException if {@code name} or
+     *     {@code value} is incorrectly formatted
+     */
+    public PKCS12Attribute(String name, String value) {
+        if (name == null || value == null) {
+            throw new NullPointerException();
+        }
+        // Validate name
+        ObjectIdentifier type;
+        try {
+            type = new ObjectIdentifier(name);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Incorrect format: name", e);
+        }
+        this.name = name;
+
+        // Validate value
+        int length = value.length();
+        String[] values;
+        if (value.charAt(0) == '[' && value.charAt(length - 1) == ']') {
+            values = value.substring(1, length - 1).split(", ");
+        } else {
+            values = new String[]{ value };
+        }
+        this.value = value;
+
+        try {
+            this.encoded = encode(type, values);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Incorrect format: value", e);
+        }
+    }
+
+    /**
+     * Constructs a PKCS12 attribute from its ASN.1 DER encoding.
+     * The DER encoding is specified by the following ASN.1 definition:
+     * <pre>
+     *
+     * Attribute ::= SEQUENCE {
+     *     type   AttributeType,
+     *     values SET OF AttributeValue
+     * }
+     * AttributeType ::= OBJECT IDENTIFIER
+     * AttributeValue ::= ANY defined by type
+     *
+     * </pre>
+     *
+     * @param encoded the attribute's ASN.1 DER encoding. It is cloned
+     *     to prevent subsequent modificaion.
+     *
+     * @exception NullPointerException if {@code encoded} is
+     *     {@code null}
+     * @exception IllegalArgumentException if {@code encoded} is
+     *     incorrectly formatted
+     */
+    public PKCS12Attribute(byte[] encoded) {
+        if (encoded == null) {
+            throw new NullPointerException();
+        }
+        this.encoded = encoded.clone();
+
+        try {
+            parse(encoded);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Incorrect format: encoded", e);
+        }
+    }
+
+    /**
+     * Returns the attribute's ASN.1 Object Identifier represented as a
+     * list of dot-separated integers.
+     *
+     * @return the attribute's identifier
+     */
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the attribute's ASN.1 DER-encoded value as a string.
+     * An ASN.1 DER-encoded value is returned in one of the following
+     * {@code String} formats:
+     * <ul>
+     * <li> the DER encoding of a basic ASN.1 type that has a natural
+     *      string representation is returned as the string itself.
+     *      Such types are currently limited to BOOLEAN, INTEGER,
+     *      OBJECT IDENTIFIER, UTCTime, GeneralizedTime and the
+     *      following six ASN.1 string types: UTF8String,
+     *      PrintableString, T61String, IA5String, BMPString and
+     *      GeneralString.
+     * <li> the DER encoding of any other ASN.1 type is not decoded but
+     *      returned as a binary string of colon-separated pairs of
+     *      hexadecimal digits.
+     * </ul>
+     * Multi-valued attributes are represented as a comma-separated
+     * list of values, enclosed in square brackets. See
+     * {@link Arrays#toString(java.lang.Object[])}.
+     *
+     * @return the attribute value's string encoding
+     */
+    @Override
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Returns the attribute's ASN.1 DER encoding.
+     *
+     * @return a clone of the attribute's DER encoding
+     */
+    public byte[] getEncoded() {
+        return encoded.clone();
+    }
+
+    /**
+     * Compares this {@code PKCS12Attribute} and a specified object for
+     * equality.
+     *
+     * @param obj the comparison object
+     *
+     * @return true if {@code obj} is a {@code PKCS12Attribute} and
+     * their DER encodings are equal.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof PKCS12Attribute)) {
+            return false;
+        }
+        return Arrays.equals(encoded, ((PKCS12Attribute) obj).getEncoded());
+    }
+
+    /**
+     * Returns the hashcode for this {@code PKCS12Attribute}.
+     * The hash code is computed from its DER encoding.
+     *
+     * @return the hash code
+     */
+    @Override
+    public int hashCode() {
+        if (hashValue == -1) {
+            Arrays.hashCode(encoded);
+        }