OpenJDK / portola / portola
changeset 16068:b2b3f6569eae
Merge
author | lana |
---|---|
date | Tue, 12 Mar 2013 16:40:22 -0700 |
parents | 7313fd7a4823 36055e4b5305 |
children | 469ad49d6185 |
files | jdk/make/tools/javazic/Makefile jdk/make/tools/src/build/tools/javazic/BackEnd.java jdk/make/tools/src/build/tools/javazic/Checksum.java jdk/make/tools/src/build/tools/javazic/DayOfWeek.java jdk/make/tools/src/build/tools/javazic/Gen.java jdk/make/tools/src/build/tools/javazic/GenDoc.java jdk/make/tools/src/build/tools/javazic/Main.java jdk/make/tools/src/build/tools/javazic/Mappings.java jdk/make/tools/src/build/tools/javazic/Month.java jdk/make/tools/src/build/tools/javazic/Rule.java jdk/make/tools/src/build/tools/javazic/RuleDay.java jdk/make/tools/src/build/tools/javazic/RuleRec.java jdk/make/tools/src/build/tools/javazic/Simple.java jdk/make/tools/src/build/tools/javazic/Time.java jdk/make/tools/src/build/tools/javazic/Timezone.java jdk/make/tools/src/build/tools/javazic/Zone.java jdk/make/tools/src/build/tools/javazic/ZoneRec.java jdk/make/tools/src/build/tools/javazic/Zoneinfo.java jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java jdk/src/share/classes/java/util/function/Block.java jdk/src/share/classes/java/util/function/DoubleBlock.java jdk/src/share/classes/java/util/function/IntBlock.java jdk/src/share/classes/java/util/function/LongBlock.java jdk/test/javax/script/RhinoExceptionTest.java |
diffstat | 269 files changed, 7265 insertions(+), 6530 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/make/common/Release.gmk Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/make/common/Release.gmk Tue Mar 12 16:40:22 2013 -0700 @@ -348,7 +348,6 @@ sun/tools/serialver \ sun/tools/tree \ sun/tools/util \ - sun/security/tools/jarsigner/JarBASE64Encoder.class \ sun/security/tools/jarsigner/Main.class \ sun/security/tools/jarsigner/JarSignerParameters.class \ sun/security/tools/jarsigner/Resources.class \ @@ -576,7 +575,6 @@ $(ECHO) "sun/tools/serialver/" >> $@ $(ECHO) "sun/tools/tree/" >> $@ $(ECHO) "sun/tools/util/" >> $@ - $(ECHO) "sun/security/tools/jarsigner/JarBASE64Encoder.class" >> $@ $(ECHO) "sun/security/tools/jarsigner/Main.class" >> $@ $(ECHO) "sun/security/tools/jarsigner/JarSignerParameters.class" >> $@ $(ECHO) "sun/security/tools/jarsigner/Resources.class" >> $@
--- a/jdk/make/java/java/FILES_java.gmk Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/make/java/java/FILES_java.gmk Tue Mar 12 16:40:22 2013 -0700 @@ -257,6 +257,7 @@ sun/util/calendar/ZoneInfoFile.java \ java/util/TooManyListenersException.java \ java/util/Comparator.java \ + java/util/Comparators.java \ java/util/Collections.java \ java/util/Iterator.java \ java/util/ListIterator.java \
--- a/jdk/make/java/zip/Makefile Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/make/java/zip/Makefile Tue Mar 12 16:40:22 2013 -0700 @@ -68,6 +68,16 @@ FILES_reorder += reorder-$(ARCH) endif endif + +# +# Use mapfile unconditionally (even with fastdebug). +# JDK's internal zlib is incompatible with stock zlib, because the +# size of struct z_stream has been changed, so internal zlib +# implementation must not be allowed to leak outside of libzip.so, +# else you get hard to debug failures with fastdebug jdk when user +# native code includes stock zlib. +# +FILES_m = mapfile-vers include $(BUILDDIR)/common/Mapfile-vers.gmk include $(BUILDDIR)/common/Library.gmk
--- a/jdk/make/launchers/Makefile Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/make/launchers/Makefile Tue Mar 12 16:40:22 2013 -0700 @@ -77,6 +77,7 @@ -J-Dsun.jvm.hotspot.debugger.useWindbgDebugger, ) $(call make-launcher, jps, sun.tools.jps.Jps, , ) $(call make-launcher, jrunscript, com.sun.tools.script.shell.Main, , ) +$(call make-launcher, jjs, jdk.nashorn.tools.Shell, , ) $(call make-launcher, jsadebugd, sun.jvm.hotspot.jdi.SADebugServer, , ) $(call make-launcher, jstack, sun.tools.jstack.JStack, \ -J-Dsun.jvm.hotspot.debugger.useProcDebugger \
--- a/jdk/make/tools/javazic/Makefile Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -# -# 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 javazic tool -# - -BUILDDIR = ../.. -PACKAGE = build.tools.javazic -PRODUCT = javazic -PROGRAM = javazic -include $(BUILDDIR)/common/Defs.gmk - -BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src -BUILDTOOL_MAIN = $(PKGDIR)/Main.java - -# -# Build tool jar rules. -# -include $(BUILDDIR)/common/BuildToolJar.gmk -
--- a/jdk/make/tools/src/build/tools/deps/refs.allowed Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/make/tools/src/build/tools/deps/refs.allowed Tue Mar 12 16:40:22 2013 -0700 @@ -33,8 +33,3 @@ # java.beans.PropertyChangeListener=java.util.logging.LogManager,sun.org.mozilla.javascript.internal.Context,compact1,compact2,compact3 java.beans.PropertyChangeEvent=sun.org.mozilla.javascript.internal.Context,compact3 - -# JFR traces even in builds with JFR disabled -com.oracle.jrockit.jfr.FlightRecorder: com.sun.management.MissionControl, compact3 -com.oracle.jrockit.jfr.management.FlightRecorderMBean: com.sun.management.MissionControl, compact3 -
--- a/jdk/make/tools/src/build/tools/javazic/BackEnd.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -/** - * <code>BackEnd</code> is an abstract base class for a back-end of compiling - * Olson's zoneinfo database and generating Java zoneinfo database. - * - * @since 1.4 - */ -abstract class BackEnd { - - /** - * Receives each zone's TimeZone information which was created by - * {@link Zoneinfo#parse} in class <code>Zoneinfo</code>, - * and processes it. - * - * @param tz Timezone object for each zone - * @return 0 if no error occurred, otherwise 1. - */ - abstract int processZoneinfo(Timezone tz); - - /** - * Receives whole information which is generated by JavaZic's front-end - * in the form of Mapping object and generates all Java zone information - * files. - * - * @param m Mappings object which is generated by - * {@link Main#compile() Main.compile()}. - * @return 0 if no error occurred, otherwise 1. - */ - abstract int generateSrc(Mappings m); - - /** - * Decides which backend class should be used and returns its instance. - * @return an instance of backend class - */ - static BackEnd getBackEnd() { - if (Zoneinfo.isYearForTimeZoneDataSpecified) { - return new Simple(); - } else if (Main.outputDoc) { - return new GenDoc(); - } else { - return new Gen(); - } - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Checksum.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.zip.CRC32; - -/** - * Checksum provides methods for calculating a CRC32 value for a - * transitions table. - * - * @since 1.4 - */ -public class Checksum extends CRC32 -{ - /** - * Updates the CRC32 value from each byte of the given int - * value. The bytes are used in the big endian order. - * @param val the int value - */ - public void update(int val) { - byte[] b = new byte[4]; - b[0] = (byte)((val >>> 24) & 0xff); - b[1] = (byte)((val >>> 16) & 0xff); - b[2] = (byte)((val >>> 8) & 0xff); - b[3] = (byte)(val & 0xff); - update(b); - } - - /** - * Updates the CRC32 value from each byte of the given long - * value. The bytes are used in the big endian order. - * @param val the long value - */ - void update(long val) { - byte[] b = new byte[8]; - b[0] = (byte)((val >>> 56) & 0xff); - b[1] = (byte)((val >>> 48) & 0xff); - b[2] = (byte)((val >>> 40) & 0xff); - b[3] = (byte)((val >>> 32) & 0xff); - b[4] = (byte)((val >>> 24) & 0xff); - b[5] = (byte)((val >>> 16) & 0xff); - b[6] = (byte)((val >>> 8) & 0xff); - b[7] = (byte)(val & 0xff); - update(b); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/DayOfWeek.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -/** - * Day of week enum. - * - * @since 1.6 - */ - -enum DayOfWeek { - SUNDAY("Sun"), - MONDAY("Mon"), - TUESDAY("Tue"), - WEDNESDAY("Wed"), - THURSDAY("Thu"), - FRIDAY("Fri"), - SATURDAY("Sat"); - - private final String abbr; - - private DayOfWeek(String abbr) { - this.abbr = abbr; - } - - String getAbbr() { - return abbr; - } - - int value() { - return ordinal() + 1; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Gen.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +0,0 @@ -/* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.DataOutputStream; -import java.io.RandomAccessFile; -import java.util.List; -import java.util.Map; -import java.util.Set; -import sun.util.calendar.ZoneInfoFile; - -/** - * <code>Gen</code> is one of back-end classes of javazic, and generates - * ZoneInfoMappings and zone-specific file for each zone. - */ -class Gen extends BackEnd { - - /** - * Generates datafile in binary TLV format for each time zone. - * Regarding contents of output files, see {@link ZoneInfoFile}. - * - * @param Timezone - * @return 0 if no errors, or 1 if error occurred. - */ - int processZoneinfo(Timezone tz) { - try { - int size; - String outputDir = Main.getOutputDir(); - String zonefile = ZoneInfoFile.getFileName(tz.getName()); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - - /* If zonefile includes file-separator, it's treated as part of - * pathname. And make directory if necessary. - */ - int index = zonefile.lastIndexOf(File.separatorChar); - if (index != -1) { - outputDir += zonefile.substring(0, index+1); - } - File outD = new File(outputDir); - outD.mkdirs(); - - FileOutputStream fos = - new FileOutputStream(outputDir + zonefile.substring(index+1)); - DataOutputStream dos = new DataOutputStream(fos); - - /* Output Label */ - dos.write(ZoneInfoFile.JAVAZI_LABEL, 0, - ZoneInfoFile.JAVAZI_LABEL.length); - - /* Output Version of ZoneInfoFile */ - dos.writeByte(ZoneInfoFile.JAVAZI_VERSION); - - List<Long> transitions = tz.getTransitions(); - if (transitions != null) { - List<Integer> dstOffsets = tz.getDstOffsets(); - List<Integer> offsets = tz.getOffsets(); - - if ((dstOffsets == null && offsets != null) || - (dstOffsets != null && offsets == null)) { - Main.panic("Data not exist. (dstOffsets or offsets)"); - return 1; - } - - /* Output Transition records */ - dos.writeByte(ZoneInfoFile.TAG_Transition); - size = transitions.size(); - dos.writeShort((size * 8) & 0xFFFF); - int dstoffset; - for (int i = 0; i < size; i++) { - /* if DST offset is 0, this means DST isn't used. - * (NOT: offset's index is 0.) - */ - if ((dstoffset = dstOffsets.get(i).intValue()) == -1) { - dstoffset = 0; - } - - dos.writeLong((transitions.get(i).longValue() << 12) - | (dstoffset << 4) - | offsets.get(i).intValue()); - - } - - /* Output data for GMTOffset */ - List<Integer> gmtoffset = tz.getGmtOffsets(); - dos.writeByte(ZoneInfoFile.TAG_Offset); - size = gmtoffset.size(); - dos.writeShort((size * 4) & 0xFFFF); - for (int i = 0; i < size; i++) { - dos.writeInt(gmtoffset.get(i)); - } - } - - /* Output data for SimpleTimeZone */ - List<RuleRec> stz = tz.getLastRules(); - if (stz != null) { - RuleRec[] rr = new RuleRec[2]; - boolean wall = true; - - rr[0] = stz.get(0); - rr[1] = stz.get(1); - - dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone); - wall = rr[0].getTime().isWall() && rr[1].getTime().isWall(); - if (wall) { - dos.writeShort(32); - } else { - dos.writeShort(40); - } - - for (int i = 0; i < 2; i++) { - dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number - dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone()); - dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt()); - dos.writeInt((int)rr[i].getTime().getTime()); - if (!wall) { - dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1); - } - } - } - - /* Output RawOffset */ - dos.writeByte(ZoneInfoFile.TAG_RawOffset); - dos.writeShort(4); - dos.writeInt(tz.getRawOffset()); - - /* Output willGMTOffsetChange flag */ - if (tz.willGMTOffsetChange()) { - dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange); - dos.writeShort(1); - dos.writeByte(1); - } - - /* Output LastDSTSaving */ - dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving); - dos.writeShort(2); - dos.writeShort(tz.getLastDSTSaving()/1000); - - /* Output checksum */ - dos.writeByte(ZoneInfoFile.TAG_CRC32); - dos.writeShort(4); - dos.writeInt(tz.getCRC32()); - - fos.close(); - dos.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - /** - * Generates ZoneInfoMappings in binary TLV format for each zone. - * Regarding contents of output files, see {@link ZoneInfoFile}. - * - * @param Mappings - * @return 0 if no errors, or 1 if error occurred. - */ - int generateSrc(Mappings map) { - try { - int index; - int block_size; - int roi_size; - long fp; - String outputDir = Main.getOutputDir(); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - - File outD = new File(outputDir); - outD.mkdirs(); - - /* Open ZoneInfoMapping file to write. */ - RandomAccessFile raf = - new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw"); - - /* Whether rawOffsetIndex list exists or not. */ - List<Integer> roi = map.getRawOffsetsIndex(); - if (roi == null) { - Main.panic("Data not exist. (rawOffsetsIndex)"); - return 1; - } - roi_size = roi.size(); - - /* Whether rawOffsetIndexTable list exists or not. */ - List<Set<String>> roit = map.getRawOffsetsIndexTable(); - if (roit == null || roit.size() != roi_size) { - Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size"); - return 1; - } - - /* Output Label */ - raf.write(ZoneInfoFile.JAVAZM_LABEL, 0, - ZoneInfoFile.JAVAZM_LABEL.length); - - /* Output Version */ - raf.writeByte(ZoneInfoFile.JAVAZM_VERSION); - - index = ZoneInfoFile.JAVAZM_LABEL.length + 2; - - /* Output Version of Olson's tzdata */ - byte[] b = Main.getVersionName().getBytes("UTF-8"); - raf.writeByte(ZoneInfoFile.TAG_TZDataVersion); - raf.writeShort((b.length+1) & 0xFFFF); - raf.write(b); - raf.writeByte(0x00); - index += b.length + 4; - - /* Output ID list. */ - raf.writeByte(ZoneInfoFile.TAG_ZoneIDs); - block_size = 2; - raf.writeShort(block_size & 0xFFFF); - short nID = 0; - raf.writeShort(nID & 0xFFFF); - for (int i = 0; i < roi_size; i++) { - for (String key : roit.get(i)) { - byte size = (byte)key.getBytes("UTF-8").length; - raf.writeByte(size & 0xFF); - raf.write(key.getBytes("UTF-8"), 0, size); - block_size += 1 + size; - nID++; - } - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.writeShort(nID & 0xFFFF); - raf.seek(fp); - - /* Output sorted rawOffset list. */ - raf.writeByte(ZoneInfoFile.TAG_RawOffsets); - index += 3 + block_size; - block_size = roi_size * 4; - raf.writeShort(block_size & 0xFFFF); - for (int i = 0; i < roi_size; i++) { - raf.writeInt(Integer.parseInt(roi.get(i).toString())); - } - - /* Output sorted rawOffsetIndex list. */ - raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices); - index += 3 + block_size; - block_size = 0; - raf.writeShort(block_size & 0xFFFF); - int num; - for (int i = 0; i < roi_size; i++) { - num = roit.get(i).size(); - block_size += num; - for (int j = 0; j < num; j++) { - raf.writeByte(i); - } - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.seek(fp); - - /* Whether alias list exists or not. */ - Map<String,String> a = map.getAliases(); - if (a == null) { - Main.panic("Data not exist. (aliases)"); - return 0; - } - - /* Output ID list. */ - raf.writeByte(ZoneInfoFile.TAG_ZoneAliases); - index += 3 + block_size; - block_size = 2; - raf.writeShort(block_size & 0xFFFF); - raf.writeShort(a.size() & 0xFFFF); - for (String key : a.keySet()) { - String alias = a.get(key); - byte key_size = (byte)key.length(); - byte alias_size = (byte)alias.length(); - raf.writeByte(key_size & 0xFF); - raf.write(key.getBytes("UTF-8"), 0, key_size); - raf.writeByte(alias_size & 0xFF); - raf.write(alias.getBytes("UTF-8"), 0, alias_size); - block_size += 2 + key_size + alias_size; - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort((block_size) & 0xFFFF); - raf.seek(fp); - - /* Output the exclude list if it exists. */ - List<String> excludedZones = map.getExcludeList(); - if (excludedZones != null) { - raf.writeByte(ZoneInfoFile.TAG_ExcludedZones); - index += 3 + block_size; - block_size = 2; - raf.writeShort(block_size & 0xFFFF); // place holder - raf.writeShort(excludedZones.size()); // the number of excluded zones - for (String name : excludedZones) { - byte size = (byte) name.length(); - raf.writeByte(size); // byte length - raf.write(name.getBytes("UTF-8"), 0, size); // zone name - block_size += 1 + size; - } - fp = raf.getFilePointer(); - raf.seek(index); - raf.writeShort(block_size & 0xFFFF); - raf.seek(fp); - } - - /* Close ZoneInfoMapping file. */ - raf.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/GenDoc.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,781 +0,0 @@ -/* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -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 sun.util.calendar.ZoneInfoFile; - -/** - * <code>GenDoc</code> is one of back-end classes of javazic, and generates - * index.html and other html files which prints the detailed time zone - * information for each zone. - */ -class GenDoc extends BackEnd { - - private static final String docDir = "doc"; - - private static final String header1 = - "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"" + - "\"http://www.w3.org/TR/REC-html40/frameset.dtd\">\n" + - "<HTML>\n<HEAD>\n<!-- Generated by javazic on "; - private static final String header2 = - "-->\n<TITLE>\n" + - "Java Platform, Standard Edition - TimeZone information based on "; - private static final String header3 = - "-->\n<TITLE>\n" + - "Java Platform, Standard Edition TimeZone - "; - private static final String header4 = - "</TITLE>\n" + - "</HEAD>\n\n"; - - private static final String body1 = - "<BODY BGCOLOR=\"white\">\n"; - private static final String body2 = - "</BODY>\n"; - - private static final String footer = - "</HTML>\n"; - - - // list of time zone name and zonefile name/real time zone name - // e.g. - // key (String) : value (String) - // "America/Denver" : "America/Denver.html" (real time zone) - // "America/Shiprock" : "America/Denver" (alias) - TreeMap<String,String> timezoneList = new TreeMap<String,String>(); - - // list of time zone's display name and time zone name - // e.g. - // key (String) : value (String) - // "Tokyo, Asia" : "Asia/Tokyo" - // "Marengo, Indiana, America" : "America/Indiana/Marengo" - // (aliases included) - TreeMap<String,String> displayNameList = new TreeMap<String,String>(); - - // list of top level regions - // e.g. - // key (String) : value (String) - // "America" : "America.html" - // (including entries in America/Indiana/, America/Kentucky/, ...) - TreeMap<String,String> regionList = new TreeMap<String,String>(); - - // mapping list from zone name to latitude & longitude - // This list is generated from zone.tab. - // e.g. - // key (String) : value (LatitudeAndLongitude object) - // "Asia/Tokyo" : latitude=35.3916, longitude=13.9444 - // (aliases not included) - HashMap<String,LatitudeAndLongitude> mapList = null; - - // SortedMap of zone IDs sorted by their GMT offsets. If zone's GMT - // offset will change in the future, its last known offset is - // used. - SortedMap<Integer, Set<String>> zonesByOffset = new TreeMap<Integer, Set<String>>(); - - /** - * Generates HTML document for each zone. - * @param Timezone - * @return 0 if no errors, or 1 if error occurred. - */ - int processZoneinfo(Timezone tz) { - try { - int size; - int index; - String outputDir = Main.getOutputDir(); - String zonename = tz.getName(); - String zonefile = ZoneInfoFile.getFileName(zonename) + ".html"; - List<RuleRec> stz = tz.getLastRules(); - timezoneList.put(zonename, zonefile); - displayNameList.put(transform(zonename), zonename); - - // Populate zonesByOffset. (Zones that will change their - // GMT offsets are also added to zonesByOffset here.) - int lastKnownOffset = tz.getRawOffset(); - Set<String> set = zonesByOffset.get(lastKnownOffset); - if (set == null) { - set = new TreeSet<String>(); - zonesByOffset.put(lastKnownOffset, set); - } - set.add(zonename); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - outputDir += docDir + File.separatorChar; - - index = zonename.indexOf('/'); - if (index != -1) { - regionList.put(zonename.substring(0, index), - zonename.substring(0, index) + ".html"); - } - - /* If zonefile includes file-separator, it's treated as part of - * pathname. And make directory if necessary. - */ - index = zonefile.lastIndexOf('/'); - if (index != -1) { - zonefile.replace('/', File.separatorChar); - outputDir += zonefile.substring(0, index+1); - } - File outD = new File(outputDir); - outD.mkdirs(); - - /* If mapfile is available, add a link to the appropriate map */ - if ((mapList == null) && (Main.getMapFile() != null)) { - FileReader fr = new FileReader(Main.getMapFile()); - BufferedReader in = new BufferedReader(fr); - mapList = new HashMap<String,LatitudeAndLongitude>(); - String line; - while ((line = in.readLine()) != null) { - // skip blank and comment lines - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - StringTokenizer tokens = new StringTokenizer(line); - String token = tokens.nextToken(); /* We don't use the first token. */ - token = tokens.nextToken(); - LatitudeAndLongitude location = new LatitudeAndLongitude(token); - token = tokens.nextToken(); - mapList.put(token, location); - } - in.close(); - } - - /* Open zoneinfo file to write. */ - FileWriter fw = new FileWriter(outputDir + zonefile.substring(index+1)); - BufferedWriter out = new BufferedWriter(fw); - - out.write(header1 + new Date() + header3 + zonename + header4); - out.write(body1 + "<FONT size=\"+2\"><B>" + zonename + "</B></FONT>"); - LatitudeAndLongitude location = mapList.get(zonename); - if (location != null) { - int deg, min, sec; - - deg = location.getLatDeg(); - min = location.getLatMin(); - sec = location.getLatSec(); - if (deg < 0) { - min = -min; - sec = -sec; - } else if (min < 0) { - sec = -sec; - } - out.write(" " + - "<A HREF=\"http://www.mapquest.com/maps/map.adp?" + - "latlongtype=degrees" + - "&latdeg=" + deg + - "&latmin=" + min + - "&latsec=" + sec); - - deg = location.getLongDeg(); - min = location.getLongMin(); - sec = location.getLongSec(); - if (deg < 0) { - min = -min; - sec = -sec; - } else if (min < 0) { - sec = -sec; - } - out.write("&longdeg=" + deg + - "&longmin=" + min + - "&longsec=" + sec + - "\" target=\"_blank\">[map]</A>"); - } - out.write("\n<P>\n"); - - List<ZoneRec> zone = tz.getZones(); - List<RuleRec> rule = tz.getRules(); - if (rule != null && zone != null) { - out.write("<TABLE BORDER=\"0\" WIDTH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\">\n" + - "<TR>\n" + - "<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\"><BR>" + - "<A HREF=\"#Rules\">Rules</A><BR></TD>\n" + - "<TD BGCOLOR=\"#EEEEFF\" WIDTH=\"50%\" ALIGN=\"CENTER\">" + - "<A HREF=\"#Zone\"><BR>Zone<BR></A></TD>\n" + - "</TR>\n</TABLE>\n"); - } - - /* Output Rule records. */ - if (rule != null) { - size = rule.size(); - out.write("<P>\n<A NAME=\"Rules\">" + - "<FONT SIZE=\"+1\"><B>Rules</B></FONT></A>\n" + - "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" + - "<TR BGCOLOR=\"#CCCCFF\">\n" + - "<TD>NAME</TD><TD>FROM</TD><TD>TO</TD><TD>TYPE</TD>" + - "<TD>IN</TD><TD>ON</TD><TD>AT</TD><TD>SAVE</TD>" + - "<TD>LETTER/S</TD><TD>NOTES</TD>\n</TR>\n"); - for (int i = 0; i < size; i++) { - out.write("<TR BGCOLOR=\"#FFFFFF\">\n"); - StringTokenizer st = new StringTokenizer(rule.get(i).getLine()); - String s; - if (st.hasMoreTokens()) { /* RULE - truncated */ - st.nextToken(); - } - if (st.hasMoreTokens()) { /* NAME */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* FROM */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* TO */ - s = st.nextToken(); - if (s.equals("min") || s.equals("max")) { - out.write("<TD><FONT COLOR=\"red\">" + s + "</FONT></TD>"); - } else { - out.write("<TD>" + s + "</TD>"); - } - } - if (st.hasMoreTokens()) { /* TYPE */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* IN */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* ON */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* AT */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* SAVE */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* LETTER/S */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* NOTES */ - s = st.nextToken(); - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - index = s.indexOf('#'); - out.write("<TD>" + s.substring(index+1) + "</TD>\n"); - } else { - out.write("<TD> </TD>\n"); - } - out.write("</TR>\n"); - } - out.write("</TABLE>\n<P> <P>\n"); - } - - /* Output Zone records. */ - if (zone != null) { - size = zone.size(); - out.write("<P>\n<A NAME=\"Zone\">" + - "<FONT SIZE=\"+1\"><B>Zone</B></FONT></A>\n" + - "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"3\" CELLSPACING=\"0\">\n" + - "<TR BGCOLOR=\"#CCCCFF\">\n<TD>GMTOFF</TD>" + - "<TD>RULES</TD><TD>FORMAT</TD><TD>UNTIL</TD>" + - "<TD>NOTES</TD>\n</TR>\n"); - for (int i = 0; i < size; i++) { - out.write("<TR>\n"); - StringTokenizer st = new StringTokenizer(zone.get(i).getLine()); - String s = st.nextToken(); - if (s.equals("Zone")) { /* NAME */ - s = st.nextToken(); - s = st.nextToken(); - } - out.write("<TD>" + s + "</TD>"); /* GMTOFFSET */ - if (st.hasMoreTokens()) { /* RULES */ - out.write("<TD>" + st.nextToken() + "</TD>"); - } - if (st.hasMoreTokens()) { /* FORMAT */ - s = st.nextToken(); - index = s.indexOf('#'); - if (index != -1) { - if (index != 0) { - out.write("<TD>" + s.substring(0, index-1) + - "</TD>"); /* FORMAT */ - s = s.substring(index+1); - } else { - out.write("<TD> </TD>"); /* FORMAT */ - } - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - out.write("<TD> </TD>"); /* UNTIL */ - out.write("<TD>" + s + "</TD>\n</TR>\n"); /* NOTES */ - continue; - } else { - out.write("<TD>" + s + "</TD>"); /* FORMAT */ - } - } - - if (st.hasMoreTokens()) { /* UNTIL */ - s = st.nextToken(); - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - index = s.indexOf('#'); - if (index != -1) { - if (index != 0) { - out.write("<TD>" + s.substring(0, index-1) + - "</TD>"); /* UNTIL */ - } else { - out.write("<TD> </TD>"); /* UNTIL */ - } - out.write("<TD>" + s.substring(index+1) + - "</TD>\n"); /* NOTES */ - } else { - out.write("<TD>" + s + "</TD>"); /* UNTIL */ - out.write("<TD> </TD>\n"); /* NOTES */ - } - } else { - out.write("<TD> </TD>"); /* UNTIL */ - out.write("<TD> </TD>\n"); /* NOTES */ - } - out.write("</TR>\n"); - } - out.write("</TABLE>\n"); - } - out.write(body2 + footer); - - out.close(); - fw.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - /** - * Generates index.html and other top-level frame files. - * @param Mappings - * @return 0 if no errors, or 1 if error occurred. - */ - int generateSrc(Mappings map) { - try { - int len; - Object o[]; - String outputDir = Main.getOutputDir(); - FileWriter fw1, fw2; - BufferedWriter out1, out2; - - /* Whether alias list exists or not. */ - Map<String,String> a = map.getAliases(); - if (a == null) { - Main.panic("Data not exist. (aliases)"); - return 1; - } - - timezoneList.putAll(a); - - /* If outputDir doesn't end with file-separator, adds it. */ - if (!outputDir.endsWith(File.separator)) { - outputDir += File.separatorChar; - } - outputDir += docDir + File.separatorChar; - - File outD = new File(outputDir); - outD.mkdirs(); - - /* Creates index.html */ - fw1 = new FileWriter(outputDir + "index.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + - "<FRAMESET cols=\"20%,80%\">\n" + - "<FRAMESET rows=\"30%,70%\">\n" + - "<FRAME src=\"overview-frame.html\" name=\"TimeZoneListFrame\">\n" + - "<FRAME src=\"allTimeZone-frame1.html\" name=\"allTimeZoneFrame\">\n" + - "</FRAMESET>" + - "<FRAME src=\"overview-summary.html\" name=\"rightFrame\">\n" + - "</FRAMESET>\n" + - "<NOFRAMES>\n" + - "<H2>\nFrame Alert\n</H2>\n\n" + - "<P>\n\n" + - "This document is designed to be viewed using the frames feature. If you see this\n" + - "message, you are using a non-frame-capable web client.\n" + - "<BR>\n" + - "Link to<A HREF=\"overview-summary.html\">Non-frame version.</A>\n" + - "</NOFRAMES>\n" + footer); - - out1.close(); - fw1.close(); - - - /* Creates overview-frame.html */ - fw1 = new FileWriter(outputDir + "overview-frame.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n" + - "<TD NOWRAP><FONT size=\"+1\">\n" + - "<B>Java<sup><font size=-2>TM</font></sup> Platform<br>Standard Ed.</B></FONT></TD>\n" + - "</TR>\n</TABLE>\n\n" + - "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n<TR>\n<TD NOWRAP>" + - "<P>\n<FONT size=\"+1\">\nAll Time Zones Sorted By:</FONT>\n<BR>\n" + - " <A HREF=\"allTimeZone-frame1.html\" TARGET=\"allTimeZoneFrame\">GMT offsets</A></FONT>\n<BR>\n" + - " <A HREF=\"allTimeZone-frame2.html\" TARGET=\"allTimeZoneFrame\">Zone names</A></FONT>\n<BR>" + - " <A HREF=\"allTimeZone-frame3.html\" TARGET=\"allTimeZoneFrame\">City names</A></FONT>\n" + - "<P>\n<FONT size=\"+1\">\nContinents and Oceans</FONT>\n<BR>\n"); - - for (String regionKey : regionList.keySet()) { - out1.write(" <A HREF=\"" + regionList.get(regionKey) + - "\" TARGET=\"allTimeZoneFrame\">" + regionKey + - "</A><BR>\n"); - - fw2 = new FileWriter(outputDir + regionList.get(regionKey), - false); - out2 = new BufferedWriter(fw2); - - out2.write(header1 + new Date() + header3 + regionKey + - header4 + body1 + "<FONT size=\"+1\"><B>" + - regionKey + "</B></FONT>\n<BR>\n<TABLE>\n<TR>\n<TD>"); - - boolean found = false; - for (String timezoneKey : timezoneList.keySet()) { - int regionIndex = timezoneKey.indexOf('/'); - if (regionIndex == -1 || - !regionKey.equals(timezoneKey.substring(0, regionIndex))) { - if (found) { - break; - } else { - continue; - } - } - - found = true; - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out2.write(timezoneKey + - " (alias for " + "<A HREF=\"" + - timezoneList.get(realName) + - "\" TARGET=\"rightFrame\">" + - realName + "</A>)"); - } else { - out2.write("<A HREF=\"" + timezoneList.get(timezoneKey) + - "\" TARGET=\"rightFrame\">" + timezoneKey + - "</A>"); - } - out2.write("<BR>\n"); - } - out2.write("</TD>\n</TR>\n</TABLE>\n" + body2 + footer); - - out2.close(); - fw2.close(); - } - out1.write("</FONT></TD>\n</TR></TABLE>\n" + body2 + footer); - - out1.close(); - fw1.close(); - - - /* Creates allTimeZone-frame1.html (Sorted by GMT offsets) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame1.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "<FONT size=\"+1\"><B>Sorted by GMT offsets</B></FONT>\n" + - "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + - "<TR>\n<TD NOWRAP>\n"); - - List<Integer> roi = map.getRawOffsetsIndex(); - List<Set<String>> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (Integer offset : zonesByOffset.keySet()) { - int off = roi.get(index); - Set<String> perRO = zonesByOffset.get(offset); - if (offset == off) { - // Merge aliases into zonesByOffset - perRO.addAll(roit.get(index)); - } - index++; - - for (String timezoneKey : perRO) { - out1.write("<TR>\n<TD><FONT SIZE=\"-1\">(" + - Time.toGMTFormat(offset.toString()) + - ")</FONT></TD>\n<TD>"); - - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(timezoneKey + - " (alias for " + "<A HREF=\"" + - timezoneList.get(realName) + - "\" TARGET=\"rightFrame\">" + realName + - "</A>)"); - } else { - out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + - "\" TARGET=\"rightFrame\">" + timezoneKey + - "</A>"); - } - out1.write("</TD>\n</TR>\n"); - } - } - out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); - - out1.close(); - fw1.close(); - - - /* Creates allTimeZone-frame2.html (Sorted by zone names) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame2.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "<FONT size=\"+1\"><B>Sorted by zone names</B></FONT>\n" + - "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + - "<TR>\n<TD NOWRAP>\n"); - o = timezoneList.keySet().toArray(); - len = timezoneList.size(); - for (int i = 0; i < len; i++) { - Object timezoneKey = o[i]; - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(timezoneKey + - " (alias for " + - "<A HREF=\"" + timezoneList.get(realName) + - "\" TARGET=\"rightFrame\">" + realName + - "</A>)"); - } else { - out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + - "\" TARGET=\"rightFrame\">" + timezoneKey + - "</A>"); - } - out1.write("<BR> \n"); - } - out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); - - out1.close(); - fw1.close(); - - /* Creates allTimeZone-frame3.html (Sorted by city names) */ - fw1 = new FileWriter(outputDir + "allTimeZone-frame3.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "<FONT size=\"+1\"><B>Sorted by city names</B></FONT>\n" + - "<BR>\n\n" + "<TABLE BORDER=\"0\" WIDTH=\"100%\">\n" + - "<TR>\n<TD NOWRAP>\n"); - - Set<String> aliasSet = a.keySet(); - len = aliasSet.size(); - String aliasNames[] = aliasSet.toArray(new String[0]); - for (int i = 0; i < len; i++) { - displayNameList.put(transform(aliasNames[i]), - aliasNames[i]); - } - - o = displayNameList.keySet().toArray(); - len = displayNameList.size(); - for (int i = 0; i < len; i++) { - Object displayName = o[i]; - Object timezoneKey = displayNameList.get(o[i]); - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(displayName + - " (alias for " + - "<A HREF=\"" + timezoneList.get(realName) + - "\" TARGET=\"rightFrame\">" + realName + - "</A>)"); - } else { - out1.write("<A HREF=\"" + timezoneList.get(timezoneKey) + - "\" TARGET=\"rightFrame\">" + displayName + - "</A>"); - } - out1.write("<BR> \n"); - } - - out1.write("</FONT></TD>\n</TR>\n</TABLE>\n" + body2 + footer); - - out1.close(); - fw1.close(); - - /* Creates overview-summary.html */ - fw1 = new FileWriter(outputDir + "overview-summary.html", false); - out1 = new BufferedWriter(fw1); - - out1.write(header1 + new Date() + header2 + Main.getVersionName() + - header4 + body1 + - "<p>This is the list of time zones generated from <B>" + - Main.getVersionName() + "</B> for Java Platform, " + - "Standard Edition. The source code can be obtained " + - "from ftp site <a href=\"ftp://elsie.nci.nih.gov/pub/\">" + - "ftp://elsie.nci.nih.gov/pub/</a>. A total of <B>" + - len + - "</B> time zones and aliases are supported " + - "in this edition. For the " + - "format of rules and zones, refer to the zic " + - "(zoneinfo compiler) man page on " + - "Solaris or Linux.</p>\n" + - "<p>Note that the time zone data is not " + - "a public interface of the Java Platform. No " + - "applications should rely on the time zone data of " + - "this document. Time zone names and data " + - "may change without any prior notice.</p>\n" + - body2 + footer); - - out1.close(); - fw1.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } - - String transform(String s) { - int index = s.lastIndexOf("/"); - - /* If the string doesn't include any delimiter, return */ - if (index == -1) { - return s; - } - - int lastIndex = index; - String str = s.substring(index+1); - do { - index = s.substring(0, lastIndex).lastIndexOf('/'); - str += ", " + s.substring(index+1, lastIndex); - lastIndex = index; - } while (index > -1); - - return str; - } - - static class LatitudeAndLongitude { - - private int latDeg, latMin, latSec, longDeg, longMin, longSec; - - LatitudeAndLongitude(String s) { - try { - // First of all, check the string has the correct format: - // either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS - - if (!s.startsWith("+") && !s.startsWith("-")) { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - int index; - if (((index = s.lastIndexOf("+")) <= 0) && - ((index = s.lastIndexOf("-")) <= 0)) { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - - if (index == 5) { - latDeg = Integer.parseInt(s.substring(1, 3)); - latMin = Integer.parseInt(s.substring(3, 5)); - latSec = 0; - } else if (index == 7) { - latDeg = Integer.parseInt(s.substring(1, 3)); - latMin = Integer.parseInt(s.substring(3, 5)); - latSec = Integer.parseInt(s.substring(5, 7)); - } else { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - if (s.startsWith("-")){ - latDeg = -latDeg; - latMin = -latMin; - latSec = -latSec; - } - - int len = s.length(); - if (index == 5 && len == 11) { - longDeg = Integer.parseInt(s.substring(index+1, index+4)); - longMin = Integer.parseInt(s.substring(index+4, index+6)); - longSec = 0; - } else if (index == 7 && len == 15) { - longDeg = Integer.parseInt(s.substring(index+1, index+4)); - longMin = Integer.parseInt(s.substring(index+4, index+6)); - longSec = Integer.parseInt(s.substring(index+6, index+8)); - } else { - Main.warning("Wrong latitude&longitude data: " + s); - return; - } - if (s.charAt(index) == '-'){ - longDeg = -longDeg; - longMin = -longMin; - longSec = -longSec; - } - } catch(Exception e) { - Main.warning("LatitudeAndLongitude() Parse error: " + s); - } - } - - int getLatDeg() { - return latDeg; - } - - int getLatMin() { - return latMin; - } - - int getLatSec() { - return latSec; - } - - int getLongDeg() { - return longDeg; - } - - int getLongMin() { - return longMin; - } - - int getLongSec() { - return longSec; - } - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Main.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.List; - -/** - * Main class for the javazic time zone data compiler. - * - * @since 1.4 - */ -public class Main { - - private static boolean verbose = false; - static boolean outputDoc = false; - - private List<String> ziFiles = new ArrayList<String>(); - private static String zoneNamesFile = null; - private static String versionName = "unknown"; - private static String outputDir = "zoneinfo"; - private static String mapFile = null; - - /** - * Parses the specified arguments and sets up the variables. - * @param argv the arguments - */ - void processArgs(String[] argv) { - for (int i = 0; i < argv.length; i++) { - String arg = argv[i]; - if (arg.startsWith("-h")) { - usage(); - System.exit(0); - } else if (arg.equals("-d")) { - outputDir = argv[++i]; - } else if (arg.equals("-v")) { - verbose = true; - } else if (arg.equals("-V")) { - versionName = argv[++i]; - } else if (arg.equals("-doc")) { - outputDoc = true; - } else if (arg.equals("-map")) { - outputDoc = true; - mapFile = argv[++i]; - } else if (arg.equals("-f")) { - zoneNamesFile = argv[++i]; - } else if (arg.equals("-S")) { - try { - Zoneinfo.setYear(Integer.parseInt(argv[++i])); - } catch (Exception e) { - error("invalid year: " + argv[i]); - usage(); - System.exit(1); - } - } else { - boolean isStartYear = arg.equals("-s"); - if (isStartYear || arg.equals("-e")) { - try { - int year = Integer.parseInt(argv[++i]); - if (isStartYear) { - Zoneinfo.setStartYear(year); - } else { - Zoneinfo.setEndYear(year); - } - } catch (Exception e) { - error("invalid year: " + argv[i]); - usage(); - System.exit(1); - } - } else { - // the rest of args are zoneinfo source files - while (i < argv.length) { - ziFiles.add(argv[i++]); - } - } - } - } - } - - /** - * Parses zoneinfo source files - */ - int compile() { - int nFiles = ziFiles.size(); - int status = 0; - Mappings maps = new Mappings(); - BackEnd backend = BackEnd.getBackEnd(); - - for (int i = 0; i < nFiles; i++) { - Zoneinfo frontend = Zoneinfo.parse(ziFiles.get(i)); - - for (String key : frontend.getZones().keySet()) { - info(key); - - Timezone tz = frontend.phase2(key); - status |= backend.processZoneinfo(tz); - } - - maps.add(frontend); - } - - // special code for dealing with the conflicting name "MET" - Zone.addMET(); - - maps.resolve(); - - status |= backend.generateSrc(maps); - - return status; - } - - public static void main(String[] argv) { - Main zic = new Main(); - - /* - * Parse args - */ - zic.processArgs(argv); - - /* - * Read target zone names - */ - if (zoneNamesFile != null) { - Zone.readZoneNames(zoneNamesFile); - } - - int status = zic.compile(); - - System.exit(status); - } - - void usage() { - System.err.println("Usage: javazic [options] file...\n"+ - " -f namefile file containing zone names\n"+ - " to be generated (ie, generating subset)\n"+ - " -d dir output directory\n"+ - " -v verbose\n"+ - " -V datavers specifies the tzdata version string\n"+ - " (eg, \"tzdata2000g\")"+ - " -S year output only SimleTimeZone data of that year\n"+ - " -s year start year (default: 1900)\n"+ - " -e year end year (default: 2037)\n"+ - " -doc generates HTML documents\n"+ - " -map mapfile generates HTML documents with map information\n"+ - " file... zoneinfo source file(s)"); - } - - /** - * @return the output directory path name - */ - static String getOutputDir() { - return outputDir; - } - - /** - * @return the map file's path and name - */ - static String getMapFile() { - return mapFile; - } - - /** - * Returns the time zone data version string specified by the -V - * option. If it is not specified, "unknown" is returned. - * @return the time zone data version string - */ - static String getVersionName() { - return versionName; - } - - /** - * Prints out the specified fatal error message and calls {@link - * java.lang.System#exit System.exit(1)}. - * @param msg the fatal error message - */ - static void panic(String msg) { - printMessage("fatal error", msg); - System.exit(1); - } - - /** - * Prints out the specified error message. - * @param msg the error message - */ - static void error(String msg) { - printMessage("error", msg); - } - - /** - * Prints out the specified warning message. - * @param msg the warning message - */ - static void warning(String msg) { - printMessage("warning", msg); - } - - /** - * Prints out the informative message. - * @param msg the informative message - */ - static void info(String msg) { - if (verbose) { - printMessage(null, msg); - } - } - - private static void printMessage(String type, String msg) { - if (type != null) { - type += ": "; - } else { - type = ""; - } - System.err.println("javazic: " + type + msg); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Mappings.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2000, 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 - * 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * <code>Mappings</code> generates two Maps and a List which are used by - * javazic BackEnd. - * - * @since 1.4 - */ -class Mappings { - // All aliases specified by Link statements. It's alias name to - // real name mappings. - private Map<String,String> aliases; - - private List<Integer> rawOffsetsIndex; - - private List<Set<String>> rawOffsetsIndexTable; - - // Zone names to be excluded from rawOffset table. Those have GMT - // offsets to change some future time. - private List<String> excludeList; - - /** - * Constructor creates some necessary instances. - */ - Mappings() { - aliases = new TreeMap<String,String>(); - rawOffsetsIndex = new LinkedList<Integer>(); - rawOffsetsIndexTable = new LinkedList<Set<String>>(); - } - - /** - * Generates aliases and rawOffsets tables. - * @param zi a Zoneinfo containing Zones - */ - void add(Zoneinfo zi) { - Map<String,Zone> zones = zi.getZones(); - - for (String zoneName : zones.keySet()) { - Zone zone = zones.get(zoneName); - String zonename = zone.getName(); - int rawOffset = zone.get(zone.size()-1).getGmtOffset(); - - // If the GMT offset of this Zone will change in some - // future time, this Zone is added to the exclude list. - boolean isExcluded = false; - for (int i = 0; i < zone.size(); i++) { - ZoneRec zrec = zone.get(i); - if ((zrec.getGmtOffset() != rawOffset) - && (zrec.getUntilTime(0) > Time.getCurrentTime())) { - if (excludeList == null) { - excludeList = new ArrayList<String>(); - } - excludeList.add(zone.getName()); - isExcluded = true; - break; - } - } - - if (!rawOffsetsIndex.contains(new Integer(rawOffset))) { - // Find the index to insert this raw offset zones - int n = rawOffsetsIndex.size(); - int i; - for (i = 0; i < n; i++) { - if (rawOffsetsIndex.get(i) > rawOffset) { - break; - } - } - rawOffsetsIndex.add(i, rawOffset); - - Set<String> perRawOffset = new TreeSet<String>(); - if (!isExcluded) { - perRawOffset.add(zonename); - } - rawOffsetsIndexTable.add(i, perRawOffset); - } else if (!isExcluded) { - int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); - Set<String> perRawOffset = rawOffsetsIndexTable.get(i); - perRawOffset.add(zonename); - } - } - - Map<String,String> a = zi.getAliases(); - // If there are time zone names which refer to any of the - // excluded zones, add those names to the excluded list. - if (excludeList != null) { - for (String zoneName : a.keySet()) { - String realname = a.get(zoneName); - if (excludeList.contains(realname)) { - excludeList.add(zoneName); - } - } - } - aliases.putAll(a); - } - - /** - * Adds valid aliases to one of per-RawOffset table and removes - * invalid aliases from aliases List. Aliases referring to - * excluded zones are not added to a per-RawOffset table. - */ - void resolve() { - int index = rawOffsetsIndexTable.size(); - List<String> toBeRemoved = new ArrayList<String>(); - for (String key : aliases.keySet()) { - boolean validname = false; - for (int j = 0; j < index; j++) { - Set<String> perRO = rawOffsetsIndexTable.get(j); - boolean isExcluded = (excludeList == null) ? - false : excludeList.contains(key); - - if ((perRO.contains(aliases.get(key)) || isExcluded) - && Zone.isTargetZone(key)) { - validname = true; - if (!isExcluded) { - perRO.add(key); - Main.info("Alias <"+key+"> added to the list."); - } - break; - } - } - - if (!validname) { - Main.info("Alias <"+key+"> removed from the list."); - toBeRemoved.add(key); - } - } - - // Remove zones, if any, from the list. - for (String key : toBeRemoved) { - aliases.remove(key); - } - // Eliminate any alias-to-alias mappings. For example, if - // there are A->B and B->C, A->B is changed to A->C. - Map<String, String> newMap = new HashMap<String, String>(); - for (String key : aliases.keySet()) { - String realid = aliases.get(key); - String leaf = realid; - while (aliases.get(leaf) != null) { - leaf = aliases.get(leaf); - } - if (!realid.equals(leaf)) { - newMap.put(key, leaf); - } - } - aliases.putAll(newMap); - } - - Map<String,String> getAliases() { - return(aliases); - } - - List<Integer> getRawOffsetsIndex() { - return(rawOffsetsIndex); - } - - List<Set<String>> getRawOffsetsIndexTable() { - return(rawOffsetsIndexTable); - } - - List<String> getExcludeList() { - return excludeList; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Month.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Month enum handles month related manipulation. - * - * @since 1.4 - */ -enum Month { - JANUARY("Jan"), - FEBRUARY("Feb"), - MARCH("Mar"), - APRIL("Apr"), - MAY("May"), - JUNE("Jun"), - JULY("Jul"), - AUGUST("Aug"), - SEPTEMBER("Sep"), - OCTOBER("Oct"), - NOVEMBER("Nov"), - DECEMBER("Dec"); - - private final String abbr; - - private static final Map<String,Month> abbreviations - = new HashMap<String,Month>(12); - - static { - for (Month m : Month.values()) { - abbreviations.put(m.abbr, m); - } - } - - private Month(String abbr) { - this.abbr = abbr; - } - - int value() { - return ordinal() + 1; - } - - /** - * Parses the specified string as a month abbreviation. - * @param name the month abbreviation - * @return the Month value - */ - static Month parse(String name) { - Month m = abbreviations.get(name); - if (m != null) { - return m; - } - return null; - } - - /** - * @param month the nunmth number (1-based) - * @return the month name in uppercase of the specified month - */ - static String toString(int month) { - if (month >= JANUARY.value() && month <= DECEMBER.value()) { - return "Calendar." + Month.values()[month - 1]; - } - throw new IllegalArgumentException("wrong month number: " + month); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Rule.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.StringTokenizer; - -/** - * Rule manipulates Rule records. - * - * @since 1.4 - */ -class Rule { - - private List<RuleRec> list; - private String name; - - /** - * Constructs a Rule which consists of a Rule record list. The - * specified name is given to this Rule. - * @param name the Rule name - */ - Rule(String name) { - this.name = name; - list = new ArrayList<RuleRec>(); - } - - /** - * Added a RuleRec to the Rule record list. - */ - void add(RuleRec rec) { - list.add(rec); - } - - /** - * @return the Rule name - */ - String getName() { - return name; - } - - /** - * Gets all rule records that cover the given year. - * - * @param year the year number for which the rule is applicable. - * @return rules in List that are collated in time. If no rule is found, an empty - * List is returned. - */ - List<RuleRec> getRules(int year) { - List<RuleRec> rules = new ArrayList<RuleRec>(3); - for (RuleRec rec : list) { - if (year >= rec.getFromYear() && year <= rec.getToYear()) { - if ((rec.isOdd() && year % 2 == 0) || (rec.isEven() && year % 2 == 1)) - continue; - rules.add(rec); - } - } - int n = rules.size(); - if (n <= 1) { - return rules; - } - if (n == 2) { - RuleRec rec1 = rules.get(0); - RuleRec rec2 = rules.get(1); - if (rec1.getMonthNum() > rec2.getMonthNum()) { - rules.set(0, rec2); - rules.set(1, rec1); - } else if (rec1.getMonthNum() == rec2.getMonthNum()) { - // TODO: it's not accurate to ignore time types (STD, WALL, UTC) - long t1 = Time.getLocalTime(year, rec1.getMonth(), - rec1.getDay(), rec1.getTime().getTime()); - long t2 = Time.getLocalTime(year, rec2.getMonth(), - rec2.getDay(), rec2.getTime().getTime()); - if (t1 > t2) { - rules.set(0, rec2); - rules.set(1, rec1); - } - } - return rules; - } - - final int y = year; - RuleRec[] recs = new RuleRec[rules.size()]; - rules.toArray(recs); - Arrays.sort(recs, new Comparator<RuleRec>() { - public int compare(RuleRec r1, RuleRec r2) { - int n = r1.getMonthNum() - r2.getMonthNum(); - if (n != 0) { - return n; - } - // TODO: it's not accurate to ignore time types (STD, WALL, UTC) - long t1 = Time.getLocalTime(y, r1.getMonth(), - r1.getDay(), r1.getTime().getTime()); - long t2 = Time.getLocalTime(y, r2.getMonth(), - r2.getDay(), r2.getTime().getTime()); - return (int)(t1 - t2); - } - public boolean equals(Object o) { - return this == o; - } - }); - rules.clear(); - for (int i = 0; i < n; i++) { - rules.add(recs[i]); - } - return rules; - } - - /** - * Gets rule records that have either "max" or cover the endYear - * value in its DST schedule. - * - * @return rules that contain last DST schedule. An empty - * ArrayList is returned if no last rules are found. - */ - List<RuleRec> getLastRules() { - RuleRec start = null; - RuleRec end = null; - - for (int i = 0; i < list.size(); i++) { - RuleRec rec = list.get(i); - if (rec.isLastRule()) { - if (rec.getSave() > 0) { - start = rec; - } else { - end = rec; - } - } - } - if (start == null || end == null) { - int endYear = Zoneinfo.getEndYear(); - for (int i = 0; i < list.size(); i++) { - RuleRec rec = list.get(i); - if (endYear >= rec.getFromYear() && endYear <= rec.getToYear()) { - if (start == null && rec.getSave() > 0) { - start = rec; - } else { - if (end == null && rec.getSave() == 0) { - end = rec; - } - } - } - } - } - - List<RuleRec> r = new ArrayList<RuleRec>(2); - if (start == null || end == null) { - if (start != null || end != null) { - Main.warning("found last rules for "+name+" inconsistent."); - } - return r; - } - - r.add(start); - r.add(end); - return r; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/RuleDay.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * RuleDay class represents the value of the "ON" field. The day of - * week values start from 1 following the {@link java.util.Calendar} - * convention. - * - * @since 1.4 - */ -class RuleDay { - private static final Map<String,DayOfWeek> abbreviations = new HashMap<String,DayOfWeek>(7); - static { - for (DayOfWeek day : DayOfWeek.values()) { - abbreviations.put(day.getAbbr(), day); - } - } - - private String dayName = null; - private DayOfWeek dow; - private boolean lastOne = false; - private int soonerOrLater = 0; - private int thanDayOfMonth; // day of month (e.g., 8 for "Sun>=8") - - RuleDay() { - } - - RuleDay(int day) { - thanDayOfMonth = day; - } - - int getDay() { - return thanDayOfMonth; - } - - /** - * @return the day of week value (1-based) - */ - int getDayOfWeekNum() { - return dow.value(); - } - - /** - * @return true if this rule day represents the last day of - * week. (e.g., lastSun). - */ - boolean isLast() { - return lastOne; - } - - /** - * @return true if this rule day represents the day of week on or - * later than (after) the {@link #getDay}. (e.g., Sun>=1) - */ - boolean isLater() { - return soonerOrLater > 0; - } - - /** - * @return true if this rule day represents the day of week on or - * earlier than (before) the {@link #getDay}. (e.g., Sun<=15) - */ - boolean isEarlier() { - return soonerOrLater < 0; - } - - /** - * @return true if this rule day represents an exact day. - */ - boolean isExact() { - return soonerOrLater == 0; - } - - /** - * Parses the "ON" field and constructs a RuleDay. - * @param day an "ON" field string (e.g., "Sun>=1") - * @return a RuleDay representing the given "ON" field - */ - static RuleDay parse(String day) { - RuleDay d = new RuleDay(); - if (day.startsWith("last")) { - d.lastOne = true; - d.dayName = day.substring(4); - d.dow = getDOW(d.dayName); - } else { - int index; - if ((index = day.indexOf(">=")) != -1) { - d.dayName = day.substring(0, index); - d.dow = getDOW(d.dayName); - d.soonerOrLater = 1; // greater or equal - d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); - } else if ((index = day.indexOf("<=")) != -1) { - d.dayName = day.substring(0, index); - d.dow = getDOW(d.dayName); - d.soonerOrLater = -1; // less or equal - d.thanDayOfMonth = Integer.parseInt(day.substring(index+2)); - } else { - // it should be an integer value. - d.thanDayOfMonth = Integer.parseInt(day); - } - } - return d; - } - - /** - * Converts this RuleDay to the SimpleTimeZone day rule. - * @return the converted SimpleTimeZone day rule - */ - int getDayForSimpleTimeZone() { - if (isLast()) { - return -1; - } - return isEarlier() ? -getDay() : getDay(); - } - - /** - * Converts this RuleDay to the SimpleTimeZone day-of-week rule. - * @return the SimpleTimeZone day-of-week rule value - */ - int getDayOfWeekForSimpleTimeZoneInt() { - if (isEarlier() || isLater()) { - return -getDayOfWeekNum(); - } - return isLast() ? getDayOfWeekNum() : 0; - } - - /** - * @return the string representation of the {@link - * #getDayOfWeekForSimpleTimeZoneInt} value - */ - String getDayOfWeekForSimpleTimeZone() { - int d = getDayOfWeekForSimpleTimeZoneInt(); - if (d == 0) { - return "0"; - } - String sign = ""; - if (d < 0) { - sign = "-"; - d = -d; - } - return sign + toString(d); - } - - private static DayOfWeek getDOW(String abbr) { - return abbreviations.get(abbr); - } - - /** - * Converts the specified day of week value to the day-of-week - * name defined in {@link java.util.Calenda}. - * @param dow 1-based day of week value - * @return the Calendar day of week name with "Calendar." prefix. - * @throws IllegalArgumentException if the specified dow value is out of range. - */ - static String toString(int dow) { - if (dow >= DayOfWeek.SUNDAY.value() && dow <= DayOfWeek.SATURDAY.value()) { - return "Calendar." + DayOfWeek.values()[dow - 1]; - } - throw new IllegalArgumentException("wrong Day_of_Week number: " + dow); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/RuleRec.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.StringTokenizer; - -/** - * RuleRec class represents one record of the Rule set. - * - * @since 1.4 - */ -class RuleRec { - private int fromYear; - private int toYear; - private String type; - private Month inMonth; - private RuleDay onDay; - private Time atTime; - private int save; - private String letters; - private String line; - private boolean isLastRule; - - int getFromYear() { - return fromYear; - } - - int getToYear() { - return toYear; - } - - Month getMonth() { - return inMonth; - } - - int getMonthNum() { - return inMonth.value(); - } - - RuleDay getDay() { - return onDay; - } - - Time getTime() { - return atTime; - } - - int getSave() { - return save; - } - - String getLine() { - return line; - } - - /** - * Sets the line from the text file. - * @param line the text of the line - */ - void setLine(String line) { - this.line = line; - } - - /** - * @return true if the rule type is "odd". - */ - boolean isOdd() { - return "odd".equals(type); - } - - /** - * @return true if the rule type is "even". - */ - boolean isEven() { - return "even".equals(type); - } - - /** - * Determines if this rule record is the last DST schedule rule. - * - * @return true if this rule record has "max" as TO (year). - */ - boolean isLastRule() { - return isLastRule; - } - - /** - * Determines if the unadjusted until time of the specified ZoneRec - * is the same as the transition time of this rule in the same - * year as the ZoneRec until year. - * - * @param zrec ZoneRec to compare to - * @param save the amount of daylight saving in milliseconds - * @param gmtOffset the GMT offset value in milliseconds - * @return true if the unadjusted until time is the same as rule's - * transition time. - */ - boolean isSameTransition(ZoneRec zrec, int save, int gmtOffset) { - long until, transition; - - if (zrec.getUntilTime().getType() != atTime.getType()) { - until = zrec.getLocalUntilTime(save, gmtOffset); - transition = Time.getLocalTime(zrec.getUntilYear(), - getMonth(), - getDay(), - save, - gmtOffset, - atTime); - } else { - until = zrec.getLocalUntilTime(); - transition = Time.getLocalTime(zrec.getUntilYear(), - getMonth(), - getDay(), - atTime.getTime()); - } - - return until == transition; - } - - /** - * Parses a Rule line and returns a RuleRec object. - * - * @param tokens a StringTokenizer object that should contain a - * token for the "FROM" field and the rest. - * @return a RuleRec object. - */ - static RuleRec parse(StringTokenizer tokens) { - RuleRec rec = new RuleRec(); - try { - // FROM - String token = tokens.nextToken(); - try { - rec.fromYear = Integer.parseInt(token); - } catch (NumberFormatException e) { - // it's not integer - if ("min".equals(token) || "minimum".equals(token)) { - rec.fromYear = Zoneinfo.getMinYear(); - } else if ("max".equals(token) || "maximum".equals(token)) { - rec.fromYear = Zoneinfo.getMaxYear(); - } else { - Main.panic("invalid year value: "+token); - } - } - - // TO - token = tokens.nextToken(); - rec.isLastRule = false; - try { - rec.toYear = Integer.parseInt(token); - } catch (NumberFormatException e) { - // it's not integer - if ("min".equals(token) || "minimum".equals(token)) { - rec.fromYear = Zoneinfo.getMinYear(); - } else if ("max".equals(token) || "maximum".equals(token)) { - rec.toYear = Integer.MAX_VALUE; - rec.isLastRule = true; - } else if ("only".equals(token)) { - rec.toYear = rec.fromYear; - } else { - Main.panic("invalid year value: "+token); - } - } - - // TYPE - rec.type = tokens.nextToken(); - - // IN - rec.inMonth = Month.parse(tokens.nextToken()); - - // ON - rec.onDay = RuleDay.parse(tokens.nextToken()); - - // AT - rec.atTime = Time.parse(tokens.nextToken()); - - // SAVE - rec.save = (int) Time.parse(tokens.nextToken()).getTime(); - - // LETTER/S - rec.letters = tokens.nextToken(); - } catch (Exception e) { - e.printStackTrace(); - } - return rec; - } - - /** - * Calculates the transition time of the given year under this rule. - * @param year the year value - * @param gmtOffset the GMT offset value in milliseconds - * @param save the amount of daylight save time - * @return the transition time in milliseconds of the given year in UTC. - */ - long getTransitionTime(int year, int gmtOffset, int save) { - long time = Time.getLocalTime(year, getMonth(), - getDay(), atTime.getTime()); - if (atTime.isSTD()) { - time -= gmtOffset; - } else if (atTime.isWall()) { - time -= gmtOffset + save; - } - return time; - } - - private static int getInt(StringTokenizer tokens) { - String token = tokens.nextToken(); - return Integer.parseInt(token); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Simple.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; - -/** - * <code>Simple</code> generates TimeZoneData, which had been used as internal - * data of TimeZone before J2SDK1.3. - * Since J2SDK1.4 doesn't need TimeZoneData, this class is for maintenance - * of old JDK release. - */ -class Simple extends BackEnd { - - /** - * Zone records which are applied for given year. - */ - private static Map<String,ZoneRec> lastZoneRecs = new HashMap<>(); - - /** - * Rule records which are applied for given year. - */ - private static Map<String,List<RuleRec>> lastRules = new TreeMap<>(); - - /** - * zone IDs sorted by their GMT offsets. If zone's GMT - * offset will change in the future, its last known offset is - * used. - */ - private SortedMap<Integer, Set<String>> zonesByOffset = new TreeMap<>(); - - /** - * Sets last Rule records and Zone records for given timezone to - * each Map. - * - * @param tz Timezone object for each zone - * @return always 0 - */ - int processZoneinfo(Timezone tz) { - String zonename = tz.getName(); - - lastRules.put(zonename, tz.getLastRules()); - lastZoneRecs.put(zonename, tz.getLastZoneRec()); - - // Populate zonesByOffset. (Zones that will change their - // GMT offsets are also added to zonesByOffset here.) - int lastKnownOffset = tz.getRawOffset(); - Set<String> set = zonesByOffset.get(lastKnownOffset); - if (set == null) { - set = new TreeSet<>(); - zonesByOffset.put(lastKnownOffset, set); - } - set.add(zonename); - - return 0; - } - - /** - * Generates TimeZoneData to output SimpleTimeZone data. - * @param map Mappings object which is generated by {@link Main#compile}. - * @return 0 if no error occurred, otherwise 1. - */ - int generateSrc(Mappings map) { - try { - File outD = new File(Main.getOutputDir()); - outD.mkdirs(); - - FileWriter fw = - new FileWriter(new File(outD, "TimeZoneData.java"), false); - BufferedWriter out = new BufferedWriter(fw); - - out.write("import java.util.SimpleTimeZone;\n\n"); - out.write(" static SimpleTimeZone zones[] = {\n"); - - Map<String,String> a = map.getAliases(); - List<Integer> roi = map.getRawOffsetsIndex(); - List<Set<String>> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (int offset : zonesByOffset.keySet()) { - int o = roi.get(index); - Set<String> set = zonesByOffset.get(offset); - if (offset == o) { - // Merge aliases into zonesByOffset - set.addAll(roit.get(index)); - } - index++; - - for (String key : set) { - ZoneRec zrec; - String realname; - List<RuleRec> stz; - if ((realname = a.get(key)) != null) { - // if this alias is not targeted, ignore it. - if (!Zone.isTargetZone(key)) { - continue; - } - stz = lastRules.get(realname); - zrec = lastZoneRecs.get(realname); - } else { - stz = lastRules.get(key); - zrec = lastZoneRecs.get(key); - } - - out.write("\t//--------------------------------------------------------------------\n"); - String s = Time.toFormedString(offset); - out.write("\tnew SimpleTimeZone(" + - Time.toFormedString(offset) + ", \"" + key + "\""); - if (realname != null) { - out.write(" /* " + realname + " */"); - } - - if (stz == null) { - out.write("),\n"); - } else { - RuleRec rr0 = stz.get(0); - RuleRec rr1 = stz.get(1); - - out.write(",\n\t " + Month.toString(rr0.getMonthNum()) + - ", " + rr0.getDay().getDayForSimpleTimeZone() + ", " + - rr0.getDay().getDayOfWeekForSimpleTimeZone() + ", " + - Time.toFormedString((int)rr0.getTime().getTime()) + ", " + - rr0.getTime().getTypeForSimpleTimeZone() + ",\n" + - - "\t " + Month.toString(rr1.getMonthNum()) + ", " + - rr1.getDay().getDayForSimpleTimeZone() + ", " + - rr1.getDay().getDayOfWeekForSimpleTimeZone() + ", " + - Time.toFormedString((int)rr1.getTime().getTime())+ ", " + - rr1.getTime().getTypeForSimpleTimeZone() + ",\n" + - - "\t " + Time.toFormedString(rr0.getSave()) + "),\n"); - - out.write("\t// " + rr0.getLine() + "\n"); - out.write("\t// " + rr1.getLine() + "\n"); - } - - String zline = zrec.getLine(); - if (zline.indexOf("Zone") == -1) { - zline = "Zone " + key + "\t" + zline.trim(); - } - out.write("\t// " + zline + "\n"); - } - } - out.write(" };\n"); - - out.close(); - fw.close(); - } catch(IOException e) { - Main.panic("IO error: "+e.getMessage()); - return 1; - } - - return 0; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Time.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.Locale; -import sun.util.calendar.CalendarDate; -import sun.util.calendar.CalendarSystem; -import sun.util.calendar.Gregorian; - -/** - * Time class represents the "AT" field and other time related information. - * - * @since 1.4 - */ -class Time { - - static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); - - // type is wall clock time - private static final int WALL = 1; - - // type is standard time - private static final int STD = 2; - - // type is UTC - private static final int UTC = 3; - - // type of representing time - private int type; - - /** - * Time from the EPOCH in milliseconds - */ - private long time; - - /** - * Current time in milliseconds - */ - private static final long currentTime = System.currentTimeMillis(); - - Time() { - time = 0L; - } - - Time(long time) { - this.time = time; - } - - void setType(int type) { - this.type = type; - } - - long getTime() { - return time; - } - - int getType() { - return type; - } - - static long getCurrentTime() { - return currentTime; - } - - /** - * @return true if the time is represented in wall-clock time. - */ - boolean isWall() { - return type == WALL; - } - - /** - * @return true if the time is represented in standard time. - */ - boolean isSTD() { - return type == STD; - } - - /** - * @return true if the time is represented in UTC time. - */ - boolean isUTC() { - return type == UTC; - } - - /** - * Converts the type to a string that represents the type in the - * SimpleTimeZone time mode. (e.g., "SimpleTimeZone.WALL_TIME"). - * @return the converted string or null if the type is undefined. - */ - String getTypeForSimpleTimeZone() { - String stz = "SimpleTimeZone."; - if (isWall()) { - return stz+"WALL_TIME"; - } - else if (isSTD()) { - return stz+"STANDARD_TIME"; - } - else if (isUTC()) { - return stz+"UTC_TIME"; - } - else { - return null; - } - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param save the amount of daylight time in milliseconds - * @param gmtOffset the GMT offset in milliseconds - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, int save, - int gmtOffset, Time time) { - long t = time.getTime(); - - if (time.isSTD()) - t = time.getTime() + save; - else if (time.isUTC()) - t = time.getTime() + save + gmtOffset; - - return getLocalTime(year, month, day, t); - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day value - * @param time the time of the day in milliseconds - * @return local time - */ - static long getLocalTime(int year, Month month, int day, long time) { - CalendarDate date = gcal.newCalendarDate(null); - date.setDate(year, month.value(), day); - long millis = gcal.getTime(date); - return millis + time; - } - - /** - * Equivalent to <code>getLocalTime(year, month, day, (long)time)</code>. - * @param year the year value - * @param month the Month value - * @param day the day value - * @param time the time of the day in milliseconds - * @return local time - */ - static long getLocalTime(int year, Month month, int day, int time) { - return getLocalTime(year, month, day, (long)time); - } - - /** - * Equivalent to {@link #getLocalTime(int, Month, RuleDay, int) - * getLocalTime(year, month, day, (int) time)}. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, long time) { - return getLocalTime(year, month, day, (int) time); - } - - /** - * Converts the given Gregorian calendar field values to local time. - * Local time is represented by the amount of milliseconds from - * January 1, 1970 0:00 GMT. - * @param year the year value - * @param month the Month value - * @param day the day represented by {@link RuleDay} - * @param time the time of the day represented by {@link Time} - * @return local time - */ - static long getLocalTime(int year, Month month, RuleDay day, int time) { - CalendarDate cdate = gcal.newCalendarDate(null); - int monthValue = month.value(); - - if (day.isLast()) { // e.g., "lastSun" - cdate.setDate(year, monthValue, 1); - cdate.setDayOfMonth(gcal.getMonthLength(cdate)); - cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); - } else if (day.isLater()) { // e.g., "Sun>=1" - cdate.setDate(year, monthValue, day.getDay()); - cdate = gcal.getNthDayOfWeek(1, day.getDayOfWeekNum(), cdate); - } else if (day.isExact()) { - cdate.setDate(year, monthValue, day.getDay()); - } else if (day.isEarlier()) { // e.g., "Sun<=15" - cdate.setDate(year, monthValue, day.getDay()); - cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); - } else { - Main.panic("invalid day type: " + day); - } - return gcal.getTime(cdate) + time; - } - - /** - * Parses the given "AT" field and constructs a Time object. - * @param the "AT" field string - * @return the Time object - */ - static Time parse(String time) { - int sign; - int index = 0; - Time tm; - - if (time.charAt(0) == '-') { - sign = -1; - index++; - } else { - sign = 1; - } - int val = 0; - int num = 0; - int countDelim = 0; - while (index < time.length()) { - char c = time.charAt(index++); - if (c == ':') { - val = val * 60 + num; - countDelim++; - num = 0; - continue; - } - int d = Character.digit(c, 10); - if (d == -1) { - --index; - break; - } - num = num * 10 + d; - } - val = val * 60 + num; - // convert val to second - for (; countDelim < 2; countDelim++) { - val *= 60; - } - tm = new Time((long)val * 1000 * sign); - if (index < time.length()) { - char c = time.charAt(index++); - if (c == 's') { - tm.setType(Time.STD); - } else if (c == 'u' || c == 'g' || c == 'z') { - tm.setType(Time.UTC); - } else if (c == 'w') { - tm.setType(Time.WALL); - } else { - Main.panic("unknown time mode: "+c); - } - } else { - tm.setType(Time.WALL); - } - return tm; - } - - /** - * Converts the given milliseconds string to a "[+-]hh:mm" string. - * @param ms the milliseconds string - */ - static String toGMTFormat(String ms) { - long sec = Long.parseLong(ms) / 1000; - char sign; - if (sec < 0) { - sign = '-'; - sec = -sec; - } else { - sign = '+'; - } - return String.format((Locale)null, "%c%02d:%02d", - sign, sec/3600, (sec%3600)/60); - } - - /** - * Converts the given millisecond value to a string for a - * SimpleTimeZone parameter. - * @param ms the millisecond value - * @return the string in a human readable form - */ - static String toFormedString(int ms) { - StringBuilder s = new StringBuilder(); - boolean minus = false; - - if (ms < 0) { - s.append("-"); - minus = true; - ms = -ms; - } else if (ms == 0) { - return "0"; - } - - int hour = ms / (60 * 60 * 1000); - ms %= (60 * 60 * 1000); - int minute = ms / (60 * 1000); - - if (hour != 0) { - if (minus && minute != 0) { - s.append("("); - } - s.append(Integer.toString(hour) + "*ONE_HOUR"); - } - - if (minute != 0) { - if (hour != 0) { - s.append("+"); - } - s.append(Integer.toString(minute) + "*ONE_MINUTE"); - if (minus && hour != 0) { - s.append(")"); - } - } - - return s.toString(); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Timezone.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.util.ArrayList; -import java.util.List; - -/** - * Timezone represents all information of a single point of time to - * generate its time zone database. - * - * @since 1.4 - */ -class Timezone { - /** - * zone name of this time zone - */ - private String name; - - /** - * transition time values in UTC (millisecond) - */ - private List<Long> transitions; - - /** - * All offset values in millisecond - * @see sun.util.calendar.ZoneInfo - */ - private List<Integer> offsets; - - /** - * Indices of GMT offset values (both raw and raw+saving) - * at transitions - */ - private List<Integer> gmtOffsets; - - /** - * Indices of regular or "direct" saving time values - * at transitions - */ - private List<Integer> dstOffsets; - - /** - * Zone records of this time zone - */ - private List<ZoneRec> usedZoneRecs; - - /** - * Rule records referred to by this time zone - */ - private List<RuleRec> usedRuleRecs; - - /** - * Type of DST rules in this time zone - */ - private int dstType; - static final int UNDEF_DST = 0; // DST type not set yet - static final int NO_DST = 1; // never observed DST - static final int LAST_DST = 2; // last rule ends in DST (all year round DST-only) - static final int X_DST = 3; // used to observe DST - static final int DST = 4; // observing DST regularly - - /** - * Raw GMT offset of this time zone in the last rule - */ - private int rawOffset; - - /** - * The CRC32 value of the transitions data - */ - private int crc32; - - /** - * The last ZoneRec - */ - private ZoneRec lastZoneRec; - - /** - * The last DST rules. lastRules[0] is the DST start - * rule. lastRules[1] is the DST end rules. - */ - private List<RuleRec> lastRules; - - /** - * The amount of DST saving value (millisecond) in the last DST - * rule. - */ - private int lastSaving; - - /** - * true if the raw offset will change in the future time. - */ - private boolean willRawOffsetChange = false; - - - /** - * Constracts a Timezone object with the given zone name. - * @param name the zone name - */ - Timezone(String name) { - this.name = name; - } - - /** - * @return the number of transitions - */ - int getNTransitions() { - if (transitions == null) { - return 0; - } - return transitions.size(); - } - - /** - * @return the zone name - */ - String getName() { - return name; - } - - /** - * Returns the list of all rule records that have been referred to - * by this time zone. - * @return the rule records list - */ - List<RuleRec> getRules() { - return usedRuleRecs; - } - - /** - * Returns the list of all zone records that have been referred to - * by this time zone. - * @return the zone records list - */ - List<ZoneRec> getZones() { - return usedZoneRecs; - } - - /** - * @return the transition table (list) - */ - List<Long> getTransitions() { - return transitions; - } - - /** - * @return the offsets list - */ - List<Integer> getOffsets() { - return offsets; - } - - /** - * @return the DST saving offsets list - */ - List<Integer> getDstOffsets() { - return dstOffsets; - } - - /** - * @return the GMT offsets list - */ - List<Integer> getGmtOffsets() { - return gmtOffsets; - } - - /** - * @return the checksum (crc32) value of the trasition table - */ - int getCRC32() { - return crc32; - } - - /** - * @return true if the GMT offset of this time zone would change - * after the time zone database has been generated, false, otherwise. - */ - boolean willGMTOffsetChange() { - return willRawOffsetChange; - } - - /** - * @return the last known GMT offset value in milliseconds - */ - int getRawOffset() { - return rawOffset; - } - - /** - * Sets time zone's GMT offset to <code>offset</code>. - * @param offset the GMT offset value in milliseconds - */ - void setRawOffset(int offset) { - rawOffset = offset; - } - - /** - * Sets time zone's GMT offset value to <code>offset</code>. If - * <code>startTime</code> is future time, then the {@link - * #willRawOffsetChange} value is set to true. - * @param offset the GMT offset value in milliseconds - * @param startTime the UTC time at which the GMT offset is in effective - */ - void setRawOffset(int offset, long startTime) { - // if this rawOffset is for the future time, let the run-time - // look for the current GMT offset. - if (startTime > Time.getCurrentTime()) { - willRawOffsetChange = true; - } - setRawOffset(offset); - } - - /** - * Adds the specified transition information to the end of the transition table. - * @param time the UTC time at which this transition happens - * @param offset the total amount of the offset from GMT in milliseconds - * @param dstOffset the amount of time in milliseconds saved at this transition - */ - void addTransition(long time, int offset, int dstOffset) { - if (transitions == null) { - transitions = new ArrayList<Long>(); - offsets = new ArrayList<Integer>(); - dstOffsets = new ArrayList<Integer>(); - } - transitions.add(time); - offsets.add(offset); - dstOffsets.add(dstOffset); - } - - /** - * Sets the type of historical daylight saving time - * observation. For example, China used to observed daylight - * saving time, but it no longer does. Then, X_DST is set to the - * China time zone. - * @param type the type of daylight saving time - */ - void setDSTType(int type) { - dstType = type; - } - - /** - * @return the type of historical daylight saving time - * observation. - */ - int getDSTType() { - return dstType; - } - - /** - * Adds the specified zone record to the zone records list. - * @param rec the zone record - */ - void addUsedRec(ZoneRec rec) { - if (usedZoneRecs == null) { - usedZoneRecs = new ArrayList<ZoneRec>(); - } - usedZoneRecs.add(rec); - } - - /** - * Adds the specified rule record to the rule records list. - * @param rec the rule record - */ - void addUsedRec(RuleRec rec) { - if (usedRuleRecs == null) { - usedRuleRecs = new ArrayList<RuleRec>(); - } - // if the last used rec is the same as the given rec, avoid - // putting the same rule. - int n = usedRuleRecs.size(); - for (int i = 0; i < n; i++) { - if (usedRuleRecs.get(i).equals(rec)) { - return; - } - } - usedRuleRecs.add(rec); - } - - /** - * Sets the last zone record for this time zone. - * @param the last zone record - */ - void setLastZoneRec(ZoneRec zrec) { - lastZoneRec = zrec; - } - - /** - * @return the last zone record for this time zone. - */ - ZoneRec getLastZoneRec() { - return lastZoneRec; - } - - /** - * Sets the last rule records for this time zone. Those are used - * for generating SimpleTimeZone parameters. - * @param rules the last rule records - */ - void setLastRules(List<RuleRec> rules) { - int n = rules.size(); - if (n > 0) { - lastRules = rules; - RuleRec rec = rules.get(0); - int offset = rec.getSave(); - if (offset > 0) { - setLastDSTSaving(offset); - } else { - System.err.println("\t No DST starting rule in the last rules."); - } - } - } - - /** - * @return the last rule records for this time zone. - */ - List<RuleRec> getLastRules() { - return lastRules; - } - - /** - * Sets the last daylight saving amount. - * @param the daylight saving amount - */ - void setLastDSTSaving(int offset) { - lastSaving = offset; - } - - /** - * @return the last daylight saving amount. - */ - int getLastDSTSaving() { - return lastSaving; - } - - /** - * Calculates the CRC32 value from the transition table and sets - * the value to <code>crc32</code>. - */ - void checksum() { - if (transitions == null) { - crc32 = 0; - return; - } - Checksum sum = new Checksum(); - for (int i = 0; i < transitions.size(); i++) { - int offset = offsets.get(i); - // adjust back to make the transition in local time - sum.update(transitions.get(i) + offset); - sum.update(offset); - sum.update(dstOffsets.get(i)); - } - crc32 = (int)sum.getValue(); - } - - /** - * Removes unnecessary transitions for Java time zone support. - */ - void optimize() { - // if there is only one offset, delete all transitions. This - // could happen if only time zone abbreviations changed. - if (gmtOffsets.size() == 1) { - transitions = null; - usedRuleRecs = null; - setDSTType(NO_DST); - return; - } - for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one - if (transitions.get(i) == transitions.get(i+1)) { - transitions.remove(i); - offsets.remove(i); - dstOffsets.remove(i); - i--; - } - } - - for (int i = 0; i < (transitions.size() - 2); i++) { // don't remove the last one - if (offsets.get(i) == offsets.get(i+1) - && dstOffsets.get(i) == dstOffsets.get(i+1)) { - transitions.remove(i+1); - offsets.remove(i+1); - dstOffsets.remove(i+1); - i--; - } - } - } - - /** - * Stores the specified offset value from GMT in the GMT offsets - * table and returns its index. The offset value includes the base - * GMT offset and any additional daylight saving if applicable. If - * the same value as the specified offset is already in the table, - * its index is returned. - * @param offset the offset value in milliseconds - * @return the index to the offset value in the GMT offsets table. - */ - int getOffsetIndex(int offset) { - return getOffsetIndex(offset, 0); - } - - /** - * Stores the specified daylight saving value in the GMT offsets - * table and returns its index. If the same value as the specified - * offset is already in the table, its index is returned. If 0 is - * specified, it's not stored in the table and -1 is returned. - * @param offset the offset value in milliseconds - * @return the index to the specified offset value in the GMT - * offsets table, or -1 if 0 is specified. - */ - int getDstOffsetIndex(int offset) { - if (offset == 0) { - return -1; - } - return getOffsetIndex(offset, 1); - } - - private int getOffsetIndex(int offset, int index) { - if (gmtOffsets == null) { - gmtOffsets = new ArrayList<Integer>(); - } - for (int i = index; i < gmtOffsets.size(); i++) { - if (offset == gmtOffsets.get(i)) { - return i; - } - } - if (gmtOffsets.size() < index) { - gmtOffsets.add(0); - } - gmtOffsets.add(offset); - return gmtOffsets.size() - 1; - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Zone.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; - -/** - * Zone holds information corresponding to a "Zone" part of a time - * zone definition file. - * - * @since 1.4 - */ -class Zone { - // zone name (e.g., "America/Los_Angeles") - private String name; - - // zone records - private List<ZoneRec> list; - - // target zone names for this compilation - private static Set<String> targetZones; - - /** - * Constructs a Zone with the specified zone name. - * @param name the zone name - */ - Zone(String name) { - this.name = name; - list = new ArrayList<ZoneRec>(); - } - - /** - * Reads time zone names to be generated, called "target zone - * name", from the specified text file and creats an internal hash - * table to keep those names. It's assumed that one text line - * contains a zone name or comments if it starts with - * '#'. Comments can't follow a zone name in a single line. - * @param fileName the text file name - */ - static void readZoneNames(String fileName) { - if (fileName == null) { - return; - } - BufferedReader in = null; - try { - FileReader fr = new FileReader(fileName); - in = new BufferedReader(fr); - } catch (FileNotFoundException e) { - Main.panic("can't open file: " + fileName); - } - targetZones = new HashSet<String>(); - String line; - - try { - while ((line = in.readLine()) != null) { - line = line.trim(); - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - if (!targetZones.add(line)) { - Main.warning("duplicated target zone name: " + line); - } - } - in.close(); - } catch (IOException e) { - Main.panic("IO error: "+e.getMessage()); - } - } - - /** - * Determines whether the specified zone is one of the target zones. - * If no target zones are specified, this method always returns - * true for any zone name. - * @param zoneName the zone name - * @return true if the specified name is a target zone. - */ - static boolean isTargetZone(String zoneName) { - if (targetZones == null) { - return true; - } - return targetZones.contains(zoneName); - } - - /** - * Forces to add "MET" to the target zone table. This is because - * there is a conflict between Java zone name "WET" and Olson zone - * name. - */ - static void addMET() { - if (targetZones != null) { - targetZones.add("MET"); - } - } - - /** - * @return the zone name - */ - String getName() { - return name; - } - - /** - * Adds the specified zone record to the zone record list. - */ - void add(ZoneRec rec) { - list.add(rec); - } - - /** - * @param index the index at which the zone record in the list is returned. - * @return the zone record specified by the index. - */ - ZoneRec get(int index) { - return list.get(index); - } - - /** - * @return the size of the zone record list - */ - int size() { - return list.size(); - } - - /** - * Resolves the reference to a rule in each zone record. - * @param zi the Zoneinfo object with which the rule reference is - * resolved. - */ - void resolve(Zoneinfo zi) { - for (int i = 0; i < list.size(); i++) { - ZoneRec rec = list.get(i); - rec.resolve(zi); - } - } -}
--- a/jdk/make/tools/src/build/tools/javazic/ZoneRec.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; - -/** - * ZoneRec hold information of time zone corresponding to each text - * line of the "Zone" part. - * - * @since 1.4 - */ -class ZoneRec { - private int gmtOffset; - private String ruleName; - private int directSave; - private Rule ruleRef; - private String format; - private boolean hasUntil; - private int untilYear; - private Month untilMonth; - private RuleDay untilDay; - private Time untilTime; - private long untilInMillis; - private String line; - - /** - * @return the "UNTIL" value in milliseconds - */ - Time getUntilTime() { - return untilTime; - } - - /** - * @return the GMT offset value in milliseconds - */ - int getGmtOffset() { - return gmtOffset; - } - - /** - * @return the rule name to which this zone record refers - */ - String getRuleName() { - return ruleName; - } - - /** - * @return the amount of saving time directly defined in the - * "RULES/SAVE" field. - */ - int getDirectSave() { - return directSave; - } - - /** - * @return true if this zone record has a reference to a rule - */ - boolean hasRuleReference() { - return ruleRef != null; - } - - /** - * Returns the "FORMAT" field string of this zone record. This - * @return the "FORMAT" field - */ - String getFormat() { - return format; - } - - /** - * @return the year in the "UNTIL" field - */ - int getUntilYear() { - return untilYear; - } - - /** - * Returns the "UNTIL" field value in milliseconds from Janurary - * 1, 1970 0:00 GMT. - * @param currentSave the amount of daylight saving in - * milliseconds that is used to adjust wall-clock time. - * @return the milliseconds value of the "UNTIL" field - */ - long getUntilTime(int currentSave) { - if (untilTime.isWall()) { - return untilInMillis - currentSave; - } - return untilInMillis; - } - - /** - * Returns the "UNTIL" time in milliseconds without adjusting GMT - * offsets or daylight saving. - * @return local "UNTIL" time in milliseconds - */ - long getLocalUntilTime() { - return Time.getLocalTime(untilYear, - untilMonth, - untilDay, - untilTime.getTime()); - } - - /** - * Returns the "UNTIL" time in milliseconds with adjusting GMT offsets and daylight saving. - * @return the "UNTIL" time after the adjustment - */ - long getLocalUntilTime(int save, int gmtOffset) { - return Time.getLocalTime(untilYear, - untilMonth, - untilDay, - save, - gmtOffset, - untilTime); - } - - /** - * @return the text line of this zone record - */ - String getLine() { - return line; - } - - /** - * Sets the specified text line to this zone record - */ - void setLine(String line) { - this.line = line; - } - - /** - * @return true if this zone record has the "UNTIL" field - */ - boolean hasUntil() { - return this.hasUntil; - } - - /** - * Adjusts the "UNTIL" time to GMT offset if this zone record has - * it. <code>untilTime</code> is not adjusted to daylight saving - * in this method. - */ - void adjustTime() { - if (!hasUntil()) { - return; - } - if (untilTime.isSTD() || untilTime.isWall()) { - // adjust to gmt offset only here. adjust to real - // wall-clock time when tracking rules - untilInMillis -= gmtOffset; - } - } - - /** - * @return the reference to the Rule object - */ - Rule getRuleRef() { - return ruleRef; - } - - /** - * Resolves the reference to a Rule and adjusts its "UNTIL" time - * to GMT offset. - */ - void resolve(Zoneinfo zi) { - if (ruleName != null && (!"-".equals(ruleName))) { - ruleRef = zi.getRule(ruleName); - } - adjustTime(); - } - - /** - * Parses a Zone text line that is described by a StringTokenizer. - * @param tokens represents tokens of a Zone text line - * @return the zone record produced by parsing the text - */ - static ZoneRec parse(StringTokenizer tokens) { - ZoneRec rec = new ZoneRec(); - try { - rec.gmtOffset = (int) Time.parse(tokens.nextToken()).getTime(); - String token = tokens.nextToken(); - char c = token.charAt(0); - if (c >= '0' && c <= '9') { - rec.directSave = (int) Time.parse(token).getTime(); - } else { - rec.ruleName = token; - } - rec.format = tokens.nextToken(); - if (tokens.hasMoreTokens()) { - rec.hasUntil = true; - rec.untilYear = Integer.parseInt(tokens.nextToken()); - if (tokens.hasMoreTokens()) { - rec.untilMonth = Month.parse(tokens.nextToken()); - } else { - rec.untilMonth = Month.JANUARY; - } - if (tokens.hasMoreTokens()) { - rec.untilDay = RuleDay.parse(tokens.nextToken()); - } else { - rec.untilDay = new RuleDay(1); - } - if (tokens.hasMoreTokens()) { - rec.untilTime = Time.parse(tokens.nextToken()); - } else { - rec.untilTime = Time.parse("0:00"); - } - rec.untilInMillis = rec.getLocalUntilTime(); - } - } catch (Exception e) { - // TODO: error reporting - e.printStackTrace(); - } - return rec; - } - - private static void panic(String msg) { - Main.panic(msg); - } -}
--- a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,569 +0,0 @@ -/* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 build.tools.javazic; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -/** - * Zoneinfo provides javazic compiler front-end functionality. - * @since 1.4 - */ -class Zoneinfo { - - private static final int minYear = 1900; - private static final int maxYear = 2037; - private static final long minTime = Time.getLocalTime(minYear, Month.JANUARY, 1, 0); - private static int startYear = minYear; - private static int endYear = maxYear; - - /** - * True if javazic should generate a list of SimpleTimeZone - * instances for the SimpleTimeZone-based time zone support. - */ - static boolean isYearForTimeZoneDataSpecified = false; - - /** - * Zone name to Zone mappings - */ - private Map<String,Zone> zones; - - /** - * Rule name to Rule mappings - */ - private Map<String,Rule> rules; - - /** - * Alias name to real name mappings - */ - private Map<String,String> aliases; - - /** - * Constracts a Zoneinfo. - */ - Zoneinfo() { - zones = new HashMap<String,Zone>(); - rules = new HashMap<String,Rule>(); - aliases = new HashMap<String,String>(); - } - - /** - * Adds the given zone to the list of Zones. - * @param zone Zone to be added to the list. - */ - void add(Zone zone) { - String name = zone.getName(); - zones.put(name, zone); - } - - /** - * Adds the given rule to the list of Rules. - * @param rule Rule to be added to the list. - */ - void add(Rule rule) { - String name = rule.getName(); - rules.put(name, rule); - } - - /** - * Puts the specifid name pair to the alias table. - * @param name1 an alias time zone name - * @param name2 the real time zone of the alias name - */ - void putAlias(String name1, String name2) { - aliases.put(name1, name2); - } - - /** - * Sets the given year for SimpleTimeZone list output. - * This method is called when the -S option is specified. - * @param year the year for which SimpleTimeZone list should be generated - */ - static void setYear(int year) { - setStartYear(year); - setEndYear(year); - isYearForTimeZoneDataSpecified = true; - } - - /** - * Sets the start year. - * @param year the start year value - * @throws IllegalArgumentException if the specified year value is - * smaller than the minimum year or greater than the end year. - */ - static void setStartYear(int year) { - if (year < minYear || year > endYear) { - throw new IllegalArgumentException("invalid start year specified: " + year); - } - startYear = year; - } - - /** - * @return the start year value - */ - static int getStartYear() { - return startYear; - } - - /** - * Sets the end year. - * @param year the end year value - * @throws IllegalArgumentException if the specified year value is - * smaller than the start year or greater than the maximum year. - */ - static void setEndYear(int year) { - if (year < startYear || year > maxYear) { - throw new IllegalArgumentException(); - } - endYear = year; - } - - /** - * @return the end year value - */ - static int getEndYear() { - return endYear; - } - - /** - * @return the minimum year value - */ - static int getMinYear() { - return minYear; - } - - /** - * @return the maximum year value - */ - static int getMaxYear() { - return maxYear; - } - - /** - * @return the alias table - */ - Map<String,String> getAliases() { - return aliases; - } - - /** - * @return the Zone list - */ - Map<String,Zone> getZones() { - return zones; - } - - /** - * @return a Zone specified by name. - * @param name a zone name - */ - Zone getZone(String name) { - return zones.get(name); - } - - /** - * @return a Rule specified by name. - * @param name a rule name - */ - Rule getRule(String name) { - return rules.get(name); - } - - private static String line; - - private static int lineNum; - - /** - * Parses the specified time zone data file and creates a Zoneinfo - * that has all Rules, Zones and Links (aliases) information. - * @param fname the time zone data file name - * @return a Zoneinfo object - */ - static Zoneinfo parse(String fname) { - BufferedReader in = null; - try { - FileReader fr = new FileReader(fname); - in = new BufferedReader(fr); - } catch (FileNotFoundException e) { - panic("can't open file: "+fname); - } - Zoneinfo zi = new Zoneinfo(); - boolean continued = false; - Zone zone = null; - String l; - lineNum = 0; - - try { - while ((line = in.readLine()) != null) { - lineNum++; - // skip blank and comment lines - if (line.length() == 0 || line.charAt(0) == '#') { - continue; - } - - // trim trailing comments - int rindex = line.lastIndexOf('#'); - if (rindex != -1) { - // take the data part of the line - l = line.substring(0, rindex); - } else { - l = line; - } - - StringTokenizer tokens = new StringTokenizer(l); - if (!tokens.hasMoreTokens()) { - continue; - } - String token = tokens.nextToken(); - - if (continued || "Zone".equals(token)) { - if (zone == null) { - if (!tokens.hasMoreTokens()) { - panic("syntax error: zone no more token"); - } - token = tokens.nextToken(); - // if the zone name is in "GMT+hh" or "GMT-hh" - // format, ignore it due to spec conflict. - if (token.startsWith("GMT+") || token.startsWith("GMT-")) { - continue; - } - zone = new Zone(token); - } else { - // no way to push the current token back... - tokens = new StringTokenizer(l); - } - - ZoneRec zrec = ZoneRec.parse(tokens); - zrec.setLine(line); - zone.add(zrec); - if ((continued = zrec.hasUntil()) == false) { - if (Zone.isTargetZone(zone.getName())) { - // zone.resolve(zi); - zi.add(zone); - } - zone = null; - } - } else if ("Rule".equals(token)) { - if (!tokens.hasMoreTokens()) { - panic("syntax error: rule no more token"); - } - token = tokens.nextToken(); - Rule rule = zi.getRule(token); - if (rule == null) { - rule = new Rule(token); - zi.add(rule); - } - RuleRec rrec = RuleRec.parse(tokens); - rrec.setLine(line); - rule.add(rrec); - } else if ("Link".equals(token)) { - // Link <newname> <oldname> - try { - String name1 = tokens.nextToken(); - String name2 = tokens.nextToken(); - - // if the zone name is in "GMT+hh" or "GMT-hh" - // format, ignore it due to spec conflict with - // custom time zones. Also, ignore "ROC" for - // PC-ness. - if (name2.startsWith("GMT+") || name2.startsWith("GMT-") - || "ROC".equals(name2)) { - continue; - } - zi.putAlias(name2, name1); - } catch (Exception e) { - panic("syntax error: no more token for Link"); - } - } - } - in.close(); - } catch (IOException ex) { - panic("IO error: " + ex.getMessage()); - } - - return zi; - } - - /** - * Interprets a zone and constructs a Timezone object that - * contains enough information on GMT offsets and DST schedules to - * generate a zone info database. - * - * @param zoneName the zone name for which a Timezone object is - * constructed. - * - * @return a Timezone object that contains all GMT offsets and DST - * rules information. - */ - Timezone phase2(String zoneName) { - Timezone tz = new Timezone(zoneName); - Zone zone = getZone(zoneName); - zone.resolve(this); - - // TODO: merge phase2's for the regular and SimpleTimeZone ones. - if (isYearForTimeZoneDataSpecified) { - ZoneRec zrec = zone.get(zone.size()-1); - tz.setLastZoneRec(zrec); - tz.setRawOffset(zrec.getGmtOffset()); - if (zrec.hasRuleReference()) { - /* - * This part assumes that the specified year is covered by - * the rules referred to by the last zone record. - */ - List<RuleRec> rrecs = zrec.getRuleRef().getRules(startYear); - - if (rrecs.size() == 2) { - // make sure that one is a start rule and the other is - // an end rule. - RuleRec r0 = rrecs.get(0); - RuleRec r1 = rrecs.get(1); - if (r0.getSave() == 0 && r1.getSave() > 0) { - rrecs.set(0, r1); - rrecs.set(1, r0); - } else if (!(r0.getSave() > 0 && r1.getSave() == 0)) { - rrecs = null; - Main.error(zoneName + ": rules for " + startYear + " not found."); - } - } else { - rrecs = null; - } - if (rrecs != null) { - tz.setLastRules(rrecs); - } - } - return tz; - } - - int gmtOffset; - int year = minYear; - int fromYear = year; - long fromTime = Time.getLocalTime(startYear, - Month.JANUARY, - 1, 0); - - // take the index 0 for the GMT offset of the last zone record - ZoneRec zrec = zone.get(zone.size()-1); - tz.getOffsetIndex(zrec.getGmtOffset()); - - int currentSave = 0; - boolean usedZone; - for (int zindex = 0; zindex < zone.size(); zindex++) { - zrec = zone.get(zindex); - usedZone = false; - gmtOffset = zrec.getGmtOffset(); - int stdOffset = zrec.getDirectSave(); - - // If this is the last zone record, take the last rule info. - if (!zrec.hasUntil()) { - tz.setRawOffset(gmtOffset, fromTime); - if (zrec.hasRuleReference()) { - tz.setLastRules(zrec.getRuleRef().getLastRules()); - } else if (stdOffset != 0) { - // in case the last rule is all year round DST-only - // (Asia/Amman once announced this rule.) - tz.setLastDSTSaving(stdOffset); - } - } - if (!zrec.hasRuleReference()) { - if (!zrec.hasUntil() || zrec.getUntilTime(stdOffset) >= fromTime) { - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+stdOffset), - tz.getDstOffsetIndex(stdOffset)); - usedZone = true; - } - currentSave = stdOffset; - // optimization in case the last rule is fixed. - if (!zrec.hasUntil()) { - if (tz.getNTransitions() > 0) { - if (stdOffset == 0) { - tz.setDSTType(Timezone.X_DST); - } else { - tz.setDSTType(Timezone.LAST_DST); - } - long time = Time.getLocalTime(maxYear, - Month.JANUARY, 1, 0); - time -= zrec.getGmtOffset(); - tz.addTransition(time, - tz.getOffsetIndex(gmtOffset+stdOffset), - tz.getDstOffsetIndex(stdOffset)); - tz.addUsedRec(zrec); - } else { - tz.setDSTType(Timezone.NO_DST); - } - break; - } - } else { - Rule rule = zrec.getRuleRef(); - boolean fromTimeUsed = false; - currentSave = 0; - year_loop: - for (year = getMinYear(); year <= endYear; year++) { - if (zrec.hasUntil() && year > zrec.getUntilYear()) { - break; - } - List<RuleRec> rules = rule.getRules(year); - if (rules.size() > 0) { - for (int i = 0; i < rules.size(); i++) { - RuleRec rrec = rules.get(i); - long transition = rrec.getTransitionTime(year, - gmtOffset, - currentSave); - if (zrec.hasUntil()) { - if (transition >= zrec.getUntilTime(currentSave)) { - break year_loop; - } - } - - if (fromTimeUsed == false) { - if (fromTime <= transition) { - fromTimeUsed = true; - - if (fromTime != minTime) { - int prevsave; - - ZoneRec prevzrec = zone.get(zindex - 1); - - // See if until time in the previous - // ZoneRec is the same thing as the - // local time in the next rule. - // (examples are Asia/Ashkhabad in 1991, - // Europe/Riga in 1989) - - if (i > 0) { - prevsave = rules.get(i-1).getSave(); - } else { - List<RuleRec> prevrules = rule.getRules(year-1); - - if (prevrules.size() > 0) { - prevsave = prevrules.get(prevrules.size()-1).getSave(); - } else { - prevsave = 0; - } - } - - if (rrec.isSameTransition(prevzrec, prevsave, gmtOffset)) { - currentSave = rrec.getSave(); - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - tz.addUsedRec(rrec); - usedZone = true; - continue; - } - if (!prevzrec.hasRuleReference() - || rule != prevzrec.getRuleRef() - || (rule == prevzrec.getRuleRef() - && gmtOffset != prevzrec.getGmtOffset())) { - int save = (fromTime == transition) ? rrec.getSave() : currentSave; - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - tz.addUsedRec(rrec); - usedZone = true; - } - } else { // fromTime == minTime - int save = rrec.getSave(); - tz.addTransition(minTime, - tz.getOffsetIndex(gmtOffset), - tz.getDstOffsetIndex(0)); - - tz.addTransition(transition, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - - tz.addUsedRec(rrec); - usedZone = true; - } - } else if (year == fromYear && i == rules.size()-1) { - int save = rrec.getSave(); - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+save), - tz.getDstOffsetIndex(save)); - } - } - - currentSave = rrec.getSave(); - if (fromTime < transition) { - tz.addTransition(transition, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - tz.addUsedRec(rrec); - usedZone = true; - } - } - } else { - if (year == fromYear) { - tz.addTransition(fromTime, - tz.getOffsetIndex(gmtOffset+currentSave), - tz.getDstOffsetIndex(currentSave)); - fromTimeUsed = true; - } - if (year == endYear && !zrec.hasUntil()) { - if (tz.getNTransitions() > 0) { - // Assume that this Zone stopped DST - tz.setDSTType(Timezone.X_DST); - long time = Time.getLocalTime(maxYear, Month.JANUARY, - 1, 0); - time -= zrec.getGmtOffset(); - tz.addTransition(time, - tz.getOffsetIndex(gmtOffset), - tz.getDstOffsetIndex(0)); - usedZone = true; - } else { - tz.setDSTType(Timezone.NO_DST); - } - } - } - } - } - if (usedZone) { - tz.addUsedRec(zrec); - } - if (zrec.hasUntil() && zrec.getUntilTime(currentSave) > fromTime) { - fromTime = zrec.getUntilTime(currentSave); - fromYear = zrec.getUntilYear(); - year = zrec.getUntilYear(); - } - } - - if (tz.getDSTType() == Timezone.UNDEF_DST) { - tz.setDSTType(Timezone.DST); - } - tz.optimize(); - tz.checksum(); - return tz; - } - - private static void panic(String msg) { - Main.panic(msg); - } -}
--- a/jdk/makefiles/CompileLaunchers.gmk Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/makefiles/CompileLaunchers.gmk Tue Mar 12 16:40:22 2013 -0700 @@ -311,6 +311,9 @@ $(eval $(call SetupLauncher,jrunscript,\ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "com.sun.tools.script.shell.Main"$(COMMA) }')) +$(eval $(call SetupLauncher,jjs,\ + -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.nashorn.tools.Shell"$(COMMA) }')) + $(eval $(call SetupLauncher,jsadebugd,\ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.jvm.hotspot.jdi.SADebugServer"$(COMMA) }' \ -DAPP_CLASSPATH='{ "/lib/tools.jar"$(COMMA) "/lib/sa-jdi.jar"$(COMMA) "/classes" }' \
--- a/jdk/makefiles/CreateJars.gmk Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/makefiles/CreateJars.gmk Tue Mar 12 16:40:22 2013 -0700 @@ -213,28 +213,28 @@ org/relaxng/datatype \ sun/awt/HKSCS.class \ sun/awt/motif/X11GB2312.class \ - sun/awt/motif/X11GB2312\$$$$Decoder.class \ - sun/awt/motif/X11GB2312\$$$$Encoder.class \ + sun/awt/motif/X11GB2312\$$Decoder.class \ + sun/awt/motif/X11GB2312\$$Encoder.class \ sun/awt/motif/X11GBK.class \ - sun/awt/motif/X11GBK\$$$$Encoder.class \ + sun/awt/motif/X11GBK\$$Encoder.class \ sun/awt/motif/X11KSC5601.class \ - sun/awt/motif/X11KSC5601\$$$$Decoder.class \ - sun/awt/motif/X11KSC5601\$$$$Encoder.class \ + sun/awt/motif/X11KSC5601\$$Decoder.class \ + sun/awt/motif/X11KSC5601\$$Encoder.class \ sun/jvmstat \ sun/net/spi/nameservice/dns \ sun/nio/cs/ext \ sun/rmi/rmic \ sun/security/ec/ECDHKeyAgreement.class \ sun/security/ec/ECDSASignature.class \ - sun/security/ec/ECDSASignature\$$$$Raw.class \ - sun/security/ec/ECDSASignature\$$$$SHA1.class \ - sun/security/ec/ECDSASignature\$$$$SHA224.class \ - sun/security/ec/ECDSASignature\$$$$SHA256.class \ - sun/security/ec/ECDSASignature\$$$$SHA384.class \ - sun/security/ec/ECDSASignature\$$$$SHA512.class \ + sun/security/ec/ECDSASignature\$$Raw.class \ + sun/security/ec/ECDSASignature\$$SHA1.class \ + sun/security/ec/ECDSASignature\$$SHA224.class \ + sun/security/ec/ECDSASignature\$$SHA256.class \ + sun/security/ec/ECDSASignature\$$SHA384.class \ + sun/security/ec/ECDSASignature\$$SHA512.class \ sun/security/ec/ECKeyFactory.class \ sun/security/ec/ECKeyPairGenerator.class \ - sun/security/ec/SunEC\$$$$1.class \ + sun/security/ec/SunEC\$$1.class \ sun/security/ec/SunEC.class \ sun/security/ec/SunECEntries.class \ sun/security/internal \ @@ -1119,6 +1119,14 @@ ########################################################################################## +# Import nashorn.jar from nashorn dist dir. +$(IMAGES_OUTPUTDIR)/lib/ext/nashorn.jar: $(NASHORN_DIST)/nashorn.jar + $(install-file) + +JARS += $(IMAGES_OUTPUTDIR)/lib/ext/nashorn.jar + +########################################################################################## + -include $(CUSTOM_MAKE_DIR)/CreateJars.gmk ##########################################################################################
--- a/jdk/makefiles/Images.gmk Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/makefiles/Images.gmk Tue Mar 12 16:40:22 2013 -0700 @@ -602,6 +602,7 @@ $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)") $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)") $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)") + if [ -n "$(JDK_ARCH_ABI_PROP_NAME)" ]; then $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"); fi $(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)") endef
--- a/jdk/makefiles/profile-rtjar-includes.txt Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/makefiles/profile-rtjar-includes.txt Tue Mar 12 16:40:22 2013 -0700 @@ -349,6 +349,7 @@ com/sun/rowset/providers \ com/sun/script/javascript \ com/sun/script/util \ + com/sun/security/auth \ com/sun/security/auth/callback \ com/sun/security/auth/login \ com/sun/security/auth/module \ @@ -448,8 +449,7 @@ sun/tracing \ sun/tracing/dtrace -PROFILE_3_RTJAR_INCLUDE_TYPES := \ - com/sun/security/auth/*.class +PROFILE_3_RTJAR_INCLUDE_TYPES := PROFILE_3_RTJAR_EXCLUDE_TYPES := \ javax/management/remote/rmi/_RMIConnectionImpl_Tie.class \ @@ -457,10 +457,10 @@ javax/management/remote/rmi/_RMIServerImpl_Tie.class \ javax/management/remote/rmi/_RMIServer_Stub.class \ com/sun/security/auth/callback/DialogCallbackHandler.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$1.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$2.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$Action.class \ - com/sun/security/auth/callback/DialogCallbackHandler\$$$$ConfirmationInfo.class + com/sun/security/auth/callback/DialogCallbackHandler\$$1.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$2.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$Action.class \ + com/sun/security/auth/callback/DialogCallbackHandler\$$ConfirmationInfo.class PROFILE_3_INCLUDE_METAINF_SERVICES := \ META-INF/services/javax.script.ScriptEngineFactory
--- a/jdk/src/share/back/transport.c Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/back/transport.c Tue Mar 12 16:40:22 2013 -0700 @@ -117,6 +117,9 @@ /* Construct library name (simple name or full path) */ dbgsysBuildLibName(libname, sizeof(libname), plibdir, name); + if (strlen(libname) == 0) { + return NULL; + } /* dlopen (unix) / LoadLibrary (windows) the transport library */ handle = dbgsysLoadLibrary(libname, buf, sizeof(buf));
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Tue Mar 12 16:40:22 2013 -0700 @@ -177,7 +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, "MethodParameters", "NB[RUNHFH]"); //define(sd, ATTR_CONTEXT_METHOD, "Code", "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]"); define(sd, ATTR_CONTEXT_CODE, "StackMapTable",
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Tue Mar 12 16:40:22 2013 -0700 @@ -1505,7 +1505,7 @@ // 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"); + IntBand method_MethodParameters_flag_FH = method_attr_bands.newIntBand("method_MethodParameters_flag_FH"); MultiBand class_attr_bands = class_bands.newMultiBand("(class_attr_bands)", UNSIGNED5); IntBand class_flags_hi = class_attr_bands.newIntBand("class_flags_hi"); @@ -1776,9 +1776,9 @@ new Band[]{ method_MethodParameters_NB, method_MethodParameters_name_RUN, - method_MethodParameters_flag_I + method_MethodParameters_flag_FH }, - "MethodParameters", "NB[RUNHI]"); + "MethodParameters", "NB[RUNHFH]"); assert(attrCodeEmpty == Package.attrCodeEmpty); predefineAttribute(X_ATTR_Signature, ATTR_CONTEXT_METHOD, new Band[] { method_Signature_RS },
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Tue Mar 12 16:40:22 2013 -0700 @@ -564,7 +564,7 @@ code.bytes = new byte[readInt()]; in.readFully(code.bytes); Entry[] cpMap = cls.getCPMap(); - Instruction.opcodeChecker(code.bytes, cpMap); + Instruction.opcodeChecker(code.bytes, cpMap, this.cls.version); int nh = readUnsignedShort(); code.setHandlerCount(nh); for (int i = 0; i < nh; i++) {
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Tue Mar 12 16:40:22 2013 -0700 @@ -207,6 +207,10 @@ return tag; } + public final boolean tagEquals(int tag) { + return getTag() == tag; + } + public Entry getRef(int i) { return null; }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Tue Mar 12 16:40:22 2013 -0700 @@ -479,4 +479,10 @@ public final static int _qldc = _xldc_op+7; public final static int _qldc_w = _xldc_op+8; public final static int _xldc_limit = _xldc_op+9; + + // handling of InterfaceMethodRef + public final static int _invoke_int_op = _xldc_limit; + public final static int _invokespecial_int = _invoke_int_op+0; + public final static int _invokestatic_int = _invoke_int_op+1; + public final static int _invoke_int_limit = _invoke_int_op+2; }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Tue Mar 12 16:40:22 2013 -0700 @@ -446,12 +446,14 @@ public static boolean isCPRefOp(int bc) { if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return true; if (bc >= _xldc_op && bc < _xldc_limit) return true; + if (bc == _invokespecial_int || bc == _invokestatic_int) return true; return false; } public static byte getCPRefOpTag(int bc) { if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][bc]; if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_LoadableValue; + if (bc == _invokestatic_int || bc == _invokespecial_int) return CONSTANT_InterfaceMethodref; return CONSTANT_None; } @@ -647,7 +649,8 @@ } } - public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap) throws FormatException { + public static void opcodeChecker(byte[] code, ConstantPool.Entry[] cpMap, + Package.Version clsVersion) throws FormatException { Instruction i = at(code, 0); while (i != null) { int opcode = i.getBC(); @@ -658,10 +661,17 @@ ConstantPool.Entry e = i.getCPRef(cpMap); if (e != null) { byte tag = i.getCPTag(); - if (!e.tagMatches(tag)) { - String message = "illegal reference, expected type=" + - ConstantPool.tagName(tag) + ": " + - i.toString(cpMap); + boolean match = e.tagMatches(tag); + if (!match && + (i.bc == _invokespecial || i.bc == _invokestatic) && + e.tagMatches(CONSTANT_InterfaceMethodref) && + clsVersion.greaterThan(Constants.JAVA7_MAX_CLASS_VERSION)) { + match = true; + } + if (!match) { + String message = "illegal reference, expected type=" + + ConstantPool.tagName(tag) + ": " + + i.toString(cpMap); throw new FormatException(message); } }
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Tue Mar 12 16:40:22 2013 -0700 @@ -1521,7 +1521,7 @@ // *method_Exceptions_RC :UNSIGNED5 (cp_Class) // *method_MethodParameters_NB: BYTE1 // *method_MethodParameters_RUN: UNSIGNED5 (cp_Utf8) - // *method_MethodParameters_I: UNSIGNED5 (flag) + // *method_MethodParameters_FH: UNSIGNED5 (flag) // // code_attr_bands: // *code_flags :UNSIGNED5 @@ -2256,6 +2256,12 @@ int origBC = bc; int size = 2; switch (bc) { + case _invokestatic_int: + origBC = _invokestatic; + break; + case _invokespecial_int: + origBC = _invokespecial; + break; case _ildc: case _cldc: case _fldc:
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Tue Mar 12 16:40:22 2013 -0700 @@ -1409,6 +1409,10 @@ int bc = i.getBC(); if (!(bc >= _first_linker_op && bc <= _last_linker_op)) return -1; MemberEntry ref = (MemberEntry) i.getCPRef(curCPMap); + // do not optimize this case, simply fall back to regular coding + if ((bc == _invokespecial || bc == _invokestatic) && + ref.tagEquals(CONSTANT_InterfaceMethodref)) + return -1; ClassEntry refClass = ref.classRef; int self_bc = _self_linker_op + (bc - _first_linker_op); if (refClass == curClass.thisClass) @@ -1609,7 +1613,16 @@ case CONSTANT_Fieldref: bc_which = bc_fieldref; break; case CONSTANT_Methodref: - bc_which = bc_methodref; break; + if (ref.tagEquals(CONSTANT_InterfaceMethodref)) { + if (bc == _invokespecial) + vbc = _invokespecial_int; + if (bc == _invokestatic) + vbc = _invokestatic_int; + bc_which = bc_imethodref; + } else { + bc_which = bc_methodref; + } + break; case CONSTANT_InterfaceMethodref: bc_which = bc_imethodref; break; case CONSTANT_InvokeDynamic:
--- a/jdk/src/share/classes/java/lang/Class.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/Class.java Tue Mar 12 16:40:22 2013 -0700 @@ -25,6 +25,7 @@ package java.lang; +import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; @@ -3084,6 +3085,16 @@ } /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */
--- a/jdk/src/share/classes/java/lang/ClassLoader.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/ClassLoader.java Tue Mar 12 16:40:22 2013 -0700 @@ -51,7 +51,6 @@ import java.util.Hashtable; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import sun.misc.ClassFileTransformer; import sun.misc.CompoundEnumeration; import sun.misc.Resource; import sun.misc.URLClassPath; @@ -669,41 +668,6 @@ return source; } - private Class<?> defineTransformedClass(String name, byte[] b, int off, int len, - ProtectionDomain pd, - ClassFormatError cfe, String source) - throws ClassFormatError - { - // Class format error - try to transform the bytecode and - // define the class again - // - ClassFileTransformer[] transformers = - ClassFileTransformer.getTransformers(); - Class<?> c = null; - - if (transformers != null) { - for (ClassFileTransformer transformer : transformers) { - try { - // Transform byte code using transformer - byte[] tb = transformer.transform(b, off, len); - c = defineClass1(name, tb, 0, tb.length, - pd, source); - break; - } catch (ClassFormatError cfe2) { - // If ClassFormatError occurs, try next transformer - } - } - } - - // Rethrow original ClassFormatError if unable to transform - // bytecode to well-formed - // - if (c == null) - throw cfe; - - return c; - } - private void postDefineClass(Class<?> c, ProtectionDomain pd) { if (pd.getCodeSource() != null) { @@ -783,17 +747,8 @@ throws ClassFormatError { protectionDomain = preDefineClass(name, protectionDomain); - - Class<?> c = null; String source = defineClassSourceLocation(protectionDomain); - - try { - c = defineClass1(name, b, off, len, protectionDomain, source); - } catch (ClassFormatError cfe) { - c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, - source); - } - + Class<?> c = defineClass1(name, b, off, len, protectionDomain, source); postDefineClass(c, protectionDomain); return c; } @@ -881,20 +836,8 @@ } protectionDomain = preDefineClass(name, protectionDomain); - - Class<?> c = null; String source = defineClassSourceLocation(protectionDomain); - - try { - c = defineClass2(name, b, b.position(), len, protectionDomain, - source); - } catch (ClassFormatError cfe) { - byte[] tb = new byte[len]; - b.get(tb); // get bytes out of byte buffer. - c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe, - source); - } - + Class<?> c = defineClass2(name, b, b.position(), len, protectionDomain, source); postDefineClass(c, protectionDomain); return c; }
--- a/jdk/src/share/classes/java/lang/Deprecated.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/Deprecated.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -36,6 +36,7 @@ * * @author Neal Gafter * @since 1.5 + * @jls 9.6.3.6 @Deprecated */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/src/share/classes/java/lang/Override.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/Override.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, 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 @@ -43,7 +43,7 @@ * * @author Peter von der Ahé * @author Joshua Bloch - * @jls 9.6.1.4 Override + * @jls 9.6.1.4 @Override * @since 1.5 */ @Target(ElementType.METHOD)
--- a/jdk/src/share/classes/java/lang/Package.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/Package.java Tue Mar 12 16:40:22 2013 -0700 @@ -25,6 +25,7 @@ package java.lang; +import java.lang.reflect.AnnotatedElement; import java.io.InputStream; import java.util.Enumeration; @@ -386,6 +387,16 @@ } /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */
--- a/jdk/src/share/classes/java/lang/SafeVarargs.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/SafeVarargs.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -85,6 +85,7 @@ * @since 1.7 * @jls 4.7 Reifiable Types * @jls 8.4.1 Formal Parameters + * @jls 9.6.3.7 @SafeVarargs */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/src/share/classes/java/lang/SecurityManager.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/SecurityManager.java Tue Mar 12 16:40:22 2013 -0700 @@ -1320,6 +1320,9 @@ * <code>AWTPermission("showWindowWithoutWarningBanner")</code> permission, * and returns <code>true</code> if a SecurityException is not thrown, * otherwise it returns <code>false</code>. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. * <p> * If you override this method, then you should make a call to * <code>super.checkTopLevelWindow</code> @@ -1340,8 +1343,12 @@ if (window == null) { throw new NullPointerException("window can't be null"); } + Permission perm = SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } try { - checkPermission(SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION); + checkPermission(perm); return true; } catch (SecurityException se) { // just return false @@ -1379,6 +1386,9 @@ * This method calls <code>checkPermission</code> with the * <code>AWTPermission("accessClipboard")</code> * permission. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. * <p> * If you override this method, then you should make a call to * <code>super.checkSystemClipboardAccess</code> @@ -1391,7 +1401,11 @@ * @see #checkPermission(java.security.Permission) checkPermission */ public void checkSystemClipboardAccess() { - checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION); + Permission perm = SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } + checkPermission(perm); } /** @@ -1400,6 +1414,10 @@ * <p> * This method calls <code>checkPermission</code> with the * <code>AWTPermission("accessEventQueue")</code> permission. + * In the case of subset Profiles of Java SE that do not include the + * {@code java.awt} package, {@code checkPermission} is instead called + * to check the permission {@code java.security.AllPermission}. + * * <p> * If you override this method, then you should make a call to * <code>super.checkAwtEventQueueAccess</code> @@ -1412,7 +1430,11 @@ * @see #checkPermission(java.security.Permission) checkPermission */ public void checkAwtEventQueueAccess() { - checkPermission(SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION); + Permission perm = SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION; + if (perm == null) { + perm = SecurityConstants.ALL_PERMISSION; + } + checkPermission(perm); } /*
--- a/jdk/src/share/classes/java/lang/SuppressWarnings.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/SuppressWarnings.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -41,8 +41,13 @@ * suppress a warning in a particular method, you should annotate that * method rather than its class. * + * @author Josh Bloch * @since 1.5 - * @author Josh Bloch + * @jls 4.8 Raw Types + * @jls 4.12.2 Variables of Reference Type + * @jls 5.1.9 Unchecked Conversion + * @jls 5.5.2 Checked Casts and Unchecked Casts + * @jls 9.6.3.5 @SuppressWarnings */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) @@ -56,9 +61,11 @@ * free to emit a warning if an annotation contains an unrecognized * warning name. * - * <p>Compiler vendors should document the warning names they support in - * conjunction with this annotation type. They are encouraged to cooperate - * to ensure that the same names work across multiple compilers. + * <p> The string {@code "unchecked"} is used to suppress + * unchecked warnings. Compiler vendors should document the + * additional warning names they support in conjunction with this + * annotation type. They are encouraged to cooperate to ensure + * that the same names work across multiple compilers. */ String[] value(); }
--- a/jdk/src/share/classes/java/lang/annotation/Inherited.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/annotation/Inherited.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, 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 @@ -44,6 +44,7 @@ * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.3 @Inherited */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java Tue Mar 12 16:28:34 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * 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. - */ -package java.lang.annotation; - -import java.util.Objects; - -/** - * Thrown to indicate that an annotation type expected to act as a - * container for another annotation type by virture of an @Repeatable - * annotation, does not act as a container. - * - * @see java.lang.reflect.AnnotatedElement - * @since 1.8 - * @jls 9.6 Annotation Types - * @jls 9.7 Annotations - */ -public class InvalidContainerAnnotationError extends AnnotationFormatError { - private static final long serialVersionUID = 5023L; - - /** - * The instance of the erroneous container. - */ - private transient Annotation container; - - /** - * The type of the annotation that should be contained in the - * container. - */ - private transient Class<? extends Annotation> annotationType; - - /** - * Constructs a new InvalidContainerAnnotationError with the - * specified detail message. - * - * @param message the detail message. - */ - public InvalidContainerAnnotationError(String message) { - super(message); - } - - /** - * Constructs a new InvalidContainerAnnotationError with the specified - * detail message and cause. Note that the detail message associated - * with {@code cause} is <i>not</i> automatically incorporated in - * this error's detail message. - * - * @param message the detail message - * @param cause the cause, may be {@code null} - */ - public InvalidContainerAnnotationError(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new InvalidContainerAnnotationError with the - * specified cause and a detail message of {@code (cause == null ? - * null : cause.toString())} (which typically contains the class - * and detail message of {@code cause}). - * - * @param cause the cause, may be {@code null} - */ - public InvalidContainerAnnotationError(Throwable cause) { - super(cause); - } - - /** - * Constructs InvalidContainerAnnotationError for the specified - * container instance and contained annotation type. - * - * @param message the detail message - * @param cause the cause, may be {@code null} - * @param container the erroneous container instance, may be - * {@code null} - * @param annotationType the annotation type intended to be - * contained, may be {@code null} - */ - public InvalidContainerAnnotationError(String message, - Throwable cause, - Annotation container, - Class<? extends Annotation> annotationType) { - super(message, cause); - this.container = container; - this.annotationType = annotationType; - } - - /** - * Returns the erroneous container. - * - * @return the erroneous container, may return {@code null} - */ - public Annotation getContainer() { - return container; - } - - /** - * Returns the annotation type intended to be contained. Returns - * {@code null} if the annotation type intended to be contained - * could not be determined. - * - * @return the annotation type intended to be contained, or {@code - * null} if unknown - */ - public Class<? extends Annotation> getAnnotationType() { - return annotationType; - } -}
--- a/jdk/src/share/classes/java/lang/annotation/Retention.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/annotation/Retention.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, 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 @@ -38,6 +38,7 @@ * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.2 @Retention */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/src/share/classes/java/lang/annotation/Target.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/annotation/Target.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, 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 @@ -59,6 +59,9 @@ * ... * } * </pre> + * + * @since 1.5 + * @jls 9.6.3.1 @Target */ @Documented @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Tue Mar 12 16:40:22 2013 -0700 @@ -34,11 +34,11 @@ import static sun.invoke.util.Wrapper.*; /** - * Abstract implementation of a meta-factory which provides parameter unrolling and input validation. + * Abstract implementation of a lambda metafactory which provides parameter unrolling and input validation. * - * @author Robert Field + * @see LambdaMetafactory */ -/*non-public*/ abstract class AbstractValidatingLambdaMetafactory { +/* package */ abstract class AbstractValidatingLambdaMetafactory { /* * For context, the comments for the following fields are marked in quotes with their values, given this program: @@ -54,16 +54,19 @@ final Class<?> targetClass; // The class calling the meta-factory via invokedynamic "class X" final MethodType invokedType; // The type of the invoked method "(CC)II" final Class<?> samBase; // The type of the returned instance "interface JJ" - final boolean isSerializable; // Should the returned instance be serializable + final MethodHandle samMethod; // Raw method handle for the functional interface method final MethodHandleInfo samInfo; // Info about the SAM method handle "MethodHandleInfo[9 II.foo(Object)Object]" final Class<?> samClass; // Interface containing the SAM method "interface II" final MethodType samMethodType; // Type of the SAM method "(Object)Object" + final MethodHandle implMethod; // Raw method handle for the implementation method final MethodHandleInfo implInfo; // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]" final int implKind; // Invocation kind for implementation "5"=invokevirtual final boolean implIsInstanceMethod; // Is the implementation an instance method "true" final Class<?> implDefiningClass; // Type defining the implementation "class CC" final MethodType implMethodType; // Type of the implementation method "(int)String" final MethodType instantiatedMethodType; // Instantiated erased functional interface method type "(Integer)Object" + final boolean isSerializable; // Should the returned instance be serializable + final Class<?>[] markerInterfaces; // Additional marker interfaces to be implemented /** @@ -80,27 +83,35 @@ * @param implMethod The implementation method which should be called (with suitable adaptation of argument * types, return types, and adjustment for captured arguments) when methods of the resulting * functional interface instance are invoked. - * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective + * @param instantiatedMethodType The signature of the primary functional interface method after type variables + * are substituted with their instantiation from the capture site * @throws ReflectiveOperationException + * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated */ AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, MethodHandle samMethod, MethodHandle implMethod, - MethodType instantiatedMethodType) - throws ReflectiveOperationException { + MethodType instantiatedMethodType, + int flags, + Class<?>[] markerInterfaces) + throws ReflectiveOperationException, LambdaConversionException { this.targetClass = caller.lookupClass(); this.invokedType = invokedType; this.samBase = invokedType.returnType(); - this.isSerializable = Serializable.class.isAssignableFrom(samBase); + this.samMethod = samMethod; this.samInfo = new MethodHandleInfo(samMethod); this.samClass = samInfo.getDeclaringClass(); this.samMethodType = samInfo.getMethodType(); + this.implMethod = implMethod; this.implInfo = new MethodHandleInfo(implMethod); - this.implKind = implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial? MethodHandleInfo.REF_invokeVirtual : implInfo.getReferenceKind(); // @@@ Temp work-around to hotspot incorrectly converting to invokespecial + // @@@ Temporary work-around pending resolution of 8005119 + this.implKind = (implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial) + ? MethodHandleInfo.REF_invokeVirtual + : implInfo.getReferenceKind(); this.implIsInstanceMethod = implKind == MethodHandleInfo.REF_invokeVirtual || implKind == MethodHandleInfo.REF_invokeSpecial || @@ -109,6 +120,30 @@ this.implMethodType = implInfo.getMethodType(); this.instantiatedMethodType = instantiatedMethodType; + + if (!samClass.isInterface()) { + throw new LambdaConversionException(String.format( + "Functional interface %s is not an interface", + samClass.getName())); + } + + boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(samBase); + for (Class<?> c : markerInterfaces) { + if (!c.isInterface()) { + throw new LambdaConversionException(String.format( + "Marker interface %s is not an interface", + c.getName())); + } + foundSerializableSupertype |= Serializable.class.isAssignableFrom(c); + } + this.isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0) + || foundSerializableSupertype; + + if (isSerializable && !foundSerializableSupertype) { + markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1); + markerInterfaces[markerInterfaces.length-1] = Serializable.class; + } + this.markerInterfaces = markerInterfaces; } /** @@ -127,8 +162,9 @@ void validateMetafactoryArgs() throws LambdaConversionException { // Check target type is a subtype of class where SAM method is defined if (!samClass.isAssignableFrom(samBase)) { - throw new LambdaConversionException(String.format("Invalid target type %s for lambda conversion; not a subtype of functional interface %s", - samBase.getName(), samClass.getName())); + throw new LambdaConversionException( + String.format("Invalid target type %s for lambda conversion; not a subtype of functional interface %s", + samBase.getName(), samClass.getName())); } switch (implKind) { @@ -149,14 +185,16 @@ final int samArity = samMethodType.parameterCount(); final int instantiatedArity = instantiatedMethodType.parameterCount(); if (implArity + receiverArity != capturedArity + samArity) { - throw new LambdaConversionException(String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface parameters, %d implementation parameters", - implIsInstanceMethod ? "instance" : "static", implInfo, - capturedArity, samArity, implArity)); + throw new LambdaConversionException( + String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface method parameters, %d implementation parameters", + implIsInstanceMethod ? "instance" : "static", implInfo, + capturedArity, samArity, implArity)); } if (instantiatedArity != samArity) { - throw new LambdaConversionException(String.format("Incorrect number of parameters for %s method %s; %d functional interface parameters, %d SAM method parameters", - implIsInstanceMethod ? "instance" : "static", implInfo, - instantiatedArity, samArity)); + throw new LambdaConversionException( + String.format("Incorrect number of parameters for %s method %s; %d instantiated parameters, %d functional interface method parameters", + implIsInstanceMethod ? "instance" : "static", implInfo, + instantiatedArity, samArity)); } // If instance: first captured arg (receiver) must be subtype of class where impl method is defined @@ -180,8 +218,9 @@ // check receiver type if (!implDefiningClass.isAssignableFrom(receiverClass)) { - throw new LambdaConversionException(String.format("Invalid receiver type %s; not a subtype of implementation type %s", - receiverClass, implDefiningClass)); + throw new LambdaConversionException( + String.format("Invalid receiver type %s; not a subtype of implementation type %s", + receiverClass, implDefiningClass)); } } else { // no receiver @@ -196,7 +235,8 @@ Class<?> capturedParamType = invokedType.parameterType(i + capturedStart); if (!capturedParamType.equals(implParamType)) { throw new LambdaConversionException( - String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s", i, capturedParamType, implParamType)); + String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s", + i, capturedParamType, implParamType)); } } // Check for adaptation match on SAM arguments @@ -206,7 +246,8 @@ Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i + samOffset); if (!isAdaptableTo(instantiatedParamType, implParamType, true)) { throw new LambdaConversionException( - String.format("Type mismatch for lambda argument %d: %s is not convertible to %s", i, instantiatedParamType, implParamType)); + String.format("Type mismatch for lambda argument %d: %s is not convertible to %s", + i, instantiatedParamType, implParamType)); } } @@ -218,7 +259,8 @@ : implMethodType.returnType(); if (!isAdaptableToAsReturn(actualReturnType, expectedType)) { throw new LambdaConversionException( - String.format("Type mismatch for lambda return: %s is not convertible to %s", actualReturnType, expectedType)); + String.format("Type mismatch for lambda return: %s is not convertible to %s", + actualReturnType, expectedType)); } } @@ -274,8 +316,8 @@ } - /*********** Logging support -- for debugging only - static final Executor logPool = Executors.newSingleThreadExecutor(); // @@@ For debugging only + /*********** Logging support -- for debugging only, uncomment as needed + static final Executor logPool = Executors.newSingleThreadExecutor(); protected static void log(final String s) { MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() { @Override @@ -297,17 +339,21 @@ ***********************/ /** - * Find the SAM method and corresponding methods which should be bridged. SAM method and those to be bridged - * will have the same name and number of parameters. Check for matching default methods (non-abstract), they - * should not be bridged-over and indicate a complex bridging situation. + * Find the functional interface method and corresponding abstract methods + * which should be bridged. The functional interface method and those to be + * bridged will have the same name and number of parameters. Check for + * matching default methods (non-abstract), the VM will create bridges for + * default methods; We don't have enough readily available type information + * to distinguish between where the functional interface method should be + * bridged and where the default method should be bridged; This situation is + * flagged. */ class MethodAnalyzer { private final Method[] methods = samBase.getMethods(); - private final List<Method> methodsFound = new ArrayList<>(methods.length); private Method samMethod = null; private final List<Method> methodsToBridge = new ArrayList<>(methods.length); - private boolean defaultMethodFound = false; + private boolean conflictFoundBetweenDefaultAndBridge = false; MethodAnalyzer() { String samMethodName = samInfo.getName(); @@ -315,31 +361,36 @@ int samParamLength = samParamTypes.length; Class<?> samReturnType = samMethodType.returnType(); Class<?> objectClass = Object.class; + List<Method> defaultMethods = new ArrayList<>(methods.length); for (Method m : methods) { if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) { Class<?>[] mParamTypes = m.getParameterTypes(); if (mParamTypes.length == samParamLength) { + // Method matches name and parameter length -- and is not Object if (Modifier.isAbstract(m.getModifiers())) { - // Exclude methods with duplicate signatures - if (methodUnique(m)) { - if (m.getReturnType().equals(samReturnType) && Arrays.equals(mParamTypes, samParamTypes)) { - // Exact match, this is the SAM method signature - samMethod = m; - } else { - methodsToBridge.add(m); - } + // Method is abstract + if (m.getReturnType().equals(samReturnType) + && Arrays.equals(mParamTypes, samParamTypes)) { + // Exact match, this is the SAM method signature + samMethod = m; + } else if (!hasMatchingBridgeSignature(m)) { + // Record bridges, exclude methods with duplicate signatures + methodsToBridge.add(m); } } else { - // This is a default method, flag for special processing - defaultMethodFound = true; - // Ignore future matching abstracts. - // Note, due to reabstraction, this is really a punt, hence pass-off to VM - methodUnique(m); + // Record default methods for conflict testing + defaultMethods.add(m); } } } } + for (Method dm : defaultMethods) { + if (hasMatchingBridgeSignature(dm)) { + conflictFoundBetweenDefaultAndBridge = true; + break; + } + } } Method getSamMethod() { @@ -350,27 +401,26 @@ return methodsToBridge; } - boolean wasDefaultMethodFound() { - return defaultMethodFound; + boolean conflictFoundBetweenDefaultAndBridge() { + return conflictFoundBetweenDefaultAndBridge; } /** - * Search the list of previously found methods to determine if there is a method with the same signature - * (return and parameter types) as the specified method. If it wasn't found before, add to the found list. + * Search the list of previously found bridge methods to determine if there is a method with the same signature + * (return and parameter types) as the specified method. * * @param m The method to match - * @return False if the method was found, True otherwise + * @return True if the method was found, False otherwise */ - private boolean methodUnique(Method m) { + private boolean hasMatchingBridgeSignature(Method m) { Class<?>[] ptypes = m.getParameterTypes(); Class<?> rtype = m.getReturnType(); - for (Method md : methodsFound) { + for (Method md : methodsToBridge) { if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) { + return true; + } + } return false; } } - methodsFound.add(m); - return true; - } - } }
--- a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -55,8 +55,7 @@ } // Factory methods: - - static DirectMethodHandle make(Class<?> receiver, MemberName member) { + static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) { MethodType mtype = member.getMethodOrFieldType(); if (!member.isStatic()) { if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor()) @@ -64,8 +63,14 @@ mtype = mtype.insertParameterTypes(0, receiver); } if (!member.isField()) { - LambdaForm lform = preparedLambdaForm(member); - return new DirectMethodHandle(mtype, lform, member); + if (refKind == REF_invokeSpecial) { + member = member.asSpecial(); + LambdaForm lform = preparedLambdaForm(member); + return new Special(mtype, lform, member); + } else { + LambdaForm lform = preparedLambdaForm(member); + return new DirectMethodHandle(mtype, lform, member); + } } else { LambdaForm lform = preparedFieldLambdaForm(member); if (member.isStatic()) { @@ -79,6 +84,12 @@ } } } + static DirectMethodHandle make(Class<?> receiver, MemberName member) { + byte refKind = member.getReferenceKind(); + if (refKind == REF_invokeSpecial) + refKind = REF_invokeVirtual; + return make(refKind, receiver, member); + } static DirectMethodHandle make(MemberName member) { if (member.isConstructor()) return makeAllocator(member); @@ -114,6 +125,10 @@ //// Implementation methods. @Override + MethodHandle viewAsType(MethodType newType) { + return new DirectMethodHandle(newType, form, member); + } + @Override @ForceInline MemberName internalMemberName() { return member; @@ -357,6 +372,21 @@ ((DirectMethodHandle)mh).ensureInitialized(); } + /** This subclass represents invokespecial instructions. */ + static class Special extends DirectMethodHandle { + private Special(MethodType mtype, LambdaForm form, MemberName member) { + super(mtype, form, member); + } + @Override + boolean isInvokeSpecial() { + return true; + } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Special(newType, form, member); + } + } + /** This subclass handles constructor references. */ static class Constructor extends DirectMethodHandle { final MemberName initMethod; @@ -369,6 +399,10 @@ this.instanceClass = instanceClass; assert(initMethod.isResolved()); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Constructor(newType, form, member, initMethod, instanceClass); + } } /*non-public*/ static Object constructorMethod(Object mh) { @@ -395,6 +429,10 @@ @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Accessor(newType, form, member, fieldOffset); + } } @ForceInline @@ -434,6 +472,10 @@ @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new StaticAccessor(newType, form, member, staticBase, staticOffset); + } } @ForceInline
--- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Tue Mar 12 16:40:22 2013 -0700 @@ -36,21 +36,28 @@ import java.security.PrivilegedAction; /** - * InnerClassLambdaMetafactory + * Lambda metafactory implementation which dynamically creates an inner-class-like class per lambda callsite. + * + * @see LambdaMetafactory */ -/*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { +/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { private static final int CLASSFILE_VERSION = 51; - private static final Type TYPE_VOID = Type.getType(void.class); private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl"; - private static final String NAME_SERIALIZABLE = "java/io/Serializable"; private static final String NAME_CTOR = "<init>"; //Serialization support - private static final String NAME_SERIALIZED_LAMBDA = "com/oracle/java/lang/invoke/SerializedLambdaImpl"; + private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; private static final String NAME_OBJECT = "java/lang/Object"; + private static final String DESCR_CTOR_SERIALIZED_LAMBDA + = MethodType.methodType(void.class, + Class.class, + int.class, String.class, String.class, String.class, + int.class, String.class, String.class, String.class, + String.class, + Object[].class).toMethodDescriptorString(); // Used to ensure that each spun class name is unique private static final AtomicInteger counter = new AtomicInteger(0); @@ -70,7 +77,7 @@ private final Type[] instantiatedArgumentTypes; // ASM types for the functional interface arguments /** - * Meta-factory constructor. + * General meta-factory constructor, standard cases and allowing for uncommon options such as serialization. * * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges * of the caller. @@ -83,16 +90,23 @@ * @param implMethod The implementation method which should be called (with suitable adaptation of argument * types, return types, and adjustment for captured arguments) when methods of the resulting * functional interface instance are invoked. - * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective + * @param instantiatedMethodType The signature of the primary functional interface method after type variables + * are substituted with their instantiation from the capture site + * @param flags A bitmask containing flags that may influence the translation of this lambda expression. Defined + * fields include FLAG_SERIALIZABLE. + * @param markerInterfaces Additional interfaces which the lambda object should implement. * @throws ReflectiveOperationException + * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated */ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, MethodHandle samMethod, MethodHandle implMethod, - MethodType instantiatedMethodType) - throws ReflectiveOperationException { - super(caller, invokedType, samMethod, implMethod, instantiatedMethodType); + MethodType instantiatedMethodType, + int flags, + Class<?>[] markerInterfaces) + throws ReflectiveOperationException, LambdaConversionException { + super(caller, invokedType, samMethod, implMethod, instantiatedMethodType, flags, markerInterfaces); implMethodClassName = implDefiningClass.getName().replace('.', '/'); implMethodName = implInfo.getName(); implMethodDesc = implMethodType.toMethodDescriptorString(); @@ -109,7 +123,6 @@ argNames[i] = "arg$" + (i + 1); } instantiatedArgumentTypes = Type.getArgumentTypes(instantiatedMethodType.toMethodDescriptorString()); - } /** @@ -120,7 +133,8 @@ * * @return a CallSite, which, when invoked, will return an instance of the * functional interface - * @throws ReflectiveOperationException, LambdaConversionException + * @throws ReflectiveOperationException + * @throws LambdaConversionException If properly formed functional interface is not found */ @Override CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { @@ -151,8 +165,8 @@ } else { return new ConstantCallSite( MethodHandles.Lookup.IMPL_LOOKUP - .findConstructor(innerClass, constructorType) - .asType(constructorType.changeReturnType(samBase))); + .findConstructor(innerClass, constructorType) + .asType(constructorType.changeReturnType(samBase))); } } @@ -161,16 +175,23 @@ * interface, define and return the class. * * @return a Class which implements the functional interface + * @throws LambdaConversionException If properly formed functional interface is not found */ - private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException { + private Class<?> spinInnerClass() throws LambdaConversionException { String samName = samBase.getName().replace('.', '/'); - - cw.visit(CLASSFILE_VERSION, ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL, - isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName}); + String[] interfaces = new String[markerInterfaces.length + 1]; + interfaces[0] = samName; + for (int i=0; i<markerInterfaces.length; i++) { + interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/'); + } + cw.visit(CLASSFILE_VERSION, ACC_SUPER, + lambdaClassName, null, + NAME_MAGIC_ACCESSOR_IMPL, interfaces); // Generate final fields to be filled in by constructor for (int i = 0; i < argTypes.length; i++) { - FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null); + FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), + null, null); fv.visitEnd(); } @@ -180,26 +201,24 @@ // Forward the SAM method if (ma.getSamMethod() == null) { - throw new LambdaConversionException(String.format("SAM method not found: %s", samMethodType)); + throw new LambdaConversionException(String.format("Functional interface method not found: %s", samMethodType)); } else { generateForwardingMethod(ma.getSamMethod(), false); } // Forward the bridges - // @@@ Once the VM can do fail-over, uncomment the default method test - if (!ma.getMethodsToBridge().isEmpty() /* && !ma.wasDefaultMethodFound() */) { + // @@@ The commented-out code is temporary, pending the VM's ability to bridge all methods on request + // @@@ Once the VM can do fail-over, uncomment the !ma.wasDefaultMethodFound() test, and emit the appropriate + // @@@ classfile attribute to request custom bridging. See 8002092. + if (!ma.getMethodsToBridge().isEmpty() /* && !ma.conflictFoundBetweenDefaultAndBridge() */ ) { for (Method m : ma.getMethodsToBridge()) { generateForwardingMethod(m, true); } } - /***** Serialization not yet supported if (isSerializable) { - String samMethodName = samInfo.getName(); - Type samType = Type.getType(samBase); - generateSerializationMethod(samType, samMethodName); + generateWriteReplace(); } - ******/ cw.visitEnd(); @@ -212,7 +231,7 @@ try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) { fos.write(classBytes); } catch (IOException ex) { - Logger.getLogger(InnerClassLambdaMetafactory.class.getName()).log(Level.SEVERE, null, ex); + PlatformLogger.getLogger(InnerClassLambdaMetafactory.class.getName()).severe(ex.getMessage(), ex); } ***/ @@ -228,7 +247,8 @@ } ); - return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd); + return (Class<?>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, + loader, pd); } /** @@ -253,40 +273,44 @@ } /** - * Generate the serialization method (if needed) + * Generate the writeReplace method (if needed for serialization) */ - /****** This code is out of date -- known to be wrong -- and not currently used ****** - private void generateSerializationMethod(Type samType, String samMethodName) { - String samMethodDesc = samMethodType.toMethodDescriptorString(); - TypeConvertingMethodAdapter mv = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL, NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, null, null)); + private void generateWriteReplace() { + TypeConvertingMethodAdapter mv + = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL, + NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, + null, null)); mv.visitCode(); mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA); - mv.dup(); - mv.visitLdcInsn(samType); - mv.visitLdcInsn(samMethodName); - mv.visitLdcInsn(samMethodDesc); - mv.visitLdcInsn(Type.getType(implDefiningClass)); - mv.visitLdcInsn(implMethodName); - mv.visitLdcInsn(implMethodDesc); + mv.visitInsn(DUP);; + mv.visitLdcInsn(Type.getType(targetClass)); + mv.visitLdcInsn(samInfo.getReferenceKind()); + mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/')); + mv.visitLdcInsn(samInfo.getName()); + mv.visitLdcInsn(samInfo.getMethodType().toMethodDescriptorString()); + mv.visitLdcInsn(implInfo.getReferenceKind()); + mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/')); + mv.visitLdcInsn(implInfo.getName()); + mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString()); + mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString()); mv.iconst(argTypes.length); mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT); for (int i = 0; i < argTypes.length; i++) { - mv.dup(); + mv.visitInsn(DUP); mv.iconst(i); mv.visitVarInsn(ALOAD, 0); - mv.getfield(lambdaClassName, argNames[i], argTypes[i].getDescriptor()); - mv.boxIfPrimitive(argTypes[i]); + mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor()); + mv.boxIfTypePrimitive(argTypes[i]); mv.visitInsn(AASTORE); } - mv.invokespecial(NAME_SERIALIZED_LAMBDA, NAME_CTOR, - "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V"); + mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR, + DESCR_CTOR_SERIALIZED_LAMBDA); mv.visitInsn(ARETURN); mv.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored mv.visitEnd(); } - ********/ /** * Generate a method which calls the lambda implementation method, @@ -321,11 +345,11 @@ if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { visitTypeInsn(NEW, implMethodClassName); - dup(); + visitInsn(DUP);; } for (int i = 0; i < argTypes.length; i++) { visitVarInsn(ALOAD, 0); - getfield(lambdaClassName, argNames[i], argTypes[i].getDescriptor()); + visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor()); } convertArgumentTypes(Type.getArgumentTypes(m)); @@ -337,7 +361,7 @@ // Note: if adapting from non-void to void, the 'return' instruction will pop the unneeded result Type samReturnType = Type.getReturnType(m); convertType(implMethodReturnType, samReturnType, samReturnType); - areturn(samReturnType); + visitInsn(samReturnType.getOpcode(Opcodes.IRETURN)); visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored visitEnd(); @@ -352,7 +376,7 @@ Type rcvrType = samArgumentTypes[0]; Type instantiatedRcvrType = instantiatedArgumentTypes[0]; - load(lvIndex + 1, rcvrType); + visitVarInsn(rcvrType.getOpcode(ILOAD), lvIndex + 1); lvIndex += rcvrType.getSize(); convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType); } @@ -362,7 +386,7 @@ Type targetType = implMethodArgumentTypes[argOffset + i]; Type instantiatedArgType = instantiatedArgumentTypes[i]; - load(lvIndex + 1, argType); + visitVarInsn(argType.getOpcode(ILOAD), lvIndex + 1); lvIndex += argType.getSize(); convertType(argType, targetType, instantiatedArgType); } @@ -388,45 +412,5 @@ throw new InternalError("Unexpected invocation kind: " + implKind); } } - - /** - * The following methods are copied from - * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very - * small and fast Java bytecode manipulation framework. Copyright (c) - * 2000-2005 INRIA, France Telecom All rights reserved. - * - * Subclass with that (removing these methods) if that package/class is - * ever added to the JDK. - */ - private void iconst(final int cst) { - if (cst >= -1 && cst <= 5) { - mv.visitInsn(Opcodes.ICONST_0 + cst); - } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) { - mv.visitIntInsn(Opcodes.BIPUSH, cst); - } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) { - mv.visitIntInsn(Opcodes.SIPUSH, cst); - } else { - mv.visitLdcInsn(cst); - } - } - - private void load(final int var, final Type type) { - mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var); - } - - private void dup() { - mv.visitInsn(Opcodes.DUP); - } - - private void areturn(final Type t) { - mv.visitInsn(t.getOpcode(Opcodes.IRETURN)); - } - - private void getfield( - final String owner, - final String name, - final String desc) { - mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc); - } } }
--- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java Tue Mar 12 16:40:22 2013 -0700 @@ -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 @@ -42,14 +42,13 @@ * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, * produces the lambda object. * - * <p>Two pieces of information are needed about the functional interface: the SAM method and the type of the SAM - * method in the functional interface. The type can be different when parameterized types are used. For example, - * consider - * <code>interface I<T> { int m(T x); }</code> if this SAM type is used in a lambda - * <code>I<Byte> v = ...</code>, we need both the actual SAM method which has the signature - * <code>(Object)int</code> and the functional interface type of the method, which has signature - * <code>(Byte)int</code>. The latter is the instantiated erased functional interface method type, or - * simply <I>instantiated method type</I>. + * <p>When parameterized types are used, the instantiated type of the functional interface method may be different + * from that in the functional interface. For example, consider + * <code>interface I<T> { int m(T x); }</code> if this functional interface type is used in a lambda + * <code>I<Byte> v = ...</code>, we need both the actual functional interface method which has the signature + * <code>(Object)int</code> and the erased instantiated type of the functional interface method (or simply + * <I>instantiated method type</I>), which has signature + * <code>(Byte)int</code>. * * <p>While functional interfaces only have a single abstract method from the language perspective (concrete * methods in Object are and default methods may be present), at the bytecode level they may actually have multiple @@ -138,11 +137,25 @@ * </tr> * </table> * + * The default bootstrap ({@link #metaFactory}) represents the common cases and uses an optimized protocol. + * Alternate bootstraps (e.g., {@link #altMetaFactory}) exist to support uncommon cases such as serialization + * or additional marker superinterfaces. * */ public class LambdaMetafactory { + /** Flag for alternate metafactories indicating the lambda object is must to be serializable */ + public static final int FLAG_SERIALIZABLE = 1 << 0; + /** + * Flag for alternate metafactories indicating the lambda object implements other marker interfaces + * besides Serializable + */ + public static final int FLAG_MARKERS = 1 << 1; + + private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; + +/** * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces. * * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges @@ -158,7 +171,8 @@ * @param implMethod The implementation method which should be called (with suitable adaptation of argument * types, return types, and adjustment for captured arguments) when methods of the resulting * functional interface instance are invoked. - * @param instantiatedMethodType The signature of the SAM method from the functional interface's perspective + * @param instantiatedMethodType The signature of the primary functional interface method after type variables + * are substituted with their instantiation from the capture site * @return a CallSite, which, when invoked, will return an instance of the functional interface * @throws ReflectiveOperationException * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated @@ -171,7 +185,72 @@ MethodType instantiatedMethodType) throws ReflectiveOperationException, LambdaConversionException { AbstractValidatingLambdaMetafactory mf; - mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType); + mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, + 0, EMPTY_CLASS_ARRAY); + mf.validateMetafactoryArgs(); + return mf.buildCallSite(); + } + + /** + * Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces, + * which supports serialization and other uncommon options. + * + * The declared argument list for this method is: + * + * CallSite altMetaFactory(MethodHandles.Lookup caller, + * String invokedName, + * MethodType invokedType, + * Object... args) + * + * but it behaves as if the argument list is: + * + * CallSite altMetaFactory(MethodHandles.Lookup caller, + * String invokedName, + * MethodType invokedType, + * MethodHandle samMethod + * MethodHandle implMethod, + * MethodType instantiatedMethodType, + * int flags, + * int markerInterfaceCount, // IF flags has MARKERS set + * Class... markerInterfaces // IF flags has MARKERS set + * ) + * + * + * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges + * of the caller. + * @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site. + * Currently unused. + * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu + * expected static type of the returned lambda object, and the static types of the captured + * arguments for the lambda. In the event that the implementation method is an instance method, + * the first argument in the invocation signature will correspond to the receiver. + * @param args argument to pass, flags, marker interface count, and marker interfaces as described above + * @return a CallSite, which, when invoked, will return an instance of the functional interface + * @throws ReflectiveOperationException + * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated + */ + public static CallSite altMetaFactory(MethodHandles.Lookup caller, + String invokedName, + MethodType invokedType, + Object... args) + throws ReflectiveOperationException, LambdaConversionException { + MethodHandle samMethod = (MethodHandle)args[0]; + MethodHandle implMethod = (MethodHandle)args[1]; + MethodType instantiatedMethodType = (MethodType)args[2]; + int flags = (Integer) args[3]; + Class<?>[] markerInterfaces; + int argIndex = 4; + if ((flags & FLAG_MARKERS) != 0) { + int markerCount = (Integer) args[argIndex++]; + markerInterfaces = new Class<?>[markerCount]; + System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount); + argIndex += markerCount; + } + else + markerInterfaces = EMPTY_CLASS_ARRAY; + AbstractValidatingLambdaMetafactory mf; + mf = new InnerClassLambdaMetafactory(caller, invokedType, samMethod, implMethod, instantiatedMethodType, + flags, markerInterfaces); mf.validateMetafactoryArgs(); return mf.buildCallSite(); }
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -1250,8 +1250,6 @@ /*non-public*/ MethodHandle viewAsType(MethodType newType) { // No actual conversions, just a new view of the same method. - if (!type.isViewableAs(newType)) - throw new InternalError(); return MethodHandleImpl.makePairwiseConvert(this, newType, 0); } @@ -1268,6 +1266,11 @@ } /*non-public*/ + boolean isInvokeSpecial() { + return false; // DMH.Special returns true + } + + /*non-public*/ Object internalValues() { return null; }
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -367,11 +367,11 @@ @Override MethodHandle viewAsType(MethodType newType) { - MethodHandle mh = super.viewAsType(newType); + if (newType.lastParameterType() != type().lastParameterType()) + throw new InternalError(); + MethodHandle newTarget = asFixedArity().viewAsType(newType); // put back the varargs bit: - MethodType type = mh.type(); - int arity = type.parameterCount(); - return mh.asVarargsCollector(type.parameterType(arity-1)); + return new AsVarargsCollector(newTarget, newType, arrayType); } @Override @@ -379,6 +379,12 @@ return asFixedArity().internalMemberName(); } + /*non-public*/ + @Override + boolean isInvokeSpecial() { + return asFixedArity().isInvokeSpecial(); + } + @Override MethodHandle bindArgument(int pos, char basicType, Object value) {
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java Tue Mar 12 16:40:22 2013 -0700 @@ -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 @@ -26,10 +26,12 @@ package java.lang.invoke; import java.lang.invoke.MethodHandleNatives.Constants; -//Not yet public: public -class MethodHandleInfo { +/** + * Cracking (reflecting) method handles back into their constituent symbolic parts. + * + */ +final class MethodHandleInfo { public static final int - REF_NONE = Constants.REF_NONE, REF_getField = Constants.REF_getField, REF_getStatic = Constants.REF_getStatic, REF_putField = Constants.REF_putField, @@ -45,12 +47,17 @@ private final MethodType methodType; private final int referenceKind; - public MethodHandleInfo(MethodHandle mh) throws ReflectiveOperationException { + public MethodHandleInfo(MethodHandle mh) { MemberName mn = mh.internalMemberName(); + if (mn == null) throw new IllegalArgumentException("not a direct method handle"); this.declaringClass = mn.getDeclaringClass(); this.name = mn.getName(); - this.methodType = mn.getMethodType(); - this.referenceKind = mn.getReferenceKind(); + this.methodType = mn.getMethodOrFieldType(); + byte refKind = mn.getReferenceKind(); + if (refKind == REF_invokeSpecial && !mh.isInvokeSpecial()) + // Devirtualized method invocation is usually formally virtual. + refKind = REF_invokeVirtual; + this.referenceKind = refKind; } public Class<?> getDeclaringClass() { @@ -65,7 +72,32 @@ return methodType; } + public int getModifiers() { + return -1; //TODO + } + public int getReferenceKind() { return referenceKind; } + + static String getReferenceKindString(int referenceKind) { + switch (referenceKind) { + case REF_getField: return "getfield"; + case REF_getStatic: return "getstatic"; + case REF_putField: return "putfield"; + case REF_putStatic: return "putstatic"; + case REF_invokeVirtual: return "invokevirtual"; + case REF_invokeStatic: return "invokestatic"; + case REF_invokeSpecial: return "invokespecial"; + case REF_newInvokeSpecial: return "newinvokespecial"; + case REF_invokeInterface: return "invokeinterface"; + default: return "UNKNOWN_REFENCE_KIND" + "[" + referenceKind + "]"; + } + } + + @Override + public String toString() { + return String.format("%s %s.%s:%s", getReferenceKindString(referenceKind), + declaringClass.getName(), name, methodType); + } }
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -1209,7 +1209,7 @@ checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); - MethodHandle mh = DirectMethodHandle.make(refc, method); + MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); mh = maybeBindCaller(method, mh); mh = mh.setVarargs(method); if (doRestrict)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java Tue Mar 12 16:40:22 2013 -0700 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 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 + * 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.invoke; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Objects; + +/** + * Serialized form of a lambda expression. The properties of this class represent the information that is present + * at the lambda factory site, including the identity of the primary functional interface method, the identity of the + * implementation method, and any variables captured from the local environment at the time of lambda capture. + * + * @see LambdaMetafactory + */ +public final class SerializedLambda implements Serializable { + private static final long serialVersionUID = 8025925345765570181L; + private final Class<?> capturingClass; + private final String functionalInterfaceClass; + private final String functionalInterfaceMethodName; + private final String functionalInterfaceMethodSignature; + private final int functionalInterfaceMethodKind; + private final String implClass; + private final String implMethodName; + private final String implMethodSignature; + private final int implMethodKind; + private final String instantiatedMethodType; + private final Object[] capturedArgs; + + /** + * Create a {@code SerializedLambda} from the low-level information present at the lambda factory site. + * + * @param capturingClass The class in which the lambda expression appears + * @param functionalInterfaceMethodKind Method handle kind (see {@link MethodHandleInfo}) for the + * functional interface method handle present at the lambda factory site + * @param functionalInterfaceClass Name, in slash-delimited form, for the functional interface class present at the + * lambda factory site + * @param functionalInterfaceMethodName Name of the primary method for the functional interface present at the + * lambda factory site + * @param functionalInterfaceMethodSignature Signature of the primary method for the functional interface present + * at the lambda factory site + * @param implMethodKind Method handle kind for the implementation method + * @param implClass Name, in slash-delimited form, for the class holding the implementation method + * @param implMethodName Name of the implementation method + * @param implMethodSignature Signature of the implementation method + * @param instantiatedMethodType The signature of the primary functional interface method after type variables + * are substituted with their instantiation from the capture site + * @param capturedArgs The dynamic arguments to the lambda factory site, which represent variables captured by + * the lambda + */ + public SerializedLambda(Class<?> capturingClass, + int functionalInterfaceMethodKind, + String functionalInterfaceClass, + String functionalInterfaceMethodName, + String functionalInterfaceMethodSignature, + int implMethodKind, + String implClass, + String implMethodName, + String implMethodSignature, + String instantiatedMethodType, + Object[] capturedArgs) { + this.capturingClass = capturingClass; + this.functionalInterfaceMethodKind = functionalInterfaceMethodKind; + this.functionalInterfaceClass = functionalInterfaceClass; + this.functionalInterfaceMethodName = functionalInterfaceMethodName; + this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature; + this.implMethodKind = implMethodKind; + this.implClass = implClass; + this.implMethodName = implMethodName; + this.implMethodSignature = implMethodSignature; + this.instantiatedMethodType = instantiatedMethodType; + this.capturedArgs = Objects.requireNonNull(capturedArgs).clone(); + } + + /** Get the name of the class that captured this lambda */ + public String getCapturingClass() { + return capturingClass.getName().replace('.', '/'); + } + + /** Get the name of the functional interface class to which this lambda has been converted */ + public String getFunctionalInterfaceClass() { + return functionalInterfaceClass; + } + + /** Get the name of the primary method for the functional interface to which this lambda has been converted */ + public String getFunctionalInterfaceMethodName() { + return functionalInterfaceMethodName; + } + + /** Get the signature of the primary method for the functional interface to which this lambda has been converted */ + public String getFunctionalInterfaceMethodSignature() { + return functionalInterfaceMethodSignature; + } + + /** Get the method handle kind (see {@link MethodHandleInfo}) of the primary method for the functional interface + * to which this lambda has been converted */ + public int getFunctionalInterfaceMethodKind() { + return functionalInterfaceMethodKind; + } + + /** Get the name of the class containing the implementation method */ + public String getImplClass() { + return implClass; + } + + /** Get the name of the implementation method */ + public String getImplMethodName() { + return implMethodName; + } + + /** Get the signature of the implementation method */ + public String getImplMethodSignature() { + return implMethodSignature; + } + + /** Get the method handle kind (see {@link MethodHandleInfo}) of the implementation method */ + public int getImplMethodKind() { + return implMethodKind; + } + + /** + * Get the signature of the primary functional interface method after type variables are substituted with + * their instantiation from the capture site + */ + public final String getInstantiatedMethodType() { + return instantiatedMethodType; + } + + /** Get the count of dynamic arguments to the lambda capture site */ + public int getCapturedArgCount() { + return capturedArgs.length; + } + + /** Get a dynamic argument to the lambda capture site */ + public Object getCapturedArg(int i) { + return capturedArgs[i]; + } + + private Object readResolve() throws ReflectiveOperationException { + try { + Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { + @Override + public Method run() throws Exception { + Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); + m.setAccessible(true); + return m; + } + }); + + return deserialize.invoke(null, this); + } + catch (PrivilegedActionException e) { + Exception cause = e.getException(); + if (cause instanceof ReflectiveOperationException) + throw (ReflectiveOperationException) cause; + else if (cause instanceof RuntimeException) + throw (RuntimeException) cause; + else + throw new RuntimeException("Exception in SerializedLambda.readResolve", e); + } + } + + @Override + public String toString() { + return String.format("SerializedLambda[capturingClass=%s, functionalInterfaceMethod=%s %s.%s:%s, " + + "implementation=%s %s.%s:%s, instantiatedMethodType=%s, numCaptured=%d]", + capturingClass, MethodHandleInfo.getReferenceKindString(functionalInterfaceMethodKind), + functionalInterfaceClass, functionalInterfaceMethodName, functionalInterfaceMethodSignature, + MethodHandleInfo.getReferenceKindString(implMethodKind), implClass, implMethodName, + implMethodSignature, instantiatedMethodType, capturedArgs.length); + } +}
--- a/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Tue Mar 12 16:40:22 2013 -0700 @@ -27,6 +27,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.Type; import sun.invoke.util.Wrapper; import static sun.invoke.util.Wrapper.*; @@ -49,6 +50,9 @@ private static final Wrapper[] FROM_WRAPPER_NAME = new Wrapper[16]; + // Table of wrappers for primitives, indexed by ASM type sorts + private static final Wrapper[] FROM_TYPE_SORT = new Wrapper[16]; + static { for (Wrapper w : Wrapper.values()) { if (w.basicTypeChar() != 'L') { @@ -71,6 +75,15 @@ initWidening(DOUBLE, Opcodes.I2D, BYTE, SHORT, INT, CHAR); initWidening(DOUBLE, Opcodes.F2D, FLOAT); initWidening(DOUBLE, Opcodes.L2D, LONG); + + FROM_TYPE_SORT[Type.BYTE] = Wrapper.BYTE; + FROM_TYPE_SORT[Type.SHORT] = Wrapper.SHORT; + FROM_TYPE_SORT[Type.INT] = Wrapper.INT; + FROM_TYPE_SORT[Type.LONG] = Wrapper.LONG; + FROM_TYPE_SORT[Type.CHAR] = Wrapper.CHAR; + FROM_TYPE_SORT[Type.FLOAT] = Wrapper.FLOAT; + FROM_TYPE_SORT[Type.DOUBLE] = Wrapper.DOUBLE; + FROM_TYPE_SORT[Type.BOOLEAN] = Wrapper.BOOLEAN; } private static void initWidening(Wrapper to, int opcode, Wrapper... from) { @@ -124,8 +137,9 @@ return "()" + w.basicTypeChar(); } - void boxIfPrimitive(Wrapper w) { - if (w.zero() != null) { + void boxIfTypePrimitive(Type t) { + Wrapper w = FROM_TYPE_SORT[t.getSort()]; + if (w != null) { box(w); } } @@ -264,4 +278,22 @@ } } } + + /** + * The following method is copied from + * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very small + * and fast Java bytecode manipulation framework. + * Copyright (c) 2000-2005 INRIA, France Telecom All rights reserved. + */ + void iconst(final int cst) { + if (cst >= -1 && cst <= 5) { + mv.visitInsn(Opcodes.ICONST_0 + cst); + } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) { + mv.visitIntInsn(Opcodes.BIPUSH, cst); + } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) { + mv.visitIntInsn(Opcodes.SIPUSH, cst); + } else { + mv.visitLdcInsn(cst); + } + } }
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Tue Mar 12 16:40:22 2013 -0700 @@ -181,6 +181,16 @@ } /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Tue Mar 12 16:40:22 2013 -0700 @@ -26,6 +26,7 @@ package java.lang.reflect; import java.lang.annotation.Annotation; +import java.lang.annotation.AnnotationFormatError; /** * Represents an annotated element of the program currently running in this @@ -86,8 +87,8 @@ * * <p>Attempting to read annotations of a repeatable annotation type T * that are contained in an annotation whose type is not, in fact, the - * containing annotation type of T will result in an - * InvalidContainerAnnotationError. + * containing annotation type of T, will result in an {@link + * AnnotationFormatError}. * * <p>Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link @@ -96,10 +97,9 @@ * * @see java.lang.EnumConstantNotPresentException * @see java.lang.TypeNotPresentException - * @see java.lang.annotation.AnnotationFormatError + * @see AnnotationFormatError * @see java.lang.annotation.AnnotationTypeMismatchException * @see java.lang.annotation.IncompleteAnnotationException - * @see java.lang.annotation.InvalidContainerAnnotationError * @since 1.5 * @author Josh Bloch */
--- a/jdk/src/share/classes/java/lang/reflect/Constructor.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java Tue Mar 12 16:40:22 2013 -0700 @@ -532,6 +532,7 @@ * {@inheritDoc} * @since 1.8 */ + @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getDeclaringClass()); }
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java Tue Mar 12 16:40:22 2013 -0700 @@ -476,6 +476,20 @@ return declaredAnnotations; } + /** + * Returns an AnnotatedType object that represents the potentially + * annotated return type of the method/constructor represented by this + * Executable. + * + * If this Executable represents a constructor, the AnnotatedType object + * represents the type of the constructed object. + * + * If this Executable represents a method, the AnnotatedType object + * represents the use of a type to specify the return type of the method. + * + * @since 1.8 + */ + public abstract AnnotatedType getAnnotatedReturnType(); /* Helper for subclasses of Executable. *
--- a/jdk/src/share/classes/java/lang/reflect/Method.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/Method.java Tue Mar 12 16:40:22 2013 -0700 @@ -629,6 +629,7 @@ * {@inheritDoc} * @since 1.8 */ + @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getGenericReturnType()); }
--- a/jdk/src/share/classes/java/lang/reflect/Parameter.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java Tue Mar 12 16:40:22 2013 -0700 @@ -115,7 +115,9 @@ (type.toString()); sb.append(Modifier.toString(getModifiers())); - sb.append(" "); + + if(0 != modifiers) + sb.append(" "); if(isVarArgs()) sb.append(typename.replaceFirst("\\[\\]$", "..."));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/net/HttpConnectSocketImpl.java Tue Mar 12 16:40:22 2013 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2010, 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.net; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Basic SocketImpl that relies on the internal HTTP protocol handler + * implementation to perform the HTTP tunneling and authentication. The + * sockets impl is swapped out and replaced with the socket from the HTTP + * handler after the tunnel is successfully setup. + * + * @since 1.8 + */ + +/*package*/ class HttpConnectSocketImpl extends PlainSocketImpl { + + private static final String httpURLClazzStr = + "sun.net.www.protocol.http.HttpURLConnection"; + private static final String netClientClazzStr = "sun.net.NetworkClient"; + private static final String doTunnelingStr = "doTunneling"; + private static final Field httpField; + private static final Field serverSocketField; + private static final Method doTunneling; + + private final String server; + private InetSocketAddress external_address; + private HashMap<Integer, Object> optionsMap = new HashMap<>(); + + static { + try { + Class<?> httpClazz = Class.forName(httpURLClazzStr, true, null); + httpField = httpClazz.getDeclaredField("http"); + doTunneling = httpClazz.getDeclaredMethod(doTunnelingStr); + Class<?> netClientClazz = Class.forName(netClientClazzStr, true, null); + serverSocketField = netClientClazz.getDeclaredField("serverSocket"); + + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<Void>() { + public Void run() { + httpField.setAccessible(true); + serverSocketField.setAccessible(true); + return null; + } + }); + } catch (ReflectiveOperationException x) { + throw new InternalError("Should not reach here", x); + } + } + + HttpConnectSocketImpl(String server, int port) { + this.server = server; + this.port = port; + } + + HttpConnectSocketImpl(Proxy proxy) { + SocketAddress a = proxy.address(); + if ( !(a instanceof InetSocketAddress) ) + throw new IllegalArgumentException("Unsupported address type"); + + InetSocketAddress ad = (InetSocketAddress) a; + server = ad.getHostString(); + port = ad.getPort(); + } + + @Override + protected void connect(SocketAddress endpoint, int timeout) + throws IOException + { + if (endpoint == null || !(endpoint instanceof InetSocketAddress)) + throw new IllegalArgumentException("Unsupported address type"); + final InetSocketAddress epoint = (InetSocketAddress)endpoint; + final String destHost = epoint.isUnresolved() ? epoint.getHostName() + : epoint.getAddress().getHostAddress(); + final int destPort = epoint.getPort(); + + SecurityManager security = System.getSecurityManager(); + if (security != null) + security.checkConnect(destHost, destPort); + + // Connect to the HTTP proxy server + String urlString = "http://" + destHost + ":" + destPort; + Socket httpSocket = privilegedDoTunnel(urlString, timeout); + + // Success! + external_address = epoint; + + // close the original socket impl and release its descriptor + close(); + + // update the Sockets impl to the impl from the http Socket + AbstractPlainSocketImpl psi = (AbstractPlainSocketImpl) httpSocket.impl; + this.getSocket().impl = psi; + + // best effort is made to try and reset options previously set + Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet(); + try { + for(Map.Entry<Integer,Object> entry : options) { + psi.setOption(entry.getKey(), entry.getValue()); + } + } catch (IOException x) { /* gulp! */ } + } + + @Override + public void setOption(int opt, Object val) throws SocketException { + super.setOption(opt, val); + + if (external_address != null) + return; // we're connected, just return + + // store options so that they can be re-applied to the impl after connect + optionsMap.put(opt, val); + } + + private Socket privilegedDoTunnel(final String urlString, + final int timeout) + throws IOException + { + try { + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction<Socket>() { + public Socket run() throws IOException { + return doTunnel(urlString, timeout); + } + }); + } catch (java.security.PrivilegedActionException pae) { + throw (IOException) pae.getException(); + } + } + + private Socket doTunnel(String urlString, int connectTimeout) + throws IOException + { + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port)); + URL destURL = new URL(urlString); + HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy); + conn.setConnectTimeout(connectTimeout); + conn.setReadTimeout(this.timeout); + conn.connect(); + doTunneling(conn); + try { + Object httpClient = httpField.get(conn); + return (Socket) serverSocketField.get(httpClient); + } catch (IllegalAccessException x) { + throw new InternalError("Should not reach here", x); + } + } + + private void doTunneling(HttpURLConnection conn) { + try { + doTunneling.invoke(conn); + } catch (ReflectiveOperationException x) { + throw new InternalError("Should not reach here", x); + } + } + + @Override + protected InetAddress getInetAddress() { + if (external_address != null) + return external_address.getAddress(); + else + return super.getInetAddress(); + } + + @Override + protected int getPort() { + if (external_address != null) + return external_address.getPort(); + else + return super.getPort(); + } + + @Override + protected int getLocalPort() { + if (socket != null) + return super.getLocalPort(); + if (external_address != null) + return external_address.getPort(); + else + return super.getLocalPort(); + } +}
--- a/jdk/src/share/classes/java/net/Socket.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/net/Socket.java Tue Mar 12 16:40:22 2013 -0700 @@ -117,8 +117,10 @@ if (proxy == null) { throw new IllegalArgumentException("Invalid Proxy"); } - Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy); - if (p.type() == Proxy.Type.SOCKS) { + Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY + : sun.net.ApplicationProxy.create(proxy); + Proxy.Type type = p.type(); + if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) { SecurityManager security = System.getSecurityManager(); InetSocketAddress epoint = (InetSocketAddress) p.address(); if (epoint.getAddress() != null) { @@ -133,7 +135,8 @@ security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } - impl = new SocksSocketImpl(p); + impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p) + : new HttpConnectSocketImpl(p); impl.setSocket(this); } else { if (p == Proxy.NO_PROXY) {
--- a/jdk/src/share/classes/java/net/URL.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/net/URL.java Tue Mar 12 16:40:22 2013 -0700 @@ -661,8 +661,8 @@ * @param file the file on the host * @param ref the internal reference in the URL */ - protected void set(String protocol, String host, - int port, String file, String ref) { + void set(String protocol, String host, int port, + String file, String ref) { synchronized (this) { this.protocol = protocol; this.host = host; @@ -698,9 +698,9 @@ * @param query the query part of this URL * @since 1.3 */ - protected void set(String protocol, String host, int port, - String authority, String userInfo, String path, - String query, String ref) { + void set(String protocol, String host, int port, + String authority, String userInfo, String path, + String query, String ref) { synchronized (this) { this.protocol = protocol; this.host = host;
--- a/jdk/src/share/classes/java/net/URLStreamHandler.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/net/URLStreamHandler.java Tue Mar 12 16:40:22 2013 -0700 @@ -509,8 +509,8 @@ /** * Sets the fields of the <code>URL</code> argument to the indicated values. - * Only classes derived from URLStreamHandler are supposed to be able - * to call the set method on a URL. + * Only classes derived from URLStreamHandler are able + * to use this method to set the values of the URL fields. * * @param u the URL to modify. * @param protocol the protocol name. @@ -539,8 +539,8 @@ /** * Sets the fields of the <code>URL</code> argument to the indicated values. - * Only classes derived from URLStreamHandler are supposed to be able - * to call the set method on a URL. + * Only classes derived from URLStreamHandler are able + * to use this method to set the values of the URL fields. * * @param u the URL to modify. * @param protocol the protocol name. This value is ignored since 1.2.
--- a/jdk/src/share/classes/java/nio/file/Files.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/nio/file/Files.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1152,7 +1152,7 @@ * and file system dependent and therefore unspecified. Minimally, the * {@link BasicFileAttributes#lastModifiedTime last-modified-time} is * copied to the target file if supported by both the source and target - * file store. Copying of file timestamps may result in precision + * file stores. Copying of file timestamps may result in precision * loss. </td> * </tr> * <tr> @@ -1169,12 +1169,12 @@ * implementation specific options. * * <p> Copying a file is not an atomic operation. If an {@link IOException} - * is thrown then it possible that the target file is incomplete or some of - * its file attributes have not been copied from the source file. When the - * {@code REPLACE_EXISTING} option is specified and the target file exists, - * then the target file is replaced. The check for the existence of the file - * and the creation of the new file may not be atomic with respect to other - * file system activities. + * is thrown, then it is possible that the target file is incomplete or some + * of its file attributes have not been copied from the source file. When + * the {@code REPLACE_EXISTING} option is specified and the target file + * exists, then the target file is replaced. The check for the existence of + * the file and the creation of the new file may not be atomic with respect + * to other file system activities. * * <p> <b>Usage Example:</b> * Suppose we want to copy a file into a directory, giving it the same file @@ -1279,15 +1279,16 @@ * <p> An implementation of this interface may support additional * implementation specific options. * - * <p> Where the move requires that the file be copied then the {@link - * BasicFileAttributes#lastModifiedTime last-modified-time} is copied to the - * new file. An implementation may also attempt to copy other file - * attributes but is not required to fail if the file attributes cannot be - * copied. When the move is performed as a non-atomic operation, and a {@code - * IOException} is thrown, then the state of the files is not defined. The - * original file and the target file may both exist, the target file may be - * incomplete or some of its file attributes may not been copied from the - * original file. + * <p> Moving a file will copy the {@link + * BasicFileAttributes#lastModifiedTime last-modified-time} to the target + * file if supported by both source and target file stores. Copying of file + * timestamps may result in precision loss. An implementation may also + * attempt to copy other file attributes but is not required to fail if the + * file attributes cannot be copied. When the move is performed as + * a non-atomic operation, and an {@code IOException} is thrown, then the + * state of the files is not defined. The original file and the target file + * may both exist, the target file may be incomplete or some of its file + * attributes may not been copied from the original file. * * <p> <b>Usage Examples:</b> * Suppose we want to rename a file to "newname", keeping the file in the
--- a/jdk/src/share/classes/java/sql/CallableStatement.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/sql/CallableStatement.java Tue Mar 12 16:40:22 2013 -0700 @@ -2621,7 +2621,7 @@ * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. * <p> - * This version of {@code registrOutParameter} should be + * This version of {@code registerOutParameter} should be * used when the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}. *<P> @@ -2649,7 +2649,7 @@ /** * Registers the designated output parameter. * This version of - * the method {@code registrOutParameter} + * the method {@code registerOutParameter} * should be used for a user-defined or {@code REF} output parameter. * Examples * of user-defined types include: {@code STRUCT}, {@code DISTINCT}, @@ -2717,7 +2717,7 @@ * register the OUT Parameter. * If the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}, the version of - * {@code registrOutParameter} that accepts a scale value + * {@code registerOutParameter} that accepts a scale value * should be used. * @exception SQLException if parameterName does not correspond to a named * parameter; if a database access error occurs or @@ -2745,7 +2745,7 @@ * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. * <p> - * This version of {@code registrOutParameter} should be + * This version of {@code registerOutParameter} should be * used when the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}. *<P> @@ -2774,7 +2774,7 @@ /** * Registers the designated output parameter. This version of - * the method {@code registrOutParameter} + * the method {@code registerOutParameter} * should be used for a user-named or REF output parameter. Examples * of user-named types include: STRUCT, DISTINCT, JAVA_OBJECT, and * named array types.
--- a/jdk/src/share/classes/java/text/DateFormat.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/DateFormat.java Tue Mar 12 16:40:22 2013 -0700 @@ -439,7 +439,12 @@ /** * Gets the time formatter with the default formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getTimeInstance(int, Locale) getTimeInstance(DEFAULT, + * Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a time formatter. */ public final static DateFormat getTimeInstance() @@ -449,7 +454,12 @@ /** * Gets the time formatter with the given formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getTimeInstance(int, Locale) getTimeInstance(style, + * Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @param style the given formatting style. For example, * SHORT for "h:mm a" in the US locale. * @return a time formatter. @@ -475,7 +485,12 @@ /** * Gets the date formatter with the default formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getDateInstance(int, Locale) getDateInstance(DEFAULT, + * Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a date formatter. */ public final static DateFormat getDateInstance() @@ -485,7 +500,12 @@ /** * Gets the date formatter with the given formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getDateInstance(int, Locale) getDateInstance(style, + * Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @param style the given formatting style. For example, * SHORT for "M/d/yy" in the US locale. * @return a date formatter. @@ -511,7 +531,12 @@ /** * Gets the date/time formatter with the default formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getDateTimeInstance(int, int, Locale) getDateTimeInstance(DEFAULT, + * DEFAULT, Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a date/time formatter. */ public final static DateFormat getDateTimeInstance() @@ -521,7 +546,12 @@ /** * Gets the date/time formatter with the given date and time - * formatting styles for the default locale. + * formatting styles for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getDateTimeInstance(int, int, Locale) getDateTimeInstance(dateStyle, + * timeStyle, Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @param dateStyle the given date formatting style. For example, * SHORT for "M/d/yy" in the US locale. * @param timeStyle the given time formatting style. For example,
--- a/jdk/src/share/classes/java/text/DateFormatSymbols.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Tue Mar 12 16:40:22 2013 -0700 @@ -104,14 +104,19 @@ /** * Construct a DateFormatSymbols object by loading format data from - * resources for the default locale. This constructor can only + * resources for the default {@link java.util.Locale.Category#FORMAT FORMAT} + * locale. This constructor can only * construct instances for the locales supported by the Java * runtime environment, not for those supported by installed * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider} * implementations. For full locale coverage, use the * {@link #getInstance(Locale) getInstance} method. - * + * <p>This is equivalent to calling + * {@link #DateFormatSymbols(Locale) + * DateFormatSymbols(Locale.getDefault(Locale.Category.FORMAT))}. * @see #getInstance() + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @exception java.util.MissingResourceException * if the resources for the default locale cannot be * found or cannot be loaded. @@ -302,6 +307,10 @@ * as for those supported by installed * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider} * implementations. + * <p>This is equivalent to calling {@link #getInstance(Locale) + * getInstance(Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a <code>DateFormatSymbols</code> instance. * @since 1.6 */
--- a/jdk/src/share/classes/java/text/DecimalFormat.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/DecimalFormat.java Tue Mar 12 16:40:22 2013 -0700 @@ -381,7 +381,8 @@ /** * Creates a DecimalFormat using the default pattern and symbols - * for the default locale. This is a convenient way to obtain a + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * This is a convenient way to obtain a * DecimalFormat when internationalization is not the main concern. * <p> * To obtain standard formats for a given locale, use the factory methods @@ -411,7 +412,8 @@ /** * Creates a DecimalFormat using the given pattern and the symbols - * for the default locale. This is a convenient way to obtain a + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * This is a convenient way to obtain a * DecimalFormat when internationalization is not the main concern. * <p> * To obtain standard formats for a given locale, use the factory methods
--- a/jdk/src/share/classes/java/text/DecimalFormatSymbols.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/DecimalFormatSymbols.java Tue Mar 12 16:40:22 2013 -0700 @@ -71,13 +71,19 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { /** - * Create a DecimalFormatSymbols object for the default locale. + * Create a DecimalFormatSymbols object for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. * This constructor can only construct instances for the locales * supported by the Java runtime environment, not for those * supported by installed * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider} * implementations. For full locale coverage, use the * {@link #getInstance(Locale) getInstance} method. + * <p>This is equivalent to calling + * {@link #DecimalFormatSymbols(Locale) + * DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT */ public DecimalFormatSymbols() { initialize( Locale.getDefault(Locale.Category.FORMAT) ); @@ -133,6 +139,11 @@ * as for those supported by installed * {@link java.text.spi.DecimalFormatSymbolsProvider * DecimalFormatSymbolsProvider} implementations. + * <p>This is equivalent to calling + * {@link #getInstance(Locale) + * getInstance(Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a <code>DecimalFormatSymbols</code> instance. * @since 1.6 */
--- a/jdk/src/share/classes/java/text/MessageFormat.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/MessageFormat.java Tue Mar 12 16:40:22 2013 -0700 @@ -348,7 +348,8 @@ private static final long serialVersionUID = 6479157306784022952L; /** - * Constructs a MessageFormat for the default locale and the + * Constructs a MessageFormat for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale and the * specified pattern. * The constructor first sets the locale, then parses the pattern and * creates a list of subformats for the format elements contained in it.
--- a/jdk/src/share/classes/java/text/NumberFormat.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/NumberFormat.java Tue Mar 12 16:40:22 2013 -0700 @@ -389,7 +389,8 @@ //============== Locale Stuff ===================== /** - * Returns a general-purpose number format for the current default locale. + * Returns a general-purpose number format for the current default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. * This is the same as calling * {@link #getNumberInstance() getNumberInstance()}. */ @@ -407,7 +408,13 @@ } /** - * Returns a general-purpose number format for the current default locale. + * Returns a general-purpose number format for the current default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getNumberInstance(Locale) + * getNumberInstance(Locale.getDefault(Locale.Category.FORMAT))}. + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT */ public final static NumberFormat getNumberInstance() { return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE); @@ -421,14 +428,20 @@ } /** - * Returns an integer number format for the current default locale. The + * Returns an integer number format for the current default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. The * returned number format is configured to round floating point numbers * to the nearest integer using half-even rounding (see {@link * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting, * and to parse only the integer part of an input string (see {@link * #isParseIntegerOnly isParseIntegerOnly}). + * <p>This is equivalent to calling + * {@link #getIntegerInstance(Locale) + * getIntegerInstance(Locale.getDefault(Locale.Category.FORMAT))}. * * @see #getRoundingMode() + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @return a number format for integer values * @since 1.4 */ @@ -453,7 +466,14 @@ } /** - * Returns a currency format for the current default locale. + * Returns a currency format for the current default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getCurrencyInstance(Locale) + * getCurrencyInstance(Locale.getDefault(Locale.Category.FORMAT))}. + * + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT */ public final static NumberFormat getCurrencyInstance() { return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE); @@ -467,7 +487,14 @@ } /** - * Returns a percentage format for the current default locale. + * Returns a percentage format for the current default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. + * <p>This is equivalent to calling + * {@link #getPercentInstance(Locale) + * getPercentInstance(Locale.getDefault(Locale.Category.FORMAT))}. + * + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT */ public final static NumberFormat getPercentInstance() { return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
--- a/jdk/src/share/classes/java/text/SimpleDateFormat.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java Tue Mar 12 16:40:22 2013 -0700 @@ -547,7 +547,8 @@ /** * Constructs a <code>SimpleDateFormat</code> using the default pattern and - * date format symbols for the default locale. + * date format symbols for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. * <b>Note:</b> This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. @@ -560,11 +561,17 @@ /** * Constructs a <code>SimpleDateFormat</code> using the given pattern and - * the default date format symbols for the default locale. + * the default date format symbols for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. * <b>Note:</b> This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. + * <p>This is equivalent to calling + * {@link #SimpleDateFormat(String, Locale) + * SimpleDateFormat(pattern, Locale.getDefault(Locale.Category.FORMAT))}. * + * @see java.util.Locale#getDefault(java.util.Locale.Category) + * @see java.util.Locale.Category#FORMAT * @param pattern the pattern describing the date and time format * @exception NullPointerException if the given pattern is null * @exception IllegalArgumentException if the given pattern is invalid
--- a/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java Tue Mar 12 16:40:22 2013 -0700 @@ -70,7 +70,7 @@ import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoField; import java.util.Arrays; -import java.util.function.Block; +import java.util.function.Consumer; /** * A reader for Hijrah Deviation files. @@ -126,13 +126,13 @@ * @param typeId the name of the calendar * @param calendarType the calendar type * @return {@code true} if the file was read and each entry accepted by the - * Block; else {@code false} no configuration was done + * Consumer; else {@code false} no configuration was done * * @throws IOException for zip/jar file handling exception. * @throws ParseException if the format of the configuration file is wrong. */ static boolean readDeviation(String typeId, String calendarType, - Block<HijrahChronology.Deviation> block) throws IOException, ParseException { + Consumer<HijrahChronology.Deviation> consumer) throws IOException, ParseException { InputStream is = getConfigFileInputStream(typeId); if (is != null) { try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { @@ -142,7 +142,7 @@ num++; HijrahChronology.Deviation entry = parseLine(line, num); if (entry != null) { - block.accept(entry); + consumer.accept(entry); } } }
--- a/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java Tue Mar 12 16:40:22 2013 -0700 @@ -121,10 +121,16 @@ } /** - * Obtains symbols for the default locale. + * Obtains symbols for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. * <p> * This method provides access to locale sensitive symbols. + * <p> + * This is equivalent to calling + * {@link #of(Locale) + * of(Locale.getDefault(Locale.Category.FORMAT))}. * + * @see java.util.Locale.Category#FORMAT * @return the info, not null */ public static DateTimeFormatSymbols ofDefaultLocale() {
--- a/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java Tue Mar 12 16:40:22 2013 -0700 @@ -1007,7 +1007,7 @@ * is used, with {@code IsoChronology} as the fallback. * <p> * Note that this method provides similar functionality to methods on - * {@code DateFormat} such as {@link DateFormat#getDateTimeInstance(int, int)}. + * {@code DateFormat} such as {@link java.text.DateFormat#getDateTimeInstance(int, int)}. * * @param dateStyle the date style to use, null means no date required * @param timeStyle the time style to use, null means no time required
--- a/jdk/src/share/classes/java/util/Calendar.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Calendar.java Tue Mar 12 16:40:22 2013 -0700 @@ -1572,7 +1572,8 @@ /** * Constructs a Calendar with the default time zone - * and locale. + * and the default {@link java.util.Locale.Category#FORMAT FORMAT} + * locale. * @see TimeZone#getDefault */ protected Calendar() @@ -1600,7 +1601,8 @@ /** * Gets a calendar using the default time zone and locale. The * <code>Calendar</code> returned is based on the current time - * in the default time zone with the default locale. + * in the default time zone with the default + * {@link Locale.Category#FORMAT FORMAT} locale. * * @return a Calendar. */ @@ -1614,7 +1616,8 @@ /** * Gets a calendar using the specified time zone and default locale. * The <code>Calendar</code> returned is based on the current time - * in the given time zone with the default locale. + * in the given time zone with the default + * {@link Locale.Category#FORMAT FORMAT} locale. * * @param zone the time zone to use * @return a Calendar.
--- a/jdk/src/share/classes/java/util/Collections.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Collections.java Tue Mar 12 16:40:22 2013 -0700 @@ -3759,7 +3759,7 @@ return c2.compareTo(c1); } - private Object readResolve() { return reverseOrder(); } + private Object readResolve() { return Collections.reverseOrder(); } } /**
--- a/jdk/src/share/classes/java/util/Comparator.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Comparator.java Tue Mar 12 16:40:22 2013 -0700 @@ -25,6 +25,11 @@ package java.util; +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import java.util.function.ToDoubleFunction; + /** * A comparison function, which imposes a <i>total ordering</i> on some * collection of objects. Comparators can be passed to a sort method (such @@ -165,4 +170,93 @@ * @see Object#hashCode() */ boolean equals(Object obj); + + /** + * Returns a comparator that imposes the reverse ordering of this + * comparator. + * + * @return A comparator that imposes the reverse ordering of this + * comparator. + * @since 1.8 + */ + default Comparator<T> reverseOrder() { + return Collections.reverseOrder(this); + } + + /** + * Constructs a lexicographic order comparator with another comparator. + * For example, a {@code Comparator<Person> byLastName} can be composed + * with another {@code Comparator<Person> byFirstName}, then {@code + * byLastName.thenComparing(byFirstName)} creates a {@code + * Comparator<Person>} which sorts by last name, and for equal last names + * sorts by first name. + * + * @param other the other comparator used when equals on this. + * @throws NullPointerException if the argument is null. + * @since 1.8 + */ + default Comparator<T> thenComparing(Comparator<? super T> other) { + return Comparators.compose(this, other); + } + + /** + * Constructs a lexicographic order comparator with a function that + * extracts a {@code Comparable} key. This default implementation calls + * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. + * + * @param <U> the {@link Comparable} type for comparison + * @param keyExtractor the function used to extract the {@link Comparable} sort key + * @throws NullPointerException if the argument is null. + * @see Comparators#comparing(Function) + * @see #thenComparing(Comparator) + * @since 1.8 + */ + default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) { + return thenComparing(Comparators.comparing(keyExtractor)); + } + + /** + * Constructs a lexicographic order comparator with a function that + * extracts a {@code int} value. This default implementation calls {@code + * thenComparing(this, Comparators.comparing(keyExtractor))}. + * + * @param keyExtractor the function used to extract the integer value + * @throws NullPointerException if the argument is null. + * @see Comparators#comparing(ToIntFunction) + * @see #thenComparing(Comparator) + * @since 1.8 + */ + default Comparator<T> thenComparing(ToIntFunction<? super T> keyExtractor) { + return thenComparing(Comparators.comparing(keyExtractor)); + } + + /** + * Constructs a lexicographic order comparator with a function that + * extracts a {@code long} value. This default implementation calls + * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. + * + * @param keyExtractor the function used to extract the long value + * @throws NullPointerException if the argument is null. + * @see Comparators#comparing(ToLongFunction) + * @see #thenComparing(Comparator) + * @since 1.8 + */ + default Comparator<T> thenComparing(ToLongFunction<? super T> keyExtractor) { + return thenComparing(Comparators.comparing(keyExtractor)); + } + + /** + * Constructs a lexicographic order comparator with a function that + * extracts a {@code double} value. This default implementation calls + * {@code thenComparing(this, Comparators.comparing(keyExtractor))}. + * + * @param keyExtractor the function used to extract the double value + * @throws NullPointerException if the argument is null. + * @see Comparators#comparing(ToDoubleFunction) + * @see #thenComparing(Comparator) + * @since 1.8 + */ + default Comparator<T> thenComparing(ToDoubleFunction<? super T> keyExtractor) { + return thenComparing(Comparators.comparing(keyExtractor)); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/util/Comparators.java Tue Mar 12 16:40:22 2013 -0700 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 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 + * 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.util; + +import java.io.Serializable; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; + +/** + * This class consists of {@code static} utility methods for comparators. Mostly + * factory method that returns a {@link Comparator}. + * + * <p> Unless otherwise noted, passing a {@code null} argument to a method in + * this class will cause a {@link NullPointerException} to be thrown. + * + * @see Comparator + * @since 1.8 + */ +public class Comparators { + private Comparators() { + throw new AssertionError("no instances"); + } + + /** + * Compares {@link Comparable} objects in natural order. + * + * @see Comparable + */ + private enum NaturalOrderComparator implements Comparator<Comparable<Object>> { + INSTANCE; + + @Override + public int compare(Comparable<Object> c1, Comparable<Object> c2) { + return c1.compareTo(c2); + } + } + + /** + * Returns a comparator that imposes the reverse of the <em>natural + * ordering</em>. + * + * <p>The returned comparator is serializable. + * + * @param <T> {@link Comparable} type + * + * @return A comparator that imposes the reverse of the <i>natural + * ordering</i> on a collection of objects that implement + * the {@link Comparable} interface. + * @see Comparable + */ + public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { + return Collections.reverseOrder(); + } + + /** + * Returns a comparator that imposes the reverse ordering of the specified + * {@link Comparator}. + * + * <p>The returned comparator is serializable (assuming the specified + * comparator is also serializable). + * + * @param <T> the element type to be compared + * @param cmp a comparator whose ordering is to be reversed by the returned + * comparator + * @return A comparator that imposes the reverse ordering of the + * specified comparator. + */ + public static <T> Comparator<T> reverseOrder(Comparator<T> cmp) { + Objects.requireNonNull(cmp); + return Collections.reverseOrder(cmp); + } + + /** + * Gets a comparator compares {@link Comparable} type in natural order. + * + * @param <T> {@link Comparable} type + */ + public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { + return (Comparator<T>) NaturalOrderComparator.INSTANCE; + } + + /** + * Gets a comparator compares {@link Map.Entry} in natural order on key. + * + * @param <K> {@link Comparable} key type + * @param <V> value type + */ + public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> naturalOrderKeys() { + return (Comparator<Map.Entry<K, V>> & Serializable) + (c1, c2) -> c1.getKey().compareTo(c2.getKey()); + } + + /** + * Gets a comparator compares {@link Map.Entry} in natural order on value. + * + * @param <K> key type + * @param <V> {@link Comparable} value type + */ + public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> naturalOrderValues() { + return (Comparator<Map.Entry<K, V>> & Serializable) + (c1, c2) -> c1.getValue().compareTo(c2.getValue()); + } + + /** + * Gets a comparator compares {@link Map.Entry} by key using the given + * {@link Comparator}. + * + * <p>The returned comparator is serializable assuming the specified + * comparators are also serializable. + * + * @param <K> key type + * @param <V> value type + * @param cmp the key {@link Comparator} + */ + public static <K, V> Comparator<Map.Entry<K, V>> byKey(Comparator<? super K> cmp) { + Objects.requireNonNull(cmp); + return (Comparator<Map.Entry<K, V>> & Serializable) + (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey()); + } + + /** + * Gets a comparator compares {@link Map.Entry} by value using the given + * {@link Comparator}. + * + * @param <K> key type + * @param <V> value type + * @param cmp the value {@link Comparator} + */ + public static <K, V> Comparator<Map.Entry<K, V>> byValue(Comparator<? super V> cmp) { + Objects.requireNonNull(cmp); + return (Comparator<Map.Entry<K, V>> & Serializable) + (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue()); + } + + /** + * Accepts a function that extracts a {@link java.lang.Comparable + * Comparable} sort key from a type {@code T}, and returns a {@code + * Comparator<T>} that compares by that sort key. For example, if a class + * {@code Person} has a {@code String}-valued getter {@code getLastName}, + * then {@code comparing(Person::getLastName)} would return a {@code + * Comparator<Person>} that compares {@code Person} objects by their last + * name. + * + * @param <T> the original element type + * @param <U> the {@link Comparable} type for comparison + * @param keyExtractor the function used to extract the {@link Comparable} sort key + */ + public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator<T> & Serializable) + (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); + } + + /** + * Accepts a function that extracts an {@code int} value from a type {@code + * T}, and returns a {@code Comparator<T>} that compares by that value. + * + * <p>The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param <T> the original element type + * @param keyExtractor the function used to extract the integer value + */ + public static <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator<T> & Serializable) + (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); + } + + /** + * Accepts a function that extracts a {@code long} value from a type {@code + * T}, and returns a {@code Comparator<T>} that compares by that value. + * + * <p>The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param <T> the original element type + * @param keyExtractor the function used to extract the long value + */ + public static <T> Comparator<T> comparing(ToLongFunction<? super T> keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator<T> & Serializable) + (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2)); + } + + /** + * Accepts a function that extracts a {@code double} value from a type + * {@code T}, and returns a {@code Comparator<T>} that compares by that + * value. + * + * <p>The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param <T> the original element type + * @param keyExtractor the function used to extract the double value + */ + public static<T> Comparator<T> comparing(ToDoubleFunction<? super T> keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator<T> & Serializable) + (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); + } + + /** + * Constructs a lexicographic order from two {@link Comparator}s. For + * example, if you have comparators {@code byLastName} and {@code + * byFirstName}, each of type {@code Comparator<Person>}, then {@code + * compose(byLastName, byFirstName)} creates a {@code Comparator<Person>} + * which sorts by last name, and for equal last names sorts by first name. + * + * <p>The returned comparator is serializable assuming the specified + * comparators are also serializable. + * + * @param <T> the element type to be compared + * @param first the first comparator + * @param second the secondary comparator used when equals on the first + */ + public static<T> Comparator<T> compose(Comparator<? super T> first, Comparator<? super T> second) { + Objects.requireNonNull(first); + Objects.requireNonNull(second); + return (Comparator<T> & Serializable) (c1, c2) -> { + int res = first.compare(c1, c2); + return (res != 0) ? res : second.compare(c1, c2); + }; + } + + /** + * Constructs a {@link BinaryOperator} which returns the lesser of two elements + * according to the specified {@code Comparator} + * + * @param comparator A {@code Comparator} for comparing the two values + * @param <T> the type of the elements to be compared + * @return a {@code BinaryOperator} which returns the lesser of its operands, + * according to the supplied {@code Comparator} + */ + public static<T> BinaryOperator<T> lesserOf(Comparator<? super T> comparator) { + return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; + } + + /** + * Constructs a {@link BinaryOperator} which returns the greater of two elements + * according to the specified {@code Comparator} + * + * @param comparator A {@code Comparator} for comparing the two values + * @param <T> the type of the elements to be compared + * @return a {@code BinaryOperator} which returns the greater of its operands, + * according to the supplied {@code Comparator} + */ + public static<T> BinaryOperator<T> greaterOf(Comparator<? super T> comparator) { + return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; + } +}
--- a/jdk/src/share/classes/java/util/Currency.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Currency.java Tue Mar 12 16:40:22 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -472,12 +472,18 @@ } /** - * Gets the symbol of this currency for the default locale. + * Gets the symbol of this currency for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale. * For example, for the US Dollar, the symbol is "$" if the default * locale is the US, while for other locales it may be "US$". If no * symbol can be determined, the ISO 4217 currency code is returned. + * <p> + * This is equivalent to calling + * {@link #getSymbol(Locale) + * getSymbol(Locale.getDefault(Locale.Category.DISPLAY))}. * - * @return the symbol of this currency for the default locale + * @return the symbol of this currency for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale */ public String getSymbol() { return getSymbol(Locale.getDefault(Locale.Category.DISPLAY)); @@ -533,10 +539,16 @@ /** * Gets the name that is suitable for displaying this currency for - * the default locale. If there is no suitable display name found + * the default {@link Locale.Category#DISPLAY DISPLAY} locale. + * If there is no suitable display name found * for the default locale, the ISO 4217 currency code is returned. + * <p> + * This is equivalent to calling + * {@link #getDisplayName(Locale) + * getDisplayName(Locale.getDefault(Locale.Category.DISPLAY))}. * - * @return the display name of this currency for the default locale + * @return the display name of this currency for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale * @since 1.7 */ public String getDisplayName() { @@ -702,7 +714,7 @@ " ignored since cutover date has not passed :" + curdata, null); return; } - } catch (IndexOutOfBoundsException | NullPointerException | ParseException ex) { + } catch (ParseException ex) { info("currency.properties entry for " + ctry + " ignored since exception encountered :" + ex.getMessage(), null); return; @@ -732,8 +744,7 @@ setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry); } - private static boolean isPastCutoverDate(String s) - throws IndexOutOfBoundsException, NullPointerException, ParseException { + private static boolean isPastCutoverDate(String s) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT); format.setTimeZone(TimeZone.getTimeZone("UTC")); format.setLenient(false);
--- a/jdk/src/share/classes/java/util/Formatter.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Formatter.java Tue Mar 12 16:40:22 2013 -0700 @@ -1900,7 +1900,8 @@ * which may be retrieved by invoking {@link #out out()} and whose * current content may be converted into a string by invoking {@link * #toString toString()}. The locale used is the {@linkplain - * Locale#getDefault() default locale} for this instance of the Java + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java * virtual machine. */ public Formatter() { @@ -1910,8 +1911,10 @@ /** * Constructs a new formatter with the specified destination. * - * <p> The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param a * Destination for the formatted output. If {@code a} is @@ -1961,8 +1964,10 @@ * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - * <p> The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param fileName * The name of the file to use as the destination of this @@ -1989,8 +1994,10 @@ /** * Constructs a new formatter with the specified file name and charset. * - * <p> The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param fileName * The name of the file to use as the destination of this @@ -2068,8 +2075,10 @@ * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - * <p> The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param file * The file to use as the destination of this formatter. If the @@ -2096,8 +2105,10 @@ /** * Constructs a new formatter with the specified file and charset. * - * <p> The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param file * The file to use as the destination of this formatter. If the @@ -2171,8 +2182,10 @@ /** * Constructs a new formatter with the specified print stream. * - * <p> The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * <p> Characters are written to the given {@link java.io.PrintStream * PrintStream} object and are therefore encoded using that object's @@ -2193,8 +2206,10 @@ * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - * <p> The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param os * The output stream to use as the destination of this formatter. @@ -2209,8 +2224,10 @@ * Constructs a new formatter with the specified output stream and * charset. * - * <p> The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + * <p> The locale used is the {@linkplain + * Locale#getDefault(Locale.Category) default locale} for + * {@linkplain Locale.Category#FORMAT formatting} for this instance of the Java + * virtual machine. * * @param os * The output stream to use as the destination of this formatter.
--- a/jdk/src/share/classes/java/util/GregorianCalendar.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/GregorianCalendar.java Tue Mar 12 16:40:22 2013 -0700 @@ -587,7 +587,8 @@ /** * Constructs a default <code>GregorianCalendar</code> using the current time - * in the default time zone with the default locale. + * in the default time zone with the default + * {@link Locale.Category#FORMAT FORMAT} locale. */ public GregorianCalendar() { this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT)); @@ -596,7 +597,8 @@ /** * Constructs a <code>GregorianCalendar</code> based on the current time - * in the given time zone with the default locale. + * in the given time zone with the default + * {@link Locale.Category#FORMAT FORMAT} locale. * * @param zone the given time zone. */
--- a/jdk/src/share/classes/java/util/IdentityHashMap.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/IdentityHashMap.java Tue Mar 12 16:40:22 2013 -0700 @@ -25,6 +25,7 @@ package java.util; import java.io.*; +import java.lang.reflect.Array; /** * This class implements the <tt>Map</tt> interface with a hash table, using @@ -1010,6 +1011,37 @@ result += System.identityHashCode(key); return result; } + public Object[] toArray() { + return toArray(new Object[size()]); + } + @SuppressWarnings("unchecked") + public <T> T[] toArray(T[] a) { + int expectedModCount = modCount; + int size = size(); + if (a.length < size) + a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); + Object[] tab = table; + int ti = 0; + for (int si = 0; si < tab.length; si += 2) { + Object key; + if ((key = tab[si]) != null) { // key present ? + // more elements than expected -> concurrent modification from other thread + if (ti >= size) { + throw new ConcurrentModificationException(); + } + a[ti++] = (T) unmaskNull(key); // unmask key + } + } + // fewer elements than expected or concurrent modification from other thread detected + if (ti < size || expectedModCount != modCount) { + throw new ConcurrentModificationException(); + } + // final null marker as per spec + if (ti < a.length) { + a[ti] = null; + } + return a; + } } /** @@ -1062,6 +1094,36 @@ public void clear() { IdentityHashMap.this.clear(); } + public Object[] toArray() { + return toArray(new Object[size()]); + } + @SuppressWarnings("unchecked") + public <T> T[] toArray(T[] a) { + int expectedModCount = modCount; + int size = size(); + if (a.length < size) + a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); + Object[] tab = table; + int ti = 0; + for (int si = 0; si < tab.length; si += 2) { + if (tab[si] != null) { // key present ? + // more elements than expected -> concurrent modification from other thread + if (ti >= size) { + throw new ConcurrentModificationException(); + } + a[ti++] = (T) tab[si+1]; // copy value + } + } + // fewer elements than expected or concurrent modification from other thread detected + if (ti < size || expectedModCount != modCount) { + throw new ConcurrentModificationException(); + } + // final null marker as per spec + if (ti < a.length) { + a[ti] = null; + } + return a; + } } /** @@ -1149,25 +1211,35 @@ } public Object[] toArray() { - int size = size(); - Object[] result = new Object[size]; - Iterator<Map.Entry<K,V>> it = iterator(); - for (int i = 0; i < size; i++) - result[i] = new AbstractMap.SimpleEntry<>(it.next()); - return result; + return toArray(new Object[size()]); } @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { + int expectedModCount = modCount; int size = size(); if (a.length < size) - a = (T[])java.lang.reflect.Array - .newInstance(a.getClass().getComponentType(), size); - Iterator<Map.Entry<K,V>> it = iterator(); - for (int i = 0; i < size; i++) - a[i] = (T) new AbstractMap.SimpleEntry<>(it.next()); - if (a.length > size) - a[size] = null; + a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); + Object[] tab = table; + int ti = 0; + for (int si = 0; si < tab.length; si += 2) { + Object key; + if ((key = tab[si]) != null) { // key present ? + // more elements than expected -> concurrent modification from other thread + if (ti >= size) { + throw new ConcurrentModificationException(); + } + a[ti++] = (T) new AbstractMap.SimpleEntry(unmaskNull(key), tab[si + 1]); + } + } + // fewer elements than expected or concurrent modification from other thread detected + if (ti < size || expectedModCount != modCount) { + throw new ConcurrentModificationException(); + } + // final null marker as per spec + if (ti < a.length) { + a[ti] = null; + } return a; } }
--- a/jdk/src/share/classes/java/util/Locale.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Locale.java Tue Mar 12 16:40:22 2013 -0700 @@ -351,7 +351,8 @@ * you can use <code>getDisplayLanguage</code> to get the name of * the language suitable for displaying to the user. Interestingly, * the <code>getDisplayXXX</code> methods are themselves locale-sensitive - * and have two versions: one that uses the default locale and one + * and have two versions: one that uses the default + * {@link Locale.Category#DISPLAY DISPLAY} locale and one * that uses the locale specified as an argument. * * <p>The Java Platform provides a number of classes that perform locale-sensitive @@ -369,7 +370,8 @@ * </pre> * </blockquote> * Each of these methods has two variants; one with an explicit locale - * and one without; the latter uses the default locale: + * and one without; the latter uses the default + * {@link Locale.Category#FORMAT FORMAT} locale: * <blockquote> * <pre> * NumberFormat.getInstance(myLocale) @@ -1645,11 +1647,15 @@ /** * Returns a name for the locale's language that is appropriate for display to the * user. - * If possible, the name returned will be localized for the default locale. - * For example, if the locale is fr_FR and the default locale + * If possible, the name returned will be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale. + * For example, if the locale is fr_FR and the default + * {@link Locale.Category#DISPLAY DISPLAY} locale * is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and - * the default locale is fr_FR, getDisplayLanguage() will return "anglais". - * If the name returned cannot be localized for the default locale, + * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR, + * getDisplayLanguage() will return "anglais". + * If the name returned cannot be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale, * (say, we don't have a Japanese name for Croatian), * this function falls back on the English name, and uses the ISO code as a last-resort * value. If the locale doesn't specify a language, this function returns the empty string. @@ -1679,10 +1685,12 @@ /** * Returns a name for the the locale's script that is appropriate for display to - * the user. If possible, the name will be localized for the default locale. Returns + * the user. If possible, the name will be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale. Returns * the empty string if this locale doesn't specify a script code. * - * @return the display name of the script code for the current default locale + * @return the display name of the script code for the current default + * {@link Locale.Category#DISPLAY DISPLAY} locale * @since 1.7 */ public String getDisplayScript() { @@ -1695,7 +1703,8 @@ * localized for the given locale. Returns the empty string if * this locale doesn't specify a script code. * - * @return the display name of the script code for the current default locale + * @return the display name of the script code for the current default + * {@link Locale.Category#DISPLAY DISPLAY} locale * @throws NullPointerException if <code>inLocale</code> is <code>null</code> * @since 1.7 */ @@ -1706,11 +1715,15 @@ /** * Returns a name for the locale's country that is appropriate for display to the * user. - * If possible, the name returned will be localized for the default locale. - * For example, if the locale is fr_FR and the default locale + * If possible, the name returned will be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale. + * For example, if the locale is fr_FR and the default + * {@link Locale.Category#DISPLAY DISPLAY} locale * is en_US, getDisplayCountry() will return "France"; if the locale is en_US and - * the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis". - * If the name returned cannot be localized for the default locale, + * the default {@link Locale.Category#DISPLAY DISPLAY} locale is fr_FR, + * getDisplayCountry() will return "Etats-Unis". + * If the name returned cannot be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale, * (say, we don't have a Japanese name for Croatia), * this function falls back on the English name, and uses the ISO code as a last-resort * value. If the locale doesn't specify a country, this function returns the empty string. @@ -1762,7 +1775,8 @@ /** * Returns a name for the locale's variant code that is appropriate for display to the - * user. If possible, the name will be localized for the default locale. If the locale + * user. If possible, the name will be localized for the default + * {@link Locale.Category#DISPLAY DISPLAY} locale. If the locale * doesn't specify a variant code, this function returns the empty string. */ public final String getDisplayVariant() {
--- a/jdk/src/share/classes/java/util/LocaleISOData.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/LocaleISOData.java Tue Mar 12 16:40:22 2013 -0700 @@ -473,7 +473,7 @@ + "YE" + "YEM" // Yemen + "YT" + "MYT" // Mayotte + "ZA" + "ZAF" // South Africa, Republic of - + "ZM" + "ZMW" // Zambia, Republic of + + "ZM" + "ZMB" // Zambia, Republic of + "ZW" + "ZWE" // Zimbabwe ;
--- a/jdk/src/share/classes/java/util/Scanner.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/Scanner.java Tue Mar 12 16:40:22 2013 -0700 @@ -151,7 +151,8 @@ * <p> An instance of this class is capable of scanning numbers in the standard * formats as well as in the formats of the scanner's locale. A scanner's * <a name="initial-locale">initial locale </a>is the value returned by the {@link - * java.util.Locale#getDefault} method; it may be changed via the {@link + * java.util.Locale#getDefault(Locale.Category) + * Locale.getDefault(Locale.Category.FORMAT)} method; it may be changed via the {@link * #useLocale} method. The {@link #reset} method will reset the value of the * scanner's locale to the initial locale regardless of whether it was * previously changed. @@ -2641,7 +2642,7 @@ * * <blockquote><pre> * scanner.useDelimiter("\\p{javaWhitespace}+") - * .useLocale(Locale.getDefault()) + * .useLocale(Locale.getDefault(Locale.Category.FORMAT)) * .useRadix(10); * </pre></blockquote> *
--- a/jdk/src/share/classes/java/util/TimeZone.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/TimeZone.java Tue Mar 12 16:40:22 2013 -0700 @@ -534,7 +534,7 @@ /** * Gets the {@code TimeZone} for the given {@code zoneId}. * - * @param zoneid a {@link ZoneId} from which the time zone ID is obtained + * @param zoneId a {@link ZoneId} from which the time zone ID is obtained * @return the specified {@code TimeZone}, or the GMT zone if the given ID * cannot be understood. * @throws NullPointerException if {@code zoneId} is {@code null}
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Tue Mar 12 16:28:34 2013 -0700 +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Tue Mar 12 16:40:22 2013 -0700 @@ -35,6 +35,7 @@ package java.util.concurrent; +import java.lang.Thread.UncaughtExceptionHandler; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -104,38 +105,45 @@ * there is little difference among choice of methods. * * <table BORDER CELLPADDING=3 CELLSPACING=1> + * <caption>Summary of task execution methods</caption> * <tr> * <td></td> * <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td> * <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td> * </tr> * <tr> - * <td> <b>Arrange async execution</td> + * <td> <b>Arrange async execution</b></td> * <td> {@link #execute(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#fork}</td> * </tr> * <tr> - * <td> <b>Await and obtain result</td> + * <td> <b>Await and obtain result</b></td> * <td> {@link #invoke(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#invoke}</td> * </tr> * <tr> - * <td> <b>Arrange exec and obtain Future</td> + * <td> <b>Arrange exec and obtain Future</b></td> * <td> {@link #submit(ForkJoinTask)}</td> * <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td> * </tr> * </table> * * <p>The common pool is by default constructed with default - * parameters, but these may be controlled by setting three {@link - * System#getProperty system properties} with prefix {@code - * java.util.concurrent.ForkJoinPool.common}: {@code parallelism} -- - * an integer greater than zero, {@code threadFactory} -- the class - * name of a {@link ForkJoinWorkerThreadFactory}, and {@code - * exceptionHandler} -- the class name of a {@link - * java.lang.Thread.UncaughtExceptionHandler - * Thread.UncaughtExceptionHandler}. Upon any error in establishing - * these settings, default parameters are used. + * parameters, but these may be controlled by setting three + * {@linkplain System#getProperty system properties}: + * <ul> + * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism} + * - the parallelism level, a non-negative integer + * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory} + * - the class name of a {@link ForkJoinWorkerThreadFactory} + * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} + * - the class name of a {@link UncaughtExceptionHandler} + * </ul> + * The system class loader is used to load these classes. + * Upon any error in establishing these settings, default parameters + * are used. It is possible to disable or limit the use of threads in + * the common pool by setting the parallelism property to zero, and/or + * using a factory that may return {@code null}. * * <p><b>Implementation notes</b>: This implementation restricts the * maximum number of running threads to 32767. Attempts to create @@ -225,18 +233,18 @@ * for work-stealing (this would contaminate lifo/fifo * processing). Instead, we randomly associate submission queues * with submitting threads, using a form of hashing. The - * ThreadLocal Submitter class contains a value initially used as - * a hash code for choosing existing queues, but may be randomly - * repositioned upon contention with other submitters. In - * essence, submitters act like workers except that they are - * restricted to executing local tasks that they submitted (or in - * the case of CountedCompleters, others with the same root task). - * However, because most shared/external queue operations are more - * expensive than internal, and because, at steady state, external - * submitters will compete for CPU with workers, ForkJoinTask.join - * and related methods disable them from repeatedly helping to - * process tasks if all workers are active. Insertion of tasks in - * shared mode requires a lock (mainly to protect in the case of + * ThreadLocalRandom probe value serves as a hash code for + * choosing existing queues, and may be randomly repositioned upon + * contention with other submitters. In essence, submitters act + * like workers except that they are restricted to executing local + * tasks that they submitted (or in the case of CountedCompleters, + * others with the same root task). However, because most + * shared/external queue operations are more expensive than + * internal, and because, at steady state, external submitters + * will compete for CPU with workers, ForkJoinTask.join and + * related methods disable them from repeatedly helping to process + * tasks if all workers are active. Insertion of tasks in shared + * mode requires a lock (mainly to protect in the case of * resizing) but we use only a simple spinlock (using bits in * field qlock), because submitters encountering a busy queue move * on to try or create other queues -- they block only when @@ -469,7 +477,7 @@ * Common Pool * =========== * - * The static commonPool always exists after static + * The static common Pool always exists after static * initialization. Since it (or any other created pool) need * never be used, we minimize initial construction overhead and * footprint to the setup of about a dozen fields, with no nested @@ -548,6 +556,7 @@ * * @param pool the pool this thread works in * @throws NullPointerException if the pool is null + * @return the new worker thread */ public ForkJoinWorkerThread newThread(ForkJoinPool pool); } @@ -564,26 +573,6 @@ } /** - * Per-thread records for threads that submit to pools. Currently - * holds only pseudo-random seed / index that is used to choose - * submission queues in method externalPush. In the future, this may - * also incorporate a means to implement different task rejection - * and resubmission policies. - * - * Seeds for submitters and workers/workQueues work in basically - * the same way but are initialized and updated using slightly - * different mechanics. Both are initialized using the same - * approach as in class ThreadLocal, where successive values are - * unlikely to collide with previous values. Seeds are then - * randomly modified upon collisions using xorshifts, which - * requires a non-zero seed. - */ - static final class Submitter { - int seed; - Submitter(int s) { seed = s; } - } - - /** * Class for artificial tasks that are used to replace the target * of local joins if they are removed from an interior queue slot * in WorkQueue.tryRemoveAndExec. We don't need the proxy to @@ -737,7 +726,7 @@ * shared-queue version is embedded in method externalPush.) * * @param task the task. Caller must ensure non-null. - * @throw RejectedExecutionException if array cannot be resized + * @throws RejectedExecutionException if array cannot be resized */ final void push(ForkJoinTask<?> task) { ForkJoinTask<?>[] a; ForkJoinPool p; @@ -936,7 +925,7 @@ * or any other cancelled task. Returns (true) on any CAS * or consistency check failure so caller can retry. * - * @return false if no progress can be made, else true; + * @return false if no progress can be made, else true */ final boolean tryRemoveAndExec(ForkJoinTask<?> task) { boolean stat = true, removed = false, empty = true; @@ -981,7 +970,7 @@ /** * Polls for and executes the given task or any other task in - * its CountedCompleter computation + * its CountedCompleter computation. */ final boolean pollAndExecCC(ForkJoinTask<?> root) { ForkJoinTask<?>[] a; int b; Object o; @@ -1055,7 +1044,6 @@ private static final int ABASE; private static final int ASHIFT; static { - int s; try { U = sun.misc.Unsafe.getUnsafe(); Class<?> k = WorkQueue.class; @@ -1063,13 +1051,13 @@ QLOCK = U.objectFieldOffset (k.getDeclaredField("qlock")); ABASE = U.arrayBaseOffset(ak); - s = U.arrayIndexScale(ak); + int scale = U.arrayIndexScale(ak); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); } catch (Exception e) { throw new Error(e); } - if ((s & (s-1)) != 0) - throw new Error("data type scale not a power of two"); - ASHIFT = 31 - Integer.numberOfLeadingZeros(s); } } @@ -1083,15 +1071,6 @@ defaultForkJoinWorkerThreadFactory; /** - * Per-thread submission bookkeeping. Shared across all pools - * to reduce ThreadLocal pollution and because random motion - * to avoid contention in one pool is likely to hold for others. - * Lazily initialized on first submission (but null-checked - * in other contexts to avoid unnecessary initialization). - */ - static final ThreadLocal<Submitter> submitters; - - /** * Permission required for callers of methods that may start or * kill threads. */ @@ -1103,12 +1082,15 @@ * to paranoically avoid potential initialization circularities * as well as to simplify generated code. */ - static final ForkJoinPool commonPool; + static final ForkJoinPool common; /** - * Common pool parallelism. Must equal commonPool.parallelism. + * Common pool parallelism. To allow simpler use and management + * when common pool threads are disabled, we allow the underlying + * common.config field to be zero, but in that case still report + * parallelism as 1 to reflect resulting caller-runs mechanics. */ - static final int commonPoolParallelism; + static final int commonParallelism; /** * Sequence number for creating workerNamePrefix. @@ -1116,8 +1098,8 @@ private static int poolNumberSequence; /** - * Return the next sequence number. We don't expect this to - * ever contend so use simple builtin sync. + * Returns the next sequence number. We don't expect this to + * ever contend, so use simple builtin sync. */ private static final synchronized int nextPoolId() { return ++poolNumberSequence; @@ -1161,7 +1143,7 @@ */ private static final int SEED_INCREMENT = 0x61c88647; - /** + /* * Bits and masks for control variables * * Field ctl is a long packed with: @@ -1268,39 +1250,28 @@ final int config; // mode and parallelism level WorkQueue[] workQueues; // main registry final ForkJoinWorkerThreadFactory factory; - final Thread.UncaughtExceptionHandler ueh; // per-worker UEH + final UncaughtExceptionHandler ueh; // per-worker UEH final String workerNamePrefix; // to create worker name string volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17; volatile Object pad18, pad19, pad1a, pad1b; - /* + /** * Acquires the plock lock to protect worker array and related * updates. This method is called only if an initial CAS on plock - * fails. This acts as a spinLock for normal cases, but falls back + * fails. This acts as a spinlock for normal cases, but falls back * to builtin monitor to block when (rarely) needed. This would be * a terrible idea for a highly contended lock, but works fine as * a more conservative alternative to a pure spinlock. */ private int acquirePlock() { - int spins = PL_SPINS, r = 0, ps, nps; + int spins = PL_SPINS, ps, nps; for (;;) { if (((ps = plock) & PL_LOCK) == 0 && U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK)) return nps; - else if (r == 0) { // randomize spins if possible - Thread t = Thread.currentThread(); WorkQueue w; Submitter z; - if ((t instanceof ForkJoinWorkerThread) && - (w = ((ForkJoinWorkerThread)t).workQueue) != null) - r = w.seed; - else if ((z = submitters.get()) != null) - r = z.seed; - else - r = 1; - } else if (spins >= 0) { - r ^= r << 1; r ^= r >>> 3; r ^= r << 10; // xorshift - if (r >= 0) + if (ThreadLocalRandom.nextSecondarySeed() >= 0) --spins; } else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) { @@ -1332,39 +1303,6 @@ } /** - * Performs secondary initialization, called when plock is zero. - * Creates workQueue array and sets plock to a valid value. The - * lock body must be exception-free (so no try/finally) so we - * optimistically allocate new array outside the lock and throw - * away if (very rarely) not needed. (A similar tactic is used in - * fullExternalPush.) Because the plock seq value can eventually - * wrap around zero, this method harmlessly fails to reinitialize - * if workQueues exists, while still advancing plock. - * - * Additionally tries to create the first worker. - */ - private void initWorkers() { - WorkQueue[] ws, nws; int ps; - int p = config & SMASK; // find power of two table size - int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots - n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; - n = (n + 1) << 1; - if ((ws = workQueues) == null || ws.length == 0) - nws = new WorkQueue[n]; - else - nws = null; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (((ws = workQueues) == null || ws.length == 0) && nws != null) - workQueues = nws; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - tryAddWorker(); - } - - /** * Tries to create and start one worker if fewer than target * parallelism level exist. Adjusts counts etc on failure. */ @@ -1406,7 +1344,7 @@ * @return the worker's queue */ final WorkQueue registerWorker(ForkJoinWorkerThread wt) { - Thread.UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; + UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; wt.setDaemon(true); if ((handler = ueh) != null) wt.setUncaughtExceptionHandler(handler); @@ -1450,7 +1388,7 @@ * array, and adjusts counts. If pool is shutting down, tries to * complete termination. * - * @param wt the worker thread or null if construction failed + * @param wt the worker thread, or null if construction failed * @param ex the exception causing failure, or null if none */ final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) { @@ -1489,7 +1427,7 @@ if (e > 0) { // activate or create replacement if ((ws = workQueues) == null || (i = e & SMASK) >= ws.length || - (v = ws[i]) != null) + (v = ws[i]) == null) break; long nc = (((long)(v.nextWait & E_MASK)) | ((long)(u + UAC_UNIT) << 32)); @@ -1526,10 +1464,10 @@ * @param task the task. Caller must ensure non-null. */ final void externalPush(ForkJoinTask<?> task) { - WorkQueue[] ws; WorkQueue q; Submitter z; int m; ForkJoinTask<?>[] a; - if ((z = submitters.get()) != null && plock > 0 && + WorkQueue[] ws; WorkQueue q; int z, m; ForkJoinTask<?>[] a; + if ((z = ThreadLocalRandom.getProbe()) != 0 && plock > 0 && (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock int b = q.base, s = q.top, n, an; if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) { @@ -1549,34 +1487,48 @@ /** * Full version of externalPush. This method is called, among * other times, upon the first submission of the first task to the - * pool, so must perform secondary initialization (via - * initWorkers). It also detects first submission by an external - * thread by looking up its ThreadLocal, and creates a new shared - * queue if the one at index if empty or contended. The plock lock - * body must be exception-free (so no try/finally) so we - * optimistically allocate new queues outside the lock and throw - * them away if (very rarely) not needed. + * pool, so must perform secondary initialization. It also + * detects first submission by an external thread by looking up + * its ThreadLocal, and creates a new shared queue if the one at + * index if empty or contended. The plock lock body must be + * exception-free (so no try/finally) so we optimistically + * allocate new queues outside the lock and throw them away if + * (very rarely) not needed. + * + * Secondary initialization occurs when plock is zero, to create + * workQueue array and set plock to a valid value. This lock body + * must also be exception-free. Because the plock seq value can + * eventually wrap around zero, this method harmlessly fails to + * reinitialize if workQueues exists, while still advancing plock. */ private void fullExternalPush(ForkJoinTask<?> task) { - int r = 0; // random index seed - for (Submitter z = submitters.get();;) { + int r; + if ((r = ThreadLocalRandom.getProbe()) == 0) { + ThreadLocalRandom.localInit(); + r = ThreadLocalRandom.getProbe(); + } + for (;;) { WorkQueue[] ws; WorkQueue q; int ps, m, k; - if (z == null) { - if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed, - r += SEED_INCREMENT) && r != 0) - submitters.set(z = new Submitter(r)); - } - else if (r == 0) { // move to a different index - r = z.seed; - r ^= r << 13; // same xorshift as WorkQueues - r ^= r >>> 17; - z.seed = r ^ (r << 5); - } - else if ((ps = plock) < 0) +