diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 70033e457d0..5371d044b91 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -348,7 +348,6 @@ TOOLS = \ 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 @@ $(NOT_RT_JAR_LIST): FRC $(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" >> $@ diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 8c2f80c5248..189b9fcb7c2 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -257,6 +257,7 @@ JAVA_JAVA_java = \ 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 \ diff --git a/jdk/make/java/zip/Makefile b/jdk/make/java/zip/Makefile index 67a8557de0b..99afd603d7c 100644 --- a/jdk/make/java/zip/Makefile +++ b/jdk/make/java/zip/Makefile @@ -68,6 +68,16 @@ ifeq ($(PLATFORM), solaris) 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 diff --git a/jdk/make/launchers/Makefile b/jdk/make/launchers/Makefile index be16512e478..47645158793 100644 --- a/jdk/make/launchers/Makefile +++ b/jdk/make/launchers/Makefile @@ -77,6 +77,7 @@ $(call make-launcher, jmap, sun.tools.jmap.JMap, \ -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 \ diff --git a/jdk/make/sun/cmm/lcms/Makefile b/jdk/make/sun/cmm/lcms/Makefile index 24fde37fba0..85b02e4960e 100644 --- a/jdk/make/sun/cmm/lcms/Makefile +++ b/jdk/make/sun/cmm/lcms/Makefile @@ -28,6 +28,9 @@ PACKAGE = sun.java2d.cmm.lcms LIBRARY = lcms PRODUCT = sun +# Use highest level of optimization on this library +OPTIMIZATION_LEVEL = HIGHEST + include $(BUILDDIR)/common/Defs.gmk # diff --git a/jdk/make/sun/cmm/lcms/mapfile-vers b/jdk/make/sun/cmm/lcms/mapfile-vers index ac4e7458b37..3d9074f746d 100644 --- a/jdk/make/sun/cmm/lcms/mapfile-vers +++ b/jdk/make/sun/cmm/lcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/jdk/make/tools/javazic/Makefile b/jdk/make/tools/javazic/Makefile deleted file mode 100644 index 4545c4d491c..00000000000 --- a/jdk/make/tools/javazic/Makefile +++ /dev/null @@ -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 - diff --git a/jdk/make/tools/src/build/tools/deps/refs.allowed b/jdk/make/tools/src/build/tools/deps/refs.allowed index 91605d535fe..ad9d5271199 100644 --- a/jdk/make/tools/src/build/tools/deps/refs.allowed +++ b/jdk/make/tools/src/build/tools/deps/refs.allowed @@ -33,8 +33,3 @@ sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,comp # 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 - diff --git a/jdk/make/tools/src/build/tools/javazic/BackEnd.java b/jdk/make/tools/src/build/tools/javazic/BackEnd.java deleted file mode 100644 index bfeda032037..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/BackEnd.java +++ /dev/null @@ -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; - -/** - * BackEnd 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 Zoneinfo, - * 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(); - } - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Checksum.java b/jdk/make/tools/src/build/tools/javazic/Checksum.java deleted file mode 100644 index 565395d5c8d..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Checksum.java +++ /dev/null @@ -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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Gen.java b/jdk/make/tools/src/build/tools/javazic/Gen.java deleted file mode 100644 index 8f3a8c5a37a..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Gen.java +++ /dev/null @@ -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; - -/** - * Gen 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 transitions = tz.getTransitions(); - if (transitions != null) { - List dstOffsets = tz.getDstOffsets(); - List 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 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 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 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> 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 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 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; - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/GenDoc.java b/jdk/make/tools/src/build/tools/javazic/GenDoc.java deleted file mode 100644 index c598b9b9dc5..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/GenDoc.java +++ /dev/null @@ -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; - -/** - * GenDoc 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 = - "\n" + - "\n\n\n\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 = - "\n" + - "\n\n"; - - private static final String body1 = - "\n"; - private static final String body2 = - "\n"; - - private static final String footer = - "\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 timezoneList = new TreeMap(); - - // 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 displayNameList = new TreeMap(); - - // list of top level regions - // e.g. - // key (String) : value (String) - // "America" : "America.html" - // (including entries in America/Indiana/, America/Kentucky/, ...) - TreeMap regionList = new TreeMap(); - - // 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 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> zonesByOffset = new TreeMap>(); - - /** - * 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 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 set = zonesByOffset.get(lastKnownOffset); - if (set == null) { - set = new TreeSet(); - 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 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 + "" + zonename + ""); - 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("   " + - "[map]"); - } - out.write("\n

\n"); - - List zone = tz.getZones(); - List rule = tz.getRules(); - if (rule != null && zone != null) { - out.write("\n" + - "\n" + - "\n" + - "\n" + - "\n

" + - "Rules
" + - "
Zone
\n"); - } - - /* Output Rule records. */ - if (rule != null) { - size = rule.size(); - out.write("

\n" + - "Rules\n" + - "\n" + - "\n" + - "" + - "" + - "\n\n"); - for (int i = 0; i < size; i++) { - out.write("\n"); - StringTokenizer st = new StringTokenizer(rule.get(i).getLine()); - String s; - if (st.hasMoreTokens()) { /* RULE - truncated */ - st.nextToken(); - } - if (st.hasMoreTokens()) { /* NAME */ - out.write(""); - } - if (st.hasMoreTokens()) { /* FROM */ - out.write(""); - } - if (st.hasMoreTokens()) { /* TO */ - s = st.nextToken(); - if (s.equals("min") || s.equals("max")) { - out.write(""); - } else { - out.write(""); - } - } - if (st.hasMoreTokens()) { /* TYPE */ - out.write(""); - } - if (st.hasMoreTokens()) { /* IN */ - out.write(""); - } - if (st.hasMoreTokens()) { /* ON */ - out.write(""); - } - if (st.hasMoreTokens()) { /* AT */ - out.write(""); - } - if (st.hasMoreTokens()) { /* SAVE */ - out.write(""); - } - if (st.hasMoreTokens()) { /* LETTER/S */ - out.write(""); - } - if (st.hasMoreTokens()) { /* NOTES */ - s = st.nextToken(); - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - index = s.indexOf('#'); - out.write("\n"); - } else { - out.write("\n"); - } - out.write("\n"); - } - out.write("
NAMEFROMTOTYPEINONATSAVELETTER/SNOTES
" + st.nextToken() + "" + st.nextToken() + "" + s + "" + s + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + st.nextToken() + "" + s.substring(index+1) + " 
\n

 

\n"); - } - - /* Output Zone records. */ - if (zone != null) { - size = zone.size(); - out.write("

\n" + - "Zone\n" + - "\n" + - "\n" + - "" + - "\n\n"); - for (int i = 0; i < size; i++) { - out.write("\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(""); /* GMTOFFSET */ - if (st.hasMoreTokens()) { /* RULES */ - out.write(""); - } - if (st.hasMoreTokens()) { /* FORMAT */ - s = st.nextToken(); - index = s.indexOf('#'); - if (index != -1) { - if (index != 0) { - out.write(""); /* FORMAT */ - s = s.substring(index+1); - } else { - out.write(""); /* FORMAT */ - } - while (st.hasMoreTokens()) { - s += " " + st.nextToken(); - } - out.write(""); /* UNTIL */ - out.write("\n\n"); /* NOTES */ - continue; - } else { - out.write(""); /* 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(""); /* UNTIL */ - } else { - out.write(""); /* UNTIL */ - } - out.write("\n"); /* NOTES */ - } else { - out.write(""); /* UNTIL */ - out.write("\n"); /* NOTES */ - } - } else { - out.write(""); /* UNTIL */ - out.write("\n"); /* NOTES */ - } - out.write("\n"); - } - out.write("
GMTOFFRULESFORMATUNTILNOTES
" + s + "" + st.nextToken() + "" + s.substring(0, index-1) + - "  " + s + "
" + s + "" + s.substring(0, index-1) + - " " + s.substring(index+1) + - "" + s + "   
\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 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 + - "\n" + - "\n" + - "\n" + - "\n" + - "" + - "\n" + - "\n" + - "\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" + - "\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 + - "\n\n" + - "\n" + - "\n
\n" + - "JavaTM Platform
Standard Ed.
\n\n" + - "\n\n\n
" + - "

\n\nAll Time Zones Sorted By:\n
\n" + - "  GMT offsets\n
\n" + - "  Zone names\n
" + - "  City names\n" + - "

\n\nContinents and Oceans\n
\n"); - - for (String regionKey : regionList.keySet()) { - out1.write("  " + regionKey + - "
\n"); - - fw2 = new FileWriter(outputDir + regionList.get(regionKey), - false); - out2 = new BufferedWriter(fw2); - - out2.write(header1 + new Date() + header3 + regionKey + - header4 + body1 + "" + - regionKey + "\n
\n\n\n\n\n
"); - - 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 " + "" + - realName + ")"); - } else { - out2.write("" + timezoneKey + - ""); - } - out2.write("
\n"); - } - out2.write("
\n" + body2 + footer); - - out2.close(); - fw2.close(); - } - out1.write("

\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 + - "Sorted by GMT offsets\n" + - "
\n\n" + "\n" + - "\n\n\n\n\n"); - } - } - out1.write("\n\n
\n"); - - List roi = map.getRawOffsetsIndex(); - List> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (Integer offset : zonesByOffset.keySet()) { - int off = roi.get(index); - Set perRO = zonesByOffset.get(offset); - if (offset == off) { - // Merge aliases into zonesByOffset - perRO.addAll(roit.get(index)); - } - index++; - - for (String timezoneKey : perRO) { - out1.write("
(" + - Time.toGMTFormat(offset.toString()) + - ")"); - - if (a.containsKey(timezoneKey)) { - Object realName = a.get(timezoneKey); - while (a.containsKey(realName)) { - realName = a.get(realName); - } - out1.write(timezoneKey + - " (alias for " + "" + realName + - ")"); - } else { - out1.write("" + timezoneKey + - ""); - } - out1.write("
\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 + - "Sorted by zone names\n" + - "
\n\n" + "\n" + - "\n\n\n
\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 " + - "" + realName + - ")"); - } else { - out1.write("" + timezoneKey + - ""); - } - out1.write("
\n"); - } - out1.write("
\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 + - "Sorted by city names\n" + - "
\n\n" + "\n" + - "\n\n\n
\n"); - - Set 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 " + - "" + realName + - ")"); - } else { - out1.write("" + displayName + - ""); - } - out1.write("
\n"); - } - - out1.write("
\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 + - "

This is the list of time zones generated from " + - Main.getVersionName() + " for Java Platform, " + - "Standard Edition. The source code can be obtained " + - "from ftp site " + - "ftp://elsie.nci.nih.gov/pub/. A total of " + - len + - " 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.

\n" + - "

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.

\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; - } - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Main.java b/jdk/make/tools/src/build/tools/javazic/Main.java deleted file mode 100644 index a91ab91fff8..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Main.java +++ /dev/null @@ -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 ziFiles = new ArrayList(); - 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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Mappings.java b/jdk/make/tools/src/build/tools/javazic/Mappings.java deleted file mode 100644 index 885b9a091b6..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Mappings.java +++ /dev/null @@ -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; - -/** - * Mappings 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 aliases; - - private List rawOffsetsIndex; - - private List> rawOffsetsIndexTable; - - // Zone names to be excluded from rawOffset table. Those have GMT - // offsets to change some future time. - private List excludeList; - - /** - * Constructor creates some necessary instances. - */ - Mappings() { - aliases = new TreeMap(); - rawOffsetsIndex = new LinkedList(); - rawOffsetsIndexTable = new LinkedList>(); - } - - /** - * Generates aliases and rawOffsets tables. - * @param zi a Zoneinfo containing Zones - */ - void add(Zoneinfo zi) { - Map 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(); - } - 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 perRawOffset = new TreeSet(); - if (!isExcluded) { - perRawOffset.add(zonename); - } - rawOffsetsIndexTable.add(i, perRawOffset); - } else if (!isExcluded) { - int i = rawOffsetsIndex.indexOf(new Integer(rawOffset)); - Set perRawOffset = rawOffsetsIndexTable.get(i); - perRawOffset.add(zonename); - } - } - - Map 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 toBeRemoved = new ArrayList(); - for (String key : aliases.keySet()) { - boolean validname = false; - for (int j = 0; j < index; j++) { - Set 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 newMap = new HashMap(); - 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 getAliases() { - return(aliases); - } - - List getRawOffsetsIndex() { - return(rawOffsetsIndex); - } - - List> getRawOffsetsIndexTable() { - return(rawOffsetsIndexTable); - } - - List getExcludeList() { - return excludeList; - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Month.java b/jdk/make/tools/src/build/tools/javazic/Month.java deleted file mode 100644 index 9e70808809f..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Month.java +++ /dev/null @@ -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 abbreviations - = new HashMap(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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Rule.java b/jdk/make/tools/src/build/tools/javazic/Rule.java deleted file mode 100644 index c8e97fccae2..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Rule.java +++ /dev/null @@ -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 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(); - } - - /** - * 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 getRules(int year) { - List rules = new ArrayList(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() { - 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 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 r = new ArrayList(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; - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/RuleDay.java b/jdk/make/tools/src/build/tools/javazic/RuleDay.java deleted file mode 100644 index 5ce43f19fce..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/RuleDay.java +++ /dev/null @@ -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 abbreviations = new HashMap(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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/RuleRec.java b/jdk/make/tools/src/build/tools/javazic/RuleRec.java deleted file mode 100644 index 37743725729..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/RuleRec.java +++ /dev/null @@ -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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Simple.java b/jdk/make/tools/src/build/tools/javazic/Simple.java deleted file mode 100644 index 69c7fe783f5..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Simple.java +++ /dev/null @@ -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; - -/** - * Simple 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 lastZoneRecs = new HashMap<>(); - - /** - * Rule records which are applied for given year. - */ - private static Map> 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> 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 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 a = map.getAliases(); - List roi = map.getRawOffsetsIndex(); - List> roit = map.getRawOffsetsIndexTable(); - - int index = 0; - for (int offset : zonesByOffset.keySet()) { - int o = roi.get(index); - Set 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 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; - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Time.java b/jdk/make/tools/src/build/tools/javazic/Time.java deleted file mode 100644 index 66458a0020d..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Time.java +++ /dev/null @@ -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 getLocalTime(year, month, day, (long)time). - * @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(); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Timezone.java b/jdk/make/tools/src/build/tools/javazic/Timezone.java deleted file mode 100644 index 941ea454563..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Timezone.java +++ /dev/null @@ -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 transitions; - - /** - * All offset values in millisecond - * @see sun.util.calendar.ZoneInfo - */ - private List offsets; - - /** - * Indices of GMT offset values (both raw and raw+saving) - * at transitions - */ - private List gmtOffsets; - - /** - * Indices of regular or "direct" saving time values - * at transitions - */ - private List dstOffsets; - - /** - * Zone records of this time zone - */ - private List usedZoneRecs; - - /** - * Rule records referred to by this time zone - */ - private List 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 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 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 getZones() { - return usedZoneRecs; - } - - /** - * @return the transition table (list) - */ - List getTransitions() { - return transitions; - } - - /** - * @return the offsets list - */ - List getOffsets() { - return offsets; - } - - /** - * @return the DST saving offsets list - */ - List getDstOffsets() { - return dstOffsets; - } - - /** - * @return the GMT offsets list - */ - List 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 offset. - * @param offset the GMT offset value in milliseconds - */ - void setRawOffset(int offset) { - rawOffset = offset; - } - - /** - * Sets time zone's GMT offset value to offset. If - * startTime 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(); - offsets = new ArrayList(); - dstOffsets = new ArrayList(); - } - 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(); - } - 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(); - } - // 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 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 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 crc32. - */ - 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(); - } - 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; - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Zone.java b/jdk/make/tools/src/build/tools/javazic/Zone.java deleted file mode 100644 index 1f4e7029c15..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Zone.java +++ /dev/null @@ -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 list; - - // target zone names for this compilation - private static Set targetZones; - - /** - * Constructs a Zone with the specified zone name. - * @param name the zone name - */ - Zone(String name) { - this.name = name; - list = new ArrayList(); - } - - /** - * 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 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); - } - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/ZoneRec.java b/jdk/make/tools/src/build/tools/javazic/ZoneRec.java deleted file mode 100644 index b175e0e93d4..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/ZoneRec.java +++ /dev/null @@ -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. untilTime 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); - } -} diff --git a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java b/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java deleted file mode 100644 index 129f87c57d2..00000000000 --- a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java +++ /dev/null @@ -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 zones; - - /** - * Rule name to Rule mappings - */ - private Map rules; - - /** - * Alias name to real name mappings - */ - private Map aliases; - - /** - * Constracts a Zoneinfo. - */ - Zoneinfo() { - zones = new HashMap(); - rules = new HashMap(); - aliases = new HashMap(); - } - - /** - * 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 getAliases() { - return aliases; - } - - /** - * @return the Zone list - */ - Map 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 - 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 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 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 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); - } -} diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index 170dc164ec4..501c986082e 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -311,6 +311,9 @@ $(eval $(call SetupLauncher,jps,\ $(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" }' \ diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index 9b38b5aba79..9df22fe8b6a 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -1219,7 +1219,7 @@ ifdef OPENJDK OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\ SRC:=$(JDK_TOPDIR)/src/share/native/sun/java2d/cmm/lcms,\ LANG:=C,\ - OPTIMIZATION:=LOW, \ + OPTIMIZATION:=HIGHEST, \ CFLAGS:=$(filter-out -xc99=%none,$(CFLAGS_JDKLIB)) \ $(SHARED_LIBRARY_FLAGS) \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index 7e33790d299..82b85dc97f3 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -213,28 +213,28 @@ RT_JAR_EXCLUDES += \ 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 @@ endif ########################################################################################## +# 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 ########################################################################################## diff --git a/jdk/makefiles/Images.gmk b/jdk/makefiles/Images.gmk index 8dedfaec3d0..4a3a23525d1 100644 --- a/jdk/makefiles/Images.gmk +++ b/jdk/makefiles/Images.gmk @@ -609,6 +609,7 @@ define create-info-file $(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 diff --git a/jdk/makefiles/mapfiles/liblcms/mapfile-vers b/jdk/makefiles/mapfiles/liblcms/mapfile-vers index 04703dffc5a..024511423d3 100644 --- a/jdk/makefiles/mapfiles/liblcms/mapfile-vers +++ b/jdk/makefiles/mapfiles/liblcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/jdk/makefiles/profile-rtjar-includes.txt b/jdk/makefiles/profile-rtjar-includes.txt index 4722727ea31..4cc528e67d5 100644 --- a/jdk/makefiles/profile-rtjar-includes.txt +++ b/jdk/makefiles/profile-rtjar-includes.txt @@ -349,6 +349,7 @@ PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ 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 @@ PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ 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 @@ PROFILE_3_RTJAR_EXCLUDE_TYPES := \ 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 diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java index a4831d29ea9..8e8527f6541 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -34,7 +34,6 @@ import javax.swing.border.Border; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; -import com.apple.laf.ClientPropertyApplicator; import com.apple.laf.ClientPropertyApplicator.Property; import apple.laf.JRSUIConstants.Size; @@ -142,35 +141,46 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { return new AquaComboBoxEditor(); } - class AquaComboBoxEditor extends BasicComboBoxEditor implements UIResource, DocumentListener { - protected AquaComboBoxEditor() { + final class AquaComboBoxEditor extends BasicComboBoxEditor + implements UIResource, DocumentListener { + + AquaComboBoxEditor() { super(); editor = new AquaCustomComboTextField(); editor.addFocusListener(this); editor.getDocument().addDocumentListener(this); } + @Override public void focusGained(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void focusLost(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void changedUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void insertUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void removeUpdate(final DocumentEvent e) { editorTextChanged(); } - protected void editorTextChanged() { + private void editorTextChanged() { if (!popup.isVisible()) return; final Object text = editor.getText(); diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java index fb37d01209c..055af2edb22 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java @@ -53,7 +53,7 @@ public abstract class CGraphicsConfig extends GraphicsConfiguration @Override public Rectangle getBounds() { - final Rectangle2D nativeBounds = nativeGetBounds(device.getCoreGraphicsScreen()); + final Rectangle2D nativeBounds = nativeGetBounds(device.getCGDisplayID()); return nativeBounds.getBounds(); // does integer rounding } diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java index bcb24ea46f7..1a5e22af582 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java @@ -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 @@ -25,11 +25,12 @@ package sun.awt; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.Window; import java.awt.AWTPermission; import java.awt.DisplayMode; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.Insets; +import java.awt.Window; import java.util.Objects; import sun.java2d.opengl.CGLGraphicsConfig; @@ -58,9 +59,12 @@ public final class CGraphicsDevice extends GraphicsDevice { } /** + * Returns CGDirectDisplayID, which is the same id as @"NSScreenNumber" in + * NSScreen. + * * @return CoreGraphics display id. */ - public int getCoreGraphicsScreen() { + public int getCGDisplayID() { return displayID; } @@ -107,8 +111,9 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetYResolution(displayID); } - private static native double nativeGetXResolution(int displayID); - private static native double nativeGetYResolution(int displayID); + public Insets getScreenInsets() { + return nativeGetScreenInsets(displayID); + } /** * Enters full-screen mode, or returns to windowed mode. @@ -214,9 +219,15 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetDisplayModes(displayID); } - private native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); + private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); - private native DisplayMode nativeGetDisplayMode(int displayID); + private static native DisplayMode nativeGetDisplayMode(int displayID); - private native DisplayMode[] nativeGetDisplayModes(int displayID); + private static native DisplayMode[] nativeGetDisplayModes(int displayID); + + private static native double nativeGetXResolution(int displayID); + + private static native double nativeGetYResolution(int displayID); + + private static native Insets nativeGetScreenInsets(int displayID); } diff --git a/jdk/src/macosx/classes/sun/font/CStrike.java b/jdk/src/macosx/classes/sun/font/CStrike.java index 61fe234cb29..9635b85a1de 100644 --- a/jdk/src/macosx/classes/sun/font/CStrike.java +++ b/jdk/src/macosx/classes/sun/font/CStrike.java @@ -500,7 +500,10 @@ public class CStrike extends FontStrike { final Iterator i = generalCache.values().iterator(); while (i.hasNext()) { final long longValue = i.next().longValue(); - if (longValue != -1 && longValue != 0) StrikeCache.freeLongPointer(longValue); + if (longValue != -1 && longValue != 0) { + removeGlyphInfoFromCache(longValue); + StrikeCache.freeLongPointer(longValue); + } } } @@ -512,7 +515,10 @@ public class CStrike extends FontStrike { private static void disposeLongArray(final long[] longArray) { for (int i = 0; i < longArray.length; i++) { final long ptr = longArray[i]; - if (ptr != 0 && ptr != -1) StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + if (ptr != 0 && ptr != -1) { + removeGlyphInfoFromCache(ptr); + StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + } } } diff --git a/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java b/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java index 7357ea6bd42..661bd6a7b42 100644 --- a/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java +++ b/jdk/src/macosx/classes/sun/font/CStrikeDisposer.java @@ -85,4 +85,6 @@ class CStrikeDisposer extends FontStrikeDisposer { } private native void freeNativeScalerContext(long pContext); + + protected static native void removeGlyphInfoFromCache(long glyphInfo); } diff --git a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java index 230f7057927..c8539a8e3f6 100644 --- a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java @@ -80,10 +80,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig private ContextCapabilities oglCaps; private OGLContext context; private final Object disposerReferent = new Object(); - - public static native int getDefaultPixFmt(int screennum); private static native boolean initCGL(); - private static native long getCGLConfigInfo(int screennum, int visualnum, + private static native long getCGLConfigInfo(int displayID, int visualnum, int swapInterval); private static native int getOGLCapabilities(long configInfo); @@ -137,15 +135,16 @@ public final class CGLGraphicsConfig extends CGraphicsConfig // Java-level context and flush the queue... OGLContext.invalidateCurrentContext(); - cfginfo = getCGLConfigInfo(device.getCoreGraphicsScreen(), pixfmt, + cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt, kOpenGLSwapInterval); - - OGLContext.setScratchSurface(cfginfo); - rq.flushAndInvokeNow(new Runnable() { - public void run() { - ids[0] = OGLContext.getOGLIdString(); - } - }); + if (cfginfo != 0L) { + OGLContext.setScratchSurface(cfginfo); + rq.flushAndInvokeNow(new Runnable() { + public void run() { + ids[0] = OGLContext.getOGLIdString(); + } + }); + } } finally { rq.unlock(); } @@ -253,8 +252,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public String toString() { - int screen = getDevice().getCoreGraphicsScreen(); - return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]"); + int displayID = getDevice().getCGDisplayID(); + return ("CGLGraphicsConfig[dev="+displayID+",pixfmt="+pixfmt+"]"); } @Override @@ -413,8 +412,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public void addDeviceEventListener(AccelDeviceEventListener l) { - int screen = getDevice().getCoreGraphicsScreen(); - AccelDeviceEventNotifier.addListener(l, screen); + int displayID = getDevice().getCGDisplayID(); + AccelDeviceEventNotifier.addListener(l, displayID); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index aa9b798c617..052b91726b6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -439,7 +439,7 @@ public abstract class LWComponentPeer } @Override - public final Graphics getGraphics() { + public Graphics getGraphics() { final Graphics g = getOnscreenGraphics(); if (g != null) { synchronized (getPeerTreeLock()){ @@ -1227,10 +1227,10 @@ public abstract class LWComponentPeer } protected void sendEventToDelegate(final AWTEvent e) { + if (getDelegate() == null || !isShowing() || !isEnabled()) { + return; + } synchronized (getDelegateLock()) { - if (getDelegate() == null || !isShowing() || !isEnabled()) { - return; - } AWTEvent delegateEvent = createDelegateEvent(e); if (delegateEvent != null) { AWTAccessor.getComponentAccessor() @@ -1244,7 +1244,12 @@ public abstract class LWComponentPeer } } - protected AWTEvent createDelegateEvent(AWTEvent e) { + /** + * Changes the target of the AWTEvent from awt component to appropriate + * swing delegate. + */ + private AWTEvent createDelegateEvent(final AWTEvent e) { + // TODO modifiers should be changed to getModifiers()|getModifiersEx()? AWTEvent delegateEvent = null; if (e instanceof MouseWheelEvent) { MouseWheelEvent me = (MouseWheelEvent) e; diff --git a/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java new file mode 100644 index 00000000000..90e2e88c441 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt; + +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.dnd.DropTarget; + +import sun.awt.CausedFocusEvent; +import sun.awt.LightweightFrame; + +public class LWLightweightFramePeer extends LWWindowPeer { + + public LWLightweightFramePeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + super(target, platformComponent, platformWindow, LWWindowPeer.PeerType.LW_FRAME); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)getTarget(); + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + protected void setVisibleImpl(final boolean visible) { + } + + @Override + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + if (!focusAllowedFor()) { + return false; + } + if (getPlatformWindow().rejectFocusRequest(cause)) { + return false; + } + + Window opposite = LWKeyboardFocusManagerPeer.getInstance(). + getCurrentFocusedWindow(); + + changeFocusedWindow(true, opposite); + + return true; + } + + @Override + public Point getLocationOnScreen() { + Rectangle bounds = getBounds(); + return new Point(bounds.x, bounds.y); // todo + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public void setBounds(int x, int y, int w, int h, int op) { + setBounds(x, y, w, h, op, true, false); + } + + @Override + public void updateCursorImmediately() { + // TODO: tries to switch to the awt/fx toolkit thread and causes a deadlock on macosx + } + + @Override + public void addDropTarget(DropTarget dt) { + } + + @Override + public void removeDropTarget(DropTarget dt) { + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index 89f39fccbf8..cad6e4353ba 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -218,6 +218,23 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { return peer; } + private LWLightweightFramePeer createDelegatedLwPeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + LWLightweightFramePeer peer = new LWLightweightFramePeer(target, platformComponent, platformWindow); + targetCreatedPeer(target, peer); + peer.initialize(); + return peer; + } + + @Override + public FramePeer createLightweightFrame(LightweightFrame target) { + PlatformComponent platformComponent = createLwPlatformComponent(); + PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.LW_FRAME); + return createDelegatedLwPeer(target, platformComponent, platformWindow); + } + @Override public WindowPeer createWindow(Window target) { PlatformComponent platformComponent = createPlatformComponent(); @@ -502,6 +519,8 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { protected abstract PlatformComponent createPlatformComponent(); + protected abstract PlatformComponent createLwPlatformComponent(); + protected abstract FileDialogPeer createFileDialogPeer(FileDialog target); // ---- UTILITY METHODS ---- // diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 5b19788f244..d50335f7cd5 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -48,7 +48,8 @@ public class LWWindowPeer FRAME, DIALOG, EMBEDDED_FRAME, - VIEW_EMBEDDED_FRAME + VIEW_EMBEDDED_FRAME, + LW_FRAME } private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWWindowPeer"); @@ -1090,7 +1091,7 @@ public class LWWindowPeer return platformWindow.requestWindowFocus(); } - private boolean focusAllowedFor() { + protected boolean focusAllowedFor() { Window window = getTarget(); // TODO: check if modal blocked return window.isVisible() && window.isEnabled() && isFocusableWindow(); @@ -1113,10 +1114,15 @@ public class LWWindowPeer return !(window instanceof Dialog || window instanceof Frame); } + @Override + public void emulateActivation(boolean activate) { + changeFocusedWindow(activate, null); + } + /* * Changes focused window on java level. */ - private void changeFocusedWindow(boolean becomesFocused, Window opposite) { + protected void changeFocusedWindow(boolean becomesFocused, Window opposite) { if (focusLog.isLoggable(PlatformLogger.FINE)) { focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java index 181d0847225..0f32d3178fd 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java @@ -128,6 +128,15 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer { } } + @Override + protected int postDropTargetEvent(Component component, int x, int y, int dropAction, + int actions, long[] formats, long nativeCtxt, int eventID, + boolean dispatchType) { + // On MacOS X all the DnD events should be synchronous + return super.postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, + eventID, SunDropTargetContextPeer.DISPATCH_SYNC); + } + // Signal drop complete: protected void doDropDone(boolean success, int dropAction, boolean isLocal) { long nativeDropTarget = this.getNativeDragContext(); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java index 370b930ea98..978f65c3c91 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java @@ -35,7 +35,7 @@ import sun.lwawt.PlatformWindow; * On OSX {@code CPlatformComponent} stores pointer to the native CAlayer which * can be used from JAWT. */ -final class CPlatformComponent extends CFRetainedResource +class CPlatformComponent extends CFRetainedResource implements PlatformComponent { private volatile PlatformWindow platformWindow; diff --git a/jdk/make/tools/src/build/tools/javazic/DayOfWeek.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java similarity index 68% rename from jdk/make/tools/src/build/tools/javazic/DayOfWeek.java rename to jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java index 9df8163fe5e..fd76cf5c898 100644 --- a/jdk/make/tools/src/build/tools/javazic/DayOfWeek.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,34 +23,31 @@ * questions. */ -package build.tools.javazic; -/** - * Day of week enum. - * - * @since 1.6 - */ +package sun.lwawt.macosx; -enum DayOfWeek { - SUNDAY("Sun"), - MONDAY("Mon"), - TUESDAY("Tue"), - WEDNESDAY("Wed"), - THURSDAY("Thu"), - FRIDAY("Fri"), - SATURDAY("Sat"); +import sun.lwawt.PlatformWindow; - private final String abbr; +class CPlatformLWComponent extends CPlatformComponent { - private DayOfWeek(String abbr) { - this.abbr = abbr; + CPlatformLWComponent() { + super(); } - String getAbbr() { - return abbr; + @Override + public long getPointer() { + return 0; } - int value() { - return ordinal() + 1; + @Override + public void initialize(final PlatformWindow platformWindow) { + } + + @Override + public void setBounds(final int x, final int y, final int w, final int h) { + } + + @Override + public void dispose() { } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java new file mode 100644 index 00000000000..e5d99678b18 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt.macosx; + +import sun.lwawt.LWWindowPeer; +import sun.java2d.SurfaceData; + +public class CPlatformLWView extends CPlatformView { + + public CPlatformLWView() { + super(); + } + + @Override + public void initialize(LWWindowPeer peer, CPlatformResponder responder) { + initializeBase(peer, responder); + } + + @Override + public long getAWTView() { + return 0; + } + + @Override + public boolean isOpaque() { + return true; + } + + @Override + public void setBounds(int x, int y, int width, int height) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void dispose() { + } + + @Override + public long getWindowLayerPtr() { + return 0; + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java new file mode 100644 index 00000000000..d7a91264328 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt.macosx; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.Insets; +import java.awt.MenuBar; +import java.awt.Point; +import java.awt.Window; +import sun.awt.CausedFocusEvent; +import sun.java2d.SurfaceData; +import sun.lwawt.LWWindowPeer; +import sun.lwawt.PlatformWindow; + +public class CPlatformLWWindow extends CPlatformWindow { + + @Override + public void initialize(Window target, LWWindowPeer peer, PlatformWindow owner) { + initializeBase(target, peer, owner, new CPlatformLWView()); + } + + @Override + public void toggleFullScreen() { + } + + @Override + public void setMenuBar(MenuBar mb) { + } + + @Override + public void dispose() { + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return null; + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public Point getLocationOnScreen() { + return null; + } + + @Override + public GraphicsDevice getGraphicsDevice() { + return null; + } + + @Override + public SurfaceData getScreenSurface() { + return null; + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public void setBounds(int x, int y, int w, int h) { + if (getPeer() != null) { + getPeer().notifyReshape(x, y, w, h); + } + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public void setTitle(String title) { + } + + @Override + public void updateIconImages() { + } + + @Override + public long getNSWindowPtr() { + return 0; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void toBack() { + } + + @Override + public void toFront() { + } + + @Override + public void setResizable(final boolean resizable) { + } + + @Override + public void setSizeConstraints(int minW, int minH, int maxW, int maxH) { + } + + @Override + public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + return false; + } + + @Override + public boolean requestWindowFocus() { + return true; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public void updateFocusableWindowState() { + } + + @Override + public Graphics transformGraphics(Graphics g) { + return null; + } + + @Override + public void setAlwaysOnTop(boolean isAlwaysOnTop) { + } + + @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse(){ + return null; + } + + @Override + public void setOpacity(float opacity) { + } + + @Override + public void setOpaque(boolean isOpaque) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public void setWindowState(int windowState) { + } + + @Override + public LWWindowPeer getPeer() { + return super.getPeer(); + } + + @Override + public CPlatformView getContentView() { + return super.getContentView(); + } + + @Override + public long getLayerPtr() { + return 0; + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java index 495657963bd..3a0bec48629 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java @@ -54,8 +54,7 @@ public class CPlatformView extends CFRetainedResource { } public void initialize(LWWindowPeer peer, CPlatformResponder responder) { - this.peer = peer; - this.responder = responder; + initializeBase(peer, responder); if (!LWCToolkit.getSunAwtDisableCALayers()) { this.windowLayer = new CGLLayer(peer); @@ -63,6 +62,11 @@ public class CPlatformView extends CFRetainedResource { setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); } + protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) { + this.peer = peer; + this.responder = responder; + } + public long getAWTView() { return ptr; } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 8f83702a209..3fb585bdb53 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -30,6 +30,7 @@ import java.awt.Dialog.ModalityType; import java.awt.event.*; import java.awt.peer.WindowPeer; import java.beans.*; +import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.swing.*; @@ -44,7 +45,7 @@ import com.apple.laf.*; import com.apple.laf.ClientPropertyApplicator.Property; import com.sun.awt.AWTUtilities; -public final class CPlatformWindow extends CFRetainedResource implements PlatformWindow { +public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { private native long nativeCreateNSWindow(long nsViewPtr, long styleBits, double x, double y, double w, double h); private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data); private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); @@ -218,11 +219,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor */ @Override // PlatformWindow public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) { - this.peer = _peer; - this.target = _target; - if (_owner instanceof CPlatformWindow) { - this.owner = (CPlatformWindow)_owner; - } + initializeBase(_target, _peer, _owner, new CPlatformView()); final int styleBits = getInitialStyleBits(); @@ -231,7 +228,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor String warningString = target.getWarningString(); responder = new CPlatformResponder(peer, false); - contentView = new CPlatformView(); contentView.initialize(peer, responder); final long nativeWindowPtr = nativeCreateNSWindow(contentView.getAWTView(), styleBits, 0, 0, 0, 0); @@ -253,6 +249,15 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor validateSurface(); } + protected void initializeBase(Window target, LWWindowPeer peer, PlatformWindow owner, CPlatformView view) { + this.peer = peer; + this.target = target; + if (owner instanceof CPlatformWindow) { + this.owner = (CPlatformWindow)owner; + } + this.contentView = view; + } + private int getInitialStyleBits() { // defaults style bits int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE; @@ -857,7 +862,16 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor private void flushBuffers() { if (isVisible() && !nativeBounds.isEmpty()) { - LWCToolkit.getLWCToolkit().flushPendingEventsOnAppkit(target); + try { + LWCToolkit.invokeAndWait(new Runnable() { + @Override + public void run() { + //Posting an empty to flush the EventQueue without blocking the main thread + } + }, target); + } catch (InterruptedException | InvocationTargetException e) { + e.printStackTrace(); + } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java index e04a45fd579..c74a589a328 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -65,7 +65,7 @@ class CRobot implements RobotPeer { mouseLastX = x; mouseLastY = y; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, mouseButtonsState, true, true); } @@ -79,7 +79,7 @@ class CRobot implements RobotPeer { public void mousePress(int buttons) { mouseButtonsState |= buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, true, false); } @@ -93,7 +93,7 @@ class CRobot implements RobotPeer { public void mouseRelease(int buttons) { mouseButtonsState &= ~buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, false, false); } @@ -163,7 +163,7 @@ class CRobot implements RobotPeer { } private native void initRobot(); - private native void mouseEvent(int screen, int lastX, int lastY, + private native void mouseEvent(int displayID, int lastX, int lastY, int buttonsState, boolean isButtonsDownState, boolean isMouseMove); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java index 94a74e5174b..6bc6cc7c41b 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java @@ -25,27 +25,33 @@ package sun.lwawt.macosx; +import sun.awt.Mutex; import sun.awt.datatransfer.ToolkitThreadBlockedHandler; -final class CToolkitThreadBlockedHandler implements ToolkitThreadBlockedHandler { - private final LWCToolkit toolkit = (LWCToolkit)java.awt.Toolkit.getDefaultToolkit(); +final class CToolkitThreadBlockedHandler extends Mutex implements ToolkitThreadBlockedHandler { + private long awtRunLoopMediator = 0; + private final boolean processEvents; - public void lock() { - } - - public void unlock() { - } - - protected boolean isOwned() { - return false; + CToolkitThreadBlockedHandler() { + super(); + this.processEvents = true; } public void enter() { - // Execute the next AppKit event while we are waiting for system to - // finish our request - this will save us from biting our own tail - toolkit.executeNextAppKitEvent(); + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + awtRunLoopMediator = LWCToolkit.createAWTRunLoopMediator(); + unlock(); + LWCToolkit.doAWTRunLoop(awtRunLoopMediator, processEvents); + lock(); } public void exit() { + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + LWCToolkit.stopAWTRunLoop(awtRunLoopMediator); + awtRunLoopMediator = 0; } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index ae6a4f77662..a15eb46a1d1 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -63,8 +63,6 @@ public final class LWCToolkit extends LWToolkit { private static native void initIDs(); - static native void executeNextAppKitEvent(); - private static CInputMethodDescriptor sInputMethodDescriptor; static { @@ -160,6 +158,8 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformEmbeddedFrame(); } else if (peerType == PeerType.VIEW_EMBEDDED_FRAME) { return new CViewPlatformEmbeddedFrame(); + } else if (peerType == PeerType.LW_FRAME) { + return new CPlatformLWWindow(); } else { assert (peerType == PeerType.SIMPLEWINDOW || peerType == PeerType.DIALOG || peerType == PeerType.FRAME); return new CPlatformWindow(); @@ -171,6 +171,11 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformComponent(); } + @Override + protected PlatformComponent createLwPlatformComponent() { + return new CPlatformLWComponent(); + } + @Override protected FileDialogPeer createFileDialogPeer(FileDialog target) { return new CFileDialog(target); @@ -346,22 +351,7 @@ public final class LWCToolkit extends LWToolkit { @Override public Insets getScreenInsets(final GraphicsConfiguration gc) { - final CGraphicsConfig cgc = (CGraphicsConfig) gc; - final int displayId = cgc.getDevice().getCoreGraphicsScreen(); - Rectangle fullScreen, workArea; - final long screen = CWrapper.NSScreen.screenByDisplayId(displayId); - try { - fullScreen = CWrapper.NSScreen.frame(screen).getBounds(); - workArea = CWrapper.NSScreen.visibleFrame(screen).getBounds(); - } finally { - CWrapper.NSObject.release(screen); - } - // Convert between Cocoa's coordinate system and Java. - int bottom = workArea.y - fullScreen.y; - int top = fullScreen.height - workArea.height - bottom; - int left = workArea.x - fullScreen.x; - int right = fullScreen.width - workArea.width - left; - return new Insets(top, left, bottom, right); + return ((CGraphicsConfig) gc).getDevice().getScreenInsets(); } @Override @@ -495,30 +485,6 @@ public final class LWCToolkit extends LWToolkit { synchronized(ret) { return ret[0]; } } - /** - * Just a wrapper for LWCToolkit.invokeAndWait. Posts an empty event to the - * appropriate event queue and waits for it to finish. - */ - public static void flushPendingEventsOnAppkit(final Component component) { - try { - invokeAndWait(new Runnable() { - @Override - public void run() { - } - }, component); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Kicks an event over to the appropriate eventqueue and waits for it to finish - // To avoid deadlocking, we manually run the NSRunLoop while waiting - // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop - // The CInvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop - public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { - invokeAndWait(event, component, true); - } - public static T invokeAndWait(final Callable callable, Component component) throws Exception { final CallableWrapper wrapper = new CallableWrapper(callable); invokeAndWait(wrapper, component); @@ -548,10 +514,27 @@ public final class LWCToolkit extends LWToolkit { } } - public static void invokeAndWait(Runnable event, Component component, boolean detectDeadlocks) throws InterruptedException, InvocationTargetException { - long mediator = createAWTRunLoopMediator(); + // Kicks an event over to the appropriate eventqueue and waits for it to finish + // To avoid deadlocking, we manually run the NSRunLoop while waiting + // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop + // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop + // Does not dispatch native events while in the loop + public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { + final long mediator = createAWTRunLoopMediator(); - InvocationEvent invocationEvent = new CPeerEvent(event, mediator); + InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) { + @Override + public void dispatch() { + try { + super.dispatch(); + } finally { + if (mediator != 0) { + stopAWTRunLoop(mediator); + } + } + } + }; if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component); @@ -564,7 +547,7 @@ public final class LWCToolkit extends LWToolkit { ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); } - doAWTRunLoop(mediator, true, detectDeadlocks); + doAWTRunLoop(mediator, false); Throwable eventException = invocationEvent.getException(); if (eventException != null) { @@ -576,7 +559,8 @@ public final class LWCToolkit extends LWToolkit { } public static void invokeLater(Runnable event, Component component) throws InvocationTargetException { - final InvocationEvent invocationEvent = new CPeerEvent(event, 0); + final InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event); if (component != null) { final AppContext appContext = SunToolkit.targetToAppContext(component); @@ -681,31 +665,6 @@ public final class LWCToolkit extends LWToolkit { return false; } - // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early - // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop - public static class CPeerEvent extends PeerEvent { - private long _mediator = 0; - - public CPeerEvent(Runnable runnable, long mediator) { - super(Toolkit.getDefaultToolkit(), runnable, null, true, 0); - _mediator = mediator; - } - - public void dispatch() { - try { - super.dispatch(); - } finally { - if (_mediator != 0) { - LWCToolkit.stopAWTRunLoop(_mediator); - } - } - } - } - - // Call through to native methods - public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); } - public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); } - private static Boolean sunAwtDisableCALayers = null; /** @@ -730,12 +689,20 @@ public final class LWCToolkit extends LWToolkit { * Native methods section ************************/ - // These are public because they are accessed from WebKitPluginObject in JavaDeploy - // Basic usage: - // createAWTRunLoopMediator. Start client code on another thread. doAWTRunLoop. When client code is finished, stopAWTRunLoop. - public static native long createAWTRunLoopMediator(); - public static native void doAWTRunLoop(long mediator, boolean awtMode, boolean detectDeadlocks); - public static native void stopAWTRunLoop(long mediator); + static native long createAWTRunLoopMediator(); + /** + * Method to run a nested run-loop. The nested loop is spinned in the javaRunLoop mode, so selectors sent + * by [JNFRunLoop performOnMainThreadWaiting] are processed. + * @param mediator a native pointer to the mediator object created by createAWTRunLoopMediator + * @param processEvents if true - dispatches event while in the nested loop. Used in DnD. + * Additional attention is needed when using this feature as we short-circuit normal event + * processing which could break Appkit. + * (One known example is when the window is resized with the mouse) + * + * if false - all events come after exit form the nested loop + */ + static native void doAWTRunLoop(long mediator, boolean processEvents); + static native void stopAWTRunLoop(long mediator); private native boolean nativeSyncQueue(long timeout); diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index cc16a2026ee..7e1f248c7ed 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -227,7 +227,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) mouseMoved: (NSEvent *)event { // TODO: better way to redirect move events to the "under" view - + NSPoint eventLocation = [event locationInWindow]; NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; @@ -668,7 +668,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) setDropTarget:(CDropTarget *)target { self._dropTarget = target; - [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) onObject:self._dropTarget withObject:nil waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES]; } /******************************** BEGIN NSDraggingSource Interface ********************************/ @@ -1215,7 +1215,7 @@ JNF_CLASS_CACHE(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod"); fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); #endif // IM_DEBUG - [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) onObject:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; [self unmarkText]; } diff --git a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m index 9a5aee94d44..6b584b21ca3 100644 --- a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m +++ b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m @@ -567,10 +567,9 @@ JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNo { JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) - onObject:[ApplicationDelegate class] + on:[ApplicationDelegate class] withObject:[NSNumber numberWithInt:notificationType] - waitUntilDone:NO - awtMode:NO]; // AWT_THREADING Safe (non-blocking) + waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) JNF_COCOA_EXIT(env); } diff --git a/jdk/src/macosx/native/sun/awt/CClipboard.m b/jdk/src/macosx/native/sun/awt/CClipboard.m index fb300f72971..bfba06b47d1 100644 --- a/jdk/src/macosx/native/sun/awt/CClipboard.m +++ b/jdk/src/macosx/native/sun/awt/CClipboard.m @@ -120,7 +120,7 @@ static CClipboard *sClipboard = nil; fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard); } } - [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) onObject:self withObject:inTypes waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES]; } - (void) _nativeDeclareTypes:(NSArray *)inTypes { @@ -135,7 +135,7 @@ static CClipboard *sClipboard = nil; - (NSArray *) javaGetTypes { NSMutableArray *args = [NSMutableArray arrayWithCapacity:1]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard getTypes returns %@", [args lastObject]); return [args lastObject]; @@ -152,7 +152,7 @@ static CClipboard *sClipboard = nil; - (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat { CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) onObject:self withObject:newUpdate waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES]; [newUpdate release]; //NSLog(@"CClipboard javaSetData forType %@", inFormat); @@ -170,7 +170,7 @@ static CClipboard *sClipboard = nil; - (NSData *) javaGetDataForType:(NSString *) inFormat { NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard javaGetDataForType %@ returns an NSData", inFormat); return [args lastObject]; diff --git a/jdk/src/macosx/native/sun/awt/CDropTarget.m b/jdk/src/macosx/native/sun/awt/CDropTarget.m index 60cd7818254..9dda8ae3551 100644 --- a/jdk/src/macosx/native/sun/awt/CDropTarget.m +++ b/jdk/src/macosx/native/sun/awt/CDropTarget.m @@ -390,8 +390,7 @@ extern JNFClassInfo jc_CDropTargetContextPeer; // Release dragging data if any when Java's AWT event thread is all finished. // Make sure dragging data is released on the native event thread. - [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) onObject:self - withObject:draggingSequenceNumberID waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO]; } - (jint)currentJavaActions { diff --git a/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m b/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m index 9bc5393d765..1e2df28dd56 100644 --- a/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m +++ b/jdk/src/macosx/native/sun/awt/CGraphicsDevice.m @@ -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 @@ -23,7 +23,8 @@ * questions. */ -#include "LWCToolkit.h" +#import "LWCToolkit.h" +#import "ThreadUtilities.h" /* * Convert the mode string to the more convinient bits per pixel value @@ -146,6 +147,47 @@ Java_sun_awt_CGraphicsDevice_nativeGetYResolution return dpi; } +/* + * Class: sun_awt_CGraphicsDevice + * Method: nativeGetScreenInsets + * Signature: (I)D + */ +JNIEXPORT jobject JNICALL +Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets + (JNIEnv *env, jclass class, jint displayID) +{ + jobject ret = NULL; + __block NSRect frame = NSZeroRect; + __block NSRect visibleFrame = NSZeroRect; +JNF_COCOA_ENTER(env); + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + NSArray *screens = [NSScreen screens]; + for (NSScreen *screen in screens) { + NSDictionary *screenInfo = [screen deviceDescription]; + NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"]; + if ([screenID pointerValue] == displayID){ + frame = [screen frame]; + visibleFrame = [screen visibleFrame]; + break; + } + } + }]; + // Convert between Cocoa's coordinate system and Java. + jint bottom = visibleFrame.origin.y - frame.origin.y; + jint top = frame.size.height - visibleFrame.size.height - bottom; + jint left = visibleFrame.origin.x - frame.origin.x; + jint right = frame.size.width - visibleFrame.size.width - left; + + static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets"); + static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V"); + ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right); + +JNF_COCOA_EXIT(env); + + return ret; +} + /* * Class: sun_awt_CGraphicsDevice * Method: nativeSetDisplayMode diff --git a/jdk/src/macosx/native/sun/awt/CMenu.m b/jdk/src/macosx/native/sun/awt/CMenu.m index e6325c2c3db..8b643b3bca0 100644 --- a/jdk/src/macosx/native/sun/awt/CMenu.m +++ b/jdk/src/macosx/native/sun/awt/CMenu.m @@ -55,11 +55,11 @@ AWT_ASSERT_APPKIT_THREAD; //- (void)finalize { [super finalize]; } - (void)addJavaSubmenu:(CMenu *)submenu { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:submenu waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES]; } - (void)addJavaMenuItem:(CMenuItem *)theMenuItem { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:theMenuItem waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES]; } - (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified { @@ -70,7 +70,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)setJavaMenuTitle:(NSString *)title { if (title) { - [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) onObject:self withObject:title waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES]; } } @@ -93,7 +93,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)deleteJavaItem:(jint)index { - [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } - (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number { @@ -139,7 +139,7 @@ CMenu * createCMenu (jobject cPeerObjGlobal) { // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenu alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES]; aCMenu = (CMenu *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/CMenuBar.m b/jdk/src/macosx/native/sun/awt/CMenuBar.m index 23c79496189..b0d67f71a2a 100644 --- a/jdk/src/macosx/native/sun/awt/CMenuBar.m +++ b/jdk/src/macosx/native/sun/awt/CMenuBar.m @@ -197,7 +197,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -216,7 +216,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -286,7 +286,7 @@ static BOOL sSetupHelpMenu = NO; - (void) javaDeleteMenu: (jint)index { if (self == sActiveMenuBar) { - [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } @synchronized(self) { @@ -388,7 +388,7 @@ Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenuBar alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES]; aCMenuBar = (CMenuBar *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/CMenuItem.m b/jdk/src/macosx/native/sun/awt/CMenuItem.m index 2281d8bcd95..b67c70658dd 100644 --- a/jdk/src/macosx/native/sun/awt/CMenuItem.m +++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m @@ -386,7 +386,7 @@ JNF_COCOA_ENTER(env); args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil]; } - [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) onObject:[CMenuItem alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES]; aCMenuItem = (CMenuItem *)[args objectAtIndex: 0]; diff --git a/jdk/src/macosx/native/sun/awt/CRobot.m b/jdk/src/macosx/native/sun/awt/CRobot.m index c04d5685a56..056fd19e29f 100644 --- a/jdk/src/macosx/native/sun/awt/CRobot.m +++ b/jdk/src/macosx/native/sun/awt/CRobot.m @@ -135,7 +135,7 @@ Java_sun_lwawt_macosx_CRobot_initRobot JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CRobot_mouseEvent (JNIEnv *env, jobject peer, - jint screenIndex, jint mouseLastX, jint mouseLastY, jint buttonsState, + jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState, jboolean isButtonsDownState, jboolean isMouseMove) { JNF_COCOA_ENTER(env); @@ -149,8 +149,6 @@ Java_sun_lwawt_macosx_CRobot_mouseEvent CGError err = kCGErrorSuccess; - CGDirectDisplayID displayID = - FindCGDirectDisplayIDForScreenIndex(screenIndex); CGRect globalDeviceBounds = CGDisplayBounds(displayID); // Set unknown mouse location, if needed. diff --git a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m index f886c4afbe1..a01bd781faa 100644 --- a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m +++ b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m @@ -1113,18 +1113,10 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; - // This code frequently gets called indirectly by Java when VoiceOver is active. - // Basically, we just have to know when we going to be a bad state, and do something "special". - // Note that while NSApplication isn't technically correct, we post a focus changed notification - // (which will call this method, but with the correct codepath) shortly afterwards. See +postFocusChanged. - if (sInPerformFromJava) { - return [NSApplication sharedApplication]; - } else { - jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) - if (focused != NULL) { - if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { - value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; - } + jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + if (focused != NULL) { + if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { + value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; } } @@ -1149,7 +1141,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessibility_focusChanged { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) onObject:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) on:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1164,7 +1156,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_valueChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postValueChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postValueChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1177,7 +1169,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectionChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1191,7 +1183,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_unregisterFromCocoaAXSy (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.h b/jdk/src/macosx/native/sun/awt/LWCToolkit.h index c318421c2e1..8df2c553996 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.h +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.h @@ -44,8 +44,6 @@ extern jint* gButtonDownMasks; + (void) eventCountPlusPlus; @end -CGDirectDisplayID FindCGDirectDisplayIDForScreenIndex(jint screenIndex); - /* * Utility Macros */ diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m index 45c546181f0..47c72abbfa5 100644 --- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m +++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m @@ -177,39 +177,6 @@ Java_sun_lwawt_macosx_LWCToolkit_beep NSBeep(); // produces both sound and visual flash, if configured in System Preferences } -CGDirectDisplayID -FindCGDirectDisplayIDForScreenIndex(jint screenIndex) -{ - // most common case - just one monitor - CGDirectDisplayID screenID = CGMainDisplayID(); - - CGDisplayCount displayCount = 0; - CGGetOnlineDisplayList(0, NULL, &displayCount); - - if ((displayCount > 1) && - (screenIndex >= 0) && - (screenIndex < (jint)displayCount)) - { - if (displayCount < 10) { - // stack allocated optimization for less than 10 monitors - CGDirectDisplayID onlineDisplays[displayCount]; - CGGetOnlineDisplayList(displayCount, onlineDisplays, &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - } else { - CGDirectDisplayID *onlineDisplays = - malloc(displayCount*sizeof(CGDirectDisplayID)); - if (onlineDisplays != NULL) { - CGGetOnlineDisplayList(displayCount, onlineDisplays, - &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - free(onlineDisplays); - } - } - } - - return screenID; -} - /* * Class: sun_lwawt_macosx_LWCToolkit * Method: initIDs @@ -332,7 +299,7 @@ AWT_ASSERT_APPKIT_THREAD; * Signature: (JZZ)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoop -(JNIEnv *env, jclass clz, jlong mediator, jboolean awtMode, jboolean detectDeadlocks) +(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents) { AWT_ASSERT_APPKIT_THREAD; JNF_COCOA_ENTER(env); @@ -341,26 +308,25 @@ JNF_COCOA_ENTER(env); if (mediatorObject == nil) return; - if (!sInPerformFromJava || !detectDeadlocks) { + // Don't use acceptInputForMode because that doesn't setup autorelease pools properly + BOOL isRunning = true; + while (![mediatorObject shouldEndRunLoop] && isRunning) { + isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode] + beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; + if (processEvents) { + //We do not spin a runloop here as date is nil, so does not matter which mode to use + NSEvent *event; + if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]) != nil) { + [NSApp sendEvent:event]; + } - NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; - NSDate *distantFuture = [NSDate distantFuture]; - NSString *mode = (awtMode) ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode; - - BOOL isRunning = YES; - while (isRunning && ![mediatorObject shouldEndRunLoop]) { - // Don't use acceptInputForMode because that doesn't setup autorelease pools properly - isRunning = [currentRunLoop runMode:mode beforeDate:distantFuture]; } - } -#ifndef PRODUCT_BUILD - if (sInPerformFromJava) { - NSLog(@"Apple AWT: Short-circuiting CToolkit.invokeAndWait trampoline deadlock!!!!!"); - NSLog(@"\tPlease file a bug report with this message and a reproducible test case."); - } -#endif + CFRelease(mediatorObject); JNF_COCOA_EXIT(env); @@ -379,7 +345,7 @@ JNF_COCOA_ENTER(env); AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); - [ThreadUtilities performOnMainThread:@selector(endRunLoop) onObject:mediatorObject withObject:nil waitUntilDone:NO awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; CFRelease(mediatorObject); @@ -463,20 +429,3 @@ Java_sun_font_FontManager_populateFontFileNameMap } -/* - * Class: sun_lwawt_macosx_LWCToolkit - * Method: executeNextAppKitEvent - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_executeNextAppKitEvent -(JNIEnv *env, jclass cls) -{ - // Simply get the next event in native loop and pass it to execution - // We'll be called repeatedly so there's no need to block here - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - NSApplication * app = [NSApplication sharedApplication]; - NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; - if (event != nil) { - [app sendEvent: event]; - } -} diff --git a/jdk/src/macosx/native/sun/font/AWTStrike.m b/jdk/src/macosx/native/sun/font/AWTStrike.m index 261bd34ae57..7f04b530ade 100644 --- a/jdk/src/macosx/native/sun/font/AWTStrike.m +++ b/jdk/src/macosx/native/sun/font/AWTStrike.m @@ -27,11 +27,13 @@ #import "java_awt_geom_PathIterator.h" #import "sun_awt_SunHints.h" #import "sun_font_CStrike.h" +#import "sun_font_CStrikeDisposer.h" #import "CGGlyphImages.h" #import "CGGlyphOutlines.h" #import "AWTStrike.h" #import "CoreTextSupport.h" //#import "jni_util.h" +#include "fontscalerdefs.h" /* Use THIS_FILE when it is available. */ #ifndef THIS_FILE @@ -423,3 +425,19 @@ JNF_COCOA_EXIT(env); return metrics; } + +extern void AccelGlyphCache_RemoveAllInfos(GlyphInfo* glyph); +/* + * Class: sun_font_CStrikeDisposer + * Method: removeGlyphInfoFromCache + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_font_CStrikeDisposer_removeGlyphInfoFromCache +(JNIEnv *env, jclass cls, jlong glyphInfo) +{ + JNF_COCOA_ENTER(env); + + AccelGlyphCache_RemoveAllCellInfos((GlyphInfo*)jlong_to_ptr(glyphInfo)); + + JNF_COCOA_EXIT(env); +} diff --git a/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m b/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m index 0bc58ec6ad3..a9de285758d 100644 --- a/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m +++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m @@ -192,12 +192,12 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo (JNIEnv *env, jclass cglgc, - jint screennum, jint pixfmt, jint swapInterval) + jint displayID, jint pixfmt, jint swapInterval) { jlong ret = 0L; JNF_COCOA_ENTER(env); NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3]; - [retArray addObject: [NSNumber numberWithInt: (int)screennum]]; + [retArray addObject: [NSNumber numberWithInt: (int)displayID]]; [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]]; [retArray addObject: [NSNumber numberWithInt: (int)swapInterval]]; if ([NSThread isMainThread]) { @@ -217,7 +217,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo + (void) _getCGLConfigInfo: (NSMutableArray *)argValue { AWT_ASSERT_APPKIT_THREAD; - jint screennum = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; + jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue]; jint swapInterval = (jint)[(NSNumber *)[argValue objectAtIndex: 2] intValue]; JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; @@ -230,16 +230,11 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt; if (sharedContext == NULL) { if (glMask == 0) { - CGDirectDisplayID id = - FindCGDirectDisplayIDForScreenIndex(screennum); - glMask = CGDisplayIDToOpenGLDisplayMask(id); + glMask = CGDisplayIDToOpenGLDisplayMask(displayID); } NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFAClosestPolicy, - NSOpenGLPFANoRecovery, - NSOpenGLPFAAccelerated, - NSOpenGLPFAFullScreen, NSOpenGLPFAWindow, NSOpenGLPFAPixelBuffer, NSOpenGLPFADoubleBuffer, @@ -412,7 +407,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo return; } memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo)); - cglinfo->screen = screennum; + cglinfo->screen = displayID; cglinfo->pixfmt = sharedPixelFormat; cglinfo->context = oglc; @@ -422,17 +417,6 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo } @end //GraphicsConfigUtil - -JNIEXPORT jint JNICALL -Java_sun_java2d_opengl_CGLGraphicsConfig_getDefaultPixFmt - (JNIEnv *env, jclass cglgc, jint screennum) -{ - J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getDefaultPixFmt"); - - CGDirectDisplayID id = FindCGDirectDisplayIDForScreenIndex(screennum); - return (jint)CGDisplayIDToOpenGLDisplayMask(id); -} - JNIEXPORT jint JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities (JNIEnv *env, jclass cglgc, jlong configInfo) diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h index c0d2054f6e3..2ee65e94c65 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h @@ -122,19 +122,12 @@ do { \ #endif /* AWT_THREAD_ASSERTS */ // -------------------------------------------------------------------------- -// This tracks if we are current inside of a performOnMainThread that is both waiting and in the AWTRunLoopMode -extern BOOL sInPerformFromJava; - -// This is an empty Obj-C object just so that -performSelectorOnMainThread -// can be used, and to use the Obj-C +initialize feature. __attribute__((visibility("default"))) -@interface ThreadUtilities : NSObject { } +@interface ThreadUtilities { } + (JNIEnv*)getJNIEnv; + (JNIEnv*)getJNIEnvUncached; -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT; - //Wrappers for the corresponding JNFRunLoop methods with a check for main thread + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block; + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait; diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m index 0b42f1b5896..d431386bbdb 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m @@ -34,85 +34,6 @@ JavaVM *jvm = NULL; static JNIEnv *appKitEnv = NULL; -static NSArray *sPerformModes = nil; -static NSArray *sAWTPerformModes = nil; - -static BOOL sLoggingEnabled = YES; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT -int sAWTThreadAsserts = 0; -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - -BOOL sInPerformFromJava = NO; - -// This class is used so that performSelectorOnMainThread can be -// controlled a little more easily by us. It has 2 roles. -// The first is to set/unset a flag (sInPerformFromJava) that code can -// check to see if we are in a synchronous perform initiated by a java thread. -// The second is to implement the CocoaComponent backward compatibility mode. -@interface CPerformer : NSObject { - id fTarget; - SEL fSelector; - id fArg; - BOOL fWait; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait; -- (void) perform; -@end - - -@implementation CPerformer - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg { - return [self initWithTarget:target selector:selector arg:arg wait:YES]; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait { - self = [super init]; - if (self != nil) { - fTarget = [target retain]; - fSelector = selector; - fArg = [arg retain]; - // Only set sInPerformFromJava if this is a synchronous perform - fWait = wait; - } - return self; -} - -- (void) dealloc { - [fTarget release]; - [fArg release]; - [super dealloc]; -} -//- (void)finalize { [super finalize]; } - -- (void) perform { - AWT_ASSERT_APPKIT_THREAD; - - // If this is the first time we're going from java thread -> appkit thread, - // set sInPerformFromJava for the duration of the invocation - BOOL nestedPerform = sInPerformFromJava; - if (fWait) { - sInPerformFromJava = YES; - } - - // Actually do the work (cheat to avoid a method call) - @try { - objc_msgSend(fTarget, fSelector, fArg); - //[fTarget performSelector:fSelector withObject:fArg]; - } @catch (NSException *e) { - NSLog(@"*** CPerformer: ignoring exception '%@' raised during perform of selector '%@' on target '%@' with args '%@'", e, NSStringFromSelector(fSelector), fTarget, fArg); - } @finally { - // If we actually set sInPerformFromJava, unset it now - if (!nestedPerform && fWait) { - sInPerformFromJava = NO; - } - } -} -@end - - @implementation ThreadUtilities + (JNIEnv*)getJNIEnv { @@ -129,36 +50,6 @@ AWT_ASSERT_APPKIT_THREAD; return env; } -+ (void)initialize { - // Headless: BOTH - // Embedded: BOTH - // Multiple Calls: NO - // Caller: Obj-C class initialization - // Thread: ? - - if (sPerformModes == nil) { - // Create list of Run Loop modes to perform on - // The default performSelector, with no mode argument, runs in Default, - // ModalPanel, and EventTracking modes - sPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, nil]; - sAWTPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, [JNFRunLoop javaRunLoopMode], nil]; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT - sAWTThreadAsserts = (getenv("COCOA_AWT_DISABLE_THREAD_ASSERTS") == NULL); -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - } -} - -// These methods can behave slightly differently than the normal -// performSelector... In particular, we define a special runloop mode -// (AWTRunLoopMode) so that we can "block" the main thread against the -// java event thread without deadlocking. See CToolkit.invokeAndWait. -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT { - CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait]; - [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method) - [performer release]; -} - + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); diff --git a/jdk/src/share/back/transport.c b/jdk/src/share/back/transport.c index 40608b31239..1d7335d660b 100644 --- a/jdk/src/share/back/transport.c +++ b/jdk/src/share/back/transport.c @@ -117,6 +117,9 @@ loadTransportLibrary(char *libdir, char *name) /* 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)); diff --git a/jdk/src/share/bin/jli_util.h b/jdk/src/share/bin/jli_util.h index 568318c95c6..388910407ff 100644 --- a/jdk/src/share/bin/jli_util.h +++ b/jdk/src/share/bin/jli_util.h @@ -66,7 +66,7 @@ int JLI_GetStdArgc(); #include #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) -#define JLI_Snprintf _snprintf +int JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 #else /* NIXES */ diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c index 61b0bbf4884..4926824e36b 100644 --- a/jdk/src/share/bin/parse_manifest.c +++ b/jdk/src/share/bin/parse_manifest.c @@ -569,9 +569,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); - + } info->manifest_version = NULL; info->main_class = NULL; info->jre_version = NULL; @@ -618,15 +618,17 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { zentry entry; void *data = NULL; - fd = open(jarfile, O_RDONLY + if ((fd = open(jarfile, O_RDONLY #ifdef O_LARGEFILE | O_LARGEFILE /* large file mode */ #endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - ); - if (fd != -1 && find_file(fd, &entry, filename) == 0) { + )) == -1) { + return NULL; + } + if (find_file(fd, &entry, filename) == 0) { data = inflate_file(fd, &entry, size); } close(fd); @@ -671,8 +673,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); + } if (rc = find_file(fd, &entry, manifest_name) != 0) { close(fd); diff --git a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java index fa7cc5612ab..98c52bc929a 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java +++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java @@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder { Signature signature = new Signature(type, name, args); Method method = CACHE.get(signature); - if (method != null) { + boolean cached = method != null; + if (cached && isPackageAccessible(method.getDeclaringClass())) { return method; } method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); - CACHE.put(signature, method); + if (!cached) { + CACHE.put(signature, method); + } return method; } diff --git a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index b69875dd481..33fa49297dd 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException; import javax.crypto.SecretKey; import javax.crypto.spec.*; +import sun.security.util.KeyUtil; + /** * This class implements the Diffie-Hellman key agreement protocol between * any number of parties. @@ -200,6 +202,9 @@ extends KeyAgreementSpi { throw new InvalidKeyException("Incompatible parameters"); } + // validate the Diffie-Hellman public key + KeyUtil.validate(dhPubKey); + // store the y value this.y = dhPubKey.getY(); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java index f6ff030263e..a6033c97b14 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java @@ -177,7 +177,7 @@ class Attribute implements Comparable { 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", diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index fdfb87dc136..322e2c33326 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -1000,7 +1000,6 @@ class BandStructure { /** Write a constant pool reference. */ public void putRef(Entry e) { - assert(index != null); addValue(encodeRefOrNull(e, index)); } public void putRef(Entry e, Index index) { @@ -1052,6 +1051,8 @@ class BandStructure { int encodeRef(Entry e, Index ix) { + if (ix == null) + throw new RuntimeException("null index for " + e.stringValue()); int coding = ix.indexOf(e); if (verbose > 2) Utils.log.fine("putRef "+coding+" => "+e); @@ -1505,7 +1506,7 @@ class BandStructure { // 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 +1777,9 @@ class BandStructure { 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 }, diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java index 3df8706da37..3da159f6e29 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java @@ -564,7 +564,7 @@ class ClassReader { 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++) { diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index ad2175f9993..1ede29134b0 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -207,6 +207,10 @@ class ConstantPool { return tag; } + public final boolean tagEquals(int tag) { + return getTag() == tag; + } + public Entry getRef(int i) { return null; } @@ -1405,6 +1409,8 @@ class ConstantPool { /** Index of all CP entries of a given tag and class. */ public Index getMemberIndex(byte tag, ClassEntry classRef) { + if (classRef == null) + throw new RuntimeException("missing class reference for " + tagName(tag)); if (indexByTagAndClass == null) indexByTagAndClass = new Index[CONSTANT_Limit][]; Index allClasses = getIndexByTag(CONSTANT_Class); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java index 15882624381..5059bc07967 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java @@ -479,4 +479,10 @@ class Constants { 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; } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java index 31ee22b059d..93175fe8ecf 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java @@ -446,12 +446,14 @@ class Instruction { 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 @@ class Instruction { } } - 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 @@ class Instruction { 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); } } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java index 532d4467664..3f2f430fb84 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java @@ -109,6 +109,10 @@ class NativeUnpack { return (p200 == null)? null: p200._nunp; } + private synchronized long getUnpackerPtr() { + return unpackerPtr; + } + // Callback from the unpacker engine to get more data. private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { if (in == null) return 0; // nothing is readable diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java index 319b8793347..b42dda30eb4 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java @@ -1521,7 +1521,7 @@ class PackageReader extends BandStructure { // *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 @@ class PackageReader extends BandStructure { 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: diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java index 47959294fd2..a78c9ae9969 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java @@ -1409,6 +1409,10 @@ class PackageWriter extends BandStructure { 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 @@ class PackageWriter extends BandStructure { 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: diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index 0dc88a108c7..309c68a8623 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarFile in, OutputStream out) throws IOException { + public synchronized void pack(JarFile in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null @@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarInputStream in, OutputStream out) throws IOException { + public synchronized void pack(JarInputStream in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone.getDefault(); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java index 5727d32986e..fd8ccfd3c71 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(InputStream in, JarOutputStream out) throws IOException { + public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } @@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(File in, JarOutputStream out) throws IOException { + public synchronized void unpack(File in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java index 728fb12a7e8..9fc0e7dbe9e 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java @@ -36,6 +36,7 @@ import java.util.logging.Level; import javax.management.ObjectName; import javax.management.loading.PrivateClassLoader; +import sun.reflect.misc.ReflectUtil; /** * This class keeps the list of Class Loaders registered in the MBean Server. @@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport final ClassLoader without, final ClassLoader stop) throws ClassNotFoundException { + ReflectUtil.checkPackageAccess(className); final int size = list.length; for(int i=0; i theClass) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + Object moi; @@ -260,6 +266,9 @@ public class MBeanInstantiator { public Object instantiate(Class theClass, Object params[], String signature[], ClassLoader loader) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + // Instantiate the new object // ------------------------------ @@ -407,6 +416,8 @@ public class MBeanInstantiator { throw new RuntimeOperationsException(new IllegalArgumentException(), "Null className passed in parameter"); } + + ReflectUtil.checkPackageAccess(className); Class theClass; if (loaderName == null) { // Load the class using the agent class loader @@ -619,13 +630,13 @@ public class MBeanInstantiator { **/ static Class loadClass(String className, ClassLoader loader) throws ReflectionException { - Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), "Exception occurred during object instantiation"); } + ReflectUtil.checkPackageAccess(className); try { if (loader == null) loader = MBeanInstantiator.class.getClassLoader(); @@ -676,6 +687,7 @@ public class MBeanInstantiator { // We need to load the class through the class // loader of the target object. // + ReflectUtil.checkPackageAccess(signature[i]); tab[i] = Class.forName(signature[i], false, aLoader); } } catch (ClassNotFoundException e) { @@ -701,7 +713,7 @@ public class MBeanInstantiator { private Constructor findConstructor(Class c, Class[] params) { try { - return c.getConstructor(params); + return ConstructorUtil.getConstructor(c, params); } catch (Exception e) { return null; } @@ -715,4 +727,18 @@ public class MBeanInstantiator { char.class, boolean.class}) primitiveClasses.put(c.getName(), c); } + + private static void checkMBeanPermission(Class clazz, + String member, + ObjectName objectName, + String actions) { + SecurityManager sm = System.getSecurityManager(); + if (clazz != null && sm != null) { + Permission perm = new MBeanPermission(clazz.getName(), + member, + objectName, + actions); + sm.checkPermission(perm); + } + } } diff --git a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java index 8109365e8d4..3af4b8b86d7 100644 --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java @@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; import com.sun.jmx.mbeanserver.MXBeanMappingFactory; +import sun.reflect.misc.ReflectUtil; /** * Base class for MBeans. There is one instance of this class for @@ -131,6 +132,7 @@ public abstract class MBeanSupport " is not an instance of " + mbeanInterfaceType.getName(); throw new NotCompliantMBeanException(msg); } + ReflectUtil.checkPackageAccess(mbeanInterfaceType); this.resource = resource; MBeanIntrospector introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType); diff --git a/jdk/src/share/classes/java/awt/CheckboxMenuItem.java b/jdk/src/share/classes/java/awt/CheckboxMenuItem.java index 635e9b55b89..ad12d4c29a9 100644 --- a/jdk/src/share/classes/java/awt/CheckboxMenuItem.java +++ b/jdk/src/share/classes/java/awt/CheckboxMenuItem.java @@ -277,7 +277,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @since 1.4 */ public synchronized ItemListener[] getItemListeners() { - return (ItemListener[])(getListeners(ItemListener.class)); + return getListeners(ItemListener.class); } /** diff --git a/jdk/src/share/classes/java/awt/Cursor.java b/jdk/src/share/classes/java/awt/Cursor.java index c340532b20d..d022a647869 100644 --- a/jdk/src/share/classes/java/awt/Cursor.java +++ b/jdk/src/share/classes/java/awt/Cursor.java @@ -163,11 +163,11 @@ public class Cursor implements java.io.Serializable { * hashtable, filesystem dir prefix, filename, and properties for custom cursors support */ - private static final Hashtable systemCustomCursors = new Hashtable(1); + private static final Hashtable systemCustomCursors = new Hashtable<>(1); private static final String systemCustomCursorDirPrefix = initCursorDir(); private static String initCursorDir() { - String jhome = (String) java.security.AccessController.doPrivileged( + String jhome = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.home")); return jhome + File.separator + "lib" + File.separator + "images" + @@ -298,7 +298,7 @@ public class Cursor implements java.io.Serializable { static public Cursor getSystemCustomCursor(final String name) throws AWTException, HeadlessException { GraphicsEnvironment.checkHeadless(); - Cursor cursor = (Cursor)systemCustomCursors.get(name); + Cursor cursor = systemCustomCursors.get(name); if (cursor == null) { synchronized(systemCustomCursors) { @@ -319,11 +319,11 @@ public class Cursor implements java.io.Serializable { final String fileName = systemCustomCursorProperties.getProperty(key); - String localized = (String)systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); + String localized = systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); if (localized == null) localized = name; - String hotspot = (String)systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); + String hotspot = systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); if (hotspot == null) throw new AWTException("no hotspot property defined for cursor: " + name); @@ -348,9 +348,9 @@ public class Cursor implements java.io.Serializable { final int fy = y; final String flocalized = localized; - cursor = (Cursor) java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws Exception { + cursor = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public Cursor run() throws Exception { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = toolkit.getImage( systemCustomCursorDirPrefix + fileName); @@ -447,8 +447,8 @@ public class Cursor implements java.io.Serializable { systemCustomCursorProperties = new Properties(); try { - AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { + AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { public Object run() throws Exception { FileInputStream fis = null; try { diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index 622a4531d3a..d27041fd322 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -39,6 +39,7 @@ import sun.awt.PeerEvent; import sun.awt.util.IdentityArrayList; import sun.awt.util.IdentityLinkedList; import sun.security.util.SecurityConstants; +import java.security.AccessControlException; /** * A Dialog is a top-level window with a title and a border @@ -128,6 +129,8 @@ public class Dialog extends Window { */ boolean undecorated = false; + private transient boolean initialized = false; + /** * Modal dialogs block all input to some top-level windows. * Whether a particular window is blocked depends on dialog's type @@ -671,6 +674,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -722,6 +726,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -851,12 +856,9 @@ public class Dialog extends Window { if (modalityType == type) { return; } - if (type == ModalityType.TOOLKIT_MODAL) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION); - } - } + + checkModalityPermission(type); + modalityType = type; modal = (modalityType != ModalityType.MODELESS); } @@ -1025,6 +1027,11 @@ public class Dialog extends Window { */ @Deprecated public void show() { + if (!initialized) { + throw new IllegalStateException("The dialog component " + + "has not been initialized properly"); + } + beforeFirstShow = false; if (!isModal()) { conditionalShow(null, null); @@ -1600,18 +1607,51 @@ public class Dialog extends Window { } } + private void checkModalityPermission(ModalityType mt) { + if (mt == ModalityType.TOOLKIT_MODAL) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission( + SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION + ); + } + } + } + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException, HeadlessException { GraphicsEnvironment.checkHeadless(); - s.defaultReadObject(); - // in 1.5 or earlier modalityType was absent, so use "modal" instead - if (modalityType == null) { - setModal(modal); + java.io.ObjectInputStream.GetField fields = + s.readFields(); + + ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); + + try { + checkModalityPermission(localModalityType); + } catch (AccessControlException ace) { + localModalityType = DEFAULT_MODALITY_TYPE; } + // in 1.5 or earlier modalityType was absent, so use "modal" instead + if (localModalityType == null) { + this.modal = fields.get("modal", false); + setModal(modal); + } else { + this.modalityType = localModalityType; + } + + this.resizable = fields.get("resizable", true); + this.undecorated = fields.get("undecorated", false); + this.title = (String)fields.get("title", ""); + blockedWindows = new IdentityArrayList<>(); + + SunToolkit.checkAndSetPolicy(this); + + initialized = true; + } /* diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 5ba9756a1af..5795c37ae91 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -171,7 +171,7 @@ public class EventQueue { * The modifiers field of the current event, if the current event is an * InputEvent or ActionEvent. */ - private WeakReference currentEvent; + private WeakReference currentEvent; /* * Non-zero if a thread is waiting in getNextEvent(int) for an event of @@ -194,7 +194,8 @@ public class EventQueue { } public void removeSourceEvents(EventQueue eventQueue, Object source, - boolean removeAllEvents) { + boolean removeAllEvents) + { eventQueue.removeSourceEvents(source, removeAllEvents); } public boolean noEvents(EventQueue eventQueue) { @@ -203,6 +204,11 @@ public class EventQueue { public void wakeup(EventQueue eventQueue, boolean isShutdown) { eventQueue.wakeup(isShutdown); } + public void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException + { + EventQueue.invokeAndWait(source, r); + } }); } @@ -809,7 +815,7 @@ public class EventQueue { pushPopLock.lock(); try { return (Thread.currentThread() == dispatchThread) - ? ((AWTEvent)currentEvent.get()) + ? currentEvent.get() : null; } finally { pushPopLock.unlock(); @@ -1167,7 +1173,7 @@ public class EventQueue { return; } - currentEvent = new WeakReference(e); + currentEvent = new WeakReference<>(e); // This series of 'instanceof' checks should be replaced with a // polymorphic type (for example, an interface which declares a @@ -1245,8 +1251,14 @@ public class EventQueue { * @since 1.2 */ public static void invokeAndWait(Runnable runnable) - throws InterruptedException, InvocationTargetException { + throws InterruptedException, InvocationTargetException + { + invokeAndWait(Toolkit.getDefaultToolkit(), runnable); + } + static void invokeAndWait(Object source, Runnable runnable) + throws InterruptedException, InvocationTargetException + { if (EventQueue.isDispatchThread()) { throw new Error("Cannot call invokeAndWait from the event dispatcher thread"); } @@ -1255,8 +1267,7 @@ public class EventQueue { Object lock = new AWTInvocationLock(); InvocationEvent event = - new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock, - true); + new InvocationEvent(source, runnable, lock, true); synchronized (lock) { Toolkit.getEventQueue().postEvent(event); diff --git a/jdk/src/share/classes/java/awt/Menu.java b/jdk/src/share/classes/java/awt/Menu.java index e702a9cb8fd..ae5d2fa2f82 100644 --- a/jdk/src/share/classes/java/awt/Menu.java +++ b/jdk/src/share/classes/java/awt/Menu.java @@ -66,7 +66,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { AWTAccessor.setMenuAccessor( new AWTAccessor.MenuAccessor() { - public Vector getItems(Menu menu) { + public Vector getItems(Menu menu) { return menu.items; } }); @@ -78,7 +78,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @serial * @see #countItems() */ - Vector items = new Vector(); + Vector items = new Vector<>(); /** * This field indicates whether the menu has the @@ -313,7 +313,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -330,7 +330,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -379,7 +379,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -396,7 +396,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -475,13 +475,13 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { return null; } - synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + synchronized Enumeration shortcuts() { + Vector shortcuts = new Vector<>(); int nitems = getItemCount(); for (int i = 0 ; i < nitems ; i++) { MenuItem mi = getItem(i); if (mi instanceof Menu) { - Enumeration e = ((Menu)mi).shortcuts(); + Enumeration e = ((Menu)mi).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } diff --git a/jdk/src/share/classes/java/awt/MenuBar.java b/jdk/src/share/classes/java/awt/MenuBar.java index 1fd442e1583..bd0a7d890c0 100644 --- a/jdk/src/share/classes/java/awt/MenuBar.java +++ b/jdk/src/share/classes/java/awt/MenuBar.java @@ -81,7 +81,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible return menuBar.helpMenu; } - public Vector getMenus(MenuBar menuBar) { + public Vector getMenus(MenuBar menuBar) { return menuBar.menus; } }); @@ -94,7 +94,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @serial * @see #countMenus() */ - Vector menus = new Vector(); + Vector menus = new Vector<>(); /** * This menu is a special menu dedicated to @@ -309,7 +309,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * be called on the toolkit thread. */ final Menu getMenuImpl(int i) { - return (Menu)menus.elementAt(i); + return menus.elementAt(i); } /** @@ -321,10 +321,10 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @since JDK1.1 */ public synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + Vector shortcuts = new Vector<>(); int nmenus = getMenuCount(); for (int i = 0 ; i < nmenus ; i++) { - Enumeration e = getMenu(i).shortcuts(); + Enumeration e = getMenu(i).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } @@ -438,7 +438,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible // HeadlessException will be thrown from MenuComponent's readObject s.defaultReadObject(); for (int i = 0; i < menus.size(); i++) { - Menu m = (Menu)menus.elementAt(i); + Menu m = menus.elementAt(i); m.parent = this; } } diff --git a/jdk/src/share/classes/java/awt/MenuComponent.java b/jdk/src/share/classes/java/awt/MenuComponent.java index ebd9c0576ba..4895fdc9548 100644 --- a/jdk/src/share/classes/java/awt/MenuComponent.java +++ b/jdk/src/share/classes/java/awt/MenuComponent.java @@ -290,7 +290,7 @@ public abstract class MenuComponent implements java.io.Serializable { public void setFont(Font f) { font = f; //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) - MenuComponentPeer peer = (MenuComponentPeer)this.peer; + MenuComponentPeer peer = this.peer; if (peer != null) { peer.setFont(f); } @@ -303,7 +303,7 @@ public abstract class MenuComponent implements java.io.Serializable { */ public void removeNotify() { synchronized (getTreeLock()) { - MenuComponentPeer p = (MenuComponentPeer)this.peer; + MenuComponentPeer p = this.peer; if (p != null) { Toolkit.getEventQueue().removeSourceEvents(this, true); this.peer = null; diff --git a/jdk/src/share/classes/java/awt/MenuItem.java b/jdk/src/share/classes/java/awt/MenuItem.java index 3b8b2cffa0e..4838d187a89 100644 --- a/jdk/src/share/classes/java/awt/MenuItem.java +++ b/jdk/src/share/classes/java/awt/MenuItem.java @@ -564,7 +564,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @since 1.4 */ public synchronized ActionListener[] getActionListeners() { - return (ActionListener[])(getListeners(ActionListener.class)); + return getListeners(ActionListener.class); } /** diff --git a/jdk/src/share/classes/java/awt/RenderingHints.java b/jdk/src/share/classes/java/awt/RenderingHints.java index 5b8daa9e519..48cf9e11d32 100644 --- a/jdk/src/share/classes/java/awt/RenderingHints.java +++ b/jdk/src/share/classes/java/awt/RenderingHints.java @@ -92,7 +92,7 @@ public class RenderingHints * {@code equals()} method. */ public abstract static class Key { - private static HashMap identitymap = new HashMap(17); + private static HashMap identitymap = new HashMap<>(17); private String getIdentity() { // Note that the identity string is dependent on 3 variables: @@ -138,7 +138,7 @@ public class RenderingHints } // Note: Use a weak reference to avoid holding on to extra // objects and classes after they should be unloaded. - identitymap.put(identity, new WeakReference(k)); + identitymap.put(identity, new WeakReference(k)); } private int privatekey; @@ -195,7 +195,7 @@ public class RenderingHints } } - HashMap hintmap = new HashMap(7); + HashMap hintmap = new HashMap<>(7); /** * Antialiasing hint key. @@ -1267,12 +1267,13 @@ public class RenderingHints * object. * @return a clone of this instance. */ + @SuppressWarnings("unchecked") public Object clone() { RenderingHints rh; try { rh = (RenderingHints) super.clone(); if (hintmap != null) { - rh.hintmap = (HashMap) hintmap.clone(); + rh.hintmap = (HashMap) hintmap.clone(); } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable diff --git a/jdk/src/share/classes/java/awt/TextComponent.java b/jdk/src/share/classes/java/awt/TextComponent.java index ecc9b3fd47c..0a2fe254fc3 100644 --- a/jdk/src/share/classes/java/awt/TextComponent.java +++ b/jdk/src/share/classes/java/awt/TextComponent.java @@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible { // the background color of non-editable TextComponents. boolean backgroundSetByClientCode = false; - /** - * True if this TextComponent has access - * to the System clipboard. - */ - transient private boolean canAccessClipboard; - transient protected TextListener textListener; /* @@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible { GraphicsEnvironment.checkHeadless(); this.text = (text != null) ? text : ""; setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); - checkSystemClipboardAccess(); } private void enableInputMethodsIfNecessary() { @@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible { /** * Assigns a valid value to the canAccessClipboard instance variable. */ - private void checkSystemClipboardAccess() { - canAccessClipboard = true; + private boolean canAccessClipboard() { SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkSystemClipboardAccess(); - } - catch (SecurityException e) { - canAccessClipboard = false; - } - } + if (sm == null) return true; + try { + sm.checkSystemClipboardAccess(); + return true; + } catch (SecurityException e) {} + return false; } /* @@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible { } } enableInputMethodsIfNecessary(); - checkSystemClipboardAccess(); } diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 4b9765443eb..68b9af95a96 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible { } else { try { - EventQueue.invokeAndWait(action); + EventQueue.invokeAndWait(this, action); } catch (InterruptedException e) { System.err.println("Disposal was interrupted:"); diff --git a/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java b/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java index d58bd92f3e0..cce9c74c192 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java +++ b/jdk/src/share/classes/java/awt/datatransfer/Clipboard.java @@ -71,7 +71,7 @@ public class Clipboard { * * @since 1.5 */ - private Set currentDataFlavors; + private Set currentDataFlavors; /** * Creates a clipboard object. @@ -313,7 +313,7 @@ public class Clipboard { if (flavorListeners == null) { return; } - Set prevDataFlavors = currentDataFlavors; + Set prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); if (prevDataFlavors.equals(currentDataFlavors)) { return; @@ -339,8 +339,8 @@ public class Clipboard { * * @since 1.5 */ - private Set getAvailableDataFlavorSet() { - Set set = new HashSet(); + private Set getAvailableDataFlavorSet() { + Set set = new HashSet<>(); Transferable contents = getContents(null); if (contents != null) { DataFlavor[] flavors = contents.getTransferDataFlavors(); diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java index 298436fc50f..3b72ed9afda 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java @@ -165,7 +165,7 @@ public class DragGestureEvent extends EventObject { *

* @return an Iterator for the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Iterator iterator() { return events.iterator(); } /** @@ -184,7 +184,7 @@ public class DragGestureEvent extends EventObject { *

* @return an array of the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Object[] toArray(Object[] array) { return events.toArray(array); } /** @@ -333,7 +333,6 @@ public class DragGestureEvent extends EventObject { component = (Component)f.get("component", null); origin = (Point)f.get("origin", null); action = f.get("action", 0); - // Pre-1.4 support. 'events' was previously non-transient try { events = (List)f.get("events", null); @@ -351,7 +350,7 @@ public class DragGestureEvent extends EventObject { /* * fields */ - + @SuppressWarnings("rawtypes") private transient List events; /** diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java index 4b433264701..1f1b9a3f488 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java @@ -297,7 +297,7 @@ public abstract class DragGestureRecognizer implements Serializable { * @return the initial event that triggered the drag gesture */ - public InputEvent getTriggerEvent() { return events.isEmpty() ? null : (InputEvent)events.get(0); } + public InputEvent getTriggerEvent() { return events.isEmpty() ? null : events.get(0); } /** * Reset the Recognizer, if its currently recognizing a gesture, ignore diff --git a/jdk/src/share/classes/java/awt/dnd/DragSource.java b/jdk/src/share/classes/java/awt/dnd/DragSource.java index 2311ccc6283..bceedda646b 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSource.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSource.java @@ -600,7 +600,7 @@ public class DragSource implements Serializable { * @since 1.4 */ public DragSourceListener[] getDragSourceListeners() { - return (DragSourceListener[])getListeners(DragSourceListener.class); + return getListeners(DragSourceListener.class); } /** @@ -660,8 +660,7 @@ public class DragSource implements Serializable { * @since 1.4 */ public DragSourceMotionListener[] getDragSourceMotionListeners() { - return (DragSourceMotionListener[]) - getListeners(DragSourceMotionListener.class); + return getListeners(DragSourceMotionListener.class); } /** @@ -896,8 +895,8 @@ public class DragSource implements Serializable { * @since 1.5 */ public static int getDragThreshold() { - int ts = ((Integer)AccessController.doPrivileged( - new GetIntegerAction("awt.dnd.drag.threshold", 0))).intValue(); + int ts = AccessController.doPrivileged( + new GetIntegerAction("awt.dnd.drag.threshold", 0)).intValue(); if (ts > 0) { return ts; } else { diff --git a/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java b/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java index 4ea863c981b..ed94ceefcf7 100644 --- a/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java +++ b/jdk/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java @@ -36,6 +36,8 @@ package java.awt.dnd; public class InvalidDnDOperationException extends IllegalStateException { + private static final long serialVersionUID = 5156676500247816278L; + static private String dft_msg = "The operation requested cannot be performed by the DnD system since it is not in the appropriate state"; /** diff --git a/jdk/src/share/classes/java/awt/geom/AffineTransform.java b/jdk/src/share/classes/java/awt/geom/AffineTransform.java index 2fa1dc2137a..751deac2497 100644 --- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java +++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java @@ -876,6 +876,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * they have not been cached. * @see #getType */ + @SuppressWarnings("fallthrough") private void calculateType() { int ret = TYPE_IDENTITY; boolean sgn0, sgn1; @@ -1038,6 +1039,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #TYPE_UNIFORM_SCALE * @since 1.2 */ + @SuppressWarnings("fallthrough") public double getDeterminant() { switch (state) { default: @@ -1250,6 +1252,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): m02 = tx * m00 + ty * m01 + m02; m12 = tx * m10 + ty * m11 + m12; @@ -1631,6 +1634,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * Y axis direction * @since 1.2 */ + @SuppressWarnings("fallthrough") public void scale(double sx, double sy) { int state = this.state; switch (state) { @@ -1705,6 +1709,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): double M0, M1; @@ -2224,6 +2229,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #preConcatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void concatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2432,6 +2438,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * @see #concatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void preConcatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2655,6 +2662,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): det = m00 * m11 - m01 * m10; if (Math.abs(det) <= Double.MIN_VALUE) { @@ -2751,6 +2759,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -2885,6 +2894,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): ptDst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); @@ -2968,6 +2978,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); @@ -3043,6 +3054,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3157,6 +3169,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3252,6 +3265,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3347,6 +3361,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3436,6 +3451,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { * inverted. * @since 1.2 */ + @SuppressWarnings("fallthrough") public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst) throws NoninvertibleTransformException { @@ -3547,6 +3563,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): M00 = m00; M01 = m01; M02 = m02; M10 = m10; M11 = m11; M12 = m12; @@ -3679,6 +3696,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return null; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11); @@ -3754,6 +3772,7 @@ public class AffineTransform implements Cloneable, java.io.Serializable { default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): M00 = m00; M01 = m01; diff --git a/jdk/src/share/classes/java/awt/peer/FramePeer.java b/jdk/src/share/classes/java/awt/peer/FramePeer.java index 8bb3b07add9..e9d2b002fb0 100644 --- a/jdk/src/share/classes/java/awt/peer/FramePeer.java +++ b/jdk/src/share/classes/java/awt/peer/FramePeer.java @@ -125,4 +125,10 @@ public interface FramePeer extends WindowPeer { // into an EmbeddedFramePeer which would extend FramePeer Rectangle getBoundsPrivate(); + /** + * Requests the peer to emulate window activation. + * + * @param activate activate or deactivate the window + */ + void emulateActivation(boolean activate); } diff --git a/jdk/src/share/classes/java/awt/peer/WindowPeer.java b/jdk/src/share/classes/java/awt/peer/WindowPeer.java index f2e8993e101..fca78b7eed4 100644 --- a/jdk/src/share/classes/java/awt/peer/WindowPeer.java +++ b/jdk/src/share/classes/java/awt/peer/WindowPeer.java @@ -27,8 +27,6 @@ package java.awt.peer; import java.awt.*; -import java.awt.image.BufferedImage; - /** * The peer interface for {@link Window}. * diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index c03149c0574..0abdcad972b 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,10 +109,6 @@ public class PropertyDescriptor extends FeatureDescriptor { if (writeMethodName != null && getWriteMethod() == null) { throw new IntrospectionException("Method not found: " + writeMethodName); } - boundInitialization(beanClass); - } - - private void boundInitialization(Class beanClass) { // If this class or one of its base classes allow PropertyChangeListener, // then we assume that any properties we discover are "bound". // See Introspector.getTargetPropertyInfo() method. @@ -163,7 +159,6 @@ public class PropertyDescriptor extends FeatureDescriptor { setReadMethod(read); setWriteMethod(write); this.baseName = base; - boundInitialization(bean); } /** diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java index 04796664fdc..0a530dd6db6 100644 --- a/jdk/src/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java @@ -1752,6 +1752,12 @@ public class ObjectInputStream ObjectStreamClass desc = readClassDesc(false); desc.checkDeserialize(); + Class cl = desc.forClass(); + if (cl == String.class || cl == Class.class + || cl == ObjectStreamClass.class) { + throw new InvalidClassException("invalid class descriptor"); + } + Object obj; try { obj = desc.isInstantiable() ? desc.newInstance() : null; diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 671d04a65c7..f0ab8b24edc 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -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; @@ -63,7 +64,9 @@ import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.scope.ClassScope; import sun.security.util.SecurityConstants; import java.lang.annotation.Annotation; +import java.lang.reflect.Proxy; import sun.reflect.annotation.*; +import sun.reflect.misc.ReflectUtil; /** * Instances of the class {@code Class} represent classes and @@ -250,11 +253,11 @@ public final ClassLoader loader) throws ClassNotFoundException { - if (loader == null) { + if (sun.misc.VM.isSystemDomainLoader(loader)) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader ccl = ClassLoader.getCallerClassLoader(); - if (ccl != null) { + if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } @@ -319,7 +322,7 @@ public final throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); } return newInstance0(); } @@ -1299,7 +1302,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here @@ -1374,7 +1377,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyFields(privateGetPublicFields(null)); } @@ -1425,7 +1428,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyMethods(privateGetPublicMethods()); } @@ -1474,7 +1477,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return copyConstructors(privateGetDeclaredConstructors(true)); } @@ -1533,7 +1536,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); @@ -1618,7 +1621,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -1672,7 +1675,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true); return getConstructor0(parameterTypes, Member.PUBLIC); } @@ -1714,7 +1717,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false); return getDeclaredClasses0(); } @@ -1758,7 +1761,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyFields(privateGetDeclaredFields(false)); } @@ -1806,7 +1809,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyMethods(privateGetDeclaredMethods(false)); } @@ -1851,7 +1854,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -1895,7 +1898,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); @@ -1950,7 +1953,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -2000,7 +2003,7 @@ public final // be very careful not to change the stack depth of this // checkMemberAccess call for security reasons // see java.lang.SecurityManager.checkMemberAccess - checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true); return getConstructor0(parameterTypes, Member.DECLARED); } @@ -2170,18 +2173,26 @@ public final *

Default policy: allow all clients access with normal Java access * control. */ - private void checkMemberAccess(int which, ClassLoader ccl) { + private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { SecurityManager s = System.getSecurityManager(); if (s != null) { s.checkMemberAccess(this, which); ClassLoader cl = getClassLoader0(); - if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) { + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); if (i != -1) { - s.checkPackageAccess(name.substring(0, i)); + // skip the package access check on a proxy class in default proxy package + String pkg = name.substring(0, i); + if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { + s.checkPackageAccess(pkg); + } } } + // check package access on the proxy interfaces + if (checkProxyInterfaces && Proxy.isProxyClass(this)) { + ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); + } } } @@ -3083,6 +3094,16 @@ public final return (A) annotations.get(annotationClass); } + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java index e62c69a1ccd..a1e18ffe62d 100644 --- a/jdk/src/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/share/classes/java/lang/ClassLoader.java @@ -51,7 +51,6 @@ import java.util.Vector; 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 @@ public abstract class ClassLoader { 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 @@ public abstract class ClassLoader { 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 @@ public abstract class ClassLoader { } 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; } diff --git a/jdk/src/share/classes/java/lang/Deprecated.java b/jdk/src/share/classes/java/lang/Deprecated.java index 2b1546bc64b..58a0691f054 100644 --- a/jdk/src/share/classes/java/lang/Deprecated.java +++ b/jdk/src/share/classes/java/lang/Deprecated.java @@ -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 @@ import static java.lang.annotation.ElementType.*; * * @author Neal Gafter * @since 1.5 + * @jls 9.6.3.6 @Deprecated */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/share/classes/java/lang/Override.java b/jdk/src/share/classes/java/lang/Override.java index ea6e54a151e..bf77344296c 100644 --- a/jdk/src/share/classes/java/lang/Override.java +++ b/jdk/src/share/classes/java/lang/Override.java @@ -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 @@ import java.lang.annotation.*; * * @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) diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index b9776f478db..7d1d38db64d 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.java @@ -25,6 +25,7 @@ package java.lang; +import java.lang.reflect.AnnotatedElement; import java.io.InputStream; import java.util.Enumeration; @@ -385,6 +386,16 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().getAnnotation(annotationClass); } + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 diff --git a/jdk/src/share/classes/java/lang/SafeVarargs.java b/jdk/src/share/classes/java/lang/SafeVarargs.java index cb14134ffbe..6fcd48e97d7 100644 --- a/jdk/src/share/classes/java/lang/SafeVarargs.java +++ b/jdk/src/share/classes/java/lang/SafeVarargs.java @@ -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 @@ import java.lang.annotation.*; * @since 1.7 * @jls 4.7 Reifiable Types * @jls 8.4.1 Formal Parameters + * @jls 9.6.3.7 @SafeVarargs */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/share/classes/java/lang/SecurityManager.java b/jdk/src/share/classes/java/lang/SecurityManager.java index 80181cd4e80..31664dc6cb2 100644 --- a/jdk/src/share/classes/java/lang/SecurityManager.java +++ b/jdk/src/share/classes/java/lang/SecurityManager.java @@ -1320,6 +1320,9 @@ class SecurityManager { * AWTPermission("showWindowWithoutWarningBanner") permission, * and returns true if a SecurityException is not thrown, * otherwise it returns false. + * 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}. *

* If you override this method, then you should make a call to * super.checkTopLevelWindow @@ -1340,8 +1343,12 @@ class SecurityManager { 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 @@ class SecurityManager { * This method calls checkPermission with the * AWTPermission("accessClipboard") * 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}. *

* If you override this method, then you should make a call to * super.checkSystemClipboardAccess @@ -1391,7 +1401,11 @@ class SecurityManager { * @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 @@ class SecurityManager { *

* This method calls checkPermission with the * AWTPermission("accessEventQueue") 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}. + * *

* If you override this method, then you should make a call to * super.checkAwtEventQueueAccess @@ -1412,7 +1430,11 @@ class SecurityManager { * @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); } /* diff --git a/jdk/src/share/classes/java/lang/SuppressWarnings.java b/jdk/src/share/classes/java/lang/SuppressWarnings.java index babb060396a..22895dc7b2c 100644 --- a/jdk/src/share/classes/java/lang/SuppressWarnings.java +++ b/jdk/src/share/classes/java/lang/SuppressWarnings.java @@ -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 @@ import static java.lang.annotation.ElementType.*; * suppress a warning in a particular method, you should annotate that * method rather than its class. * - * @since 1.5 * @author Josh Bloch + * @since 1.5 + * @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 @@ public @interface SuppressWarnings { * free to emit a warning if an annotation contains an unrecognized * warning name. * - *

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. + *

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(); } diff --git a/jdk/src/share/classes/java/lang/annotation/Inherited.java b/jdk/src/share/classes/java/lang/annotation/Inherited.java index a7efa6b41d2..83391e29eac 100644 --- a/jdk/src/share/classes/java/lang/annotation/Inherited.java +++ b/jdk/src/share/classes/java/lang/annotation/Inherited.java @@ -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 @@ package java.lang.annotation; * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.3 @Inherited */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java deleted file mode 100644 index 37d00a98b40..00000000000 --- a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java +++ /dev/null @@ -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 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 not 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 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 getAnnotationType() { - return annotationType; - } -} diff --git a/jdk/src/share/classes/java/lang/annotation/Retention.java b/jdk/src/share/classes/java/lang/annotation/Retention.java index df04a31db90..1c27ca0871e 100644 --- a/jdk/src/share/classes/java/lang/annotation/Retention.java +++ b/jdk/src/share/classes/java/lang/annotation/Retention.java @@ -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 @@ package java.lang.annotation; * * @author Joshua Bloch * @since 1.5 + * @jls 9.6.3.2 @Retention */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/share/classes/java/lang/annotation/Target.java b/jdk/src/share/classes/java/lang/annotation/Target.java index dc67de3f071..cdf4a748ae5 100644 --- a/jdk/src/share/classes/java/lang/annotation/Target.java +++ b/jdk/src/share/classes/java/lang/annotation/Target.java @@ -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 @@ package java.lang.annotation; * ... * } * + * + * @since 1.5 + * @jls 9.6.3.1 @Target */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java index 516443dc186..892a9dd5316 100644 --- a/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java +++ b/jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java @@ -34,11 +34,11 @@ import sun.invoke.util.Wrapper; 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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; * @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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; // 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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; 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 @@ import static sun.invoke.util.Wrapper.*; : 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 @@ import static sun.invoke.util.Wrapper.*; } - /*********** 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 @@ import static sun.invoke.util.Wrapper.*; ***********************/ /** - * 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 methodsFound = new ArrayList<>(methods.length); private Method samMethod = null; private final List methodsToBridge = new ArrayList<>(methods.length); - private boolean defaultMethodFound = false; + private boolean conflictFoundBetweenDefaultAndBridge = false; MethodAnalyzer() { String samMethodName = samInfo.getName(); @@ -315,31 +361,36 @@ import static sun.invoke.util.Wrapper.*; int samParamLength = samParamTypes.length; Class samReturnType = samMethodType.returnType(); Class objectClass = Object.class; + List 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 @@ import static sun.invoke.util.Wrapper.*; 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; - } - } } diff --git a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java index 0df8e730937..7793bc2dd98 100644 --- a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -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 @@ -51,12 +51,21 @@ class DirectMethodHandle extends MethodHandle { private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form); if (!member.isResolved()) throw new InternalError(); + + if (member.getDeclaringClass().isInterface() && !member.isAbstract()) { + // Check for corner case: invokeinterface of Object method + MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); + m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); + if (m != null && m.isPublic()) { + member = m; + } + } + this.member = member; } // 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 +73,14 @@ class DirectMethodHandle extends MethodHandle { 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 +94,12 @@ class DirectMethodHandle extends MethodHandle { } } } + 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 +135,10 @@ class DirectMethodHandle extends MethodHandle { //// Implementation methods. @Override + MethodHandle viewAsType(MethodType newType) { + return new DirectMethodHandle(newType, form, member); + } + @Override @ForceInline MemberName internalMemberName() { return member; @@ -357,6 +382,21 @@ class DirectMethodHandle extends MethodHandle { ((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 +409,10 @@ class DirectMethodHandle extends MethodHandle { 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 +439,10 @@ class DirectMethodHandle extends MethodHandle { @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new Accessor(newType, form, member, fieldOffset); + } } @ForceInline @@ -434,6 +482,10 @@ class DirectMethodHandle extends MethodHandle { @Override Object checkCast(Object obj) { return fieldType.cast(obj); } + @Override + MethodHandle viewAsType(MethodType newType) { + return new StaticAccessor(newType, form, member, staticBase, staticOffset); + } } @ForceInline diff --git a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 13999001cdc..f7191f7679f 100644 --- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -36,21 +36,28 @@ import java.security.AccessController; 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 = ""; //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 @@ import java.security.PrivilegedAction; 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 @@ import java.security.PrivilegedAction; * @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 @@ import java.security.PrivilegedAction; argNames[i] = "arg$" + (i + 1); } instantiatedArgumentTypes = Type.getArgumentTypes(instantiatedMethodType.toMethodDescriptorString()); - } /** @@ -120,7 +133,8 @@ import java.security.PrivilegedAction; * * @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 @@ import java.security.PrivilegedAction; } 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 @@ import java.security.PrivilegedAction; * 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 Class 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) 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 @@ import java.security.PrivilegedAction; } /** - * 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 @@ import java.security.PrivilegedAction; 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 @@ import java.security.PrivilegedAction; // 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 @@ import java.security.PrivilegedAction; 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 @@ import java.security.PrivilegedAction; 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 @@ import java.security.PrivilegedAction; 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); - } } } diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java index 378494b48d3..d179d438e8a 100644 --- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java +++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java @@ -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 @@ package java.lang.invoke; * method, and the static types of the captured lambda arguments, and link a call site which, when invoked, * produces the lambda object. * - *

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 - * interface I<T> { int m(T x); } if this SAM type is used in a lambda - * I<Byte> v = ..., we need both the actual SAM method which has the signature - * (Object)int and the functional interface type of the method, which has signature - * (Byte)int. The latter is the instantiated erased functional interface method type, or - * simply instantiated method type. + *

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 + * interface I<T> { int m(T x); } if this functional interface type is used in a lambda + * I<Byte> v = ..., we need both the actual functional interface method which has the signature + * (Object)int and the erased instantiated type of the functional interface method (or simply + * instantiated method type), which has signature + * (Byte)int. * *

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 @@ package java.lang.invoke; * * * + * 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 @@ public class LambdaMetafactory { * @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 @@ public class LambdaMetafactory { 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(); } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java index aa323eb358a..774faff5afb 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java @@ -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 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*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); } @@ -1267,6 +1265,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); return null; // DMH returns DMH.member } + /*non-public*/ + boolean isInvokeSpecial() { + return false; // DMH.Special returns true + } + /*non-public*/ Object internalValues() { return null; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 3cdd99cc4a1..a18a7a484a8 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -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 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @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 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return asFixedArity().internalMemberName(); } + /*non-public*/ + @Override + boolean isInvokeSpecial() { + return asFixedArity().isInvokeSpecial(); + } + @Override MethodHandle bindArgument(int pos, char basicType, Object value) { @@ -801,12 +807,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static MethodHandle bindCaller(MethodHandle mh, Class hostClass) { // Do not use this function to inject calls into system classes. - if (hostClass == null) { - hostClass = C_Trampoline; - } else if (hostClass.isArray() || + if (hostClass == null + || (hostClass.isArray() || hostClass.isPrimitive() || hostClass.getName().startsWith("java.") || - hostClass.getName().startsWith("sun.")) { + hostClass.getName().startsWith("sun."))) { throw new InternalError(); // does not happen, and should not anyway } // For simplicity, convert mh to a varargs-like method. @@ -816,23 +821,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return restoreToType(bccInvoker.bindTo(vamh), mh.type()); } - // This class ("Trampoline") is known to be inside a dead-end class loader. - // Inject all doubtful calls into this class. - private static Class C_Trampoline; - static { - Class tramp = null; - try { - final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline - java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class); - tramp = (Class) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG }); - if (tramp.getClassLoader() == BindCaller.class.getClassLoader()) - throw new RuntimeException(tramp.getName()+" class loader"); - } catch (Throwable ex) { - throw new InternalError(ex); - } - C_Trampoline = tramp; - } - private static MethodHandle makeInjectedInvoker(Class hostClass) { Class bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); if (hostClass.getClassLoader() != bcc.getClassLoader()) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java index b73dd6350cd..380ca59b6e1 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java @@ -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 @@ class MethodHandleInfo { 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 @@ class MethodHandleInfo { 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); + } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index fcc928a327d..db072126e1f 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -393,15 +393,33 @@ class MethodHandleNatives { */ // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive. static boolean isCallerSensitive(MemberName mem) { - assert(mem.isInvocable()); + if (!mem.isInvocable()) return false; // fields are not caller sensitive Class defc = mem.getDeclaringClass(); switch (mem.getName()) { case "doPrivileged": + case "doPrivilegedWithCombiner": return defc == java.security.AccessController.class; + case "checkMemberAccess": + return canBeCalledVirtual(mem, java.lang.SecurityManager.class); case "getUnsafe": return defc == sun.misc.Unsafe.class; case "lookup": return defc == java.lang.invoke.MethodHandles.class; + case "findStatic": + case "findVirtual": + case "findConstructor": + case "findSpecial": + case "findGetter": + case "findSetter": + case "findStaticGetter": + case "findStaticSetter": + case "bind": + case "unreflect": + case "unreflectSpecial": + case "unreflectConstructor": + case "unreflectGetter": + case "unreflectSetter": + return defc == java.lang.invoke.MethodHandles.Lookup.class; case "invoke": return defc == java.lang.reflect.Method.class; case "get": @@ -455,7 +473,7 @@ class MethodHandleNatives { if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true; break; case "getContextClassLoader": - return defc == java.lang.Thread.class; + return canBeCalledVirtual(mem, java.lang.Thread.class); case "getPackage": case "getPackages": return defc == java.lang.Package.class; @@ -473,9 +491,13 @@ class MethodHandleNatives { break; case "getCallerClassLoader": return defc == java.lang.ClassLoader.class; + case "registerAsParallelCapable": + return canBeCalledVirtual(mem, java.lang.ClassLoader.class); case "getProxyClass": case "newProxyInstance": return defc == java.lang.reflect.Proxy.class; + case "asInterfaceInstance": + return defc == java.lang.invoke.MethodHandleProxies.class; case "getBundle": case "clearCache": return defc == java.util.ResourceBundle.class; @@ -492,4 +514,11 @@ class MethodHandleNatives { throw new InternalError(e); } } + static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass) { + Class symbolicRefClass = symbolicRef.getDeclaringClass(); + if (symbolicRefClass == definingClass) return true; + if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false; + return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef + symbolicRefClass.isInterface()); // Mdef implements Msym + } } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 20bc06de879..ade1630dcfb 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -26,8 +26,12 @@ package java.lang.invoke; import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.invoke.WrapperInstance; import java.util.ArrayList; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; /** * This class consists exclusively of static methods that help adapt @@ -137,6 +141,21 @@ public class MethodHandleProxies { T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) throw new IllegalArgumentException("not a public interface: "+intfc.getName()); + final MethodHandle mh; + if (System.getSecurityManager() != null) { + final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; + ReflectUtil.checkProxyPackageAccess(ccl, intfc); + mh = ccl != null ? bindCaller(target, caller) : target; + } else { + mh = target; + } + ClassLoader proxyLoader = intfc.getClassLoader(); + if (proxyLoader == null) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP + proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader(); + } final Method[] methods = getSingleNameMethods(intfc); if (methods == null) throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); @@ -144,31 +163,58 @@ public class MethodHandleProxies { for (int i = 0; i < methods.length; i++) { Method sm = methods[i]; MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes()); - MethodHandle checkTarget = target.asType(smMT); // make throw WMT + MethodHandle checkTarget = mh.asType(smMT); // make throw WMT checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); } - return intfc.cast(Proxy.newProxyInstance( - intfc.getClassLoader(), - new Class[]{ intfc, WrapperInstance.class }, - new InvocationHandler() { - private Object getArg(String name) { - if ((Object)name == "getWrapperInstanceTarget") return target; - if ((Object)name == "getWrapperInstanceType") return intfc; - throw new AssertionError(); + final InvocationHandler ih = new InvocationHandler() { + private Object getArg(String name) { + if ((Object)name == "getWrapperInstanceTarget") return target; + if ((Object)name == "getWrapperInstanceType") return intfc; + throw new AssertionError(); + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + for (int i = 0; i < methods.length; i++) { + if (method.equals(methods[i])) + return vaTargets[i].invokeExact(args); } - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - for (int i = 0; i < methods.length; i++) { - if (method.equals(methods[i])) - return vaTargets[i].invokeExact(args); - } - if (method.getDeclaringClass() == WrapperInstance.class) - return getArg(method.getName()); - if (isObjectMethod(method)) - return callObjectMethod(proxy, method, args); - throw new InternalError("bad proxy method: "+method); - } - })); + if (method.getDeclaringClass() == WrapperInstance.class) + return getArg(method.getName()); + if (isObjectMethod(method)) + return callObjectMethod(proxy, method, args); + throw new InternalError("bad proxy method: "+method); + } + }; + + final Object proxy; + if (System.getSecurityManager() != null) { + // sun.invoke.WrapperInstance is a restricted interface not accessible + // by any non-null class loader. + final ClassLoader loader = proxyLoader; + proxy = AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return Proxy.newProxyInstance( + loader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + }); + } else { + proxy = Proxy.newProxyInstance(proxyLoader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + return intfc.cast(proxy); + } + + private static MethodHandle bindCaller(MethodHandle target, Class hostClass) { + MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass); + if (target.isVarargsCollector()) { + MethodType type = cbmh.type(); + int arity = type.parameterCount(); + return cbmh.asVarargsCollector(type.parameterType(arity-1)); + } + return cbmh; } /** diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index e7007dd2b89..f4cad4deaa8 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -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 @@ -598,7 +598,8 @@ public class MethodHandles { MethodHandle findStatic(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(REF_invokeStatic, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + return getDirectMethod(REF_invokeStatic, refc, method, callerClass); } /** @@ -652,7 +653,8 @@ public class MethodHandles { byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(refKind, refc, method); + Class callerClass = findBoundCallerClass(method); + return getDirectMethod(refKind, refc, method, callerClass); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -736,7 +738,8 @@ public class MethodHandles { Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); } /** @@ -879,7 +882,8 @@ return mh1; Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); return mh.bindReceiver(receiver).setVarargs(method); } @@ -910,8 +914,9 @@ return mh1; if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method); + return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); } /** @@ -940,8 +945,9 @@ return mh1; Lookup specialLookup = this.in(specialCaller); MemberName method = new MemberName(m, true); assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method); + return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); } /** @@ -1039,8 +1045,30 @@ return mh1; throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); } + /** + * Find my trustable caller class if m is a caller sensitive method. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). + * This is the same caller class as is used by checkSecurityManager. + * This function performs stack walk magic: do not refactor it. + */ + Class findBoundCallerClass(MemberName m) { + Class callerClass = null; + if (MethodHandleNatives.isCallerSensitive(m)) { + // Do not refactor this to a more "logical" place, since it is stack walk magic. + // Note that this is the same expression as in Step 2 below in checkSecurityManager. + callerClass = ((allowedModes & PRIVATE) != 0 + ? lookupClass // for strong access modes, no extra check + // next line does stack walk magic; do not refactor: + : getCallerClassAtEntryPoint(true)); + } + return callerClass; + } /** * Perform necessary access checks. + * Determines a trustable caller class to compare with refc, the symbolic reference class. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). * This function performs stack walk magic: do not refactor it. */ void checkSecurityManager(Class refc, MemberName m) { @@ -1195,22 +1223,22 @@ return mh1; return mh.viewAsType(narrowType); } - private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method) throws IllegalAccessException { + private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { return getDirectMethodCommon(refKind, refc, method, (refKind == REF_invokeSpecial || (MethodHandleNatives.refKindHasReceiver(refKind) && - restrictProtectedReceiver(method)))); + restrictProtectedReceiver(method))), callerClass); } - private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method) throws IllegalAccessException { - return getDirectMethodCommon(refKind, refc, method, false); + private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { + return getDirectMethodCommon(refKind, refc, method, false, callerClass); } private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, - boolean doRestrict) throws IllegalAccessException { + boolean doRestrict, Class callerClass) throws IllegalAccessException { checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); - MethodHandle mh = DirectMethodHandle.make(refc, method); - mh = maybeBindCaller(method, mh); + MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); + mh = maybeBindCaller(method, mh, callerClass); mh = mh.setVarargs(method); if (doRestrict) mh = restrictReceiver(method, mh, lookupClass()); @@ -1219,12 +1247,14 @@ return mh1; private MethodHandle fakeMethodHandleInvoke(MemberName method) { return throwException(method.getReturnType(), UnsupportedOperationException.class); } - private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { + private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, + Class callerClass) + throws IllegalAccessException { if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) return mh; Class hostClass = lookupClass; if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup - hostClass = null; + hostClass = callerClass; // callerClass came from a security manager style stack walk MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); // Note: caller will apply varargs after this step happens. return cbmh; @@ -1262,7 +1292,7 @@ return mh1; } else if (MethodHandleNatives.refKindIsMethod(refKind)) { MemberName method = (resolved != null) ? resolved : resolveOrFail(refKind, defc, name, (MethodType) type); - return getDirectMethod(refKind, defc, method); + return getDirectMethod(refKind, defc, method, lookupClass); } else if (refKind == REF_newInvokeSpecial) { assert(name == null || name.equals("")); MemberName ctor = (resolved != null) ? resolved diff --git a/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java new file mode 100644 index 00000000000..3679e3f726d --- /dev/null +++ b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java @@ -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() { + @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); + } +} diff --git a/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java index 7384bee464c..3aa63c84ae7 100644 --- a/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java +++ b/jdk/src/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java @@ -27,6 +27,7 @@ package java.lang.invoke; 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 @@ class TypeConvertingMethodAdapter extends MethodVisitor { 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 @@ class TypeConvertingMethodAdapter extends MethodVisitor { 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 @@ class TypeConvertingMethodAdapter extends MethodVisitor { 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 @@ class TypeConvertingMethodAdapter extends MethodVisitor { } } } + + /** + * 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); + } + } } diff --git a/jdk/src/share/classes/java/lang/management/ManagementFactory.java b/jdk/src/share/classes/java/lang/management/ManagementFactory.java index d99333c9e11..278ace1d7d1 100644 --- a/jdk/src/share/classes/java/lang/management/ManagementFactory.java +++ b/jdk/src/share/classes/java/lang/management/ManagementFactory.java @@ -802,20 +802,20 @@ public class ManagementFactory { */ private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) { // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean - final DynamicMBean dmbean; - if (pmo instanceof DynamicMBean) { - dmbean = DynamicMBean.class.cast(pmo); - } else if (pmo instanceof NotificationEmitter) { - dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); - } else { - dmbean = new StandardMBean(pmo, null, true); - } - try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Void run() throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { + final DynamicMBean dmbean; + if (pmo instanceof DynamicMBean) { + dmbean = DynamicMBean.class.cast(pmo); + } else if (pmo instanceof NotificationEmitter) { + dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); + } else { + dmbean = new StandardMBean(pmo, null, true); + } + mbs.registerMBean(dmbean, pmo.getObjectName()); return null; } diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index d198d939d4b..f98aed5db25 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -181,6 +181,16 @@ public class AccessibleObject implements AnnotatedElement { } /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + + /** * @throws NullPointerException {@inheritDoc} * @since 1.8 */ diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index d6cffec2f28..b2c43de3d7b 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -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 @@ import java.lang.annotation.Annotation; * *

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}. * *

Finally, attempting to read a member whose definition has evolved * incompatibly will result in a {@link @@ -96,10 +97,9 @@ import java.lang.annotation.Annotation; * * @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 */ diff --git a/jdk/src/share/classes/java/lang/reflect/Constructor.java b/jdk/src/share/classes/java/lang/reflect/Constructor.java index bbfd1d5ab9d..bdbd7c30e20 100644 --- a/jdk/src/share/classes/java/lang/reflect/Constructor.java +++ b/jdk/src/share/classes/java/lang/reflect/Constructor.java @@ -532,6 +532,7 @@ public final class Constructor extends Executable { * {@inheritDoc} * @since 1.8 */ + @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getDeclaringClass()); } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 83b5e9c87a4..1a89968b175 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -476,6 +476,20 @@ public abstract class Executable extends AccessibleObject 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. * diff --git a/jdk/src/share/classes/java/lang/reflect/Method.java b/jdk/src/share/classes/java/lang/reflect/Method.java index 1507c77194a..30e764694d0 100644 --- a/jdk/src/share/classes/java/lang/reflect/Method.java +++ b/jdk/src/share/classes/java/lang/reflect/Method.java @@ -629,6 +629,7 @@ public final class Method extends Executable { * {@inheritDoc} * @since 1.8 */ + @Override public AnnotatedType getAnnotatedReturnType() { return getAnnotatedReturnType0(getGenericReturnType()); } diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 9c808310c0c..e479bfd9326 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -115,7 +115,9 @@ public final class Parameter implements AnnotatedElement { (type.toString()); sb.append(Modifier.toString(getModifiers())); - sb.append(" "); + + if(0 != modifiers) + sb.append(" "); if(isVarArgs()) sb.append(typename.replaceFirst("\\[\\]$", "...")); diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index 9f5bb289dd3..e946ba3226d 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -27,6 +27,9 @@ package java.lang.reflect; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -36,6 +39,9 @@ import java.util.Set; import java.util.List; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; /** * {@code Proxy} provides static methods for creating dynamic proxy @@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable { * @param h the invocation handler for this proxy instance */ protected Proxy(InvocationHandler h) { + doNewInstanceCheck(); this.h = h; } + private static class ProxyAccessHelper { + // The permission is implementation specific. + static final Permission PROXY_PERMISSION = + new ReflectPermission("proxyConstructorNewInstance"); + // These system properties are defined to provide a short-term + // workaround if customers need to disable the new security checks. + static final boolean allowNewInstance; + static final boolean allowNullLoader; + static { + allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); + allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); + } + + private static boolean getBooleanProperty(final String key) { + String s = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(key); + } + }); + return Boolean.valueOf(s); + } + + static boolean needsNewInstanceCheck(Class proxyClass) { + if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { + return false; + } + + if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { + // all proxy interfaces are public + return false; + } + for (Class intf : proxyClass.getInterfaces()) { + if (!Modifier.isPublic(intf.getModifiers())) { + return true; + } + } + return false; + } + } + + /* + * Access check on a proxy class that implements any non-public interface. + * + * @throws SecurityException if a security manager exists, and + * the caller does not have the permission. + */ + private void doNewInstanceCheck() { + SecurityManager sm = System.getSecurityManager(); + Class proxyClass = this.getClass(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { + try { + sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); + } catch (SecurityException e) { + throw new SecurityException("Not allowed to construct a Proxy " + + "instance that implements a non-public interface", e); + } + } + } + /** * Returns the {@code java.lang.Class} object for a proxy class * given a class loader and an array of interfaces. The proxy class @@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable { Class... interfaces) throws IllegalArgumentException { + return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor + } + + private static void checkProxyLoader(ClassLoader ccl, + ClassLoader loader) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (loader == null && ccl != null) { + if (!ProxyAccessHelper.allowNullLoader) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + } + + /* + * Generate a proxy class (caller-sensitive). + * + * To define a proxy class, it performs the access checks as in + * Class.forName (VM will invoke ClassLoader.checkPackageAccess): + * 1. "getClassLoader" permission check if loader == null + * 2. checkPackageAccess on the interfaces it implements + * + * To get a constructor and new instance of a proxy class, it performs + * the package access check on the interfaces it implements + * as in Class.getConstructor. + * + * If an interface is non-public, the proxy class must be defined by + * the defining loader of the interface. If the caller's class loader + * is not the same as the defining loader of the interface, the VM + * will throw IllegalAccessError when the generated proxy class is + * being defined via the defineClass0 method. + */ + private static Class getProxyClass0(ClassLoader loader, + Class... interfaces) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller.getClassLoader(); + checkProxyLoader(ccl, loader); + ReflectUtil.checkProxyPackageAccess(ccl, interfaces); + } + if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } @@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable { } } - if (proxyPkg == null) { // if no non-public proxy interfaces, - proxyPkg = ""; // use the unnamed package + if (proxyPkg == null) { + // if no non-public proxy interfaces, use com.sun.proxy package + proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } { @@ -598,22 +710,46 @@ public class Proxy implements java.io.Serializable { /* * Look up or generate the designated proxy class. */ - Class cl = getProxyClass(loader, interfaces); + Class cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor /* * Invoke its constructor with the designated invocation handler. */ try { - Constructor cons = cl.getConstructor(constructorParams); - return cons.newInstance(new Object[] { h }); - } catch (NoSuchMethodException | - IllegalAccessException | - InstantiationException | - InvocationTargetException e) { + final Constructor cons = cl.getConstructor(constructorParams); + final InvocationHandler ih = h; + SecurityManager sm = System.getSecurityManager(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { + // create proxy instance with doPrivilege as the proxy class may + // implement non-public interfaces that requires a special permission + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return newInstance(cons, ih); + } + }); + } else { + return newInstance(cons, ih); + } + } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } + private static Object newInstance(Constructor cons, InvocationHandler h) { + try { + return cons.newInstance(new Object[] {h} ); + } catch (IllegalAccessException | InstantiationException e) { + throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + throw new InternalError(t.toString(), t); + } + } + } + /** * Returns true if and only if the specified class was dynamically * generated to be a proxy class using the {@code getProxyClass} diff --git a/jdk/src/share/classes/java/net/HttpConnectSocketImpl.java b/jdk/src/share/classes/java/net/HttpConnectSocketImpl.java new file mode 100644 index 00000000000..b6e70cafd94 --- /dev/null +++ b/jdk/src/share/classes/java/net/HttpConnectSocketImpl.java @@ -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 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() { + 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> options = optionsMap.entrySet(); + try { + for(Map.Entry 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() { + 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(); + } +} diff --git a/jdk/src/share/classes/java/net/InetSocketAddress.java b/jdk/src/share/classes/java/net/InetSocketAddress.java index b250b18ce5a..d4322e9b427 100644 --- a/jdk/src/share/classes/java/net/InetSocketAddress.java +++ b/jdk/src/share/classes/java/net/InetSocketAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,9 +24,12 @@ */ package java.net; -import java.io.ObjectInputStream; import java.io.IOException; import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.ObjectStreamField; /** * @@ -46,23 +49,105 @@ import java.io.InvalidObjectException; * @see java.net.ServerSocket * @since 1.4 */ -public class InetSocketAddress extends SocketAddress { - /* The hostname of the Socket Address - * @serial - */ - private String hostname = null; - /* The IP address of the Socket Address - * @serial - */ - private InetAddress addr = null; - /* The port number of the Socket Address - * @serial - */ - private int port; +public class InetSocketAddress + extends SocketAddress +{ + // Private implementation class pointed to by all public methods. + private static class InetSocketAddressHolder { + // The hostname of the Socket Address + private String hostname; + // The IP address of the Socket Address + private InetAddress addr; + // The port number of the Socket Address + private int port; + + private InetSocketAddressHolder(String hostname, InetAddress addr, int port) { + this.hostname = hostname; + this.addr = addr; + this.port = port; + } + + private int getPort() { + return port; + } + + private InetAddress getAddress() { + return addr; + } + + private String getHostName() { + if (hostname != null) + return hostname; + if (addr != null) + return addr.getHostName(); + return null; + } + + private String getHostString() { + if (hostname != null) + return hostname; + if (addr != null) { + if (addr.hostName != null) + return addr.hostName; + else + return addr.getHostAddress(); + } + return null; + } + + private boolean isUnresolved() { + return addr == null; + } + + @Override + public String toString() { + if (isUnresolved()) { + return hostname + ":" + port; + } else { + return addr.toString() + ":" + port; + } + } + + @Override + public final boolean equals(Object obj) { + if (obj == null || !(obj instanceof InetSocketAddressHolder)) + return false; + InetSocketAddressHolder that = (InetSocketAddressHolder)obj; + boolean sameIP; + if (addr != null) + sameIP = addr.equals(that.addr); + else if (hostname != null) + sameIP = (that.addr == null) && + hostname.equalsIgnoreCase(that.hostname); + else + sameIP = (that.addr == null) && (that.hostname == null); + return sameIP && (port == that.port); + } + + @Override + public final int hashCode() { + if (addr != null) + return addr.hashCode() + port; + if (hostname != null) + return hostname.toLowerCase().hashCode() + port; + return port; + } + } + + private final transient InetSocketAddressHolder holder; private static final long serialVersionUID = 5076001401234631237L; - private InetSocketAddress() { + private static int checkPort(int port) { + if (port < 0 || port > 0xFFFF) + throw new IllegalArgumentException("port out of range:" + port); + return port; + } + + private static String checkHost(String hostname) { + if (hostname == null) + throw new IllegalArgumentException("hostname can't be null"); + return hostname; } /** @@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress { * range of valid port values. */ public InetSocketAddress(InetAddress addr, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - this.port = port; - if (addr == null) - this.addr = InetAddress.anyLocalAddress(); - else - this.addr = addr; + holder = new InetSocketAddressHolder( + null, + addr == null ? InetAddress.anyLocalAddress() : addr, + checkPort(port)); } /** @@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress { * @see #isUnresolved() */ public InetSocketAddress(String hostname, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (hostname == null) { - throw new IllegalArgumentException("hostname can't be null"); - } + checkHost(hostname); + InetAddress addr = null; + String host = null; try { addr = InetAddress.getByName(hostname); } catch(UnknownHostException e) { - this.hostname = hostname; - addr = null; + host = hostname; } - this.port = port; + holder = new InetSocketAddressHolder(host, addr, checkPort(port)); + } + + // private constructor for creating unresolved instances + private InetSocketAddress(int port, String hostname) { + holder = new InetSocketAddressHolder(hostname, null, port); } /** @@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress { * @since 1.5 */ public static InetSocketAddress createUnresolved(String host, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (host == null) { - throw new IllegalArgumentException("hostname can't be null"); - } - InetSocketAddress s = new InetSocketAddress(); - s.port = port; - s.hostname = host; - s.addr = null; - return s; + return new InetSocketAddress(checkPort(port), checkHost(host)); } - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); + /** + * @serialField hostname String + * @serialField addr InetAddress + * @serialField port int + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("hostname", String.class), + new ObjectStreamField("addr", InetAddress.class), + new ObjectStreamField("port", int.class)}; + + private void writeObject(ObjectOutputStream out) + throws IOException + { + // Don't call defaultWriteObject() + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("hostname", holder.hostname); + pfields.put("addr", holder.addr); + pfields.put("port", holder.port); + out.writeFields(); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = in.readFields(); + final String oisHostname = (String)oisFields.get("hostname", null); + final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null); + final int oisPort = oisFields.get("port", -1); // Check that our invariants are satisfied - if (port < 0 || port > 0xFFFF) { - throw new InvalidObjectException("port out of range:" + port); - } - - if (hostname == null && addr == null) { + checkPort(oisPort); + if (oisHostname == null && oisAddr == null) throw new InvalidObjectException("hostname and addr " + "can't both be null"); + + InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname, + oisAddr, + oisPort); + UNSAFE.putObject(this, FIELDS_OFFSET, h); + } + + private void readObjectNoData() + throws ObjectStreamException + { + throw new InvalidObjectException("Stream data required"); + } + + private static final long FIELDS_OFFSET; + private static final sun.misc.Unsafe UNSAFE; + static { + try { + sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + FIELDS_OFFSET = unsafe.objectFieldOffset( + InetSocketAddress.class.getDeclaredField("holder")); + UNSAFE = unsafe; + } catch (ReflectiveOperationException e) { + throw new Error(e); } } @@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress { * @return the port number. */ public final int getPort() { - return port; + return holder.getPort(); } /** @@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress { * @return the InetAdress or null if it is unresolved. */ public final InetAddress getAddress() { - return addr; + return holder.getAddress(); } /** @@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress { * @return the hostname part of the address. */ public final String getHostName() { - if (hostname != null) - return hostname; - if (addr != null) - return addr.getHostName(); - return null; + return holder.getHostName(); } /** * Returns the hostname, or the String form of the address if it * doesn't have a hostname (it was created using a literal). - * This has the benefit of not attemptimg a reverse lookup. + * This has the benefit of not attempting a reverse lookup. * * @return the hostname, or String representation of the address. * @since 1.7 */ public final String getHostString() { - if (hostname != null) - return hostname; - if (addr != null) { - if (addr.hostName != null) - return addr.hostName; - else - return addr.getHostAddress(); - } - return null; + return holder.getHostString(); } /** @@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress { * an InetAddress. */ public final boolean isUnresolved() { - return addr == null; + return holder.isUnresolved(); } /** @@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress { * * @return a string representation of this object. */ + @Override public String toString() { - if (isUnresolved()) { - return hostname + ":" + port; - } else { - return addr.toString() + ":" + port; - } + return holder.toString(); } /** @@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress { * false otherwise. * @see java.net.InetAddress#equals(java.lang.Object) */ + @Override public final boolean equals(Object obj) { if (obj == null || !(obj instanceof InetSocketAddress)) return false; - InetSocketAddress sockAddr = (InetSocketAddress) obj; - boolean sameIP = false; - if (this.addr != null) - sameIP = this.addr.equals(sockAddr.addr); - else if (this.hostname != null) - sameIP = (sockAddr.addr == null) && - this.hostname.equalsIgnoreCase(sockAddr.hostname); - else - sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null); - return sameIP && (this.port == sockAddr.port); + return holder.equals(((InetSocketAddress) obj).holder); } /** @@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress { * * @return a hash code value for this socket address. */ + @Override public final int hashCode() { - if (addr != null) - return addr.hashCode() + port; - if (hostname != null) - return hostname.toLowerCase().hashCode() + port; - return port; + return holder.hashCode(); } } diff --git a/jdk/src/share/classes/java/net/Socket.java b/jdk/src/share/classes/java/net/Socket.java index 22d4d6acd0a..d4f28e9ab6d 100644 --- a/jdk/src/share/classes/java/net/Socket.java +++ b/jdk/src/share/classes/java/net/Socket.java @@ -117,8 +117,10 @@ class Socket implements java.io.Closeable { 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 @@ class Socket implements java.io.Closeable { 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) { diff --git a/jdk/src/share/classes/java/net/URL.java b/jdk/src/share/classes/java/net/URL.java index 62271037126..caa1d5964cb 100644 --- a/jdk/src/share/classes/java/net/URL.java +++ b/jdk/src/share/classes/java/net/URL.java @@ -661,8 +661,8 @@ public final class URL implements java.io.Serializable { * @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 @@ public final class URL implements java.io.Serializable { * @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; diff --git a/jdk/src/share/classes/java/net/URLStreamHandler.java b/jdk/src/share/classes/java/net/URLStreamHandler.java index 6af130b6c4c..0561527488d 100644 --- a/jdk/src/share/classes/java/net/URLStreamHandler.java +++ b/jdk/src/share/classes/java/net/URLStreamHandler.java @@ -509,8 +509,8 @@ public abstract class URLStreamHandler { /** * Sets the fields of the URL 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 @@ public abstract class URLStreamHandler { /** * Sets the fields of the URL 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. diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index c1c85b521e0..2db7ba25c4a 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -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 @@ public final class Files { * 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. * * @@ -1169,12 +1169,12 @@ public final class Files { * implementation specific options. * *

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. * *

Usage Example: * Suppose we want to copy a file into a directory, giving it the same file @@ -1279,15 +1279,16 @@ public final class Files { *

An implementation of this interface may support additional * implementation specific options. * - *

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. + *

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. * *

Usage Examples: * Suppose we want to rename a file to "newname", keeping the file in the diff --git a/jdk/src/share/classes/java/sql/CallableStatement.java b/jdk/src/share/classes/java/sql/CallableStatement.java index 1200f771dad..a39af405220 100644 --- a/jdk/src/share/classes/java/sql/CallableStatement.java +++ b/jdk/src/share/classes/java/sql/CallableStatement.java @@ -2621,7 +2621,7 @@ public interface CallableStatement extends PreparedStatement { * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. *

- * 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}. *

@@ -2649,7 +2649,7 @@ public interface CallableStatement extends PreparedStatement { /** * 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 @@ public interface CallableStatement extends PreparedStatement { * 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 @@ public interface CallableStatement extends PreparedStatement { * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. *

- * 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}. *

@@ -2774,7 +2774,7 @@ public interface CallableStatement extends PreparedStatement { /** * 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. diff --git a/jdk/src/share/classes/java/text/DateFormat.java b/jdk/src/share/classes/java/text/DateFormat.java index d1bb6e682dd..fcb21e6928c 100644 --- a/jdk/src/share/classes/java/text/DateFormat.java +++ b/jdk/src/share/classes/java/text/DateFormat.java @@ -439,7 +439,12 @@ public abstract class DateFormat extends Format { /** * Gets the time formatter with the default formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + *

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 @@ public abstract class DateFormat extends Format { /** * Gets the time formatter with the given formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + *

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 @@ public abstract class DateFormat extends Format { /** * Gets the date formatter with the default formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + *

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 @@ public abstract class DateFormat extends Format { /** * Gets the date formatter with the given formatting style - * for the default locale. + * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale. + *

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 @@ public abstract class DateFormat extends Format { /** * 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. + *

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 @@ public abstract class DateFormat extends Format { /** * 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. + *

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, diff --git a/jdk/src/share/classes/java/text/DateFormatSymbols.java b/jdk/src/share/classes/java/text/DateFormatSymbols.java index b4c380d2c05..80e4f03a38a 100644 --- a/jdk/src/share/classes/java/text/DateFormatSymbols.java +++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java @@ -104,14 +104,19 @@ public class DateFormatSymbols implements Serializable, Cloneable { /** * 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. - * + *

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 @@ public class DateFormatSymbols implements Serializable, Cloneable { * as for those supported by installed * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider} * implementations. + *

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 DateFormatSymbols instance. * @since 1.6 */ diff --git a/jdk/src/share/classes/java/text/DecimalFormat.java b/jdk/src/share/classes/java/text/DecimalFormat.java index 38c930372c1..bd37b2ed471 100644 --- a/jdk/src/share/classes/java/text/DecimalFormat.java +++ b/jdk/src/share/classes/java/text/DecimalFormat.java @@ -381,7 +381,8 @@ public class DecimalFormat extends NumberFormat { /** * 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. *

* To obtain standard formats for a given locale, use the factory methods @@ -411,7 +412,8 @@ public class DecimalFormat extends NumberFormat { /** * 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. *

* To obtain standard formats for a given locale, use the factory methods diff --git a/jdk/src/share/classes/java/text/DecimalFormatSymbols.java b/jdk/src/share/classes/java/text/DecimalFormatSymbols.java index 9274208fe8f..f0b2212eaf5 100644 --- a/jdk/src/share/classes/java/text/DecimalFormatSymbols.java +++ b/jdk/src/share/classes/java/text/DecimalFormatSymbols.java @@ -71,13 +71,19 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter; 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. + *

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 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { * as for those supported by installed * {@link java.text.spi.DecimalFormatSymbolsProvider * DecimalFormatSymbolsProvider} implementations. + *

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 DecimalFormatSymbols instance. * @since 1.6 */ diff --git a/jdk/src/share/classes/java/text/MessageFormat.java b/jdk/src/share/classes/java/text/MessageFormat.java index e695b37a679..e5c8c811f04 100644 --- a/jdk/src/share/classes/java/text/MessageFormat.java +++ b/jdk/src/share/classes/java/text/MessageFormat.java @@ -348,7 +348,8 @@ public class MessageFormat extends Format { 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. diff --git a/jdk/src/share/classes/java/text/NumberFormat.java b/jdk/src/share/classes/java/text/NumberFormat.java index eaed665e54c..c1b8310096b 100644 --- a/jdk/src/share/classes/java/text/NumberFormat.java +++ b/jdk/src/share/classes/java/text/NumberFormat.java @@ -389,7 +389,8 @@ public abstract class NumberFormat extends Format { //============== 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 @@ public abstract class NumberFormat extends Format { } /** - * 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 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 @@ public abstract class NumberFormat extends Format { } /** - * 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}). + *

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 @@ public abstract class NumberFormat extends Format { } /** - * 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. + *

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 @@ public abstract class NumberFormat extends Format { } /** - * 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. + *

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); diff --git a/jdk/src/share/classes/java/text/SimpleDateFormat.java b/jdk/src/share/classes/java/text/SimpleDateFormat.java index 0c1f4aa6a61..82b48964eea 100644 --- a/jdk/src/share/classes/java/text/SimpleDateFormat.java +++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java @@ -547,7 +547,8 @@ public class SimpleDateFormat extends DateFormat { /** * Constructs a SimpleDateFormat 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. * Note: This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. @@ -560,11 +561,17 @@ public class SimpleDateFormat extends DateFormat { /** * Constructs a SimpleDateFormat 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. * Note: This constructor may not support all locales. * For full coverage, use the factory methods in the {@link DateFormat} * class. + *

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 diff --git a/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java b/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java index 67495d040eb..0c207af62bc 100644 --- a/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java +++ b/jdk/src/share/classes/java/time/chrono/HijrahDeviationReader.java @@ -70,7 +70,7 @@ import java.time.LocalDate; 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 @@ final class HijrahDeviationReader { * @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 block) throws IOException, ParseException { + Consumer consumer) throws IOException, ParseException { InputStream is = getConfigFileInputStream(typeId); if (is != null) { try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { @@ -142,7 +142,7 @@ final class HijrahDeviationReader { num++; HijrahChronology.Deviation entry = parseLine(line, num); if (entry != null) { - block.accept(entry); + consumer.accept(entry); } } } diff --git a/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java b/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java index 14a116760f1..0bfe8441020 100644 --- a/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java +++ b/jdk/src/share/classes/java/time/format/DateTimeFormatSymbols.java @@ -121,10 +121,16 @@ public final class DateTimeFormatSymbols { } /** - * Obtains symbols for the default locale. + * Obtains symbols for the default + * {@link java.util.Locale.Category#FORMAT FORMAT} locale. *

* This method provides access to locale sensitive symbols. + *

+ * 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() { diff --git a/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java index f2ed2317865..e413d4b1e64 100644 --- a/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1007,7 +1007,7 @@ public final class DateTimeFormatterBuilder { * is used, with {@code IsoChronology} as the fallback. *

* 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 diff --git a/jdk/src/share/classes/java/util/Calendar.java b/jdk/src/share/classes/java/util/Calendar.java index f14ee6d6ef4..c57f50c59b3 100644 --- a/jdk/src/share/classes/java/util/Calendar.java +++ b/jdk/src/share/classes/java/util/Calendar.java @@ -1572,7 +1572,8 @@ public abstract class Calendar implements Serializable, Cloneable, ComparableCalendar 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 @@ public abstract class Calendar implements Serializable, Cloneable, ComparableCalendar 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. diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java index 58eae6f9509..b6bac484dac 100644 --- a/jdk/src/share/classes/java/util/Collections.java +++ b/jdk/src/share/classes/java/util/Collections.java @@ -3759,7 +3759,7 @@ public class Collections { return c2.compareTo(c1); } - private Object readResolve() { return reverseOrder(); } + private Object readResolve() { return Collections.reverseOrder(); } } /** diff --git a/jdk/src/share/classes/java/util/Comparator.java b/jdk/src/share/classes/java/util/Comparator.java index 35ead373b82..017c2e78e2c 100644 --- a/jdk/src/share/classes/java/util/Comparator.java +++ b/jdk/src/share/classes/java/util/Comparator.java @@ -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 total ordering on some * collection of objects. Comparators can be passed to a sort method (such @@ -165,4 +170,93 @@ public interface Comparator { * @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 reverseOrder() { + return Collections.reverseOrder(this); + } + + /** + * Constructs a lexicographic order comparator with another comparator. + * For example, a {@code Comparator byLastName} can be composed + * with another {@code Comparator byFirstName}, then {@code + * byLastName.thenComparing(byFirstName)} creates a {@code + * Comparator} 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 thenComparing(Comparator 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 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 > Comparator thenComparing(Function 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 thenComparing(ToIntFunction 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 thenComparing(ToLongFunction 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 thenComparing(ToDoubleFunction keyExtractor) { + return thenComparing(Comparators.comparing(keyExtractor)); + } } diff --git a/jdk/src/share/classes/java/util/Comparators.java b/jdk/src/share/classes/java/util/Comparators.java new file mode 100644 index 00000000000..75821339b49 --- /dev/null +++ b/jdk/src/share/classes/java/util/Comparators.java @@ -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}. + * + *

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> { + INSTANCE; + + @Override + public int compare(Comparable c1, Comparable c2) { + return c1.compareTo(c2); + } + } + + /** + * Returns a comparator that imposes the reverse of the natural + * ordering. + * + *

The returned comparator is serializable. + * + * @param {@link Comparable} type + * + * @return A comparator that imposes the reverse of the natural + * ordering on a collection of objects that implement + * the {@link Comparable} interface. + * @see Comparable + */ + public static > Comparator reverseOrder() { + return Collections.reverseOrder(); + } + + /** + * Returns a comparator that imposes the reverse ordering of the specified + * {@link Comparator}. + * + *

The returned comparator is serializable (assuming the specified + * comparator is also serializable). + * + * @param 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 Comparator reverseOrder(Comparator cmp) { + Objects.requireNonNull(cmp); + return Collections.reverseOrder(cmp); + } + + /** + * Gets a comparator compares {@link Comparable} type in natural order. + * + * @param {@link Comparable} type + */ + public static > Comparator naturalOrder() { + return (Comparator) NaturalOrderComparator.INSTANCE; + } + + /** + * Gets a comparator compares {@link Map.Entry} in natural order on key. + * + * @param {@link Comparable} key type + * @param value type + */ + public static , V> Comparator> naturalOrderKeys() { + return (Comparator> & Serializable) + (c1, c2) -> c1.getKey().compareTo(c2.getKey()); + } + + /** + * Gets a comparator compares {@link Map.Entry} in natural order on value. + * + * @param key type + * @param {@link Comparable} value type + */ + public static > Comparator> naturalOrderValues() { + return (Comparator> & Serializable) + (c1, c2) -> c1.getValue().compareTo(c2.getValue()); + } + + /** + * Gets a comparator compares {@link Map.Entry} by key using the given + * {@link Comparator}. + * + *

The returned comparator is serializable assuming the specified + * comparators are also serializable. + * + * @param key type + * @param value type + * @param cmp the key {@link Comparator} + */ + public static Comparator> byKey(Comparator cmp) { + Objects.requireNonNull(cmp); + return (Comparator> & Serializable) + (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey()); + } + + /** + * Gets a comparator compares {@link Map.Entry} by value using the given + * {@link Comparator}. + * + * @param key type + * @param value type + * @param cmp the value {@link Comparator} + */ + public static Comparator> byValue(Comparator cmp) { + Objects.requireNonNull(cmp); + return (Comparator> & 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} 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} that compares {@code Person} objects by their last + * name. + * + * @param the original element type + * @param the {@link Comparable} type for comparison + * @param keyExtractor the function used to extract the {@link Comparable} sort key + */ + public static > Comparator comparing(Function keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator & 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} that compares by that value. + * + *

The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param the original element type + * @param keyExtractor the function used to extract the integer value + */ + public static Comparator comparing(ToIntFunction keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator & 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} that compares by that value. + * + *

The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param the original element type + * @param keyExtractor the function used to extract the long value + */ + public static Comparator comparing(ToLongFunction keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator & 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} that compares by that + * value. + * + *

The returned comparator is serializable assuming the specified + * function is also serializable. + * + * @see #comparing(Function) + * @param the original element type + * @param keyExtractor the function used to extract the double value + */ + public static Comparator comparing(ToDoubleFunction keyExtractor) { + Objects.requireNonNull(keyExtractor); + return (Comparator & 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}, then {@code + * compose(byLastName, byFirstName)} creates a {@code Comparator} + * which sorts by last name, and for equal last names sorts by first name. + * + *

The returned comparator is serializable assuming the specified + * comparators are also serializable. + * + * @param the element type to be compared + * @param first the first comparator + * @param second the secondary comparator used when equals on the first + */ + public static Comparator compose(Comparator first, Comparator second) { + Objects.requireNonNull(first); + Objects.requireNonNull(second); + return (Comparator & 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 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 BinaryOperator lesserOf(Comparator 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 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 BinaryOperator greaterOf(Comparator comparator) { + return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; + } +} diff --git a/jdk/src/share/classes/java/util/Currency.java b/jdk/src/share/classes/java/util/Currency.java index f201dae410a..09e7046849b 100644 --- a/jdk/src/share/classes/java/util/Currency.java +++ b/jdk/src/share/classes/java/util/Currency.java @@ -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 @@ public final class Currency implements Serializable { } /** - * 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. + *

+ * 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 @@ public final class Currency implements Serializable { /** * 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. + *

+ * 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 @@ public final class Currency implements Serializable { " 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 @@ public final class Currency implements Serializable { 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); diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index c645861521c..65a6f0b3634 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -1900,7 +1900,8 @@ public final class Formatter implements Closeable, Flushable { * 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 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a new formatter with the specified destination. * - *

The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - *

The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a new formatter with the specified file name and charset. * - *

The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - *

The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a new formatter with the specified file and charset. * - *

The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { /** * Constructs a new formatter with the specified print stream. * - *

The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + *

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. * *

Characters are written to the given {@link java.io.PrintStream * PrintStream} object and are therefore encoded using that object's @@ -2193,8 +2206,10 @@ public final class Formatter implements Closeable, Flushable { * java.nio.charset.Charset#defaultCharset() default charset} for this * instance of the Java virtual machine. * - *

The locale used is the {@linkplain Locale#getDefault() default - * locale} for this instance of the Java virtual machine. + *

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 @@ public final class Formatter implements Closeable, Flushable { * Constructs a new formatter with the specified output stream and * charset. * - *

The locale used is the {@linkplain Locale#getDefault default - * locale} for this instance of the Java virtual machine. + *

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. diff --git a/jdk/src/share/classes/java/util/GregorianCalendar.java b/jdk/src/share/classes/java/util/GregorianCalendar.java index 4e063ee70ba..96501286e75 100644 --- a/jdk/src/share/classes/java/util/GregorianCalendar.java +++ b/jdk/src/share/classes/java/util/GregorianCalendar.java @@ -587,7 +587,8 @@ public class GregorianCalendar extends Calendar { /** * Constructs a default GregorianCalendar 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 @@ public class GregorianCalendar extends Calendar { /** * Constructs a GregorianCalendar 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. */ diff --git a/jdk/src/share/classes/java/util/IdentityHashMap.java b/jdk/src/share/classes/java/util/IdentityHashMap.java index 0a71e5bd5a9..49bb9943ff6 100644 --- a/jdk/src/share/classes/java/util/IdentityHashMap.java +++ b/jdk/src/share/classes/java/util/IdentityHashMap.java @@ -25,6 +25,7 @@ package java.util; import java.io.*; +import java.lang.reflect.Array; /** * This class implements the Map interface with a hash table, using @@ -1010,6 +1011,37 @@ public class IdentityHashMap result += System.identityHashCode(key); return result; } + public Object[] toArray() { + return toArray(new Object[size()]); + } + @SuppressWarnings("unchecked") + public 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 class IdentityHashMap public void clear() { IdentityHashMap.this.clear(); } + public Object[] toArray() { + return toArray(new Object[size()]); + } + @SuppressWarnings("unchecked") + public 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 class IdentityHashMap } public Object[] toArray() { - int size = size(); - Object[] result = new Object[size]; - Iterator> 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[] 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> 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; } } diff --git a/jdk/src/share/classes/java/util/Locale.java b/jdk/src/share/classes/java/util/Locale.java index 198148206d1..69f277659ab 100644 --- a/jdk/src/share/classes/java/util/Locale.java +++ b/jdk/src/share/classes/java/util/Locale.java @@ -351,7 +351,8 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter; * you can use getDisplayLanguage to get the name of * the language suitable for displaying to the user. Interestingly, * the getDisplayXXX 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. * *

The Java Platform provides a number of classes that perform locale-sensitive @@ -369,7 +370,8 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter; * * * 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: *

*
  *     NumberFormat.getInstance(myLocale)
@@ -1645,11 +1647,15 @@ public final class Locale implements Cloneable, Serializable {
     /**
      * 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 @@ public final class Locale implements Cloneable, Serializable {
 
     /**
      * 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 @@ public final class Locale implements Cloneable, Serializable {
      * 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 inLocale is null
      * @since 1.7
      */
@@ -1706,11 +1715,15 @@ public final class Locale implements Cloneable, Serializable {
     /**
      * 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 @@ public final class Locale implements Cloneable, Serializable {
 
     /**
      * 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() {
diff --git a/jdk/src/share/classes/java/util/LocaleISOData.java b/jdk/src/share/classes/java/util/LocaleISOData.java
index c49abb06eaf..170fef69193 100644
--- a/jdk/src/share/classes/java/util/LocaleISOData.java
+++ b/jdk/src/share/classes/java/util/LocaleISOData.java
@@ -473,7 +473,7 @@ class LocaleISOData {
         + "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
         ;
 
diff --git a/jdk/src/share/classes/java/util/Scanner.java b/jdk/src/share/classes/java/util/Scanner.java
index 3c558114ac7..cc19b0d1257 100644
--- a/jdk/src/share/classes/java/util/Scanner.java
+++ b/jdk/src/share/classes/java/util/Scanner.java
@@ -151,7 +151,8 @@ import sun.misc.LRUCache;
  * 

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 * initial locale 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 @@ public final class Scanner implements Iterator, Closeable { * *

      *   scanner.useDelimiter("\\p{javaWhitespace}+")
-     *          .useLocale(Locale.getDefault())
+     *          .useLocale(Locale.getDefault(Locale.Category.FORMAT))
      *          .useRadix(10);
      * 
* diff --git a/jdk/src/share/classes/java/util/TimeZone.java b/jdk/src/share/classes/java/util/TimeZone.java index 66297c015b9..cc8fe5dc356 100644 --- a/jdk/src/share/classes/java/util/TimeZone.java +++ b/jdk/src/share/classes/java/util/TimeZone.java @@ -534,7 +534,7 @@ abstract public class TimeZone implements Serializable, Cloneable { /** * 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} diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java index 86bb3b59ebc..0bb27589e60 100644 --- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java @@ -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 @@ import java.util.concurrent.TimeUnit; * there is little difference among choice of methods. * * + * * * * * * * - * + * * * * * - * + * * * * * - * + * * * * *
Summary of task execution methods
Call from non-fork/join clients Call from within fork/join computations
Arrange async execution Arrange async execution {@link #execute(ForkJoinTask)} {@link ForkJoinTask#fork}
Await and obtain result Await and obtain result {@link #invoke(ForkJoinTask)} {@link ForkJoinTask#invoke}
Arrange exec and obtain Future Arrange exec and obtain Future {@link #submit(ForkJoinTask)} {@link ForkJoinTask#fork} (ForkJoinTasks are Futures)
* *

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}: + *

    + *
  • {@code java.util.concurrent.ForkJoinPool.common.parallelism} + * - the parallelism level, a non-negative integer + *
  • {@code java.util.concurrent.ForkJoinPool.common.threadFactory} + * - the class name of a {@link ForkJoinWorkerThreadFactory} + *
  • {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} + * - the class name of a {@link UncaughtExceptionHandler} + *
+ * 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}. * *

Implementation notes: This implementation restricts the * maximum number of running threads to 32767. Attempts to create @@ -225,18 +233,18 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { * * @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); } @@ -563,26 +572,6 @@ public class ForkJoinPool extends AbstractExecutorService { } } - /** - * 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 @@ -737,7 +726,7 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { /** * 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 @@ public class ForkJoinPool extends AbstractExecutorService { 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 @@ public class ForkJoinPool extends AbstractExecutorService { 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); } } @@ -1082,15 +1070,6 @@ public class ForkJoinPool extends AbstractExecutorService { public static final ForkJoinWorkerThreadFactory 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 submitters; - /** * Permission required for callers of methods that may start or * kill threads. @@ -1103,12 +1082,15 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { 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 @@ public class ForkJoinPool extends AbstractExecutorService { */ private static final int SEED_INCREMENT = 0x61c88647; - /** + /* * Bits and masks for control variables * * Field ctl is a long packed with: @@ -1268,39 +1250,28 @@ public class ForkJoinPool extends AbstractExecutorService { 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)) { @@ -1331,39 +1302,6 @@ public class ForkJoinPool extends AbstractExecutorService { synchronized (this) { notifyAll(); } } - /** - * 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 @@ public class ForkJoinPool extends AbstractExecutorService { * @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 @@ public class ForkJoinPool extends AbstractExecutorService { * 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 @@ public class ForkJoinPool extends AbstractExecutorService { 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 @@ public class ForkJoinPool extends AbstractExecutorService { * @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 @@ public class ForkJoinPool extends AbstractExecutorService { /** * 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) + boolean move = false; + if ((ps = plock) < 0) throw new RejectedExecutionException(); else if (ps == 0 || (ws = workQueues) == null || - (m = ws.length - 1) < 0) - initWorkers(); + (m = ws.length - 1) < 0) { // initialize workQueues + 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; + WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ? + new WorkQueue[n] : 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); + } else if ((q = ws[k = r & m & SQMASK]) != null) { if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { ForkJoinTask[] a = q.array; @@ -1598,7 +1550,7 @@ public class ForkJoinPool extends AbstractExecutorService { return; } } - r = 0; // move on failure + move = true; // move on failure } else if (((ps = plock) & PL_LOCK) == 0) { // create new queue q = new WorkQueue(this, null, SHARED_QUEUE, r); @@ -1612,7 +1564,9 @@ public class ForkJoinPool extends AbstractExecutorService { releasePlock(nps); } else - r = 0; // try elsewhere while lock held + move = true; // move if busy + if (move) + r = ThreadLocalRandom.advanceProbe(r); } } @@ -1703,7 +1657,7 @@ public class ForkJoinPool extends AbstractExecutorService { * park awaiting signal, else lingering to help scan and signal. * * * If a non-empty queue discovered or left as a hint, - * help wake up other workers before return + * help wake up other workers before return. * * @param w the worker (via its WorkQueue) * @return a task or null if none found @@ -1758,14 +1712,13 @@ public class ForkJoinPool extends AbstractExecutorService { else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK)) idleAwaitWork(w, nc, c); } - else if (w.eventCount < 0 && !tryTerminate(false, false) && - ctl == c) { // block + else if (w.eventCount < 0 && ctl == c) { Thread wt = Thread.currentThread(); Thread.interrupted(); // clear status U.putObject(wt, PARKBLOCKER, this); w.parker = wt; // emulate LockSupport.park if (w.eventCount < 0) // recheck - U.park(false, 0L); + U.park(false, 0L); // block w.parker = null; U.putObject(wt, PARKBLOCKER, null); } @@ -1774,7 +1727,7 @@ public class ForkJoinPool extends AbstractExecutorService { (ws = workQueues) != null && h < ws.length && (q = ws[h]) != null) { // signal others before retry WorkQueue v; Thread p; int u, i, s; - for (int n = (config & SMASK) >>> 1;;) { + for (int n = (config & SMASK) - 1;;) { int idleCount = (w.eventCount < 0) ? 0 : -1; if (((s = idleCount - q.base + q.top) <= n && (n = s) <= 0) || @@ -1814,7 +1767,8 @@ public class ForkJoinPool extends AbstractExecutorService { */ private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) { if (w != null && w.eventCount < 0 && - !tryTerminate(false, false) && (int)prevCtl != 0) { + !tryTerminate(false, false) && (int)prevCtl != 0 && + ctl == currentCtl) { int dc = -(short)(currentCtl >>> TC_SHIFT); long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT; long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP; @@ -1832,6 +1786,7 @@ public class ForkJoinPool extends AbstractExecutorService { if (deadline - System.nanoTime() <= 0L && U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) { w.eventCount = (w.eventCount + E_SEQ) | E_MASK; + w.hint = -1; w.qlock = -1; // shrink break; } @@ -1973,7 +1928,6 @@ public class ForkJoinPool extends AbstractExecutorService { * @param task the task to join * @param mode if shared, exit upon completing any task * if all workers are active - * */ private int helpComplete(ForkJoinTask task, int mode) { WorkQueue[] ws; WorkQueue q; int m, n, s, u; @@ -2125,29 +2079,22 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Returns a (probably) non-empty steal queue, if one is found - * during a random, then cyclic scan, else null. This method must - * be retried by caller if, by the time it tries to use the queue, - * it is empty. + * during a scan, else null. This method must be retried by + * caller if, by the time it tries to use the queue, it is empty. * @param r a (random) seed for scanning */ private WorkQueue findNonEmptyStealQueue(int r) { - for (WorkQueue[] ws;;) { - int ps = plock, m, n; - if ((ws = workQueues) == null || (m = ws.length - 1) < 1) - return null; - for (int j = (m + 1) << 2; ;) { - WorkQueue q = ws[(((r + j) << 1) | 1) & m]; - if (q != null && (n = q.base - q.top) < 0) { - if (n < -1) - signalWork(q); - return q; - } - else if (--j < 0) { - if (plock == ps) - return null; - break; + for (;;) { + int ps = plock, m; WorkQueue[] ws; WorkQueue q; + if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { + for (int j = (m + 1) << 2; j >= 0; --j) { + if ((q = ws[(((r + j) << 1) | 1) & m]) != null && + q.base - q.top < 0) + return q; } } + if (plock == ps) + return null; } } @@ -2159,37 +2106,34 @@ public class ForkJoinPool extends AbstractExecutorService { */ final void helpQuiescePool(WorkQueue w) { for (boolean active = true;;) { - ForkJoinTask localTask; // exhaust local queue - while ((localTask = w.nextLocalTask()) != null) - localTask.doExec(); - // Similar to loop in scan(), but ignoring submissions - WorkQueue q = findNonEmptyStealQueue(w.nextSeed()); - if (q != null) { - ForkJoinTask t; int b; + long c; WorkQueue q; ForkJoinTask t; int b; + while ((t = w.nextLocalTask()) != null) { + if (w.base - w.top < 0) + signalWork(w); + t.doExec(); + } + if ((q = findNonEmptyStealQueue(w.nextSeed())) != null) { if (!active) { // re-establish active count - long c; active = true; do {} while (!U.compareAndSwapLong (this, CTL, c = ctl, c + AC_UNIT)); } - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) + if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); w.runSubtask(t); + } } - else { - long c; - if (active) { // decrement active count without queuing + else if (active) { // decrement active count without queuing + long nc = (c = ctl) - AC_UNIT; + if ((int)(nc >> AC_SHIFT) + (config & SMASK) == 0) + return; // bypass decrement-then-increment + if (U.compareAndSwapLong(this, CTL, c, nc)) active = false; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, c -= AC_UNIT)); - } - else - c = ctl; // re-increment on exit - if ((int)(c >> AC_SHIFT) + (config & SMASK) == 0) { - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, c + AC_UNIT)); - break; - } } + else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) == 0 && + U.compareAndSwapLong(this, CTL, c, c + AC_UNIT)) + return; } } @@ -2205,8 +2149,11 @@ public class ForkJoinPool extends AbstractExecutorService { return t; if ((q = findNonEmptyStealQueue(w.nextSeed())) == null) return null; - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) + if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); return t; + } } } @@ -2235,7 +2182,7 @@ public class ForkJoinPool extends AbstractExecutorService { * producing extra tasks amortizes the uncertainty of progress and * diffusion assumptions. * - * So, users will want to use values larger, but not much larger + * So, users will want to use values larger (but not much larger) * than 1 to both smooth over transient shortages and hedge * against uneven progress; as traded off against the cost of * extra task overhead. We leave the user to pick a threshold @@ -2288,45 +2235,49 @@ public class ForkJoinPool extends AbstractExecutorService { * @return true if now terminating or terminated */ private boolean tryTerminate(boolean now, boolean enable) { - if (this == commonPool) // cannot shut down + int ps; + if (this == common) // cannot shut down return false; + if ((ps = plock) >= 0) { // enable by setting plock + if (!enable) + return false; + if ((ps & PL_LOCK) != 0 || + !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) + ps = acquirePlock(); + int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN; + if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) + releasePlock(nps); + } for (long c;;) { - if (((c = ctl) & STOP_BIT) != 0) { // already terminating + if (((c = ctl) & STOP_BIT) != 0) { // already terminating if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) { synchronized (this) { - notifyAll(); // signal when 0 workers + notifyAll(); // signal when 0 workers } } return true; } - if (plock >= 0) { // not yet enabled - int ps; - if (!enable) + if (!now) { // check if idle & no tasks + WorkQueue[] ws; WorkQueue w; + if ((int)(c >> AC_SHIFT) != -(config & SMASK)) return false; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (!U.compareAndSwapInt(this, PLOCK, ps, SHUTDOWN)) - releasePlock(SHUTDOWN); - } - if (!now) { // check if idle & no tasks - if ((int)(c >> AC_SHIFT) != -(config & SMASK) || - hasQueuedSubmissions()) - return false; - // Check for unqueued inactive workers. One pass suffices. - WorkQueue[] ws = workQueues; WorkQueue w; - if (ws != null) { - for (int i = 1; i < ws.length; i += 2) { - if ((w = ws[i]) != null && w.eventCount >= 0) - return false; + if ((ws = workQueues) != null) { + for (int i = 0; i < ws.length; ++i) { + if ((w = ws[i]) != null) { + if (!w.isEmpty()) { // signal unprocessed tasks + signalWork(w); + return false; + } + if ((i & 1) != 0 && w.eventCount >= 0) + return false; // unqueued inactive worker + } } } } if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) { for (int pass = 0; pass < 3; ++pass) { - WorkQueue[] ws = workQueues; - if (ws != null) { - WorkQueue w; Thread wt; + WorkQueue[] ws; WorkQueue w; Thread wt; + if ((ws = workQueues) != null) { int n = ws.length; for (int i = 0; i < n; ++i) { if ((w = ws[i]) != null) { @@ -2337,7 +2288,7 @@ public class ForkJoinPool extends AbstractExecutorService { if (!wt.isInterrupted()) { try { wt.interrupt(); - } catch (SecurityException ignore) { + } catch (Throwable ignore) { } } U.unpark(wt); @@ -2348,7 +2299,7 @@ public class ForkJoinPool extends AbstractExecutorService { // Wake up workers parked on event queue int i, e; long cc; Thread p; while ((e = (int)(cc = ctl) & E_MASK) != 0 && - (i = e & SMASK) < n && + (i = e & SMASK) < n && i >= 0 && (w = ws[i]) != null) { long nc = ((long)(w.nextWait & E_MASK) | ((cc + AC_UNIT) & AC_MASK) | @@ -2374,26 +2325,26 @@ public class ForkJoinPool extends AbstractExecutorService { * least one task. */ static WorkQueue commonSubmitterQueue() { - ForkJoinPool p; WorkQueue[] ws; int m; Submitter z; - return ((z = submitters.get()) != null && - (p = commonPool) != null && + ForkJoinPool p; WorkQueue[] ws; int m, z; + return ((z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0) ? - ws[m & z.seed & SQMASK] : null; + ws[m & z & SQMASK] : null; } /** * Tries to pop the given task from submitter's queue in common pool. */ static boolean tryExternalUnpush(ForkJoinTask t) { - ForkJoinPool p; WorkQueue[] ws; WorkQueue q; Submitter z; - ForkJoinTask[] a; int m, s; + ForkJoinPool p; WorkQueue[] ws; WorkQueue q; + ForkJoinTask[] a; int m, s, z; if (t != null && - (z = submitters.get()) != null && - (p = commonPool) != null && + (z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && (s = q.top) != q.base && (a = q.array) != null) { long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; @@ -2445,9 +2396,10 @@ public class ForkJoinPool extends AbstractExecutorService { if (task != null) task.doExec(); if (root.status < 0 || - (u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0) + (config != 0 && + ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))) break; - if (task == null) { + if (task == null) { helpSignal(root, q.poolIndex); if (root.status >= 0) helpComplete(root, SHARED_QUEUE); @@ -2463,14 +2415,14 @@ public class ForkJoinPool extends AbstractExecutorService { */ static void externalHelpJoin(ForkJoinTask t) { // Some hard-to-avoid overlap with tryExternalUnpush - ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; Submitter z; - ForkJoinTask[] a; int m, s, n; + ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; + ForkJoinTask[] a; int m, s, n, z; if (t != null && - (z = submitters.get()) != null && - (p = commonPool) != null && + (z = ThreadLocalRandom.getProbe()) != 0 && + (p = common) != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0 && - (q = ws[m & z.seed & SQMASK]) != null && + (q = ws[m & z & SQMASK]) != null && (a = q.array) != null) { int am = a.length - 1; if ((s = q.top) != q.base) { @@ -2496,18 +2448,6 @@ public class ForkJoinPool extends AbstractExecutorService { } } - /** - * Restricted version of helpQuiescePool for external callers - */ - static void externalHelpQuiescePool() { - ForkJoinPool p; ForkJoinTask t; WorkQueue q; int b; - if ((p = commonPool) != null && - (q = p.findNonEmptyStealQueue(1)) != null && - (b = q.base) - q.top < 0 && - (t = q.pollAt(b)) != null) - t.doExec(); - } - // Exported methods // Constructors @@ -2524,7 +2464,7 @@ public class ForkJoinPool extends AbstractExecutorService { * java.lang.RuntimePermission}{@code ("modifyThread")} */ public ForkJoinPool() { - this(Runtime.getRuntime().availableProcessors(), + this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()), defaultForkJoinWorkerThreadFactory, null, false); } @@ -2572,50 +2512,63 @@ public class ForkJoinPool extends AbstractExecutorService { */ public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory, - Thread.UncaughtExceptionHandler handler, + UncaughtExceptionHandler handler, boolean asyncMode) { + this(checkParallelism(parallelism), + checkFactory(factory), + handler, + asyncMode, + "ForkJoinPool-" + nextPoolId() + "-worker-"); checkPermission(); - if (factory == null) - throw new NullPointerException(); + } + + private static int checkParallelism(int parallelism) { if (parallelism <= 0 || parallelism > MAX_CAP) throw new IllegalArgumentException(); + return parallelism; + } + + private static ForkJoinWorkerThreadFactory checkFactory + (ForkJoinWorkerThreadFactory factory) { + if (factory == null) + throw new NullPointerException(); + return factory; + } + + /** + * Creates a {@code ForkJoinPool} with the given parameters, without + * any security checks or parameter validation. Invoked directly by + * makeCommonPool. + */ + private ForkJoinPool(int parallelism, + ForkJoinWorkerThreadFactory factory, + UncaughtExceptionHandler handler, + boolean asyncMode, + String workerNamePrefix) { + this.workerNamePrefix = workerNamePrefix; this.factory = factory; this.ueh = handler; this.config = parallelism | (asyncMode ? (FIFO_QUEUE << 16) : 0); long np = (long)(-parallelism); // offset ctl counts this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); - int pn = nextPoolId(); - StringBuilder sb = new StringBuilder("ForkJoinPool-"); - sb.append(Integer.toString(pn)); - sb.append("-worker-"); - this.workerNamePrefix = sb.toString(); - } - - /** - * Constructor for common pool, suitable only for static initialization. - * Basically the same as above, but uses smallest possible initial footprint. - */ - ForkJoinPool(int parallelism, long ctl, - ForkJoinWorkerThreadFactory factory, - Thread.UncaughtExceptionHandler handler) { - this.config = parallelism; - this.ctl = ctl; - this.factory = factory; - this.ueh = handler; - this.workerNamePrefix = "ForkJoinPool.commonPool-worker-"; } /** * Returns the common pool instance. This pool is statically - * constructed; its run state is unaffected by attempts to - * {@link #shutdown} or {@link #shutdownNow}. + * constructed; its run state is unaffected by attempts to {@link + * #shutdown} or {@link #shutdownNow}. However this pool and any + * ongoing processing are automatically terminated upon program + * {@link System#exit}. Any program that relies on asynchronous + * task processing to complete before program termination should + * invoke {@code commonPool().}{@link #awaitQuiescence awaitQuiescence}, + * before exit. * * @return the common pool instance * @since 1.8 */ public static ForkJoinPool commonPool() { - // assert commonPool != null : "static init error"; - return commonPool; + // assert common != null : "static init error"; + return common; } // Execution methods @@ -2671,7 +2624,7 @@ public class ForkJoinPool extends AbstractExecutorService { if (task instanceof ForkJoinTask) // avoid re-wrap job = (ForkJoinTask) task; else - job = new ForkJoinTask.AdaptedRunnableAction(task); + job = new ForkJoinTask.RunnableExecuteAction(task); externalPush(job); } @@ -2738,27 +2691,23 @@ public class ForkJoinPool extends AbstractExecutorService { // In previous versions of this class, this method constructed // a task to run ForkJoinTask.invokeAll, but now external // invocation of multiple tasks is at least as efficient. - List> fs = new ArrayList>(tasks.size()); - // Workaround needed because method wasn't declared with - // wildcards in return type but should have been. - @SuppressWarnings({"unchecked", "rawtypes"}) - List> futures = (List>) (List) fs; + ArrayList> futures = new ArrayList>(tasks.size()); boolean done = false; try { for (Callable t : tasks) { ForkJoinTask f = new ForkJoinTask.AdaptedCallable(t); + futures.add(f); externalPush(f); - fs.add(f); } - for (ForkJoinTask f : fs) - f.quietlyJoin(); + for (int i = 0, size = futures.size(); i < size; i++) + ((ForkJoinTask)futures.get(i)).quietlyJoin(); done = true; return futures; } finally { if (!done) - for (ForkJoinTask f : fs) - f.cancel(false); + for (int i = 0, size = futures.size(); i < size; i++) + futures.get(i).cancel(false); } } @@ -2777,7 +2726,7 @@ public class ForkJoinPool extends AbstractExecutorService { * * @return the handler, or {@code null} if none */ - public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { + public UncaughtExceptionHandler getUncaughtExceptionHandler() { return ueh; } @@ -2787,7 +2736,8 @@ public class ForkJoinPool extends AbstractExecutorService { * @return the targeted parallelism level of this pool */ public int getParallelism() { - return config & SMASK; + int par = (config & SMASK); + return (par > 0) ? par : 1; } /** @@ -2797,7 +2747,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @since 1.8 */ public static int getCommonPoolParallelism() { - return commonPoolParallelism; + return commonParallelism; } /** @@ -3055,7 +3005,7 @@ public class ForkJoinPool extends AbstractExecutorService { * Possibly initiates an orderly shutdown in which previously * submitted tasks are executed, but no new tasks will be * accepted. Invocation has no effect on execution state if this - * is the {@link #commonPool}, and no additional effect if + * is the {@link #commonPool()}, and no additional effect if * already shut down. Tasks that are in the process of being * submitted concurrently during the course of this method may or * may not be rejected. @@ -3073,7 +3023,7 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Possibly attempts to cancel and/or stop all tasks, and reject * all subsequently submitted tasks. Invocation has no effect on - * execution state if this is the {@link #commonPool}, and no + * execution state if this is the {@link #commonPool()}, and no * additional effect if already shut down. Otherwise, tasks that * are in the process of being submitted or executed concurrently * during the course of this method may or may not be @@ -3136,9 +3086,10 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Blocks until all tasks have completed execution after a * shutdown request, or the timeout occurs, or the current thread - * is interrupted, whichever happens first. Note that the {@link - * #commonPool()} never terminates until program shutdown so - * this method will always time out. + * is interrupted, whichever happens first. Because the {@link + * #commonPool()} never terminates until program shutdown, when + * applied to the common pool, this method is equivalent to {@link + * #awaitQuiescence(long, TimeUnit)} but always returns {@code false}. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument @@ -3148,6 +3099,12 @@ public class ForkJoinPool extends AbstractExecutorService { */ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (this == common) { + awaitQuiescence(timeout, unit); + return false; + } long nanos = unit.toNanos(timeout); if (isTerminated()) return true; @@ -3166,6 +3123,62 @@ public class ForkJoinPool extends AbstractExecutorService { return terminated; } + /** + * If called by a ForkJoinTask operating in this pool, equivalent + * in effect to {@link ForkJoinTask#helpQuiesce}. Otherwise, + * waits and/or attempts to assist performing tasks until this + * pool {@link #isQuiescent} or the indicated timeout elapses. + * + * @param timeout the maximum time to wait + * @param unit the time unit of the timeout argument + * @return {@code true} if quiescent; {@code false} if the + * timeout elapsed. + */ + public boolean awaitQuiescence(long timeout, TimeUnit unit) { + long nanos = unit.toNanos(timeout); + ForkJoinWorkerThread wt; + Thread thread = Thread.currentThread(); + if ((thread instanceof ForkJoinWorkerThread) && + (wt = (ForkJoinWorkerThread)thread).pool == this) { + helpQuiescePool(wt.workQueue); + return true; + } + long startTime = System.nanoTime(); + WorkQueue[] ws; + int r = 0, m; + boolean found = true; + while (!isQuiescent() && (ws = workQueues) != null && + (m = ws.length - 1) >= 0) { + if (!found) { + if ((System.nanoTime() - startTime) > nanos) + return false; + Thread.yield(); // cannot block + } + found = false; + for (int j = (m + 1) << 2; j >= 0; --j) { + ForkJoinTask t; WorkQueue q; int b; + if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) { + found = true; + if ((t = q.pollAt(b)) != null) { + if (q.base - q.top < 0) + signalWork(q); + t.doExec(); + } + break; + } + } + } + return true; + } + + /** + * Waits and/or attempts to assist performing tasks indefinitely + * until the {@link #commonPool()} {@link #isQuiescent}. + */ + static void quiesceCommonPool() { + common.awaitQuiescence(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } + /** * Interface for extending managed parallelism for tasks running * in {@link ForkJoinPool}s. @@ -3175,9 +3188,9 @@ public class ForkJoinPool extends AbstractExecutorService { * not necessary. Method {@code block} blocks the current thread * if necessary (perhaps internally invoking {@code isReleasable} * before actually blocking). These actions are performed by any - * thread invoking {@link ForkJoinPool#managedBlock}. The - * unusual methods in this API accommodate synchronizers that may, - * but don't usually, block for long periods. Similarly, they + * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}. + * The unusual methods in this API accommodate synchronizers that + * may, but don't usually, block for long periods. Similarly, they * allow more efficient internal handling of cases in which * additional workers may be, but usually are not, needed to * ensure sufficient parallelism. Toward this end, @@ -3235,6 +3248,7 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Returns {@code true} if blocking is unnecessary. + * @return {@code true} if blocking is unnecessary */ boolean isReleasable(); } @@ -3319,7 +3333,7 @@ public class ForkJoinPool extends AbstractExecutorService { private static final long QLOCK; static { - int s; // initialize field offsets for CAS etc + // initialize field offsets for CAS etc try { U = sun.misc.Unsafe.getUnsafe(); Class k = ForkJoinPool.class; @@ -3339,54 +3353,58 @@ public class ForkJoinPool extends AbstractExecutorService { (wk.getDeclaredField("qlock")); Class ak = ForkJoinTask[].class; ABASE = U.arrayBaseOffset(ak); - s = U.arrayIndexScale(ak); - ASHIFT = 31 - Integer.numberOfLeadingZeros(s); + 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"); - submitters = new ThreadLocal(); - ForkJoinWorkerThreadFactory fac = defaultForkJoinWorkerThreadFactory = + defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory(); modifyThreadPermission = new RuntimePermission("modifyThread"); - /* - * Establish common pool parameters. For extra caution, - * computations to set up common pool state are here; the - * constructor just assigns these values to fields. - */ + common = java.security.AccessController.doPrivileged + (new java.security.PrivilegedAction() { + public ForkJoinPool run() { return makeCommonPool(); }}); + int par = common.config; // report 1 even if threads disabled + commonParallelism = par > 0 ? par : 1; + } - int par = 0; - Thread.UncaughtExceptionHandler handler = null; - try { // TBD: limit or report ignored exceptions? + /** + * Creates and returns the common pool, respecting user settings + * specified via system properties. + */ + private static ForkJoinPool makeCommonPool() { + int parallelism = -1; + ForkJoinWorkerThreadFactory factory + = defaultForkJoinWorkerThreadFactory; + UncaughtExceptionHandler handler = null; + try { // ignore exceptions in accesing/parsing properties String pp = System.getProperty ("java.util.concurrent.ForkJoinPool.common.parallelism"); - String hp = System.getProperty - ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); String fp = System.getProperty ("java.util.concurrent.ForkJoinPool.common.threadFactory"); - if (fp != null) - fac = ((ForkJoinWorkerThreadFactory)ClassLoader. - getSystemClassLoader().loadClass(fp).newInstance()); - if (hp != null) - handler = ((Thread.UncaughtExceptionHandler)ClassLoader. - getSystemClassLoader().loadClass(hp).newInstance()); + String hp = System.getProperty + ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); if (pp != null) - par = Integer.parseInt(pp); + parallelism = Integer.parseInt(pp); + if (fp != null) + factory = ((ForkJoinWorkerThreadFactory)ClassLoader. + getSystemClassLoader().loadClass(fp).newInstance()); + if (hp != null) + handler = ((UncaughtExceptionHandler)ClassLoader. + getSystemClassLoader().loadClass(hp).newInstance()); } catch (Exception ignore) { } - if (par <= 0) - par = Runtime.getRuntime().availableProcessors(); - if (par > MAX_CAP) - par = MAX_CAP; - commonPoolParallelism = par; - long np = (long)(-par); // precompute initial ctl value - long ct = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); - - commonPool = new ForkJoinPool(par, ct, fac, handler); + if (parallelism < 0) + parallelism = Runtime.getRuntime().availableProcessors(); + if (parallelism > MAX_CAP) + parallelism = MAX_CAP; + return new ForkJoinPool(parallelism, factory, handler, false, + "ForkJoinPool.commonPool-worker-"); } } diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java index 3b4fbb1d8fa..a17cc28b744 100644 --- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java @@ -464,7 +464,7 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Records exception and possibly propagates + * Records exception and possibly propagates. * * @return status on exit */ @@ -497,7 +497,7 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Removes exception node and clears status + * Removes exception node and clears status. */ private void clearExceptionalCompletion() { int h = System.identityHashCode(this); @@ -635,7 +635,7 @@ public abstract class ForkJoinTask implements Future, Serializable { throw (Error)ex; if (ex instanceof RuntimeException) throw (RuntimeException)ex; - throw uncheckedThrowable(ex, RuntimeException.class); + ForkJoinTask.uncheckedThrow(ex); } } @@ -645,8 +645,9 @@ public abstract class ForkJoinTask implements Future, Serializable { * unchecked exceptions */ @SuppressWarnings("unchecked") static - T uncheckedThrowable(final Throwable t, final Class c) { - return (T)t; // rely on vacuous cast + void uncheckedThrow(Throwable t) throws T { + if (t != null) + throw (T)t; // rely on vacuous cast } /** @@ -681,7 +682,7 @@ public abstract class ForkJoinTask implements Future, Serializable { if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ((ForkJoinWorkerThread)t).workQueue.push(this); else - ForkJoinPool.commonPool.externalPush(this); + ForkJoinPool.common.externalPush(this); return this; } @@ -857,7 +858,7 @@ public abstract class ForkJoinTask implements Future, Serializable { *

This method is designed to be invoked by other * tasks. To terminate the current task, you can just return or * throw an unchecked exception from its computation method, or - * invoke {@link #completeExceptionally}. + * invoke {@link #completeExceptionally(Throwable)}. * * @param mayInterruptIfRunning this value has no effect in the * default implementation because interrupts are not used to @@ -1007,8 +1008,9 @@ public abstract class ForkJoinTask implements Future, Serializable { if (Thread.interrupted()) throw new InterruptedException(); // Messy in part because we measure in nanosecs, but wait in millisecs - int s; long ns, ms; - if ((s = status) >= 0 && (ns = unit.toNanos(timeout)) > 0L) { + int s; long ms; + long ns = unit.toNanos(timeout); + if ((s = status) >= 0 && ns > 0L) { long deadline = System.nanoTime() + ns; ForkJoinPool p = null; ForkJoinPool.WorkQueue w = null; @@ -1104,7 +1106,7 @@ public abstract class ForkJoinTask implements Future, Serializable { wt.pool.helpQuiescePool(wt.workQueue); } else - ForkJoinPool.externalHelpQuiescePool(); + ForkJoinPool.quiesceCommonPool(); } /** @@ -1390,6 +1392,24 @@ public abstract class ForkJoinTask implements Future, Serializable { private static final long serialVersionUID = 5232453952276885070L; } + /** + * Adaptor for Runnables in which failure forces worker exception + */ + static final class RunnableExecuteAction extends ForkJoinTask { + final Runnable runnable; + RunnableExecuteAction(Runnable runnable) { + if (runnable == null) throw new NullPointerException(); + this.runnable = runnable; + } + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) { } + public final boolean exec() { runnable.run(); return true; } + void internalPropagateException(Throwable ex) { + rethrow(ex); // rethrow outside exec() catches. + } + private static final long serialVersionUID = 5232453952276885070L; + } + /** * Adaptor for Callables */ diff --git a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java index 08c870f0c22..c19d5128574 100644 --- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -83,22 +83,20 @@ public class ThreadLocalRandom extends Random { * programs. * * Because this class is in a different package than class Thread, - * field access methods must use Unsafe to bypass access control - * rules. The base functionality of Random methods is - * conveniently isolated in method next(bits), that just reads and - * writes the Thread field rather than its own field. However, to - * conform to the requirements of the Random constructor, during - * construction, the common static ThreadLocalRandom must maintain - * initialization and value fields, mainly for the sake of - * disabling user calls to setSeed while still allowing a call - * from constructor. For serialization compatibility, these - * fields are left with the same declarations as used in the - * previous ThreadLocal-based version of this class, that used - * them differently. Note that serialization is completely - * unnecessary because there is only a static singleton. But these - * mechanics still ensure compatibility across versions. + * field access methods use Unsafe to bypass access control rules. + * The base functionality of Random methods is conveniently + * isolated in method next(bits), that just reads and writes the + * Thread field rather than its own field. However, to conform to + * the requirements of the Random superclass constructor, the + * common static ThreadLocalRandom maintains an "initialized" + * field for the sake of rejecting user calls to setSeed while + * still allowing a call from constructor. Note that + * serialization is completely unnecessary because there is only a + * static singleton. But we generate a serial form containing + * "rnd" and "initialized" fields to ensure compatibility across + * versions. * - * Per-instance initialization is similar to that in the no-arg + * Per-thread initialization is similar to that in the no-arg * Random constructor, but we avoid correlation among not only * initial seeds of those created in different threads, but also * those created using class Random itself; while at the same time @@ -132,10 +130,11 @@ public class ThreadLocalRandom extends Random { private static final ThreadLocal nextLocalGaussian = new ThreadLocal(); - /* - * Field used only during singleton initialization + /** + * Field used only during singleton initialization. + * True when constructor completes. */ - boolean initialized; // true when constructor completes + boolean initialized; /** Constructor used only for static singleton */ private ThreadLocalRandom() { @@ -184,7 +183,8 @@ public class ThreadLocalRandom extends Random { * @throws UnsupportedOperationException always */ public void setSeed(long seed) { - if (initialized) // allow call from super() constructor + // only allow call from super() constructor + if (initialized) throw new UnsupportedOperationException(); } @@ -357,39 +357,29 @@ public class ThreadLocalRandom extends Random { r ^= r >>> 17; r ^= r << 5; } - else if ((r = (int)UNSAFE.getLong(t, SEED)) == 0) - r = 1; // avoid zero + else { + localInit(); + if ((r = (int)UNSAFE.getLong(t, SEED)) == 0) + r = 1; // avoid zero + } UNSAFE.putInt(t, SECONDARY, r); return r; } - // Serialization support, maintains original persistent form. + // Serialization support private static final long serialVersionUID = -5851777807851030925L; /** * @serialField rnd long + * seed for random computations * @serialField initialized boolean - * @serialField pad0 long - * @serialField pad1 long - * @serialField pad2 long - * @serialField pad3 long - * @serialField pad4 long - * @serialField pad5 long - * @serialField pad6 long - * @serialField pad7 long + * always true */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("rnd", long.class), - new ObjectStreamField("initialized", boolean.class), - new ObjectStreamField("pad0", long.class), - new ObjectStreamField("pad1", long.class), - new ObjectStreamField("pad2", long.class), - new ObjectStreamField("pad3", long.class), - new ObjectStreamField("pad4", long.class), - new ObjectStreamField("pad5", long.class), - new ObjectStreamField("pad6", long.class), - new ObjectStreamField("pad7", long.class) }; + new ObjectStreamField("initialized", boolean.class) + }; /** * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it). @@ -398,16 +388,8 @@ public class ThreadLocalRandom extends Random { throws java.io.IOException { java.io.ObjectOutputStream.PutField fields = out.putFields(); - fields.put("rnd", 0L); + fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED)); fields.put("initialized", true); - fields.put("pad0", 0L); - fields.put("pad1", 0L); - fields.put("pad2", 0L); - fields.put("pad3", 0L); - fields.put("pad4", 0L); - fields.put("pad5", 0L); - fields.put("pad6", 0L); - fields.put("pad7", 0L); out.writeFields(); } diff --git a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java index db7adf0e417..b7be7274d3f 100644 --- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -34,8 +34,10 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.atomic.AtomicInteger; import java.util.*; /** @@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * policy limiting the number of threads. Even though it is not * treated as an error, failure to create threads may result in * new tasks being rejected or existing ones remaining stuck in - * the queue. On the other hand, no special precautions exist to - * handle OutOfMemoryErrors that might be thrown while trying to - * create threads, since there is generally no recourse from - * within this class. + * the queue. + * + * We go further and preserve pool invariants even in the face of + * errors such as OutOfMemoryError, that might be thrown while + * trying to create threads. Such errors are rather common due to + * the need to allocate a native stack in Thread#start, and users + * will want to perform clean pool shutdown to clean up. There + * will likely be enough memory available for the cleanup code to + * complete without encountering yet another OutOfMemoryError. */ private volatile ThreadFactory threadFactory; @@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * task execution. This protects against interrupts that are * intended to wake up a worker thread waiting for a task from * instead interrupting a task being run. We implement a simple - * non-reentrant mutual exclusion lock rather than use ReentrantLock - * because we do not want worker tasks to be able to reacquire the - * lock when they invoke pool control methods like setCorePoolSize. + * non-reentrant mutual exclusion lock rather than use + * ReentrantLock because we do not want worker tasks to be able to + * reacquire the lock when they invoke pool control methods like + * setCorePoolSize. Additionally, to suppress interrupts until + * the thread actually starts running tasks, we initialize lock + * state to a negative value, and clear it upon start (in + * runWorker). */ private final class Worker extends AbstractQueuedSynchronizer @@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { + setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } @@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { // The value 1 represents the locked state. protected boolean isHeldExclusively() { - return getState() == 1; + return getState() != 0; } protected boolean tryAcquire(int unused) { @@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService { public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } + + void interruptIfStarted() { + Thread t; + if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { + try { + t.interrupt(); + } catch (SecurityException ignore) { + } + } + } } /* @@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - for (Worker w : workers) { - try { - w.thread.interrupt(); - } catch (SecurityException ignore) { - } - } + for (Worker w : workers) + w.interruptIfStarted(); } finally { mainLock.unlock(); } @@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService { private static final boolean ONLY_ONE = true; - /** - * Ensures that unless the pool is stopping, the current thread - * does not have its interrupt set. This requires a double-check - * of state in case the interrupt was cleared concurrently with a - * shutdownNow -- if so, the interrupt is re-enabled. - */ - private void clearInterruptsForTaskRun() { - if (runStateLessThan(ctl.get(), STOP) && - Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP)) - Thread.currentThread().interrupt(); - } - /* * Misc utilities, most of which are also exported to * ScheduledThreadPoolExecutor @@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * Checks if a new worker can be added with respect to current * pool state and the given bound (either core or maximum). If so, * the worker count is adjusted accordingly, and, if possible, a - * new worker is created and started running firstTask as its + * new worker is created and started, running firstTask as its * first task. This method returns false if the pool is stopped or * eligible to shut down. It also returns false if the thread - * factory fails to create a thread when asked, which requires a - * backout of workerCount, and a recheck for termination, in case - * the existence of this worker was holding up termination. + * factory fails to create a thread when asked. If the thread + * creation fails, either due to the thread factory returning + * null, or due to an exception (typically OutOfMemoryError in + * Thread#start), we roll back cleanly. * * @param firstTask the task the new thread should run first (or * null if none). Workers are created with an initial first task @@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } - Worker w = new Worker(firstTask); - Thread t = w.thread; + boolean workerStarted = false; + boolean workerAdded = false; + Worker w = null; + try { + final ReentrantLock mainLock = this.mainLock; + w = new Worker(firstTask); + final Thread t = w.thread; + if (t != null) { + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int c = ctl.get(); + int rs = runStateOf(c); + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); + } + return workerStarted; + } + + /** + * Rolls back the worker thread creation. + * - removes worker from workers, if present + * - decrements worker count + * - rechecks for termination, in case the existence of this + * worker was holding up termination + */ + private void addWorkerFailed(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int c = ctl.get(); - int rs = runStateOf(c); - - if (t == null || - (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null))) { - decrementWorkerCount(); - tryTerminate(); - return false; - } - - workers.add(w); - - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; + if (w != null) + workers.remove(w); + decrementWorkerCount(); + tryTerminate(); } finally { mainLock.unlock(); } - - t.start(); - // It is possible (but unlikely) for a thread to have been - // added to workers, but not yet started, during transition to - // STOP, which could result in a rare missed interrupt, - // because Thread.interrupt is not guaranteed to have any effect - // on a non-yet-started Thread (see Thread#interrupt). - if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) - t.interrupt(); - - return true; } /** @@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param w the worker */ final void runWorker(Worker w) { + Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; + w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); - clearInterruptsForTaskRun(); + // If pool is stopping, ensure thread is interrupted; + // if not, ensure thread is not interrupted. This + // requires a recheck in second case to deal with + // shutdownNow race while clearing interrupt + if ((runStateAtLeast(ctl.get(), STOP) || + (Thread.interrupted() && + runStateAtLeast(ctl.get(), STOP))) && + !wt.isInterrupted()) + wt.interrupt(); try { - beforeExecute(w.thread, task); + beforeExecute(wt, task); Throwable thrown = null; try { task.run(); @@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } } + diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java index b48ef72dfc9..8fed658a54c 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -219,7 +219,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { int prev, next; do { prev = get(); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSet(prev, next)); return prev; } @@ -238,7 +238,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { int prev, next; do { prev = get(); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSet(prev, next)); return next; } @@ -262,7 +262,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { int prev, next; do { prev = get(); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSet(prev, next)); return prev; } @@ -286,7 +286,7 @@ public class AtomicInteger extends Number implements java.io.Serializable { int prev, next; do { prev = get(); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSet(prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 6e4d226ba80..7c259fee06f 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -263,7 +263,7 @@ public class AtomicIntegerArray implements java.io.Serializable { int prev, next; do { prev = getRaw(offset); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -284,7 +284,7 @@ public class AtomicIntegerArray implements java.io.Serializable { int prev, next; do { prev = getRaw(offset); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSetRaw(offset, prev, next)); return next; } @@ -310,7 +310,7 @@ public class AtomicIntegerArray implements java.io.Serializable { int prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -336,7 +336,7 @@ public class AtomicIntegerArray implements java.io.Serializable { int prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index fcd5dd05f28..4a8d1df5a63 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -281,7 +281,7 @@ public abstract class AtomicIntegerFieldUpdater { int prev, next; do { prev = get(obj); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -301,7 +301,7 @@ public abstract class AtomicIntegerFieldUpdater { int prev, next; do { prev = get(obj); - next = updateFunction.operateAsInt(prev); + next = updateFunction.applyAsInt(prev); } while (!compareAndSet(obj, prev, next)); return next; } @@ -326,7 +326,7 @@ public abstract class AtomicIntegerFieldUpdater { int prev, next; do { prev = get(obj); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -351,7 +351,7 @@ public abstract class AtomicIntegerFieldUpdater { int prev, next; do { prev = get(obj); - next = accumulatorFunction.operateAsInt(prev, x); + next = accumulatorFunction.applyAsInt(prev, x); } while (!compareAndSet(obj, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java index 2e58d29b211..35af7759ac7 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -233,7 +233,7 @@ public class AtomicLong extends Number implements java.io.Serializable { long prev, next; do { prev = get(); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSet(prev, next)); return prev; } @@ -252,7 +252,7 @@ public class AtomicLong extends Number implements java.io.Serializable { long prev, next; do { prev = get(); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSet(prev, next)); return next; } @@ -276,7 +276,7 @@ public class AtomicLong extends Number implements java.io.Serializable { long prev, next; do { prev = get(); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSet(prev, next)); return prev; } @@ -300,7 +300,7 @@ public class AtomicLong extends Number implements java.io.Serializable { long prev, next; do { prev = get(); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSet(prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index 2536a9b8e93..216479abeca 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -262,7 +262,7 @@ public class AtomicLongArray implements java.io.Serializable { long prev, next; do { prev = getRaw(offset); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -283,7 +283,7 @@ public class AtomicLongArray implements java.io.Serializable { long prev, next; do { prev = getRaw(offset); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSetRaw(offset, prev, next)); return next; } @@ -309,7 +309,7 @@ public class AtomicLongArray implements java.io.Serializable { long prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -335,7 +335,7 @@ public class AtomicLongArray implements java.io.Serializable { long prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index a7672263a77..e5c6e8a0044 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -284,7 +284,7 @@ public abstract class AtomicLongFieldUpdater { long prev, next; do { prev = get(obj); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -304,7 +304,7 @@ public abstract class AtomicLongFieldUpdater { long prev, next; do { prev = get(obj); - next = updateFunction.operateAsLong(prev); + next = updateFunction.applyAsLong(prev); } while (!compareAndSet(obj, prev, next)); return next; } @@ -329,7 +329,7 @@ public abstract class AtomicLongFieldUpdater { long prev, next; do { prev = get(obj); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -354,7 +354,7 @@ public abstract class AtomicLongFieldUpdater { long prev, next; do { prev = get(obj); - next = accumulatorFunction.operateAsLong(prev, x); + next = accumulatorFunction.applyAsLong(prev, x); } while (!compareAndSet(obj, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java index 95b88d127e2..ddce0734300 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -157,7 +157,7 @@ public class AtomicReference implements java.io.Serializable { V prev, next; do { prev = get(); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSet(prev, next)); return prev; } @@ -176,7 +176,7 @@ public class AtomicReference implements java.io.Serializable { V prev, next; do { prev = get(); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSet(prev, next)); return next; } @@ -200,7 +200,7 @@ public class AtomicReference implements java.io.Serializable { V prev, next; do { prev = get(); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(prev, next)); return prev; } @@ -224,7 +224,7 @@ public class AtomicReference implements java.io.Serializable { V prev, next; do { prev = get(); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 3e6ce969847..f8787ba1d40 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -217,7 +217,7 @@ public class AtomicReferenceArray implements java.io.Serializable { E prev, next; do { prev = getRaw(offset); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -238,7 +238,7 @@ public class AtomicReferenceArray implements java.io.Serializable { E prev, next; do { prev = getRaw(offset); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSetRaw(offset, prev, next)); return next; } @@ -264,7 +264,7 @@ public class AtomicReferenceArray implements java.io.Serializable { E prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return prev; } @@ -290,7 +290,7 @@ public class AtomicReferenceArray implements java.io.Serializable { E prev, next; do { prev = getRaw(offset); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSetRaw(offset, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index a92d914ff77..933e5e4fc92 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -200,7 +200,7 @@ public abstract class AtomicReferenceFieldUpdater { V prev, next; do { prev = get(obj); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -220,7 +220,7 @@ public abstract class AtomicReferenceFieldUpdater { V prev, next; do { prev = get(obj); - next = updateFunction.operate(prev); + next = updateFunction.apply(prev); } while (!compareAndSet(obj, prev, next)); return next; } @@ -245,7 +245,7 @@ public abstract class AtomicReferenceFieldUpdater { V prev, next; do { prev = get(obj); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(obj, prev, next)); return prev; } @@ -270,7 +270,7 @@ public abstract class AtomicReferenceFieldUpdater { V prev, next; do { prev = get(obj); - next = accumulatorFunction.operate(prev, x); + next = accumulatorFunction.apply(prev, x); } while (!compareAndSet(obj, prev, next)); return next; } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java b/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java index 17556500af3..277f185f869 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java @@ -100,14 +100,14 @@ public class DoubleAccumulator extends Striped64 implements Serializable { Cell[] as; long b, v, r; int m; Cell a; if ((as = cells) != null || (r = Double.doubleToRawLongBits - (function.operateAsDouble + (function.applyAsDouble (Double.longBitsToDouble(b = base), x))) != b && !casBase(b, r)) { boolean uncontended = true; if (as == null || (m = as.length - 1) < 0 || (a = as[getProbe() & m]) == null || !(uncontended = (r = Double.doubleToRawLongBits - (function.operateAsDouble + (function.applyAsDouble (Double.longBitsToDouble(v = a.value), x))) == v || a.cas(v, r))) doubleAccumulate(x, function, uncontended); @@ -129,7 +129,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable { if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) - result = function.operateAsDouble + result = function.applyAsDouble (result, Double.longBitsToDouble(a.value)); } } @@ -174,7 +174,7 @@ public class DoubleAccumulator extends Striped64 implements Serializable { if ((a = as[i]) != null) { double v = Double.longBitsToDouble(a.value); a.value = identity; - result = function.operateAsDouble(result, v); + result = function.applyAsDouble(result, v); } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java b/jdk/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java index 855b09e44de..bfddcd3dcbd 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/LongAccumulator.java @@ -101,12 +101,12 @@ public class LongAccumulator extends Striped64 implements Serializable { public void accumulate(long x) { Cell[] as; long b, v, r; int m; Cell a; if ((as = cells) != null || - (r = function.operateAsLong(b = base, x)) != b && !casBase(b, r)) { + (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) { boolean uncontended = true; if (as == null || (m = as.length - 1) < 0 || (a = as[getProbe() & m]) == null || !(uncontended = - (r = function.operateAsLong(v = a.value, x)) == v || + (r = function.applyAsLong(v = a.value, x)) == v || a.cas(v, r))) longAccumulate(x, function, uncontended); } @@ -127,7 +127,7 @@ public class LongAccumulator extends Striped64 implements Serializable { if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) - result = function.operateAsLong(result, a.value); + result = function.applyAsLong(result, a.value); } } return result; @@ -171,7 +171,7 @@ public class LongAccumulator extends Striped64 implements Serializable { if ((a = as[i]) != null) { long v = a.value; a.value = identity; - result = function.operateAsLong(result, v); + result = function.applyAsLong(result, v); } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/Striped64.java b/jdk/src/share/classes/java/util/concurrent/atomic/Striped64.java index 03969d76dca..708b4c2574f 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/Striped64.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/Striped64.java @@ -253,7 +253,7 @@ abstract class Striped64 extends Number { else if (!wasUncontended) // CAS already known to fail wasUncontended = true; // Continue after rehash else if (a.cas(v = a.value, ((fn == null) ? v + x : - fn.operateAsLong(v, x)))) + fn.applyAsLong(v, x)))) break; else if (n >= NCPU || cells != as) collide = false; // At max size or stale @@ -291,7 +291,7 @@ abstract class Striped64 extends Number { break; } else if (casBase(v = base, ((fn == null) ? v + x : - fn.operateAsLong(v, x)))) + fn.applyAsLong(v, x)))) break; // Fall back on using base } } @@ -344,7 +344,7 @@ abstract class Striped64 extends Number { Double.doubleToRawLongBits (Double.longBitsToDouble(v) + x) : Double.doubleToRawLongBits - (fn.operateAsDouble + (fn.applyAsDouble (Double.longBitsToDouble(v), x))))) break; else if (n >= NCPU || cells != as) @@ -387,7 +387,7 @@ abstract class Striped64 extends Number { Double.doubleToRawLongBits (Double.longBitsToDouble(v) + x) : Double.doubleToRawLongBits - (fn.operateAsDouble + (fn.applyAsDouble (Double.longBitsToDouble(v), x))))) break; // Fall back on using base } diff --git a/jdk/src/share/classes/java/util/function/BiConsumer.java b/jdk/src/share/classes/java/util/function/BiConsumer.java new file mode 100644 index 00000000000..80bdcfa3b15 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/BiConsumer.java @@ -0,0 +1,50 @@ +/* + * 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.util.function; + +/** + * An operation which accepts two input arguments and returns no result. This is + * the two-arity specialization of {@link Consumer}. Unlike most other + * functional interfaces, {@code BiConsumer} is expected to operate via + * side-effects. + * + * @param the type of the first argument to the {@code accept} operation. + * @param the type of the second argument to the {@code accept} operation. + * + * @see Consumer + * @since 1.8 + */ +@FunctionalInterface +public interface BiConsumer { + + /** + * Performs operations upon the provided objects which may modify those + * objects and/or external state. + * + * @param t an input object + * @param u an input object + */ + void accept(T t, U u); +} diff --git a/jdk/src/share/classes/java/util/function/BiFunction.java b/jdk/src/share/classes/java/util/function/BiFunction.java new file mode 100644 index 00000000000..85dc2a0a3cb --- /dev/null +++ b/jdk/src/share/classes/java/util/function/BiFunction.java @@ -0,0 +1,51 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input arguments, yielding an appropriate result. This + * is the two-arity specialization of {@link Function}. A function may + * variously provide a mapping between types, object instances or keys and + * values or any other form of transformation upon the input. + * + * @param the type of the first argument to the {@code apply} operation. + * @param the type of the second argument to the {@code apply} operation. + * @param the type of results returned by the {@code apply} operation. + * + * @see Function + * @since 1.8 + */ +@FunctionalInterface +public interface BiFunction { + + /** + * Compute the result of applying the function to the input arguments + * + * @param t an input object + * @param u an input object + * @return the function result + */ + R apply(T t, U u); +} diff --git a/jdk/src/share/classes/java/util/function/BiPredicate.java b/jdk/src/share/classes/java/util/function/BiPredicate.java new file mode 100644 index 00000000000..9a8665fa151 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/BiPredicate.java @@ -0,0 +1,103 @@ +/* + * 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.util.function; + +import java.util.Objects; + +/** + * Determines if the input objects match some criteria. This is the two-arity + * specialization of {@link Predicate}. + * + * @param the type of the first argument to {@code test}. + * @param the type of the second argument to {@code test}. + * + * @see Predicate + * @since 1.8 + */ +@FunctionalInterface +public interface BiPredicate { + + /** + * Return {@code true} if the inputs match some criteria. + * + * @param t an input object. + * @param u an input object. + * @return {@code true} if the inputs match some criteria. + */ + boolean test(T t, U u); + + /** + * Returns a predicate which evaluates to {@code true} only if this + * predicate and the provided predicate both evaluate to {@code true}. If + * this predicate returns {@code false} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} only if both + * predicates return {@code true}. + */ + public default BiPredicate and(BiPredicate p) { + Objects.requireNonNull(p); + return (T t, U u) -> test(t, u) && p.test(t, u); + } + + /** + * Returns a predicate which negates the result of this predicate. + * + * @return a new predicate who's result is always the opposite of this + * predicate. + */ + public default BiPredicate negate() { + return (T t, U u) -> !test(t, u); + } + + /** + * Returns a predicate which evaluates to {@code true} if either this + * predicate or the provided predicate evaluates to {@code true}. If this + * predicate returns {@code true} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ORed with this predicate. + * @return a new predicate which returns {@code true} if either predicate + * returns {@code true}. + */ + public default BiPredicate or(BiPredicate p) { + Objects.requireNonNull(p); + return (T t, U u) -> test(t, u) || p.test(t, u); + } + + /** + * Returns a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + * + * @param p a predicate which will be logically-XORed with this predicate. + * @return a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + */ + public default BiPredicate xor(BiPredicate p) { + Objects.requireNonNull(p); + return (T t, U u) -> test(t, u) ^ p.test(t, u); + } +} diff --git a/jdk/src/share/classes/java/util/function/BinaryOperator.java b/jdk/src/share/classes/java/util/function/BinaryOperator.java index 2e9050e59f2..e81bce8c553 100644 --- a/jdk/src/share/classes/java/util/function/BinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/BinaryOperator.java @@ -25,24 +25,14 @@ package java.util.function; /** - * An operation upon two operands yielding a result. The operands and the result - * are all of the same type. + * An operation upon two operands yielding a result. This is a specialization of + * {@code BiFunction} where the operands and the result are all of the same type. * - * @param the type of operands to {@code operate} and of the result + * @param the type of operands to {@code apply} and of the result * + * @see BiFunction * @since 1.8 */ @FunctionalInterface -public interface BinaryOperator { - - /** - * Returns the result of the operation upon the operands. - * The operands are named {@code left} and {@code right} for operations - * where the order of operands matters. - * - * @param left the left operand - * @param right the right operand - * @return the result of the operation - */ - public T operate(T left, T right); +public interface BinaryOperator extends BiFunction { } diff --git a/jdk/src/share/classes/java/util/function/BooleanSupplier.java b/jdk/src/share/classes/java/util/function/BooleanSupplier.java new file mode 100644 index 00000000000..f145b621156 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/BooleanSupplier.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.function; + + +/** + * A supplier of {@code boolean} values. This is the {@code boolean}-providing + * primitive specialization of {@link Supplier}. + * + * @see Supplier + * @since 1.8 + */ +@FunctionalInterface +public interface BooleanSupplier { + + /** + * Returns a {@code boolean} value. + * + * @return a {@code boolean} value + */ + public boolean getAsBoolean(); +} diff --git a/jdk/src/share/classes/java/util/function/Block.java b/jdk/src/share/classes/java/util/function/Consumer.java similarity index 84% rename from jdk/src/share/classes/java/util/function/Block.java rename to jdk/src/share/classes/java/util/function/Consumer.java index c41e9a45a5a..e9cb175d59b 100644 --- a/jdk/src/share/classes/java/util/function/Block.java +++ b/jdk/src/share/classes/java/util/function/Consumer.java @@ -25,19 +25,19 @@ package java.util.function; /** - * An operation upon an input object. The operation may modify that object or - * external state (other objects). + * An operation which accepts a single input argument and returns no result. + * Unlike most other functional interfaces, {@code Consumer} is expected to + * operate via side-effects. * * @param The type of input objects to {@code accept} * * @since 1.8 */ @FunctionalInterface -public interface Block { +public interface Consumer { /** - * Use the input object in operations which may modify that object or - * external state (other objects). + * Accept an input value. * * @param t the input object */ diff --git a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java index f63403bb37e..de9855bd4d1 100644 --- a/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/DoubleBinaryOperator.java @@ -26,23 +26,22 @@ package java.util.function; /** * An operation on two {@code double} operands yielding a {@code double} result. + * This is the primitive type specialization of {@link BinaryOperator} for + * {@code double}. * + * @see BinaryOperator * @since 1.8 */ @FunctionalInterface -public interface DoubleBinaryOperator /* extends BinaryOperator */ { -// -// @Override -// public default Double operate(Double left, Double right) { return operateAsDouble((double) left, (double) right); } - +public interface DoubleBinaryOperator { /** * Returns the {@code double} result of the operation upon the * {@code double} operands. The parameters are named {@code left} and * {@code right} for operations where the order of parameters matters. * * @param left the left operand value - * @param right the right operand value + * @param right the right operand value * @return the result of the operation */ - public double operateAsDouble(double left, double right); + public double applyAsDouble(double left, double right); } diff --git a/jdk/src/share/classes/java/util/function/DoubleBlock.java b/jdk/src/share/classes/java/util/function/DoubleConsumer.java similarity index 75% rename from jdk/src/share/classes/java/util/function/DoubleBlock.java rename to jdk/src/share/classes/java/util/function/DoubleConsumer.java index ae000841ae1..2ea35749737 100644 --- a/jdk/src/share/classes/java/util/function/DoubleBlock.java +++ b/jdk/src/share/classes/java/util/function/DoubleConsumer.java @@ -25,22 +25,21 @@ package java.util.function; /** - * An operation upon a {@code double} input value. The operation may modify - * external state. - * - *

This is the primitive type specialization of {@link Block} for - * {@code double} and also may be used as a {@code Block}. + * An operation which accepts a single double argument and returns no result. + * This is the primitive type specialization of {@link Consumer} for + * {@code double}. Unlike most other functional interfaces, + * {@code DoubleConsumer} is expected to operate via side-effects. * + * @see Consumer * @since 1.8 */ @FunctionalInterface -public interface DoubleBlock { +public interface DoubleConsumer { /** - * Use the {@code double} input value in an operation which may modify - * external state. + * Accept an input value. * - * @param t the input value + * @param value the input value */ - public void accept(double t); + public void accept(double value); } diff --git a/jdk/src/share/classes/java/util/function/DoubleFunction.java b/jdk/src/share/classes/java/util/function/DoubleFunction.java index d9c522c8e94..fcc6bb9dfde 100644 --- a/jdk/src/share/classes/java/util/function/DoubleFunction.java +++ b/jdk/src/share/classes/java/util/function/DoubleFunction.java @@ -25,22 +25,23 @@ package java.util.function; /** - * Apply a function to the input object yielding an appropriate {@code double} - * value; this is the {@code double}-bearing specialization for {@link Function}. + * Apply a function to the double-valued input argument, yielding an appropriate + * result. This is the {@code double}-consuming primitive specialization for + * {@link Function}. * - * @param the type of input objects to the function + * @param the type of output objects from the function * + * @see Function * @since 1.8 */ @FunctionalInterface -public interface DoubleFunction { +public interface DoubleFunction { /** - * Apply a function to the input object yielding an appropriate - * {@code double} value. + * Compute the result of applying the function to the input argument * - * @param t the input object - * @return the function result value + * @param value the input value + * @return the function result */ - public double applyAsDouble(T t); + public R apply(double value); } diff --git a/jdk/src/share/classes/java/util/function/DoublePredicate.java b/jdk/src/share/classes/java/util/function/DoublePredicate.java new file mode 100644 index 00000000000..e132f9b74d2 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/DoublePredicate.java @@ -0,0 +1,101 @@ +/* + * 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.util.function; + +import java.util.Objects; + +/** + * Determines if the {@code double} input value matches some criteria. This is + * the {@code double}-consuming primitive type specialization of + * {@link Predicate}. + * + * @see Predicate + * @since 1.8 + */ +@FunctionalInterface +public interface DoublePredicate { + + /** + * Returns {@code true} if the input value matches some criteria. + * + * @param value the value to be tested. + * @return {@code true} if the input value matches some criteria, otherwise + * {@code false}. + */ + public boolean test(double value); + + /** + * Returns a predicate which evaluates to {@code true} only if this + * predicate and the provided predicate both evaluate to {@code true}. If + * this predicate returns {@code false} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} only if both + * predicates return {@code true}. + */ + public default DoublePredicate and(DoublePredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) && p.test(value); + } + + /** + * Returns a predicate which negates the result of this predicate. + * + * @return a new predicate who's result is always the opposite of this + * predicate. + */ + public default DoublePredicate negate() { + return (value) -> !test(value); + } + + /** + * Returns a predicate which evaluates to {@code true} if either this + * predicate or the provided predicate evaluates to {@code true}. If this + * predicate returns {@code true} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} if either predicate + * returns {@code true}. + */ + public default DoublePredicate or(DoublePredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) || p.test(value); + } + + /** + * Returns a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + * + * @param p a predicate which will be logically-XORed with this predicate. + * @return a predicate that evaluates to {@code true} if all or none of the + * component predicates evaluate to {@code true}. + */ + public default DoublePredicate xor(DoublePredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) ^ p.test(value); + } +} diff --git a/jdk/src/share/classes/java/util/function/DoubleSupplier.java b/jdk/src/share/classes/java/util/function/DoubleSupplier.java index 19d75353045..9f9ab4e9f5a 100644 --- a/jdk/src/share/classes/java/util/function/DoubleSupplier.java +++ b/jdk/src/share/classes/java/util/function/DoubleSupplier.java @@ -25,11 +25,10 @@ package java.util.function; /** - * A supplier of {@code double} values. - * - *

This is the primitive type specialization of {@link Supplier} for - * {@code double} and also may be used as a {@code Supplier}. + * A supplier of {@code double} values. This is the {@code double}-providing + * primitive specialization of {@link Supplier}. * + * @see Supplier * @since 1.8 */ @FunctionalInterface diff --git a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java index 3843f8bc7ee..e9be79f5bb9 100644 --- a/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/DoubleUnaryOperator.java @@ -25,9 +25,11 @@ package java.util.function; /** - * An operation on a single {@code double} operand yielding a {@code double} - * result. + * An operation on a {@code double} operand yielding a {@code double} + * result. This is the primitive type specialization of {@link UnaryOperator} + * for {@code double}. * + * @see UnaryOperator * @since 1.8 */ @FunctionalInterface @@ -40,5 +42,5 @@ public interface DoubleUnaryOperator { * @param operand the operand value * @return the operation result value */ - public double operateAsDouble(double operand); + public double applyAsDouble(double operand); } diff --git a/jdk/src/share/classes/java/util/function/Function.java b/jdk/src/share/classes/java/util/function/Function.java index 82bae01701d..ff4b538c1a9 100644 --- a/jdk/src/share/classes/java/util/function/Function.java +++ b/jdk/src/share/classes/java/util/function/Function.java @@ -24,14 +24,14 @@ */ package java.util.function; + /** - * Apply a function to the input object yielding an appropriate result object. A + * Apply a function to the input argument, yielding an appropriate result. A * function may variously provide a mapping between types, object instances or * keys and values or any other form of transformation upon the input. * - * @param the type of input objects to the {@code apply} operation - * @param the type of result objects from the {@code apply} operation. May - * be the same type as {@code }. + * @param the type of the input to the {@code apply} operation. + * @param the type of the result of the {@code apply} operation. * * @since 1.8 */ @@ -39,7 +39,7 @@ package java.util.function; public interface Function { /** - * Yield an appropriate result object for the input object. + * Compute the result of applying the function to the input argument * * @param t the input object * @return the function result diff --git a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java index e25c2ba101f..f139118e3f1 100644 --- a/jdk/src/share/classes/java/util/function/IntBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/IntBinaryOperator.java @@ -26,7 +26,10 @@ package java.util.function; /** * An operation on two {@code int} operands yielding an {@code int} result. + * This is the primitive type specialization of {@link BinaryOperator} for + * {@code int}. * + * @see BinaryOperator * @since 1.8 */ @FunctionalInterface @@ -41,5 +44,5 @@ public interface IntBinaryOperator { * @param right the right operand value * @return the result of the operation */ - public int operateAsInt(int left, int right); + public int applyAsInt(int left, int right); } diff --git a/jdk/src/share/classes/java/util/function/IntBlock.java b/jdk/src/share/classes/java/util/function/IntConsumer.java similarity index 75% rename from jdk/src/share/classes/java/util/function/IntBlock.java rename to jdk/src/share/classes/java/util/function/IntConsumer.java index 33cdbe79f51..28a6ec46e2f 100644 --- a/jdk/src/share/classes/java/util/function/IntBlock.java +++ b/jdk/src/share/classes/java/util/function/IntConsumer.java @@ -25,22 +25,21 @@ package java.util.function; /** - * An operation upon an {@code int} input value. The operation may modify - * external state. - * - *

This is the primitive type specialization of {@link Block} for - * {@code int} and also may be used as a {@code Block}. + * An operation which accepts a single integer argument and returns no result. + * This is the primitive type specialization of {@link Consumer} for {@code int}. + * Unlike most other functional interfaces, {@code IntConsumer} is expected to + * operate via side-effects. * + * @see Consumer * @since 1.8 */ @FunctionalInterface -public interface IntBlock { +public interface IntConsumer { /** - * Use the {@code int} input value in an operation which may modify external - * state. + * Accept an input value. * - * @param t the input value + * @param value the input value */ - public void accept(int t); + public void accept(int value); } diff --git a/jdk/src/share/classes/java/util/function/IntFunction.java b/jdk/src/share/classes/java/util/function/IntFunction.java index 6e1418533fe..b5faecc0ea7 100644 --- a/jdk/src/share/classes/java/util/function/IntFunction.java +++ b/jdk/src/share/classes/java/util/function/IntFunction.java @@ -25,22 +25,23 @@ package java.util.function; /** - * Apply a function to the input object yielding an appropriate {@code int} - * value; this is the {@code int}-bearing specialization for {@link Function}. + * Apply a function to the integer-valued input argument, yielding an + * appropriate result. This is the {@code int}-consuming primitive + * specialization for {@link Function}. * - * @param the type of input objects to the function + * @param the type of output objects from the function * + * @see Function * @since 1.8 */ @FunctionalInterface -public interface IntFunction { +public interface IntFunction { /** - * Apply a function to the input object yielding an appropriate {@code int} - * value. + * Compute the result of applying the function to the input argument * - * @param t the input object - * @return the function result value + * @param value the input value + * @return the function result */ - public int applyAsInt(T t); + public R apply(int value); } diff --git a/jdk/src/share/classes/java/util/function/IntPredicate.java b/jdk/src/share/classes/java/util/function/IntPredicate.java new file mode 100644 index 00000000000..17cc49c754e --- /dev/null +++ b/jdk/src/share/classes/java/util/function/IntPredicate.java @@ -0,0 +1,100 @@ +/* + * 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.util.function; + +import java.util.Objects; + +/** + * Determines if the {@code int} input value matches some criteria. This is the + * {@code int}-consuming primitive type specialization of {@link Predicate}. + * + * @see Predicate + * @since 1.8 + */ +@FunctionalInterface +public interface IntPredicate { + + /** + * Returns {@code true} if the input value matches some criteria. + * + * @param value the value to be tested. + * @return {@code true} if the input value matches some criteria, otherwise + * {@code false} + */ + public boolean test(int value); + + /** + * Returns a predicate which evaluates to {@code true} only if this + * predicate and the provided predicate both evaluate to {@code true}. If + * this predicate returns {@code false} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} only if both + * predicates return {@code true}. + */ + public default IntPredicate and(IntPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) && p.test(value); + } + + /** + * Returns a predicate which negates the result of this predicate. + * + * @return a new predicate who's result is always the opposite of this + * predicate. + */ + public default IntPredicate negate() { + return (value) -> !test(value); + } + + /** + * Returns a predicate which evaluates to {@code true} if either this + * predicate or the provided predicate evaluates to {@code true}. If this + * predicate returns {@code true} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ORed with this predicate. + * @return a new predicate which returns {@code true} if either predicate + * returns {@code true}. + */ + public default IntPredicate or(IntPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) || p.test(value); + } + + /** + * Returns a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + * + * @param p a predicate which will be logically-XORed with this predicate. + * @return a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true} + */ + public default IntPredicate xor(IntPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) ^ p.test(value); + } +} diff --git a/jdk/src/share/classes/java/util/function/IntSupplier.java b/jdk/src/share/classes/java/util/function/IntSupplier.java index c73fc84e3be..d857b7882b4 100644 --- a/jdk/src/share/classes/java/util/function/IntSupplier.java +++ b/jdk/src/share/classes/java/util/function/IntSupplier.java @@ -25,11 +25,10 @@ package java.util.function; /** - * A supplier of {@code int} values. - * - *

This is the primitive type specialization of {@link Supplier} for - * {@code int} and also may be used as a {@code Supplier}. + * A supplier of {@code int} values. This is the {@code int}-providing + * primitive specialization of {@link Supplier}. * + * @see Supplier * @since 1.8 */ @FunctionalInterface diff --git a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java index 2c429951c28..a3b868dff54 100644 --- a/jdk/src/share/classes/java/util/function/IntUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/IntUnaryOperator.java @@ -26,18 +26,21 @@ package java.util.function; /** * An operation on a single {@code int} operand yielding an {@code int} result. + * This is the primitive type specialization of {@link UnaryOperator} for + * {@code int}. * + * @see UnaryOperator * @since 1.8 */ @FunctionalInterface public interface IntUnaryOperator { /** - * Returns the {@code int} result of the operation upon the {@code int} - * operand. + * Returns the {@code int} value result of the operation upon the + * {@code int} operand. * * @param operand the operand value * @return the operation result value */ - public int operateAsInt(int operand); + public int applyAsInt(int operand); } diff --git a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java index f767c92a355..d08271d30b1 100644 --- a/jdk/src/share/classes/java/util/function/LongBinaryOperator.java +++ b/jdk/src/share/classes/java/util/function/LongBinaryOperator.java @@ -26,7 +26,10 @@ package java.util.function; /** * An operation on two {@code long} operands yielding a {@code long} result. + * This is the primitive type specialization of {@link BinaryOperator} for + * {@code long}. * + * @see BinaryOperator * @since 1.8 */ @FunctionalInterface @@ -41,5 +44,5 @@ public interface LongBinaryOperator { * @param right the right operand value * @return the result of the operation */ - public long operateAsLong(long left, long right); + public long applyAsLong(long left, long right); } diff --git a/jdk/src/share/classes/java/util/function/LongBlock.java b/jdk/src/share/classes/java/util/function/LongConsumer.java similarity index 75% rename from jdk/src/share/classes/java/util/function/LongBlock.java rename to jdk/src/share/classes/java/util/function/LongConsumer.java index 71606ecf9ed..072c0972a60 100644 --- a/jdk/src/share/classes/java/util/function/LongBlock.java +++ b/jdk/src/share/classes/java/util/function/LongConsumer.java @@ -25,22 +25,21 @@ package java.util.function; /** - * An operation upon a {@code long} input value. The operation may modify - * external state. - * - *

This is the primitive type specialization of {@link Block} for - * {@code long} and also may be used as a {@code Block}. + * An operation which accepts a single long argument and returns no result. + * This is the {@code long}-consuming primitive type specialization of + * {@link Consumer}. Unlike most other functional interfaces, {@code LongConsumer} + * is expected to operate via side-effects. * + * @see Consumer * @since 1.8 */ @FunctionalInterface -public interface LongBlock { +public interface LongConsumer { /** - * Use the {@code long} input value in an operation which may modify - * external state. + * Accept an input value. * - * @param t the input value + * @param value the input value */ - public void accept(long t); + public void accept(long value); } diff --git a/jdk/src/share/classes/java/util/function/LongFunction.java b/jdk/src/share/classes/java/util/function/LongFunction.java index 61c4fbf6475..924eb43be17 100644 --- a/jdk/src/share/classes/java/util/function/LongFunction.java +++ b/jdk/src/share/classes/java/util/function/LongFunction.java @@ -25,22 +25,23 @@ package java.util.function; /** - * Apply a function to the input object yielding an appropriate {@code long} - * value; this is the {@code long}-bearing specialization for {@link Function}. + * Apply a function to the long-valued input argument, yielding an appropriate + * result. This is the {@code long}-consuming primitive specialization for + * {@link Function}. * - * @param the type of input objects to the function + * @param the type of output objects from the function * + * @see Function * @since 1.8 */ @FunctionalInterface -public interface LongFunction { +public interface LongFunction { /** - * Apply a function to the input object yielding an appropriate {@code long} - * value. + * Compute the result of applying the function to the input argument * - * @param t the input object - * @return the function result value + * @param value the input value + * @return the function result */ - public long applyAsLong(T t); + public R apply(long value); } diff --git a/jdk/src/share/classes/java/util/function/LongPredicate.java b/jdk/src/share/classes/java/util/function/LongPredicate.java new file mode 100644 index 00000000000..ca542a41246 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/LongPredicate.java @@ -0,0 +1,100 @@ +/* + * 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.util.function; + +import java.util.Objects; + +/** + * Determines if the {@code long} input value matches some criteria. This is the + * {@code long}-consuming primitive type specialization of {@link Predicate}. + * + * @see Predicate + * @since 1.8 + */ +@FunctionalInterface +public interface LongPredicate { + + /** + * Returns {@code true} if the input value matches some criteria. + * + * @param value the value to be tested. + * @return {@code true} if the input value matches some criteria, otherwise + * {@code false}. + */ + public boolean test(long value); + + /** + * Returns a predicate which evaluates to {@code true} only if this + * predicate and the provided predicate both evaluate to {@code true}. If + * this predicate returns {@code false} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} only if both + * predicates return {@code true}. + */ + public default LongPredicate and(LongPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) && p.test(value); + } + + /** + * Returns a predicate which negates the result of this predicate. + * + * @return a new predicate who's result is always the opposite of this + * predicate. + */ + public default LongPredicate negate() { + return (value) -> !test(value); + } + + /** + * Returns a predicate which evaluates to {@code true} if either this + * predicate or the provided predicate evaluates to {@code true}. If this + * predicate returns {@code true} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ORed with this predicate. + * @return a new predicate which returns {@code true} if either predicate + * returns {@code true}. + */ + public default LongPredicate or(LongPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) || p.test(value); + } + + /** + * Returns a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + * + * @param p a predicate which will be logically-XORed with this predicate. + * @return a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + */ + public default LongPredicate xor(LongPredicate p) { + Objects.requireNonNull(p); + return (value) -> test(value) ^ p.test(value); + } +} diff --git a/jdk/src/share/classes/java/util/function/LongSupplier.java b/jdk/src/share/classes/java/util/function/LongSupplier.java index f56ad7df282..2d5a3def105 100644 --- a/jdk/src/share/classes/java/util/function/LongSupplier.java +++ b/jdk/src/share/classes/java/util/function/LongSupplier.java @@ -25,11 +25,10 @@ package java.util.function; /** - * A supplier of {@code long} values. - * - *

This is the primitive type specialization of {@link Supplier} for - * {@code long} and also may be used as a {@code Supplier}. + * A supplier of {@code long} values. This is the {@code long}-providing + * primitive specialization of {@link Supplier}. * + * @see Supplier * @since 1.8 */ @FunctionalInterface @@ -38,7 +37,7 @@ public interface LongSupplier { /** * Returns a {@code long} value. * - * @return a {@code long} value. + * @return a {@code long} value */ public long getAsLong(); } diff --git a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java index f27ddf5a81a..3632e2a118a 100644 --- a/jdk/src/share/classes/java/util/function/LongUnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/LongUnaryOperator.java @@ -26,7 +26,10 @@ package java.util.function; /** * An operation on a single {@code long} operand yielding a {@code long} result. + * This is the primitive type specialization of {@link UnaryOperator} for + * {@code long}. * + * @see UnaryOperator * @since 1.8 */ @FunctionalInterface @@ -39,5 +42,5 @@ public interface LongUnaryOperator { * @param operand the operand value * @return the operation result value */ - public long operateAsLong(long operand); + public long applyAsLong(long operand); } diff --git a/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java new file mode 100644 index 00000000000..24e4c29327c --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ObjDoubleConsumer.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.function; + +/** + * An operation which accepts an object reference and a double, and returns no + * result. This is the {@code (reference, double)} specialization of + * {@link BiConsumer}. Unlike most other functional interfaces, + * {@code ObjDoubleConsumer} is expected to operate via side-effects. + * + * @param Type of reference argument to {@code accept()}. + * + * @see BiConsumer + * @since 1.8 + */ +@FunctionalInterface +public interface ObjDoubleConsumer { + + /** + * Accept a set of input values. + * + * @param t an input object + * @param value an input value + */ + public void accept(T t, double value); +} diff --git a/jdk/src/share/classes/java/util/function/ObjIntConsumer.java b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java new file mode 100644 index 00000000000..fa63af5cff6 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ObjIntConsumer.java @@ -0,0 +1,48 @@ +/* + * 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.util.function; + +/** + * An operation which accepts an object reference and an int, and returns no + * result. This is the {@code (reference, int)} specialization of + * {@link BiConsumer}. Unlike most other functional interfaces, + * {@code ObjIntConsumer} is expected to operate via side-effects. + * + * @param Type of reference argument to {@code accept()}. + * + * @see BiConsumer + * @since 1.8 + */ +@FunctionalInterface +public interface ObjIntConsumer { + + /** + * Accept a set of input values. + * + * @param t an input object + * @param value an input value + */ + public void accept(T t, int value); +} diff --git a/jdk/src/share/classes/java/util/function/ObjLongConsumer.java b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java new file mode 100644 index 00000000000..c2f19fba741 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ObjLongConsumer.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.function; + +/** + * An operation which accepts an object reference and a long, and returns no + * result. This is the {@code (reference, long)} specialization of + * {@link BiConsumer}. Unlike most other functional interfaces, + * {@code ObjLongConsumer} is expected to operate via side-effects. + * + * @param Type of reference argument to {@code accept()}. + * + * @see BiConsumer + * @since 1.8 + */ +@FunctionalInterface +public interface ObjLongConsumer { + + /** + * Accept a set of input values. + * + * @param t an input object + * @param value an input value + */ + public void accept(T t, long value); +} diff --git a/jdk/src/share/classes/java/util/function/Predicate.java b/jdk/src/share/classes/java/util/function/Predicate.java index 9b440787485..627771e26af 100644 --- a/jdk/src/share/classes/java/util/function/Predicate.java +++ b/jdk/src/share/classes/java/util/function/Predicate.java @@ -24,10 +24,12 @@ */ package java.util.function; +import java.util.Objects; + /** * Determines if the input object matches some criteria. * - * @param the type of input objects to {@code test} + * @param the type of argument to {@code test} * * @since 1.8 */ @@ -42,4 +44,57 @@ public interface Predicate { * {@code false} */ public boolean test(T t); + + /** + * Returns a predicate which evaluates to {@code true} only if this + * predicate and the provided predicate both evaluate to {@code true}. If + * this predicate returns {@code false} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ANDed with this predicate. + * @return a new predicate which returns {@code true} only if both + * predicates return {@code true}. + */ + public default Predicate and(Predicate p) { + Objects.requireNonNull(p); + return (t) -> test(t) && p.test(t); + } + + /** + * Returns a predicate which negates the result of this predicate. + * + * @return a new predicate who's result is always the opposite of this + * predicate. + */ + public default Predicate negate() { + return (t) -> !test(t); + } + + /** + * Returns a predicate which evaluates to {@code true} if either this + * predicate or the provided predicate evaluates to {@code true}. If this + * predicate returns {@code true} then the remaining predicate is not + * evaluated. + * + * @param p a predicate which will be logically-ORed with this predicate. + * @return a new predicate which returns {@code true} if either predicate + * returns {@code true}. + */ + public default Predicate or(Predicate p) { + Objects.requireNonNull(p); + return (t) -> test(t) || p.test(t); + } + + /** + * Returns a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + * + * @param p a predicate which will be logically-XORed with this predicte. + * @return a predicate that evaluates to {@code true} if both or neither of + * the component predicates evaluate to {@code true}. + */ + public default Predicate xor(Predicate p) { + Objects.requireNonNull(p); + return (t) -> test(t) ^ p.test(t); + } } diff --git a/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java new file mode 100644 index 00000000000..8826e12dad7 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToDoubleBiFunction.java @@ -0,0 +1,50 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input arguments, yielding an appropriate result. + * This is the {@code double}-bearing specialization for {@link BiFunction}. + * + * @param the type of the first argument to the {@code applyAsDouble} + * operation. + * @param the type of the second argument to the {@code applyAsDouble} + * operation. + * + * @see BiFunction + * @since 1.8 + */ +@FunctionalInterface +public interface ToDoubleBiFunction { + + /** + * Compute the result of applying the function to the input arguments + * + * @param t an input object + * @param u an input object + * @return the function result value + */ + public double applyAsDouble(T t, U u); +} diff --git a/jdk/src/share/classes/java/util/function/ToDoubleFunction.java b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java new file mode 100644 index 00000000000..87f19fce41e --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToDoubleFunction.java @@ -0,0 +1,46 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input argument, yielding an appropriate result. + * This is the {@code double}-bearing specialization for {@link Function}. + * + * @param the type of input objects to the function + * + * @see Function + * @since 1.8 + */ +@FunctionalInterface +public interface ToDoubleFunction { + + /** + * Compute the result of applying the function to the input argument + * + * @param t the input object + * @return the function result value + */ + public double applyAsDouble(T t); +} diff --git a/jdk/src/share/classes/java/util/function/ToIntBiFunction.java b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java new file mode 100644 index 00000000000..d7c727fa31c --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToIntBiFunction.java @@ -0,0 +1,50 @@ +/* + * 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.function; + +/** + * Apply a function to the input arguments, yielding an appropriate result. + * This is the {@code int}-bearing specialization for {@link BiFunction}. + * + * @param the type of the first argument to the {@code applyAsLong} + * operation. + * @param the type of the second argument to the {@code applyAsLong} + * operation. + * + * @see BiFunction + * @since 1.8 + */ +@FunctionalInterface +public interface ToIntBiFunction { + + /** + * Compute the result of applying the function to the input arguments + * + * @param t an input object + * @param u an input object + * @return the function result value + */ + public int applyAsInt(T t, U u); +} diff --git a/jdk/src/share/classes/java/util/function/ToIntFunction.java b/jdk/src/share/classes/java/util/function/ToIntFunction.java new file mode 100644 index 00000000000..848a7b4486c --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToIntFunction.java @@ -0,0 +1,46 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input argument, yielding an appropriate result. + * This is the {@code int}-bearing specialization for {@link Function}. + * + * @param the type of input objects to the function + * + * @see Function + * @since 1.8 + */ +@FunctionalInterface +public interface ToIntFunction { + + /** + * Compute the result of applying the function to the input arguments + * + * @param t the input object + * @return the function result value + */ + public int applyAsInt(T t); +} diff --git a/jdk/src/share/classes/java/util/function/ToLongBiFunction.java b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java new file mode 100644 index 00000000000..994fa49a536 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToLongBiFunction.java @@ -0,0 +1,50 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input arguments, yielding an appropriate result. + * This is the {@code long}-bearing specialization for {@link BiFunction}. + * + * @param the type of the first argument to the {@code applyAsLong} + * operation. + * @param the type of the second argument to the {@code applyAsLong} + * operation. + * + * @see BiFunction + * @since 1.8 + */ +@FunctionalInterface +public interface ToLongBiFunction { + + /** + * Compute the result of applying the function to the input arguments. + * + * @param t an input object + * @param u an input object + * @return the function result value + */ + public long applyAsLong(T t, U u); +} diff --git a/jdk/src/share/classes/java/util/function/ToLongFunction.java b/jdk/src/share/classes/java/util/function/ToLongFunction.java new file mode 100644 index 00000000000..6d5877b6814 --- /dev/null +++ b/jdk/src/share/classes/java/util/function/ToLongFunction.java @@ -0,0 +1,46 @@ +/* + * 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.util.function; + +/** + * Apply a function to the input argument, yielding an appropriate result. + * This is the {@code long}-bearing specialization for {@link Function}. + * + * @param the type of input objects to the function + * + * @see Function + * @since 1.8 + */ +@FunctionalInterface +public interface ToLongFunction { + + /** + * Compute the result of applying the function to the input arguments. + * + * @param t the input object + * @return the function result value + */ + public long applyAsLong(T t); +} diff --git a/jdk/src/share/classes/java/util/function/UnaryOperator.java b/jdk/src/share/classes/java/util/function/UnaryOperator.java index a8aaa0dcd6b..8e92291887e 100644 --- a/jdk/src/share/classes/java/util/function/UnaryOperator.java +++ b/jdk/src/share/classes/java/util/function/UnaryOperator.java @@ -26,20 +26,14 @@ package java.util.function; /** * An operation upon a single operand yielding a result. The operand and the - * result are of the same type. + * result are of the same type. This is a specialization of {@code Function} for + * the case where the operand and result are of the same type. * - * @param the type of operand to {@code operate} and of the result + * @param the type of operand to {@code apply} and of the result * + * @see Function * @since 1.8 */ @FunctionalInterface -public interface UnaryOperator { - - /** - * Returns the result of the operation upon the operand. - * - * @param operand the operand - * @return the operation result - */ - public T operate(T operand); +public interface UnaryOperator extends Function { } diff --git a/jdk/src/share/classes/java/util/function/package-info.java b/jdk/src/share/classes/java/util/function/package-info.java index 0d1eecf5139..36eda330d19 100644 --- a/jdk/src/share/classes/java/util/function/package-info.java +++ b/jdk/src/share/classes/java/util/function/package-info.java @@ -22,27 +22,62 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + /** - * Functional interfaces provide typing for lambda expressions. Each - * functional interface provides a single abstract method to which the lambda - * expression's parameter and return types are matched. + * Functional interfaces provide target types for lambda expressions + * and method references. Each functional interface has a single abstract method + * to which the lambda expression's parameter and return types are matched or + * adapted. Functional interfaces can provide a target type in multiple contexts, + * such as assignment context, method invocation, or cast context: * - *

The interfaces in this package are all functional interfaces used with the - * collections and streams frameworks. The operation identified by each - * interface is generally applied to a collection or stream of objects. + *

+ *     Predicate<String> p = String::isEmpty;
+ *
+ *     stream.filter(e -> e.getSize() > 10)...
+ *
+ *     stream.map((ToIntFunction) e -> e.getSize())...
+ * 
+ * + *

The interfaces in this package are functional interfaces used by the JDK, + * and are available to be used by user code as well. While they do not identify + * a complete set of function shapes to which lambda expressions might be adapted, + * they provide enough to cover common requirements. + * + *

The interfaces in this package are annotated with @{link FunctionalInterface}. + * This annotation is not a requirement for the compiler to recognize an interface + * as a functional interface, but merely an aid to capture design intent and enlist the + * help of the compiler in identifying accidental violations of design intent. + * + *

The functional interfaces in this package follow an extensible naming convention, + * as follows: * - *

All functional interface implementations are expected to ensure that: *

    - *
  • When used for aggregate operations upon many elements it should not be - * assumed that the operation will be called upon elements in any specific order. - *
  • - *
  • {@code null} values are accepted and returned by these functional - * interfaces according to the constraints of the specification in which the - * functional interfaces are used. The functional interfaces themselves do not - * constrain or mandate use of {@code null} values. Most usages of the - * functional interfaces will define the role, if any, of {@code null} for that - * context. - *
  • + *
  • There are several basic function shapes, including {@link java.util.function.Function} ({@code T -> R}), + * {@link java.util.function.Consumer} ({@code T -> void}), + * {@link java.util.function.Predicate} ({@code T -> boolean}), + * and {@link java.util.function.Supplier} ({@code () -> T}). + *
  • + *
  • Function shapes have a natural arity based on how they are most commonly used. + * The basic shapes can be modified by an arity prefix to indicate a different arity, + * such as {@link java.util.function.BiFunction} ({@code (T, U) -> R}). + *
  • + *
  • There are additional derived function shapes which extend the basic function + * shapes, including {@link java.util.function.UnaryOperator} (extends {@code Function}) and + * {@link java.util.function.BinaryOperator} (extends {@code BiFunction}). + *
  • + *
  • Type parameters of functional interfaces can be specialized to primitives with + * additional type prefixes. To specialize the return type for a type that has both + * generic return type and generic arguments, we prefix {@code ToXxx}, as in + * {@link java.util.function.ToIntFunction}. Otherwise, type arguments are specialized left-to-right, + * as in {@link java.util.function.DoubleConsumer} or {@link java.util.function.ObjIntConsumer}. + * (The type prefix {@code Obj} is used to indicate that we don't want to specialize this parameter, + * but want to move on to the next parameter.) These schemes can be combined as in {@code IntToDoubleFunction}. + *
  • + *
  • If there are specialization prefixes for all arguments, the arity prefix may be left + * out (as in {@link java.util.function.ObjIntConsumer}). + *
  • *
+ * + * @see java.lang.FunctionalInterface */ package java.util.function; diff --git a/jdk/src/share/classes/java/util/jar/JarFile.java b/jdk/src/share/classes/java/util/jar/JarFile.java index 513d509e2f8..84c03753cfe 100644 --- a/jdk/src/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/share/classes/java/util/jar/JarFile.java @@ -34,6 +34,7 @@ import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; +import sun.misc.IOUtils; import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.misc.SharedSecrets; @@ -63,8 +64,13 @@ class JarFile extends ZipFile { private JarVerifier jv; private boolean jvInitialized; private boolean verify; - private boolean computedHasClassPathAttribute; + + // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true) private boolean hasClassPathAttribute; + // indicates if Profile attribute present (only valid if hasCheckedSpecialAttributes true) + private boolean hasProfileAttribute; + // true if manifest checked for special attributes + private volatile boolean hasCheckedSpecialAttributes; // Set up JavaUtilJarAccess in SharedSecrets static { @@ -329,6 +335,9 @@ class JarFile extends ZipFile { if (names != null) { for (int i = 0; i < names.length; i++) { JarEntry e = getJarEntry(names[i]); + if (e == null) { + throw new JarException("corrupted jar file"); + } if (!e.isDirectory()) { if (mev == null) { mev = new ManifestEntryVerifier @@ -348,6 +357,10 @@ class JarFile extends ZipFile { // treat the jar file as being unsigned jv = null; verify = false; + if (JarVerifier.debug != null) { + JarVerifier.debug.println("jarfile parsing error!"); + ex.printStackTrace(); + } } // if after initializing the verifier we have nothing @@ -375,11 +388,9 @@ class JarFile extends ZipFile { * META-INF files. */ private byte[] getBytes(ZipEntry ze) throws IOException { - byte[] b = new byte[(int)ze.getSize()]; - try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) { - is.readFully(b, 0, b.length); + try (InputStream is = super.getInputStream(ze)) { + return IOUtils.readFully(is, (int)ze.getSize(), true); } - return b; } /** @@ -421,27 +432,45 @@ class JarFile extends ZipFile { jv); } - // Statics for hand-coded Boyer-Moore search in hasClassPathAttribute() + // Statics for hand-coded Boyer-Moore search + private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'}; + private static final char[] PROFILE_CHARS = { 'p', 'r', 'o', 'f', 'i', 'l', 'e' }; // The bad character shift for "class-path" - private static int[] lastOcc; + private static final int[] CLASSPATH_LASTOCC; // The good suffix shift for "class-path" - private static int[] optoSft; - // Initialize the shift arrays to search for "class-path" - private static char[] src = {'c','l','a','s','s','-','p','a','t','h'}; + private static final int[] CLASSPATH_OPTOSFT; + // The bad character shift for "profile" + private static final int[] PROFILE_LASTOCC; + // The good suffix shift for "profile" + private static final int[] PROFILE_OPTOSFT; + static { - lastOcc = new int[128]; - optoSft = new int[10]; - lastOcc[(int)'c']=1; - lastOcc[(int)'l']=2; - lastOcc[(int)'s']=5; - lastOcc[(int)'-']=6; - lastOcc[(int)'p']=7; - lastOcc[(int)'a']=8; - lastOcc[(int)'t']=9; - lastOcc[(int)'h']=10; + CLASSPATH_LASTOCC = new int[128]; + CLASSPATH_OPTOSFT = new int[10]; + CLASSPATH_LASTOCC[(int)'c'] = 1; + CLASSPATH_LASTOCC[(int)'l'] = 2; + CLASSPATH_LASTOCC[(int)'s'] = 5; + CLASSPATH_LASTOCC[(int)'-'] = 6; + CLASSPATH_LASTOCC[(int)'p'] = 7; + CLASSPATH_LASTOCC[(int)'a'] = 8; + CLASSPATH_LASTOCC[(int)'t'] = 9; + CLASSPATH_LASTOCC[(int)'h'] = 10; for (int i=0; i<9; i++) - optoSft[i]=10; - optoSft[9]=1; + CLASSPATH_OPTOSFT[i] = 10; + CLASSPATH_OPTOSFT[9]=1; + + PROFILE_LASTOCC = new int[128]; + PROFILE_OPTOSFT = new int[7]; + PROFILE_LASTOCC[(int)'p'] = 1; + PROFILE_LASTOCC[(int)'r'] = 2; + PROFILE_LASTOCC[(int)'o'] = 3; + PROFILE_LASTOCC[(int)'f'] = 4; + PROFILE_LASTOCC[(int)'i'] = 5; + PROFILE_LASTOCC[(int)'l'] = 6; + PROFILE_LASTOCC[(int)'e'] = 7; + for (int i=0; i<6; i++) + PROFILE_OPTOSFT[i] = 7; + PROFILE_OPTOSFT[6] = 1; } private JarEntry getManEntry() { @@ -466,49 +495,70 @@ class JarFile extends ZipFile { return manEntry; } - // Returns true iff this jar file has a manifest with a class path - // attribute. Returns false if there is no manifest or the manifest - // does not contain a "Class-Path" attribute. Currently exported to - // core libraries via sun.misc.SharedSecrets. + /** + * Returns {@code true} iff this JAR file has a manifest with the + * Class-Path attribute + */ boolean hasClassPathAttribute() throws IOException { - if (computedHasClassPathAttribute) { - return hasClassPathAttribute; - } - - hasClassPathAttribute = false; - if (!isKnownToNotHaveClassPathAttribute()) { - JarEntry manEntry = getManEntry(); - if (manEntry != null) { - byte[] b = new byte[(int)manEntry.getSize()]; - try (DataInputStream dis = new DataInputStream( - super.getInputStream(manEntry))) { - dis.readFully(b, 0, b.length); - } - - int last = b.length - src.length; - int i = 0; - next: - while (i<=last) { - for (int j=9; j>=0; j--) { - char c = (char) b[i+j]; - c = (((c-'A')|('Z'-c)) >= 0) ? (char)(c + 32) : c; - if (c != src[j]) { - i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]); - continue next; - } - } - hasClassPathAttribute = true; - break; - } - } - } - computedHasClassPathAttribute = true; + checkForSpecialAttributes(); return hasClassPathAttribute; } + /** + * Returns {@code true} iff this JAR file has a manifest with the + * Profile attribute + */ + boolean hasProfileAttribute() throws IOException { + checkForSpecialAttributes(); + return hasProfileAttribute; + } + + /** + * Returns true if the pattern {@code src} is found in {@code b}. + * The {@code lastOcc} and {@code optoSft} arrays are the precomputed + * bad character and good suffix shifts. + */ + private boolean match(char[] src, byte[] b, int[] lastOcc, int[] optoSft) { + int len = src.length; + int last = b.length - len; + int i = 0; + next: + while (i<=last) { + for (int j=(len-1); j>=0; j--) { + char c = (char) b[i+j]; + c = (((c-'A')|('Z'-c)) >= 0) ? (char)(c + 32) : c; + if (c != src[j]) { + i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]); + continue next; + } + } + return true; + } + return false; + } + + /** + * On first invocation, check if the JAR file has the Class-Path + * and/or Profile attributes. A no-op on subsequent calls. + */ + private void checkForSpecialAttributes() throws IOException { + if (hasCheckedSpecialAttributes) return; + if (!isKnownNotToHaveSpecialAttributes()) { + JarEntry manEntry = getManEntry(); + if (manEntry != null) { + byte[] b = getBytes(manEntry); + if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT)) + hasClassPathAttribute = true; + if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT)) + hasProfileAttribute = true; + } + } + hasCheckedSpecialAttributes = true; + } + private static String javaHome; - private static String[] jarNames; - private boolean isKnownToNotHaveClassPathAttribute() { + private static volatile String[] jarNames; + private boolean isKnownNotToHaveSpecialAttributes() { // Optimize away even scanning of manifest for jar files we // deliver which don't have a class-path attribute. If one of // these jars is changed to include such an attribute this code @@ -518,19 +568,20 @@ class JarFile extends ZipFile { new GetPropertyAction("java.home")); } if (jarNames == null) { - String[] names = new String[10]; + String[] names = new String[11]; String fileSep = File.separator; int i = 0; names[i++] = fileSep + "rt.jar"; - names[i++] = fileSep + "sunrsasign.jar"; names[i++] = fileSep + "jsse.jar"; names[i++] = fileSep + "jce.jar"; names[i++] = fileSep + "charsets.jar"; names[i++] = fileSep + "dnsns.jar"; - names[i++] = fileSep + "ldapsec.jar"; + names[i++] = fileSep + "zipfs.jar"; names[i++] = fileSep + "localedata.jar"; + names[i++] = fileSep = "cldrdata.jar"; names[i++] = fileSep + "sunjce_provider.jar"; names[i++] = fileSep + "sunpkcs11.jar"; + names[i++] = fileSep + "sunec.jar"; jarNames = names; } diff --git a/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java b/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java index 9541a5a45f3..86a7ec5d2c6 100644 --- a/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java +++ b/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java @@ -37,6 +37,10 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess { return jar.hasClassPathAttribute(); } + public boolean jarFileHasProfileAttribute(JarFile jar) throws IOException { + return jar.hasProfileAttribute(); + } + public CodeSource[] getCodeSources(JarFile jar, URL url) { return jar.getCodeSources(url); } diff --git a/jdk/src/share/classes/java/util/logging/Level.java b/jdk/src/share/classes/java/util/logging/Level.java index 286ed5e6008..6847518ce02 100644 --- a/jdk/src/share/classes/java/util/logging/Level.java +++ b/jdk/src/share/classes/java/util/logging/Level.java @@ -24,6 +24,10 @@ */ package java.util.logging; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.ResourceBundle; /** @@ -59,7 +63,6 @@ import java.util.ResourceBundle; */ public class Level implements java.io.Serializable { - private static java.util.ArrayList known = new java.util.ArrayList<>(); private static String defaultBundle = "sun.util.logging.resources.logging"; /** @@ -77,6 +80,9 @@ public class Level implements java.io.Serializable { */ private final String resourceBundleName; + // localized level name + private String localizedLevelName; + /** * OFF is a special level that can be used to turn off logging. * This level is initialized to Integer.MAX_VALUE. @@ -202,9 +208,8 @@ public class Level implements java.io.Serializable { this.name = name; this.value = value; this.resourceBundleName = resourceBundleName; - synchronized (Level.class) { - known.add(this); - } + this.localizedLevelName = resourceBundleName == null ? name : null; + KnownLevel.add(this); } /** @@ -236,12 +241,76 @@ public class Level implements java.io.Serializable { * @return localized name */ public String getLocalizedName() { + return getLocalizedLevelName(); + } + + // package-private getLevelName() is used by the implementation + // instead of getName() to avoid calling the subclass's version + final String getLevelName() { + return this.name; + } + + final synchronized String getLocalizedLevelName() { + if (localizedLevelName != null) { + return localizedLevelName; + } + try { ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); - return rb.getString(name); + localizedLevelName = rb.getString(name); } catch (Exception ex) { - return name; + localizedLevelName = name; } + return localizedLevelName; + } + + // Returns a mirrored Level object that matches the given name as + // specified in the Level.parse method. Returns null if not found. + // + // It returns the same Level object as the one returned by Level.parse + // method if the given name is a non-localized name or integer. + // + // If the name is a localized name, findLevel and parse method may + // return a different level value if there is a custom Level subclass + // that overrides Level.getLocalizedName() to return a different string + // than what's returned by the default implementation. + // + static Level findLevel(String name) { + if (name == null) { + throw new NullPointerException(); + } + + KnownLevel level; + + // Look for a known Level with the given non-localized name. + level = KnownLevel.findByName(name); + if (level != null) { + return level.mirroredLevel; + } + + // Now, check if the given name is an integer. If so, + // first look for a Level with the given value and then + // if necessary create one. + try { + int x = Integer.parseInt(name); + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); + } + return level.mirroredLevel; + } catch (NumberFormatException ex) { + // Not an integer. + // Drop through. + } + + level = KnownLevel.findByLocalizedLevelName(name); + if (level != null) { + return level.mirroredLevel; + } + + return null; } /** @@ -268,21 +337,15 @@ public class Level implements java.io.Serializable { // Serialization magic to prevent "doppelgangers". // This is a performance optimization. private Object readResolve() { - synchronized (Level.class) { - for (int i = 0; i < known.size(); i++) { - Level other = known.get(i); - if (this.name.equals(other.name) && this.value == other.value - && (this.resourceBundleName == other.resourceBundleName || - (this.resourceBundleName != null && - this.resourceBundleName.equals(other.resourceBundleName)))) { - return other; - } - } - // Woops. Whoever sent us this object knows - // about a new log level. Add it to our list. - known.add(this); - return this; + KnownLevel o = KnownLevel.matches(this); + if (o != null) { + return o.levelObject; } + + // Woops. Whoever sent us this object knows + // about a new log level. Add it to our list. + Level level = new Level(this.name, this.value, this.resourceBundleName); + return level; } /** @@ -296,6 +359,7 @@ public class Level implements java.io.Serializable { *
  • "SEVERE" *
  • "1000" * + * * @param name string to be parsed * @throws NullPointerException if the name is null * @throws IllegalArgumentException if the value is not valid. @@ -315,12 +379,12 @@ public class Level implements java.io.Serializable { // Check that name is not null. name.length(); + KnownLevel level; + // Look for a known Level with the given non-localized name. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.name)) { - return l; - } + level = KnownLevel.findByName(name); + if (level != null) { + return level.levelObject; } // Now, check if the given name is an integer. If so, @@ -328,14 +392,13 @@ public class Level implements java.io.Serializable { // if necessary create one. try { int x = Integer.parseInt(name); - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (l.value == x) { - return l; - } + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); } - // Create a new Level. - return new Level(name, x); + return level.levelObject; } catch (NumberFormatException ex) { // Not an integer. // Drop through. @@ -344,11 +407,9 @@ public class Level implements java.io.Serializable { // Finally, look for a known level with the given localized name, // in the current default locale. // This is relatively expensive, but not excessively so. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.getLocalizedName())) { - return l; - } + level = KnownLevel.findByLocalizedName(name); + if (level != null) { + return level.levelObject; } // OK, we've tried everything and failed @@ -375,4 +436,124 @@ public class Level implements java.io.Serializable { public int hashCode() { return this.value; } + + // KnownLevel class maintains the global list of all known levels. + // The API allows multiple custom Level instances of the same name/value + // be created. This class provides convenient methods to find a level + // by a given name, by a given value, or by a given localized name. + // + // KnownLevel wraps the following Level objects: + // 1. levelObject: standard Level object or custom Level object + // 2. mirroredLevel: Level object representing the level specified in the + // logging configuration. + // + // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // are non-final but the name and resource bundle name are parameters to + // the Level constructor. Use the mirroredLevel object instead of the + // levelObject to prevent the logging framework to execute foreign code + // implemented by untrusted Level subclass. + // + // Implementation Notes: + // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // were final, the following KnownLevel implementation can be removed. + // Future API change should take this into consideration. + static final class KnownLevel { + private static Map> nameToLevels = new HashMap<>(); + private static Map> intToLevels = new HashMap<>(); + final Level levelObject; // instance of Level class or Level subclass + final Level mirroredLevel; // instance of Level class + KnownLevel(Level l) { + this.levelObject = l; + if (l.getClass() == Level.class) { + this.mirroredLevel = l; + } else { + this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName); + } + } + + static synchronized void add(Level l) { + // the mirroredLevel object is always added to the list + // before the custom Level instance + KnownLevel o = new KnownLevel(l); + List list = nameToLevels.get(l.name); + if (list == null) { + list = new ArrayList<>(); + nameToLevels.put(l.name, list); + } + list.add(o); + + list = intToLevels.get(l.value); + if (list == null) { + list = new ArrayList<>(); + intToLevels.put(l.value, list); + } + list.add(o); + } + + // Returns a KnownLevel with the given non-localized name. + static synchronized KnownLevel findByName(String name) { + List list = nameToLevels.get(name); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given value. + static synchronized KnownLevel findByValue(int value) { + List list = intToLevels.get(value); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedLevelName() method (i.e. found + // from the resourceBundle associated with the Level object). + // This method does not call Level.getLocalizedName() that may + // be overridden in a subclass implementation + static synchronized KnownLevel findByLocalizedLevelName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedLevelName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedName() method + static synchronized KnownLevel findByLocalizedName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + static synchronized KnownLevel matches(Level l) { + List list = nameToLevels.get(l.name); + if (list != null) { + for (KnownLevel level : list) { + Level other = level.mirroredLevel; + if (l.value == other.value && + (l.resourceBundleName == other.resourceBundleName || + (l.resourceBundleName != null && + l.resourceBundleName.equals(other.resourceBundleName)))) { + return level; + } + } + } + return null; + } + } + } diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index 2041acba80d..3cb35f584f4 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -35,6 +35,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.beans.PropertyChangeListener; +import java.net.URL; +import sun.misc.JavaAWTAccess; +import sun.misc.SharedSecrets; +import sun.security.action.GetPropertyAction; /** * There is a single global LogManager object that is used to @@ -152,10 +156,9 @@ public class LogManager { // count to allow for cases where the same listener is registered many times. private final Map listenerMap = new HashMap<>(); - // Table of named Loggers that maps names to Loggers. - private Hashtable namedLoggers = new Hashtable<>(); - // Tree of named Loggers - private LogNode root = new LogNode(null); + // LoggerContext for system loggers and user loggers + private final LoggerContext systemContext = new SystemLoggerContext(); + private final LoggerContext userContext = new LoggerContext(); private Logger rootLogger; // Have we done the primordial reading of the configuration file? @@ -194,11 +197,12 @@ public class LogManager { // Create and retain Logger for the root of the namespace. manager.rootLogger = manager.new RootLogger(); manager.addLogger(manager.rootLogger); + manager.systemContext.addLocalLogger(manager.rootLogger); // Adding the global Logger. Doing so in the Logger. // would deadlock with the LogManager.. - Logger.getGlobal().setLogManager(manager); - manager.addLogger(Logger.getGlobal()); + Logger.global.setLogManager(manager); + manager.addLogger(Logger.global); // We don't call readConfiguration() here, as we may be running // very early in the JVM startup sequence. Instead readConfiguration @@ -276,14 +280,14 @@ public class LogManager { return; } readPrimordialConfiguration = true; + try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Void run() throws Exception { readConfiguration(); // Platform loggers begin to delegate to java.util.logging.Logger sun.util.logging.PlatformLogger.redirectPlatformLoggers(); - return null; } }); @@ -375,20 +379,68 @@ public class LogManager { } } - // Package-level method. + // Returns the LoggerContext for the user code (i.e. application or AppContext). + // Loggers are isolated from each AppContext. + private LoggerContext getUserContext() { + LoggerContext context = null; + + SecurityManager sm = System.getSecurityManager(); + JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess(); + if (sm != null && javaAwtAccess != null) { + synchronized (javaAwtAccess) { + // AppContext.getAppContext() returns the system AppContext if called + // from a system thread but Logger.getLogger might be called from + // an applet code. Instead, find the AppContext of the applet code + // from the execution stack. + Object ecx = javaAwtAccess.getExecutionContext(); + if (ecx == null) { + // fall back to AppContext.getAppContext() + ecx = javaAwtAccess.getContext(); + } + context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class); + if (context == null) { + if (javaAwtAccess.isMainAppContext()) { + context = userContext; + } else { + context = new LoggerContext(); + // during initialization, rootLogger is null when + // instantiating itself RootLogger + if (manager.rootLogger != null) + context.addLocalLogger(manager.rootLogger); + } + javaAwtAccess.put(ecx, LoggerContext.class, context); + } + } + } else { + context = userContext; + } + return context; + } + + private List contexts() { + List cxs = new ArrayList<>(); + cxs.add(systemContext); + cxs.add(getUserContext()); + return cxs; + } + // Find or create a specified logger instance. If a logger has // already been created with the given name it is returned. // Otherwise a new logger instance is created and registered // in the LogManager global namespace. - // This method will always return a non-null Logger object. // Synchronization is not required here. All synchronization for // adding a new Logger object is handled by addLogger(). - Logger demandLogger(String name) { + // + // This method must delegate to the LogManager implementation to + // add a new Logger or return the one that has been added previously + // as a LogManager subclass may override the addLogger, getLogger, + // readConfiguration, and other methods. + Logger demandLogger(String name, String resourceBundleName) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, null); + Logger newLogger = new Logger(name, resourceBundleName); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -413,24 +465,249 @@ public class LogManager { return result; } - // If logger.getUseParentHandlers() returns 'true' and any of the logger's - // parents have levels or handlers defined, make sure they are instantiated. - private void processParentHandlers(Logger logger, String name) { - int ix = 1; - for (;;) { - int ix2 = name.indexOf(".", ix); - if (ix2 < 0) { - break; - } - String pname = name.substring(0,ix2); + Logger demandSystemLogger(String name, String resourceBundleName) { + // Add a system logger in the system context's namespace + final Logger sysLogger = systemContext.demandLogger(name, resourceBundleName); - if (getProperty(pname+".level") != null || - getProperty(pname+".handlers") != null) { - // This pname has a level/handlers definition. - // Make sure it exists. - demandLogger(pname); + // Add the system logger to the LogManager's namespace if not exist + // so that there is only one single logger of the given name. + // System loggers are visible to applications unless a logger of + // the same name has been added. + Logger logger; + do { + // First attempt to call addLogger instead of getLogger + // This would avoid potential bug in custom LogManager.getLogger + // implementation that adds a logger if does not exist + if (addLogger(sysLogger)) { + // successfully added the new system logger + logger = sysLogger; + } else { + logger = getLogger(name); } - ix = ix2+1; + } while (logger == null); + + // LogManager will set the sysLogger's handlers via LogManager.addLogger method. + if (logger != sysLogger && sysLogger.getHandlers().length == 0) { + // if logger already exists but handlers not set + final Logger l = logger; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + for (Handler hdl : l.getHandlers()) { + sysLogger.addHandler(hdl); + } + return null; + } + }); + } + return sysLogger; + } + + // LoggerContext maintains the logger namespace per context. + // The default LogManager implementation has one system context and user + // context. The system context is used to maintain the namespace for + // all system loggers and is queried by the system code. If a system logger + // doesn't exist in the user context, it'll also be added to the user context. + // The user context is queried by the user code and all other loggers are + // added in the user context. + static class LoggerContext { + // Table of named Loggers that maps names to Loggers. + private final Hashtable namedLoggers = new Hashtable<>(); + // Tree of named Loggers + private final LogNode root; + + private LoggerContext() { + this.root = new LogNode(null, this); + } + + Logger demandLogger(String name, String resourceBundleName) { + // a LogManager subclass may have its own implementation to add and + // get a Logger. So delegate to the LogManager to do the work. + return manager.demandLogger(name, resourceBundleName); + } + + synchronized Logger findLogger(String name) { + LoggerWeakRef ref = namedLoggers.get(name); + if (ref == null) { + return null; + } + Logger logger = ref.get(); + if (logger == null) { + // Hashtable holds stale weak reference + // to a logger which has been GC-ed. + removeLogger(name); + } + return logger; + } + + // Add a logger to this context. This method will only set its level + // and process parent loggers. It doesn't set its handlers. + synchronized boolean addLocalLogger(Logger logger) { + final String name = logger.getName(); + if (name == null) { + throw new NullPointerException(); + } + + // cleanup some Loggers that have been GC'ed + manager.drainLoggerRefQueueBounded(); + + LoggerWeakRef ref = namedLoggers.get(name); + if (ref != null) { + if (ref.get() == null) { + // It's possible that the Logger was GC'ed after the + // drainLoggerRefQueueBounded() call above so allow + // a new one to be registered. + removeLogger(name); + } else { + // We already have a registered logger with the given name. + return false; + } + } + + // We're adding a new logger. + // Note that we are creating a weak reference here. + ref = manager.new LoggerWeakRef(logger); + namedLoggers.put(name, ref); + + // Apply any initial level defined for the new logger. + Level level = manager.getLevelProperty(name + ".level", null); + if (level != null) { + doSetLevel(logger, level); + } + + // instantiation of the handler is done in the LogManager.addLogger + // implementation as a handler class may be only visible to LogManager + // subclass for the custom log manager case + processParentHandlers(logger, name); + + // Find the new node and its parent. + LogNode node = getNode(name); + node.loggerRef = ref; + Logger parent = null; + LogNode nodep = node.parent; + while (nodep != null) { + LoggerWeakRef nodeRef = nodep.loggerRef; + if (nodeRef != null) { + parent = nodeRef.get(); + if (parent != null) { + break; + } + } + nodep = nodep.parent; + } + + if (parent != null) { + doSetParent(logger, parent); + } + // Walk over the children and tell them we are their new parent. + node.walkAndSetParent(logger); + // new LogNode is ready so tell the LoggerWeakRef about it + ref.setNode(node); + return true; + } + + void removeLogger(String name) { + namedLoggers.remove(name); + } + + synchronized Enumeration getLoggerNames() { + return namedLoggers.keys(); + } + + // If logger.getUseParentHandlers() returns 'true' and any of the logger's + // parents have levels or handlers defined, make sure they are instantiated. + private void processParentHandlers(final Logger logger, final String name) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + if (logger != manager.rootLogger) { + boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true); + if (!useParent) { + logger.setUseParentHandlers(false); + } + } + return null; + } + }); + + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (manager.getProperty(pname + ".level") != null || + manager.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + demandLogger(pname, null); + } + ix = ix2+1; + } + } + + // Gets a node in our tree of logger nodes. + // If necessary, create it. + LogNode getNode(String name) { + if (name == null || name.equals("")) { + return root; + } + LogNode node = root; + while (name.length() > 0) { + int ix = name.indexOf("."); + String head; + if (ix > 0) { + head = name.substring(0, ix); + name = name.substring(ix + 1); + } else { + head = name; + name = ""; + } + if (node.children == null) { + node.children = new HashMap<>(); + } + LogNode child = node.children.get(head); + if (child == null) { + child = new LogNode(node, this); + node.children.put(head, child); + } + node = child; + } + return node; + } + } + + static class SystemLoggerContext extends LoggerContext { + // Add a system logger in the system context's namespace as well as + // in the LogManager's namespace if not exist so that there is only + // one single logger of the given name. System loggers are visible + // to applications unless a logger of the same name has been added. + Logger demandLogger(String name, String resourceBundleName) { + Logger result = findLogger(name); + if (result == null) { + // only allocate the new system logger once + Logger newLogger = new Logger(name, resourceBundleName); + do { + if (addLocalLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + result = newLogger; + } else { + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); + } + } while (result == null); + } + return result; } } @@ -439,32 +716,27 @@ public class LogManager { // be made based on the logging configuration, which can // only be modified by trusted code. private void loadLoggerHandlers(final Logger logger, final String name, - final String handlersPropertyName) { + final String handlersPropertyName) + { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - if (logger != rootLogger) { - boolean useParent = getBooleanProperty(name + ".useParentHandlers", true); - if (!useParent) { - logger.setUseParentHandlers(false); - } - } - String names[] = parseClassNames(handlersPropertyName); for (int i = 0; i < names.length; i++) { String word = names[i]; try { Class clz = ClassLoader.getSystemClassLoader().loadClass(word); - Handler hdl = (Handler) clz.newInstance(); - try { - // Check if there is a property defining the - // this handler's level. - String levs = getProperty(word + ".level"); - if (levs != null) { - hdl.setLevel(Level.parse(levs)); + Handler hdl = (Handler) clz.newInstance(); + // Check if there is a property defining the + // this handler's level. + String levs = getProperty(word + ".level"); + if (levs != null) { + Level l = Level.findLevel(levs); + if (l != null) { + hdl.setLevel(l); + } else { + // Probably a bad level. Drop through. + System.err.println("Can't set level for " + word); } - } catch (Exception ex) { - System.err.println("Can't set level for " + word); - // Probably a bad level. Drop through. } // Add this Handler to the logger logger.addHandler(hdl); @@ -475,7 +747,8 @@ public class LogManager { } } return null; - }}); + } + }); } @@ -520,7 +793,7 @@ public class LogManager { if (node != null) { // if we have a LogNode, then we were a named Logger // so clear namedLoggers weak ref to us - manager.namedLoggers.remove(name); + node.context.removeLogger(name); name = null; // clear our ref to the Logger's name node.loggerRef = null; // clear LogNode's weak ref to us @@ -609,73 +882,22 @@ public class LogManager { * false if a logger of that name already exists. * @exception NullPointerException if the logger name is null. */ - public synchronized boolean addLogger(Logger logger) { + public boolean addLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); } - - // cleanup some Loggers that have been GC'ed - drainLoggerRefQueueBounded(); - - LoggerWeakRef ref = namedLoggers.get(name); - if (ref != null) { - if (ref.get() == null) { - // It's possible that the Logger was GC'ed after the - // drainLoggerRefQueueBounded() call above so allow - // a new one to be registered. - namedLoggers.remove(name); - } else { - // We already have a registered logger with the given name. - return false; - } + LoggerContext cx = getUserContext(); + if (cx.addLocalLogger(logger)) { + // Do we have a per logger handler too? + // Note: this will add a 200ms penalty + loadLoggerHandlers(logger, name, name + ".handlers"); + return true; + } else { + return false; } - - // We're adding a new logger. - // Note that we are creating a weak reference here. - ref = new LoggerWeakRef(logger); - namedLoggers.put(name, ref); - - // Apply any initial level defined for the new logger. - Level level = getLevelProperty(name+".level", null); - if (level != null) { - doSetLevel(logger, level); - } - - // Do we have a per logger handler too? - // Note: this will add a 200ms penalty - loadLoggerHandlers(logger, name, name+".handlers"); - processParentHandlers(logger, name); - - // Find the new node and its parent. - LogNode node = findNode(name); - node.loggerRef = ref; - Logger parent = null; - LogNode nodep = node.parent; - while (nodep != null) { - LoggerWeakRef nodeRef = nodep.loggerRef; - if (nodeRef != null) { - parent = nodeRef.get(); - if (parent != null) { - break; - } - } - nodep = nodep.parent; - } - - if (parent != null) { - doSetParent(logger, parent); - } - // Walk over the children and tell them we are their new parent. - node.walkAndSetParent(logger); - - // new LogNode is ready so tell the LoggerWeakRef about it - ref.setNode(node); - - return true; } - // Private method to set a level on a logger. // If necessary, we raise privilege before doing the call. private static void doSetLevel(final Logger logger, final Level level) { @@ -694,8 +916,6 @@ public class LogManager { }}); } - - // Private method to set a parent on a logger. // If necessary, we raise privilege before doing the setParent call. private static void doSetParent(final Logger logger, final Logger parent) { @@ -714,36 +934,6 @@ public class LogManager { }}); } - // Find a node in our tree of logger nodes. - // If necessary, create it. - private LogNode findNode(String name) { - if (name == null || name.equals("")) { - return root; - } - LogNode node = root; - while (name.length() > 0) { - int ix = name.indexOf("."); - String head; - if (ix > 0) { - head = name.substring(0,ix); - name = name.substring(ix+1); - } else { - head = name; - name = ""; - } - if (node.children == null) { - node.children = new HashMap<>(); - } - LogNode child = node.children.get(head); - if (child == null) { - child = new LogNode(node); - node.children.put(head, child); - } - node = child; - } - return node; - } - /** * Method to find a named logger. *

    @@ -759,18 +949,8 @@ public class LogManager { * @param name name of the logger * @return matching logger or null if none is found */ - public synchronized Logger getLogger(String name) { - LoggerWeakRef ref = namedLoggers.get(name); - if (ref == null) { - return null; - } - Logger logger = ref.get(); - if (logger == null) { - // Hashtable holds stale weak reference - // to a logger which has been GC-ed. - namedLoggers.remove(name); - } - return logger; + public Logger getLogger(String name) { + return getUserContext().findLogger(name); } /** @@ -789,8 +969,8 @@ public class LogManager { *

    * @return enumeration of logger name strings */ - public synchronized Enumeration getLoggerNames() { - return namedLoggers.keys(); + public Enumeration getLoggerNames() { + return getUserContext().getLoggerNames(); } /** @@ -875,20 +1055,20 @@ public class LogManager { // the global handlers, if they haven't been initialized yet. initializedGlobalHandlers = true; } - Enumeration enum_ = getLoggerNames(); - while (enum_.hasMoreElements()) { - String name = enum_.nextElement(); - resetLogger(name); + for (LoggerContext cx : contexts()) { + Enumeration enum_ = cx.getLoggerNames(); + while (enum_.hasMoreElements()) { + String name = enum_.nextElement(); + Logger logger = cx.findLogger(name); + if (logger != null) { + resetLogger(logger); + } + } } } - // Private method to reset an individual target logger. - private void resetLogger(String name) { - Logger logger = getLogger(name); - if (logger == null) { - return; - } + private void resetLogger(Logger logger) { // Close all the Logger's handlers. Handler[] targets = logger.getHandlers(); for (int i = 0; i < targets.length; i++) { @@ -900,6 +1080,7 @@ public class LogManager { // Problems closing a handler? Keep going... } } + String name = logger.getName(); if (name != null && name.equals("")) { // This is the root logger. logger.setLevel(defaultLevel); @@ -1065,11 +1246,8 @@ public class LogManager { if (val == null) { return defaultValue; } - try { - return Level.parse(val.trim()); - } catch (Exception ex) { - return defaultValue; - } + Level l = Level.findLevel(val.trim()); + return l != null ? l : defaultValue; } // Package private method to get a filter property. @@ -1159,9 +1337,11 @@ public class LogManager { HashMap children; LoggerWeakRef loggerRef; LogNode parent; + final LoggerContext context; - LogNode(LogNode parent) { + LogNode(LogNode parent, LoggerContext context) { this.parent = parent; + this.context = context; } // Recursive method to walk the tree below a node and set @@ -1188,7 +1368,6 @@ public class LogManager { // that we only instantiate the global handlers when they // are first needed. private class RootLogger extends Logger { - private RootLogger() { super("", null); setLevel(defaultLevel); @@ -1234,11 +1413,13 @@ public class LogManager { System.err.println("Bad level value for property: " + key); continue; } - Logger l = getLogger(name); - if (l == null) { - continue; + for (LoggerContext cx : contexts()) { + Logger l = cx.findLogger(name); + if (l == null) { + continue; + } + l.setLevel(level); } - l.setLevel(level); } } diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java index 4e52c235c0c..5d060059e60 100644 --- a/jdk/src/share/classes/java/util/logging/Logger.java +++ b/jdk/src/share/classes/java/util/logging/Logger.java @@ -314,6 +314,40 @@ public class Logger { } } + // Until all JDK code converted to call sun.util.logging.PlatformLogger + // (see 7054233), we need to determine if Logger.getLogger is to add + // a system logger or user logger. + // + // As an interim solution, if the immediate caller whose caller loader is + // null, we assume it's a system logger and add it to the system context. + // These system loggers only set the resource bundle to the given + // resource bundle name (rather than the default system resource bundle). + private static class SystemLoggerHelper { + static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck"); + private static boolean getBooleanProperty(final String key) { + String s = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(key); + } + }); + return Boolean.valueOf(s); + } + } + + private static Logger demandLogger(String name, String resourceBundleName) { + LogManager manager = LogManager.getLogManager(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null && !SystemLoggerHelper.disableCallerCheck) { + // 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller + final int SKIP_FRAMES = 3; + Class caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES); + if (caller.getClassLoader() == null) { + return manager.demandSystemLogger(name, resourceBundleName); + } + } + return manager.demandLogger(name, resourceBundleName); + } + /** * Find or create a logger for a named subsystem. If a logger has * already been created with the given name it is returned. Otherwise @@ -355,8 +389,7 @@ public class Logger { // would throw an IllegalArgumentException in the second call // because the wrapper would result in an attempt to replace // the existing "resourceBundleForFoo" with null. - LogManager manager = LogManager.getLogManager(); - return manager.demandLogger(name); + return demandLogger(name, null); } /** @@ -403,8 +436,7 @@ public class Logger { // Synchronization is not required here. All synchronization for // adding a new Logger object is handled by LogManager.addLogger(). public static Logger getLogger(String name, String resourceBundleName) { - LogManager manager = LogManager.getLogManager(); - Logger result = manager.demandLogger(name); + Logger result = demandLogger(name, resourceBundleName); // MissingResourceException or IllegalArgumentException can be // thrown by setupResourceInfo(). @@ -412,6 +444,17 @@ public class Logger { return result; } + // package-private + // Add a platform logger to the system context. + // i.e. caller of sun.util.logging.PlatformLogger.getLogger + static Logger getPlatformLogger(String name) { + LogManager manager = LogManager.getLogManager(); + + // all loggers in the system context will default to + // the system logger's resource bundle + Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME); + return result; + } /** * Create an anonymous Logger. The newly created Logger is not @@ -564,7 +607,7 @@ public class Logger { private void doLog(LogRecord lr) { lr.setLoggerName(name); String ebname = getEffectiveResourceBundleName(); - if (ebname != null) { + if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) { lr.setResourceBundleName(ebname); lr.setResourceBundle(findResourceBundle(ebname)); } @@ -1547,6 +1590,23 @@ public class Logger { // May also return null if we can't find the resource bundle and // there is no suitable previous cached value. + static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging"; + + private static ResourceBundle findSystemResourceBundle(final Locale locale) { + // the resource bundle is in a restricted package + return AccessController.doPrivileged(new PrivilegedAction() { + public ResourceBundle run() { + try { + return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME, + locale, + ClassLoader.getSystemClassLoader()); + } catch (MissingResourceException e) { + throw new InternalError(e.toString()); + } + } + }); + } + private synchronized ResourceBundle findResourceBundle(String name) { // Return a null bundle for a null name. if (name == null) { @@ -1561,6 +1621,13 @@ public class Logger { return catalog; } + if (name.equals(SYSTEM_LOGGER_RB_NAME)) { + catalog = findSystemResourceBundle(currentLocale); + catalogName = name; + catalogLocale = currentLocale; + return catalog; + } + // Use the thread's context ClassLoader. If there isn't one, // use the SystemClassloader. ClassLoader cl = Thread.currentThread().getContextClassLoader(); @@ -1577,7 +1644,6 @@ public class Logger { // ClassLoader. Drop through. } - // Fall back to searching up the call stack and trying each // calling ClassLoader. for (int ix = 0; ; ix++) { diff --git a/jdk/src/share/classes/java/util/logging/Logging.java b/jdk/src/share/classes/java/util/logging/Logging.java index 10b183fffb2..e22a82e9d19 100644 --- a/jdk/src/share/classes/java/util/logging/Logging.java +++ b/jdk/src/share/classes/java/util/logging/Logging.java @@ -34,7 +34,7 @@ import java.util.ArrayList; * * The LoggingMXBean interface provides a standard * method for management access to the individual - * java.util.Logger objects available at runtime. + * {@code Logger} objects available at runtime. * * @author Ron Mann * @author Mandy Chung @@ -75,7 +75,7 @@ class Logging implements LoggingMXBean { if (level == null) { return EMPTY_STRING; } else { - return level.getName(); + return level.getLevelName(); } } @@ -85,7 +85,6 @@ class Logging implements LoggingMXBean { } Logger logger = logManager.getLogger(loggerName); - if (logger == null) { throw new IllegalArgumentException("Logger " + loggerName + "does not exist"); @@ -94,7 +93,10 @@ class Logging implements LoggingMXBean { Level level = null; if (levelName != null) { // parse will throw IAE if logLevel is invalid - level = Level.parse(levelName); + level = Level.findLevel(levelName); + if (level == null) { + throw new IllegalArgumentException("Unknown level \"" + levelName + "\""); + } } logger.setLevel(level); diff --git a/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java b/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java index 0edc6f30290..a207d1f8409 100644 --- a/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java +++ b/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java @@ -37,7 +37,8 @@ class LoggingProxyImpl implements LoggingProxy { @Override public Object getLogger(String name) { - return Logger.getLogger(name); + // always create a platform logger with the resource bundle name + return Logger.getPlatformLogger(name); } @Override @@ -92,12 +93,16 @@ class LoggingProxyImpl implements LoggingProxy { @Override public Object parseLevel(String levelName) { - return Level.parse(levelName); + Level level = Level.findLevel(levelName); + if (level == null) { + throw new IllegalArgumentException("Unknown level \"" + levelName + "\""); + } + return level; } @Override public String getLevelName(Object level) { - return ((Level) level).getName(); + return ((Level) level).getLevelName(); } @Override diff --git a/jdk/src/share/classes/java/util/logging/SimpleFormatter.java b/jdk/src/share/classes/java/util/logging/SimpleFormatter.java index 7dfa53f2439..4dfb3fc7c64 100644 --- a/jdk/src/share/classes/java/util/logging/SimpleFormatter.java +++ b/jdk/src/share/classes/java/util/logging/SimpleFormatter.java @@ -162,7 +162,7 @@ public class SimpleFormatter extends Formatter { dat, source, record.getLoggerName(), - record.getLevel().getLocalizedName(), + record.getLevel().getLocalizedLevelName(), message, throwable); } diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index c1600a94317..6d28adaf0f7 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -39,11 +39,13 @@ import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.logging.Level; import java.util.Map; import java.util.Set; @@ -78,6 +80,8 @@ import javax.management.RuntimeErrorException; import javax.management.RuntimeOperationsException; import javax.management.ServiceNotFoundException; import javax.management.loading.ClassLoaderRepository; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; @@ -138,6 +142,9 @@ public class RequiredModelMBean private boolean registered = false; private transient MBeanServer server = null; + private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess(); + final private AccessControlContext acc = AccessController.getContext(); + /*************************************/ /* constructors */ /*************************************/ @@ -1025,10 +1032,31 @@ public class RequiredModelMBean if (opClassName != null) { try { - final ClassLoader targetClassLoader = - targetObject.getClass().getClassLoader(); - targetClass = Class.forName(opClassName, false, - targetClassLoader); + AccessControlContext stack = AccessController.getContext(); + final Object obj = targetObject; + final String className = opClassName; + final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; + + targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + final ClassLoader targetClassLoader = + obj.getClass().getClassLoader(); + return Class.forName(className, false, + targetClassLoader); + } catch (ClassNotFoundException e) { + caughtException[0] = e; + } + return null; + } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; + } } catch (ClassNotFoundException e) { final String msg = "class for invoke " + opName + " not found"; @@ -1061,9 +1089,9 @@ public class RequiredModelMBean return result; } - private static Method resolveMethod(Class targetClass, + private Method resolveMethod(Class targetClass, String opMethodName, - String[] sig) + final String[] sig) throws ReflectionException { final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER); @@ -1078,30 +1106,45 @@ public class RequiredModelMBean if (sig == null) argClasses = null; else { + final AccessControlContext stack = AccessController.getContext(); + final ReflectionException[] caughtException = new ReflectionException[1]; final ClassLoader targetClassLoader = targetClass.getClassLoader(); argClasses = new Class[sig.length]; - for (int i = 0; i < sig.length; i++) { - if (tracing) { - MODELMBEAN_LOGGER.logp(Level.FINER, - RequiredModelMBean.class.getName(),"resolveMethod", - "resolve type " + sig[i]); - } - argClasses[i] = (Class) primitiveClassMap.get(sig[i]); - if (argClasses[i] == null) { - try { - argClasses[i] = - Class.forName(sig[i], false, targetClassLoader); - } catch (ClassNotFoundException e) { + + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + + @Override + public Void run() { + for (int i = 0; i < sig.length; i++) { if (tracing) { MODELMBEAN_LOGGER.logp(Level.FINER, - RequiredModelMBean.class.getName(), - "resolveMethod", - "class not found"); + RequiredModelMBean.class.getName(),"resolveMethod", + "resolve type " + sig[i]); + } + argClasses[i] = (Class) primitiveClassMap.get(sig[i]); + if (argClasses[i] == null) { + try { + ReflectUtil.checkPackageAccess(sig[i]); + argClasses[i] = + Class.forName(sig[i], false, targetClassLoader); + } catch (ClassNotFoundException e) { + if (tracing) { + MODELMBEAN_LOGGER.logp(Level.FINER, + RequiredModelMBean.class.getName(), + "resolveMethod", + "class not found"); + } + final String msg = "Parameter class not found"; + caughtException[0] = new ReflectionException(e, msg); + } } - final String msg = "Parameter class not found"; - throw new ReflectionException(e, msg); } + return null; } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; } } @@ -1133,7 +1176,7 @@ public class RequiredModelMBean /* Find a method in RequiredModelMBean as determined by the given parameters. Return null if there is none, or if the parameters exclude using it. Called from invoke. */ - private static Method findRMMBMethod(String opMethodName, + private Method findRMMBMethod(String opMethodName, Object targetObjectField, String opClassName, String[] sig) { @@ -1155,19 +1198,29 @@ public class RequiredModelMBean if (opClassName == null) targetClass = rmmbClass; else { - try { - final ClassLoader targetClassLoader = - rmmbClass.getClassLoader(); - targetClass = Class.forName(opClassName, false, - targetClassLoader); - if (!rmmbClass.isAssignableFrom(targetClass)) - return null; - } catch (ClassNotFoundException e) { - return null; - } + AccessControlContext stack = AccessController.getContext(); + final String className = opClassName; + targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + final ClassLoader targetClassLoader = + rmmbClass.getClassLoader(); + Class clz = Class.forName(className, false, + targetClassLoader); + if (!rmmbClass.isAssignableFrom(clz)) + return null; + return clz; + } catch (ClassNotFoundException e) { + return null; + } + } + }, stack, acc); } try { - return resolveMethod(targetClass, opMethodName, sig); + return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null; } catch (ReflectionException e) { return null; } @@ -1177,12 +1230,35 @@ public class RequiredModelMBean * Invoke the given method, and throw the somewhat unpredictable * appropriate exception if the method itself gets an exception. */ - private Object invokeMethod(String opName, Method method, - Object targetObject, Object[] opArgs) + private Object invokeMethod(String opName, final Method method, + final Object targetObject, final Object[] opArgs) throws MBeanException, ReflectionException { try { - ReflectUtil.checkPackageAccess(method.getDeclaringClass()); - return MethodUtil.invoke(method, targetObject, opArgs); + final Throwable[] caughtException = new Throwable[1]; + AccessControlContext stack = AccessController.getContext(); + Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + + @Override + public Object run() { + try { + ReflectUtil.checkPackageAccess(method.getDeclaringClass()); + return MethodUtil.invoke(method, targetObject, opArgs); + } catch (InvocationTargetException e) { + caughtException[0] = e; + } catch (IllegalAccessException e) { + caughtException[0] = e; + } + return null; + } + }, stack, acc); + if (caughtException[0] != null) { + if (caughtException[0] instanceof Exception) { + throw (Exception)caughtException[0]; + } else if(caughtException[0] instanceof Error) { + throw (Error)caughtException[0]; + } + } + return rslt; } catch (RuntimeErrorException ree) { throw new RuntimeOperationsException(ree, "RuntimeException occurred in RequiredModelMBean "+ @@ -1567,7 +1643,7 @@ public class RequiredModelMBean } // make sure response class matches type field - String respType = attrInfo.getType(); + final String respType = attrInfo.getType(); if (response != null) { String responseClass = response.getClass().getName(); if (!respType.equals(responseClass)) { @@ -1590,9 +1666,31 @@ public class RequiredModelMBean // inequality may come from type subclassing boolean subtype; try { - ClassLoader cl = - response.getClass().getClassLoader(); - Class c = Class.forName(respType, true, cl); + final Class respClass = response.getClass(); + final Exception[] caughException = new Exception[1]; + + AccessControlContext stack = AccessController.getContext(); + + Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(respType); + ClassLoader cl = + respClass.getClassLoader(); + return Class.forName(respType, true, cl); + } catch (Exception e) { + caughException[0] = e; + } + return null; + } + }, stack, acc); + + if (caughException[0] != null) { + throw caughException[0]; + } + subtype = c.isInstance(response); } catch (Exception e) { subtype = false; @@ -2745,16 +2843,37 @@ public class RequiredModelMBean return MBeanServerFactory.getClassLoaderRepository(server); } - private Class loadClass(String className) + private Class loadClass(final String className) throws ClassNotFoundException { - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - final ClassLoaderRepository clr = - getClassLoaderRepository(); - if (clr == null) throw new ClassNotFoundException(className); - return clr.loadClass(className); + AccessControlContext stack = AccessController.getContext(); + final ClassNotFoundException[] caughtException = new ClassNotFoundException[1]; + + Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction>() { + + @Override + public Class run() { + try { + ReflectUtil.checkPackageAccess(className); + return Class.forName(className); + } catch (ClassNotFoundException e) { + final ClassLoaderRepository clr = + getClassLoaderRepository(); + try { + if (clr == null) throw new ClassNotFoundException(className); + return clr.loadClass(className); + } catch (ClassNotFoundException ex) { + caughtException[0] = ex; + } + } + return null; + } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; } + + return c; } diff --git a/jdk/src/share/classes/javax/swing/JFrame.java b/jdk/src/share/classes/javax/swing/JFrame.java index cccd6f98aa5..aee994eecf9 100644 --- a/jdk/src/share/classes/javax/swing/JFrame.java +++ b/jdk/src/share/classes/javax/swing/JFrame.java @@ -387,13 +387,14 @@ public class JFrame extends Frame implements WindowConstants, operation != EXIT_ON_CLOSE) { throw new IllegalArgumentException("defaultCloseOperation must be one of: DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE, DISPOSE_ON_CLOSE, or EXIT_ON_CLOSE"); } - if (this.defaultCloseOperation != operation) { - if (operation == EXIT_ON_CLOSE) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkExit(0); - } + + if (operation == EXIT_ON_CLOSE) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkExit(0); } + } + if (this.defaultCloseOperation != operation) { int oldValue = this.defaultCloseOperation; this.defaultCloseOperation = operation; firePropertyChange("defaultCloseOperation", oldValue, operation); diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index c607a9a5ba9..bed8e5ca93e 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -781,15 +781,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); if (corner == null || corner instanceof UIResource){ corner = null; - Object componentClass = UIManager.get( - "Table.scrollPaneCornerComponent"); - if (componentClass instanceof Class){ - try { - corner = (Component) - ((Class)componentClass).newInstance(); - } catch (Exception e) { - // just ignore and don't set corner - } + try { + corner = (Component) UIManager.get( + "Table.scrollPaneCornerComponent"); + } catch (Exception e) { + // just ignore and don't set corner } scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, corner); diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index aa3f8bdf50c..8f2e6093393 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -27,11 +27,12 @@ package javax.swing; import java.awt.*; import java.awt.event.*; -import java.awt.peer.ComponentPeer; -import java.awt.peer.ContainerPeer; import java.awt.image.VolatileImage; +import java.security.AccessControlContext; import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.applet.*; import sun.awt.AWTAccessor; @@ -39,6 +40,8 @@ import sun.awt.AppContext; import sun.awt.DisplayChangedListener; import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; +import sun.misc.JavaSecurityAccess; +import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; import com.sun.java.swing.SwingUtilities3; @@ -176,6 +179,9 @@ public class RepaintManager */ private final ProcessingRunnable processingRunnable; + private final static JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + static { volatileImageBufferEnabled = "true".equals(AccessController. @@ -548,13 +554,26 @@ public class RepaintManager // This is called from the toolkit thread when awt needs to run a // Runnable before we paint. // - void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c, - Runnable r) { + void nativeQueueSurfaceDataRunnable(AppContext appContext, + final Component c, final Runnable r) + { synchronized(this) { if (runnableList == null) { runnableList = new LinkedList(); } - runnableList.add(r); + runnableList.add(new Runnable() { + public void run() { + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(c); + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + public Void run() { + r.run(); + return null; + } + }, stack, acc); + } + }); } scheduleProcessingRunnable(appContext); } @@ -652,9 +671,9 @@ public class RepaintManager * @see #addInvalidComponent */ public void validateInvalidComponents() { - java.util.List ic; + final java.util.List ic; synchronized(this) { - if(invalidComponents == null) { + if (invalidComponents == null) { return; } ic = invalidComponents; @@ -662,7 +681,17 @@ public class RepaintManager } int n = ic.size(); for(int i = 0; i < n; i++) { - ic.get(i).validate(); + final Component c = ic.get(i); + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(c); + javaSecurityAccess.doIntersectionPrivilege( + new PrivilegedAction() { + public Void run() { + c.validate(); + return null; + } + }, stack, acc); } } @@ -740,78 +769,78 @@ public class RepaintManager paintDirtyRegions(tmpDirtyComponents); } - private void paintDirtyRegions(Map - tmpDirtyComponents){ - int i, count; - java.util.List roots; - Component dirtyComponent; - - count = tmpDirtyComponents.size(); - if (count == 0) { + private void paintDirtyRegions( + final Map tmpDirtyComponents) + { + if (tmpDirtyComponents.isEmpty()) { return; } - Rectangle rect; - int localBoundsX = 0; - int localBoundsY = 0; - int localBoundsH; - int localBoundsW; - - roots = new ArrayList(count); - + final java.util.List roots = + new ArrayList(tmpDirtyComponents.size()); for (Component dirty : tmpDirtyComponents.keySet()) { collectDirtyComponents(tmpDirtyComponents, dirty, roots); } - count = roots.size(); + final AtomicInteger count = new AtomicInteger(roots.size()); painting = true; try { - for(i=0 ; i < count ; i++) { - dirtyComponent = roots.get(i); - rect = tmpDirtyComponents.get(dirtyComponent); - // Sometimes when RepaintManager is changed during the painting - // we may get null here, see #6995769 for details - if (rect == null) { - continue; - } - localBoundsH = dirtyComponent.getHeight(); - localBoundsW = dirtyComponent.getWidth(); - - SwingUtilities.computeIntersection(localBoundsX, - localBoundsY, - localBoundsW, - localBoundsH, - rect); - if (dirtyComponent instanceof JComponent) { - ((JComponent)dirtyComponent).paintImmediately( - rect.x,rect.y,rect.width, rect.height); - } - else if (dirtyComponent.isShowing()) { - Graphics g = JComponent.safelyGetGraphics( - dirtyComponent, dirtyComponent); - // If the Graphics goes away, it means someone disposed of - // the window, don't do anything. - if (g != null) { - g.setClip(rect.x, rect.y, rect.width, rect.height); - try { - dirtyComponent.paint(g); - } finally { - g.dispose(); + for (int j=0 ; j < count.get(); j++) { + final int i = j; + final Component dirtyComponent = roots.get(j); + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent); + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction() { + public Void run() { + Rectangle rect = tmpDirtyComponents.get(dirtyComponent); + // Sometimes when RepaintManager is changed during the painting + // we may get null here, see #6995769 for details + if (rect == null) { + return null; } + + int localBoundsH = dirtyComponent.getHeight(); + int localBoundsW = dirtyComponent.getWidth(); + SwingUtilities.computeIntersection(0, + 0, + localBoundsW, + localBoundsH, + rect); + if (dirtyComponent instanceof JComponent) { + ((JComponent)dirtyComponent).paintImmediately( + rect.x,rect.y,rect.width, rect.height); + } + else if (dirtyComponent.isShowing()) { + Graphics g = JComponent.safelyGetGraphics( + dirtyComponent, dirtyComponent); + // If the Graphics goes away, it means someone disposed of + // the window, don't do anything. + if (g != null) { + g.setClip(rect.x, rect.y, rect.width, rect.height); + try { + dirtyComponent.paint(g); + } finally { + g.dispose(); + } + } + } + // If the repaintRoot has been set, service it now and + // remove any components that are children of repaintRoot. + if (repaintRoot != null) { + adjustRoots(repaintRoot, roots, i + 1); + count.set(roots.size()); + paintManager.isRepaintingRoot = true; + repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), + repaintRoot.getHeight()); + paintManager.isRepaintingRoot = false; + // Only service repaintRoot once. + repaintRoot = null; + } + + return null; } - } - // If the repaintRoot has been set, service it now and - // remove any components that are children of repaintRoot. - if (repaintRoot != null) { - adjustRoots(repaintRoot, roots, i + 1); - count = roots.size(); - paintManager.isRepaintingRoot = true; - repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(), - repaintRoot.getHeight()); - paintManager.isRepaintingRoot = false; - // Only service repaintRoot once. - repaintRoot = null; - } + }, stack, acc); } } finally { painting = false; diff --git a/jdk/src/share/classes/javax/swing/SwingUtilities.java b/jdk/src/share/classes/javax/swing/SwingUtilities.java index 956bb838be7..6bb308d2f1e 100644 --- a/jdk/src/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/share/classes/javax/swing/SwingUtilities.java @@ -356,7 +356,7 @@ public class SwingUtilities implements SwingConstants sourceEvent.getYOnScreen(), sourceEvent.getClickCount(), sourceEvent.isPopupTrigger(), - MouseEvent.NOBUTTON ); + sourceEvent.getButton()); } return newEvent; } diff --git a/jdk/src/share/classes/javax/swing/UIDefaults.java b/jdk/src/share/classes/javax/swing/UIDefaults.java index 9f22122d7b2..9f304e742c7 100644 --- a/jdk/src/share/classes/javax/swing/UIDefaults.java +++ b/jdk/src/share/classes/javax/swing/UIDefaults.java @@ -677,6 +677,8 @@ public class UIDefaults extends Hashtable try { String className = (String)get(uiClassID); if (className != null) { + ReflectUtil.checkPackageAccess(className); + Class cls = (Class)get(className); if (cls == null) { if (uiClassLoader == null) { diff --git a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java index b03bf653fc5..402a6885982 100644 --- a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java +++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java @@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends SynthLookAndFeel { // Store Table ScrollPane Corner Component uiDefaults.put("Table.scrollPaneCornerComponent", - TableScrollPaneCorner.class); + new UIDefaults.ActiveValue() { + @Override + public Object createValue(UIDefaults table) { + return new TableScrollPaneCorner(); + } + }); // Setup the settings for ToolBarSeparator which is custom // installed for Nimbus diff --git a/jdk/src/share/classes/javax/swing/text/html/FormView.java b/jdk/src/share/classes/javax/swing/text/html/FormView.java index 294637272f3..2d25516f339 100644 --- a/jdk/src/share/classes/javax/swing/text/html/FormView.java +++ b/jdk/src/share/classes/javax/swing/text/html/FormView.java @@ -159,6 +159,10 @@ public class FormView extends ComponentView implements ActionListener { attr.getAttribute(StyleConstants.NameAttribute); JComponent c = null; Object model = attr.getAttribute(StyleConstants.ModelAttribute); + + // Remove listeners previously registered in shared model + // when a new UI component is replaced. See bug 7189299. + removeStaleListenerForModel(model); if (t == HTML.Tag.INPUT) { c = createInputComponent(attr, model); } else if (t == HTML.Tag.SELECT) { @@ -310,6 +314,63 @@ public class FormView extends ComponentView implements ActionListener { return c; } + private void removeStaleListenerForModel(Object model) { + if (model instanceof DefaultButtonModel) { + // case of JButton whose model is DefaultButtonModel + // Need to remove stale ActionListener, ChangeListener and + // ItemListener that are instance of AbstractButton$Handler. + DefaultButtonModel buttonModel = (DefaultButtonModel) model; + String listenerClass = "javax.swing.AbstractButton$Handler"; + for (ActionListener listener : buttonModel.getActionListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeActionListener(listener); + } + } + for (ChangeListener listener : buttonModel.getChangeListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeChangeListener(listener); + } + } + for (ItemListener listener : buttonModel.getItemListeners()) { + if (listenerClass.equals(listener.getClass().getName())) { + buttonModel.removeItemListener(listener); + } + } + } else if (model instanceof AbstractListModel) { + // case of JComboBox and JList + // For JList, the stale ListDataListener is instance + // BasicListUI$Handler. + // For JComboBox, there are 2 stale ListDataListeners, which are + // BasicListUI$Handler and BasicComboBoxUI$Handler. + AbstractListModel listModel = (AbstractListModel) model; + String listenerClass1 = + "javax.swing.plaf.basic.BasicListUI$Handler"; + String listenerClass2 = + "javax.swing.plaf.basic.BasicComboBoxUI$Handler"; + for (ListDataListener listener : listModel.getListDataListeners()) { + if (listenerClass1.equals(listener.getClass().getName()) + || listenerClass2.equals(listener.getClass().getName())) + { + listModel.removeListDataListener(listener); + } + } + } else if (model instanceof AbstractDocument) { + // case of JPasswordField, JTextField and JTextArea + // All have 2 stale DocumentListeners. + String listenerClass1 = + "javax.swing.plaf.basic.BasicTextUI$UpdateHandler"; + String listenerClass2 = + "javax.swing.text.DefaultCaret$Handler"; + AbstractDocument docModel = (AbstractDocument) model; + for (DocumentListener listener : docModel.getDocumentListeners()) { + if (listenerClass1.equals(listener.getClass().getName()) + || listenerClass2.equals(listener.getClass().getName())) + { + docModel.removeDocumentListener(listener); + } + } + } + } /** * Determines the maximum span for this view along an @@ -347,7 +408,7 @@ public class FormView extends ComponentView implements ActionListener { /** - * Responsible for processeing the ActionEvent. + * Responsible for processing the ActionEvent. * If the element associated with the FormView, * has a type of "submit", "reset", "text" or "password" * then the action is processed. In the case of a "submit" diff --git a/jdk/src/share/classes/sun/applet/AppletPanel.java b/jdk/src/share/classes/sun/applet/AppletPanel.java index e090beec417..5ca566214db 100644 --- a/jdk/src/share/classes/sun/applet/AppletPanel.java +++ b/jdk/src/share/classes/sun/applet/AppletPanel.java @@ -45,6 +45,7 @@ import java.util.*; import java.util.Collections; import java.util.Locale; import java.util.WeakHashMap; +import sun.awt.AWTAccessor; import sun.awt.AppContext; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; @@ -448,12 +449,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // to avoid deadlock. try { final AppletPanel p = this; - - EventQueue.invokeAndWait(new Runnable() { - public void run() { - p.validate(); - } - }); + Runnable r = new Runnable() { + public void run() { + p.validate(); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -478,18 +479,19 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { try { final AppletPanel p = this; final Applet a = applet; + Runnable r = new Runnable() { + public void run() { + p.validate(); + a.setVisible(true); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - p.validate(); - a.setVisible(true); - - // Fix for BugTraq ID 4041703. - // Set the default focus for an applet. - if (hasInitialFocus()) - setDefaultFocus(); + // Fix for BugTraq ID 4041703. + // Set the default focus for an applet. + if (hasInitialFocus()) { + setDefaultFocus(); } - }); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -512,13 +514,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // to avoid deadlock. try { final Applet a = applet; - - EventQueue.invokeAndWait(new Runnable() { - public void run() - { - a.setVisible(false); - } - }); + Runnable r = new Runnable() { + public void run() { + a.setVisible(false); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -570,17 +571,14 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { } status = APPLET_DISPOSE; - try - { + try { final Applet a = applet; - - EventQueue.invokeAndWait(new Runnable() - { - public void run() - { + Runnable r = new Runnable() { + public void run() { remove(a); } - }); + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 03486cdae49..1907ac4c7c1 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -34,6 +34,8 @@ import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.geom.Point2D; import java.awt.peer.ComponentPeer; + +import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; import java.io.File; @@ -476,6 +478,12 @@ public final class AWTAccessor { * appeared. */ void wakeup(EventQueue eventQueue, boolean isShutdown); + + /** + * Static in EventQueue + */ + void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException; } /* diff --git a/jdk/src/share/classes/sun/awt/AppContext.java b/jdk/src/share/classes/sun/awt/AppContext.java index 0756b6c82bd..47f472737ea 100644 --- a/jdk/src/share/classes/sun/awt/AppContext.java +++ b/jdk/src/share/classes/sun/awt/AppContext.java @@ -327,21 +327,27 @@ public final class AppContext { // Before we return the main "system" AppContext, check to // see if there's an AWTSecurityManager installed. If so, // allow it to choose the AppContext to return. - SecurityManager securityManager = System.getSecurityManager(); - if ((securityManager != null) && - (securityManager instanceof AWTSecurityManager)) - { - AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager; - AppContext secAppContext = awtSecMgr.getAppContext(); - if (secAppContext != null) { - appContext = secAppContext; // Return what we're told - } + AppContext secAppContext = getExecutionAppContext(); + if (secAppContext != null) { + appContext = secAppContext; // Return what we're told } } return appContext; } + private final static AppContext getExecutionAppContext() { + SecurityManager securityManager = System.getSecurityManager(); + if ((securityManager != null) && + (securityManager instanceof AWTSecurityManager)) + { + AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager; + AppContext secAppContext = awtSecMgr.getAppContext(); + return secAppContext; // Return what we're told + } + return null; + } + /** * Returns the main ("system") AppContext. * @@ -806,6 +812,21 @@ public final class AppContext { public boolean isMainAppContext() { return (numAppContexts.get() == 1); } + public Object getContext() { + return getAppContext(); + } + public Object getExecutionContext() { + return getExecutionAppContext(); + } + public Object get(Object context, Object key) { + return ((AppContext)context).get(key); + } + public void put(Object context, Object key, Object value) { + ((AppContext)context).put(key, value); + } + public void remove(Object context, Object key) { + ((AppContext)context).remove(key); + } }); } } diff --git a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java index d05e30fe742..0ae1ec762df 100644 --- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java +++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java @@ -582,5 +582,8 @@ public abstract class EmbeddedFrame extends Frame public void repositionSecurityWarning() { } - } + + public void emulateActivation(boolean activate) { + } + } } // class EmbeddedFrame diff --git a/jdk/src/share/classes/sun/awt/HToolkit.java b/jdk/src/share/classes/sun/awt/HToolkit.java index 57217678bfc..8671d8b5150 100644 --- a/jdk/src/share/classes/sun/awt/HToolkit.java +++ b/jdk/src/share/classes/sun/awt/HToolkit.java @@ -64,6 +64,11 @@ public class HToolkit extends SunToolkit throw new HeadlessException(); } + public FramePeer createLightweightFrame(LightweightFrame target) + throws HeadlessException { + throw new HeadlessException(); + } + public FramePeer createFrame(Frame target) throws HeadlessException { throw new HeadlessException(); diff --git a/jdk/src/share/classes/sun/awt/LightweightFrame.java b/jdk/src/share/classes/sun/awt/LightweightFrame.java new file mode 100644 index 00000000000..71e3dd30333 --- /dev/null +++ b/jdk/src/share/classes/sun/awt/LightweightFrame.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt; + +import java.awt.Container; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.MenuBar; +import java.awt.MenuComponent; +import java.awt.Toolkit; +import java.awt.peer.FramePeer; + +/** + * The class provides basic functionality for a lightweight frame + * implementation. A subclass is expected to provide painting to an + * offscreen image and access to it. Thus it can be used for lightweight + * embedding. + * + * @author Artem Ananiev + * @author Anton Tarasov + */ +@SuppressWarnings("serial") +public abstract class LightweightFrame extends Frame { + + /** + * Constructs a new, initially invisible {@code LightweightFrame} + * instance. + */ + public LightweightFrame() { + setUndecorated(true); + setResizable(true); + setEnabled(true); + } + + /** + * Blocks introspection of a parent window by this child. + * + * @return null + */ + @Override public final Container getParent() { return null; } + + @Override public Graphics getGraphics() { return null; } + + @Override public final boolean isResizable() { return true; } + + // Block modification of any frame attributes, since they aren't + // applicable for a lightweight frame. + + @Override public final void setTitle(String title) {} + @Override public final void setIconImage(Image image) {} + @Override public final void setIconImages(java.util.List icons) {} + @Override public final void setMenuBar(MenuBar mb) {} + @Override public final void setResizable(boolean resizable) {} + @Override public final void remove(MenuComponent m) {} + @Override public final void toFront() {} + @Override public final void toBack() {} + + @Override public void addNotify() { + synchronized (getTreeLock()) { + if (getPeer() == null) { + SunToolkit stk = (SunToolkit)Toolkit.getDefaultToolkit(); + try { + setPeer(stk.createLightweightFrame(this)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + super.addNotify(); + } + } + + private void setPeer(final FramePeer p) { + AWTAccessor.getComponentAccessor().setPeer(this, p); + } + + /** + * Requests the peer to emulate activation or deactivation of the + * frame. Peers should override this method if they are to implement + * this functionality. + * + * @param activate if true, activates the frame; + * otherwise, deactivates the frame + */ + public void emulateActivation(boolean activate) { + ((FramePeer)getPeer()).emulateActivation(activate); + } + + /** + * Delegates the focus grab action to the client (embedding) application. + * The method is called by the AWT grab machinery. + * + * @see SunToolkit#grab(java.awt.Window) + */ + public abstract void grabFocus(); + + /** + * Delegates the focus ungrab action to the client (embedding) application. + * The method is called by the AWT grab machinery. + * + * @see SunToolkit#ungrab(java.awt.Window) + */ + public abstract void ungrabFocus(); +} diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 4ae6a94f0dc..8fc568913fb 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -131,6 +131,9 @@ public abstract class SunToolkit extends Toolkit public abstract FramePeer createFrame(Frame target) throws HeadlessException; + public abstract FramePeer createLightweightFrame(LightweightFrame target) + throws HeadlessException; + public abstract DialogPeer createDialog(Dialog target) throws HeadlessException; diff --git a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java index f8dd9dfc380..7465d52c8bf 100644 --- a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -1873,7 +1873,7 @@ search: */ public class ReencodingInputStream extends InputStream { protected BufferedReader wrapped; - protected final char[] in = new char[1]; + protected final char[] in = new char[2]; protected byte[] out; protected CharsetEncoder encoder; @@ -1926,7 +1926,7 @@ search: try { encoder = Charset.forName(targetEncoding).newEncoder(); - out = new byte[(int)(encoder.maxBytesPerChar() + 0.5)]; + out = new byte[(int)(encoder.maxBytesPerChar() * 2 + 0.5)]; inBuf = CharBuffer.wrap(in); outBuf = ByteBuffer.wrap(out); } catch (IllegalCharsetNameException e) { @@ -1950,31 +1950,50 @@ search: } } + private int readChar() throws IOException { + int c = wrapped.read(); + + if (c == -1) { // -1 is EOS + eos = true; + return -1; + } + + // "c == 0" is not quite correct, but good enough on Windows. + if (numTerminators > 0 && c == 0) { + eos = true; + return -1; + } else if (eoln != null && matchCharArray(eoln, c)) { + c = '\n' & 0xFFFF; + } + + return c; + } + public int read() throws IOException { if (eos) { return -1; } if (index >= limit) { - int c = wrapped.read(); - - if (c == -1) { // -1 is EOS - eos = true; + // deal with supplementary characters + int c = readChar(); + if (c == -1) { return -1; } - // "c == 0" is not quite correct, but good enough on Windows. - if (numTerminators > 0 && c == 0) { - eos = true; - return -1; - } else if (eoln != null && matchCharArray(eoln, c)) { - c = '\n' & 0xFFFF; + in[0] = (char) c; + in[1] = 0; + inBuf.limit(1); + if (Character.isHighSurrogate((char) c)) { + c = readChar(); + if (c != -1) { + in[1] = (char) c; + inBuf.limit(2); + } } - in[0] = (char)c; - inBuf.rewind(); - outBuf.rewind(); + outBuf.limit(out.length).rewind(); encoder.encode(inBuf, outBuf, false); outBuf.flip(); limit = outBuf.limit(); diff --git a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java index 302a6dbc62e..360bb9a63a6 100644 --- a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java +++ b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java @@ -498,7 +498,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, SunDropTargetEvent.MOUSE_DROPPED, - SunDropTargetContextPeer.DISPATCH_SYNC); + !SunDropTargetContextPeer.DISPATCH_SYNC); } /** diff --git a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java index c92f7665904..49c642e37db 100644 --- a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java @@ -198,7 +198,7 @@ public class ByteComponentRaster extends SunWritableRaster { } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -857,38 +857,68 @@ public class ByteComponentRaster extends SunWritableRaster { } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + protected final void verify() { + for (int i = 0; i < dataOffsets.length; i++) { if (dataOffsets[i] < 0) { - throw new RasterFormatException("Data offsets for band "+i+ - "("+dataOffsets[i]+ - ") must be >= 0"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // we can be sure that width and height are greater than 0 + if (scanlineStride < 0 || + scanlineStride > (Integer.MAX_VALUE / height)) + { + // integer overflow + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + int lastScanOffset = (height - 1) * scanlineStride; + + if (pixelStride < 0 || + pixelStride > (Integer.MAX_VALUE / width)) + { + // integer overflow + throw new RasterFormatException("Incorrect pixel stride: " + + pixelStride); + } + int lastPixelOffset = (width - 1) * pixelStride; + + if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { + // integer overflow + throw new RasterFormatException("Incorrect raster attributes"); + } + lastPixelOffset += lastScanOffset; + + for (int i = 0; i < numDataElements; i++) { + size = lastPixelOffset + dataOffsets[i]; + if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { + throw new RasterFormatException("Incorrect band offset: " + + dataOffsets[i]); + + } + if (size > maxSize) { maxSize = size; } } if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff --git a/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java b/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java index b721d686867..4279ce1f90a 100644 --- a/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -250,7 +250,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { } } - verify(false); + verify(); } /** @@ -1292,33 +1292,6 @@ public class ByteInterleavedRaster extends ByteComponentRaster { return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ByteInterleavedRaster: width = "+width+" height = " + height diff --git a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java index bc39bd2f0c8..df2c0f7d663 100644 --- a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java @@ -198,7 +198,7 @@ public class ShortComponentRaster extends SunWritableRaster { } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -791,38 +791,67 @@ public class ShortComponentRaster extends SunWritableRaster { } /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. + * Verify that the layout parameters are consistent with the data. + * + * The method verifies whether scanline stride and pixel stride do not + * cause an integer overflow during calculation of a position of the pixel + * in data buffer. It also verifies whether the data buffer has enough data + * to correspond the raster layout attributes. + * + * @throws RasterFormatException if an integer overflow is detected, + * or if data buffer has not enough capacity. */ - private void verify (boolean strictCheck) { - // Make sure data for Raster is in a legal range - for (int i=0; i < dataOffsets.length; i++) { + protected final void verify() { + for (int i = 0; i < dataOffsets.length; i++) { if (dataOffsets[i] < 0) { - throw new RasterFormatException("Data offsets for band "+i+ - "("+dataOffsets[i]+ - ") must be >= 0"); + throw new RasterFormatException("Data offsets for band " + i + + "(" + dataOffsets[i] + + ") must be >= 0"); } } int maxSize = 0; int size; - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; + // we can be sure that width and height are greater than 0 + if (scanlineStride < 0 || + scanlineStride > (Integer.MAX_VALUE / height)) + { + // integer overflow + throw new RasterFormatException("Incorrect scanline stride: " + + scanlineStride); + } + int lastScanOffset = (height - 1) * scanlineStride; + + if (pixelStride < 0 || + pixelStride > (Integer.MAX_VALUE / width)) + { + // integer overflow + throw new RasterFormatException("Incorrect pixel stride: " + + pixelStride); + } + int lastPixelOffset = (width - 1) * pixelStride; + + if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) { + // integer overflow + throw new RasterFormatException("Incorrect raster attributes"); + } + lastPixelOffset += lastScanOffset; + + for (int i = 0; i < numDataElements; i++) { + size = lastPixelOffset + dataOffsets[i]; + if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { + throw new RasterFormatException("Incorrect band offset: " + + dataOffsets[i]); + } + if (size > maxSize) { maxSize = size; } } if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); + throw new RasterFormatException("Data array too small (should be " + + maxSize + " )"); } } diff --git a/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java b/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java index ef624f978c2..c55d111d7fd 100644 --- a/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -171,7 +171,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { sampleModel); } this.bandOffset = this.dataOffsets[0]; - verify(false); + verify(); } /** @@ -762,33 +762,6 @@ public class ShortInterleavedRaster extends ShortComponentRaster { return createCompatibleWritableRaster(width,height); } - /** - * Verify that the layout parameters are consistent with - * the data. If strictCheck - * is false, this method will check for ArrayIndexOutOfBounds conditions. If - * strictCheck is true, this method will check for additional error - * conditions such as line wraparound (width of a line greater than - * the scanline stride). - * @return String Error string, if the layout is incompatible with - * the data. Otherwise returns null. - */ - private void verify (boolean strictCheck) { - int maxSize = 0; - int size; - - for (int i=0; i < numDataElements; i++) { - size = (height-1)*scanlineStride + (width-1)*pixelStride + - dataOffsets[i]; - if (size > maxSize) { - maxSize = size; - } - } - if (data.length < maxSize) { - throw new RasterFormatException("Data array too small (should be "+ - maxSize+" )"); - } - } - public String toString() { return new String ("ShortInterleavedRaster: width = "+width +" height = " + height diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java index 5cfda3cdb74..c6eae65a73a 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java @@ -25,29 +25,91 @@ package sun.java2d.cmm.lcms; -import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; -import java.awt.color.CMMException; +import java.util.Arrays; +import java.util.HashMap; import sun.java2d.cmm.ColorTransform; import sun.java2d.cmm.PCMM; -import sun.java2d.cmm.lcms.LCMS; -import sun.java2d.cmm.lcms.LCMSTransform; public class LCMS implements PCMM { /* methods invoked from ICC_Profile */ - public native long loadProfile(byte[] data); + @Override + public long loadProfile(byte[] data) { + long id = loadProfileNative(data); - public native void freeProfile(long profileID); + if (id != 0L) { + if (profiles == null) { + profiles = new HashMap<>(); + } + profiles.put(id, new TagCache(id)); + } + return id; + } + + private native long loadProfileNative(byte[] data); + + @Override + public void freeProfile(long profileID) { + TagCache c = profiles.remove(profileID); + if (c != null) { + c.clear(); + } + if (profiles.isEmpty()) { + profiles = null; + } + freeProfileNative(profileID); + } + + private native void freeProfileNative(long profileID); public native synchronized int getProfileSize(long profileID); public native synchronized void getProfileData(long profileID, byte[] data); - public native synchronized int getTagSize(long profileID, int tagSignature); - public native synchronized void getTagData(long profileID, int tagSignature, - byte[] data); - public native synchronized void setTagData(long profileID, int tagSignature, + @Override + public synchronized int getTagSize(long profileID, int tagSignature) { + TagCache cache = profiles.get(profileID); + + if (cache == null) { + cache = new TagCache(profileID); + profiles.put(profileID, cache); + } + + TagData t = cache.getTag(tagSignature); + return t == null ? 0 : t.getSize(); + } + + private static native byte[] getTagNative(long profileID, int signature); + + @Override + public synchronized void getTagData(long profileID, int tagSignature, + byte[] data) + { + TagCache cache = profiles.get(profileID); + + if (cache == null) { + cache = new TagCache(profileID); + profiles.put(profileID, cache); + } + + TagData t = cache.getTag(tagSignature); + if (t != null) { + t.copyDataTo(data); + } + } + + @Override + public synchronized void setTagData(long profileID, int tagSignature, byte[] data) { + TagCache cache = profiles.get(profileID); + + if (cache != null) { + cache.clear(); + } + setTagDataNative(profileID, tagSignature, data); + } + + private native synchronized void setTagDataNative(long profileID, int tagSignature, byte[] data); public static native long getProfileID(ICC_Profile profile); @@ -103,4 +165,59 @@ public class LCMS implements PCMM { initLCMS(LCMSTransform.class, LCMSImageLayout.class, ICC_Profile.class); } + + private static class TagData { + private int signature; + private byte[] data; + + TagData(int sig, byte[] data) { + this.signature = sig; + this.data = data; + } + + int getSize() { + return data.length; + } + + byte[] getData() { + return Arrays.copyOf(data, data.length); + } + + void copyDataTo(byte[] dst) { + System.arraycopy(data, 0, dst, 0, data.length); + } + + int getSignature() { + return signature; + } + } + + private static class TagCache { + private long profileID; + private HashMap tags; + + TagCache(long id) { + profileID = id; + + tags = new HashMap<>(); + } + + TagData getTag(int sig) { + TagData t = tags.get(sig); + if (t == null) { + byte[] tagData = getTagNative(profileID, sig); + if (tagData != null) { + t = new TagData(sig, tagData); + tags.put(sig, t); + } + } + return t; + } + + void clear() { + tags.clear(); + } + } + + private static HashMap profiles; } diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java index 3695a163211..b53bd9a45d3 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSImageLayout.java @@ -22,26 +22,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.java2d.cmm.lcms; -import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.ComponentColorModel; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.DataBufferUShort; -import java.awt.image.DataBufferInt; import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.awt.image.SampleModel; import sun.awt.image.ByteComponentRaster; import sun.awt.image.ShortComponentRaster; import sun.awt.image.IntegerComponentRaster; - class LCMSImageLayout { public static int BYTES_SH(int x) { @@ -49,47 +42,34 @@ class LCMSImageLayout { } public static int EXTRA_SH(int x) { - return x<<7; + return x << 7; } public static int CHANNELS_SH(int x) { - return x<<3; + return x << 3; } - - public static final int SWAPFIRST = 1<<14; - - public static final int DOSWAP = 1<<10; - + public static final int SWAPFIRST = 1 << 14; + public static final int DOSWAP = 1 << 10; public static final int PT_RGB_8 = - CHANNELS_SH(3) | BYTES_SH(1); - + CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_GRAY_8 = - CHANNELS_SH(1) | BYTES_SH(1); - + CHANNELS_SH(1) | BYTES_SH(1); public static final int PT_GRAY_16 = - CHANNELS_SH(1) | BYTES_SH(2); - + CHANNELS_SH(1) | BYTES_SH(2); public static final int PT_RGBA_8 = - EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); - + EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_ARGB_8 = - EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST; - + EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1) | SWAPFIRST; public static final int PT_BGR_8 = - DOSWAP | CHANNELS_SH(3) | BYTES_SH(1); - + DOSWAP | CHANNELS_SH(3) | BYTES_SH(1); public static final int PT_ABGR_8 = - DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); - - public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) | - BYTES_SH(1) | DOSWAP | SWAPFIRST; - - public static final int DT_BYTE = 0; - public static final int DT_SHORT = 1; - public static final int DT_INT = 2; - public static final int DT_DOUBLE = 3; - - + DOSWAP | EXTRA_SH(1) | CHANNELS_SH(3) | BYTES_SH(1); + public static final int PT_BGRA_8 = EXTRA_SH(1) | CHANNELS_SH(3) + | BYTES_SH(1) | DOSWAP | SWAPFIRST; + public static final int DT_BYTE = 0; + public static final int DT_SHORT = 1; + public static final int DT_INT = 2; + public static final int DT_DOUBLE = 3; boolean isIntPacked = false; int pixelType; int dataType; @@ -98,25 +78,30 @@ class LCMSImageLayout { int nextRowOffset; int offset; + /* This flag indicates whether the image can be processed + * at once by doTransfrom() native call. Otherwise, the + * image is processed scan by scan. + */ + private boolean imageAtOnce = false; Object dataArray; + private LCMSImageLayout(int np, int pixelType, int pixelSize) { this.pixelType = pixelType; width = np; height = 1; - nextRowOffset = np*pixelSize; + nextRowOffset = np * pixelSize; offset = 0; } private LCMSImageLayout(int width, int height, int pixelType, - int pixelSize) { + int pixelSize) { this.pixelType = pixelType; this.width = width; this.height = height; - nextRowOffset = width*pixelSize; + nextRowOffset = width * pixelSize; offset = 0; } - public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) { this(np, pixelType, pixelSize); dataType = DT_BYTE; @@ -135,102 +120,218 @@ class LCMSImageLayout { dataArray = data; } - public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) - { + public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) { this(np, pixelType, pixelSize); dataType = DT_DOUBLE; dataArray = data; } - public LCMSImageLayout(BufferedImage image) { - ShortComponentRaster shortRaster; - IntegerComponentRaster intRaster; - ByteComponentRaster byteRaster; + private LCMSImageLayout() { + } + + /* This method creates a layout object for given image. + * Returns null if the image is not supported by current implementation. + */ + public static LCMSImageLayout createImageLayout(BufferedImage image) { + LCMSImageLayout l = new LCMSImageLayout(); + switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: - pixelType = PT_ARGB_8; - isIntPacked = true; + l.pixelType = PT_ARGB_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_INT_ARGB: - pixelType = PT_ARGB_8; - isIntPacked = true; + l.pixelType = PT_ARGB_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_INT_BGR: - pixelType = PT_ABGR_8; - isIntPacked = true; + l.pixelType = PT_ABGR_8; + l.isIntPacked = true; break; case BufferedImage.TYPE_3BYTE_BGR: - pixelType = PT_BGR_8; + l.pixelType = PT_BGR_8; break; case BufferedImage.TYPE_4BYTE_ABGR: - pixelType = PT_ABGR_8; + l.pixelType = PT_ABGR_8; break; case BufferedImage.TYPE_BYTE_GRAY: - pixelType = PT_GRAY_8; + l.pixelType = PT_GRAY_8; break; case BufferedImage.TYPE_USHORT_GRAY: - pixelType = PT_GRAY_16; + l.pixelType = PT_GRAY_16; break; default: - // TODO: Add support for some images having - // SinglePixelPackedModel and ComponentSampleModel - throw new IllegalArgumentException( - "CMMImageLayout - bad image type passed to constructor"); + /* ColorConvertOp creates component images as + * default destination, so this kind of images + * has to be supported. + */ + ColorModel cm = image.getColorModel(); + if (cm instanceof ComponentColorModel) { + ComponentColorModel ccm = (ComponentColorModel) cm; + + // verify whether the component size is fine + int[] cs = ccm.getComponentSize(); + for (int s : cs) { + if (s != 8) { + return null; + } + } + + return createImageLayout(image.getRaster()); + + } + return null; } - width = image.getWidth(); - height = image.getHeight(); + l.width = image.getWidth(); + l.height = image.getHeight(); switch (image.getType()) { case BufferedImage.TYPE_INT_RGB: case BufferedImage.TYPE_INT_ARGB: case BufferedImage.TYPE_INT_BGR: - intRaster = (IntegerComponentRaster)image.getRaster(); - nextRowOffset = intRaster.getScanlineStride()*4; - offset = intRaster.getDataOffset(0)*4; - dataArray = intRaster.getDataStorage(); - dataType = DT_INT; + do { + IntegerComponentRaster intRaster = (IntegerComponentRaster) + image.getRaster(); + l.nextRowOffset = intRaster.getScanlineStride() * 4; + l.offset = intRaster.getDataOffset(0) * 4; + l.dataArray = intRaster.getDataStorage(); + l.dataType = DT_INT; + + if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_3BYTE_BGR: case BufferedImage.TYPE_4BYTE_ABGR: - byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); - int firstBand = image.getSampleModel().getNumBands() - 1; - offset = byteRaster.getDataOffset(firstBand); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + do { + ByteComponentRaster byteRaster = (ByteComponentRaster) + image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); + int firstBand = image.getSampleModel().getNumBands() - 1; + l.offset = byteRaster.getDataOffset(firstBand); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_BYTE_GRAY: - byteRaster = (ByteComponentRaster)image.getRaster(); - nextRowOffset = byteRaster.getScanlineStride(); - offset = byteRaster.getDataOffset(0); - dataArray = byteRaster.getDataStorage(); - dataType = DT_BYTE; + do { + ByteComponentRaster byteRaster = (ByteComponentRaster) + image.getRaster(); + l.nextRowOffset = byteRaster.getScanlineStride(); + l.offset = byteRaster.getDataOffset(0); + l.dataArray = byteRaster.getDataStorage(); + l.dataType = DT_BYTE; + + if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; case BufferedImage.TYPE_USHORT_GRAY: - shortRaster = (ShortComponentRaster)image.getRaster(); - nextRowOffset = shortRaster.getScanlineStride()*2; - offset = shortRaster.getDataOffset(0) * 2; - dataArray = shortRaster.getDataStorage(); - dataType = DT_SHORT; + do { + ShortComponentRaster shortRaster = (ShortComponentRaster) + image.getRaster(); + l.nextRowOffset = shortRaster.getScanlineStride() * 2; + l.offset = shortRaster.getDataOffset(0) * 2; + l.dataArray = shortRaster.getDataStorage(); + l.dataType = DT_SHORT; + + if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) { + l.imageAtOnce = true; + } + } while (false); break; + default: + return null; + } + return l; + } + + private static enum BandOrder { + DIRECT, + INVERTED, + ARBITRARY, + UNKNOWN; + + public static BandOrder getBandOrder(int[] bandOffsets) { + BandOrder order = UNKNOWN; + + int numBands = bandOffsets.length; + + for (int i = 0; (order != ARBITRARY) && (i < bandOffsets.length); i++) { + switch (order) { + case UNKNOWN: + if (bandOffsets[i] == i) { + order = DIRECT; + } else if (bandOffsets[i] == (numBands - 1 - i)) { + order = INVERTED; + } else { + order = ARBITRARY; + } + break; + case DIRECT: + if (bandOffsets[i] != i) { + order = ARBITRARY; + } + break; + case INVERTED: + if (bandOffsets[i] != (numBands - 1 - i)) { + order = ARBITRARY; + } + break; + } + } + return order; } } - public static boolean isSupported(BufferedImage image) { - switch (image.getType()) { - case BufferedImage.TYPE_INT_RGB: - case BufferedImage.TYPE_INT_ARGB: - case BufferedImage.TYPE_INT_BGR: - case BufferedImage.TYPE_3BYTE_BGR: - case BufferedImage.TYPE_4BYTE_ABGR: - case BufferedImage.TYPE_BYTE_GRAY: - case BufferedImage.TYPE_USHORT_GRAY: - return true; + public static LCMSImageLayout createImageLayout(Raster r) { + LCMSImageLayout l = new LCMSImageLayout(); + if (r instanceof ByteComponentRaster) { + ByteComponentRaster br = (ByteComponentRaster)r; + + ComponentSampleModel csm = (ComponentSampleModel)r.getSampleModel(); + + l.pixelType = CHANNELS_SH(br.getNumBands()) | BYTES_SH(1); + + int[] bandOffsets = csm.getBandOffsets(); + BandOrder order = BandOrder.getBandOrder(bandOffsets); + + int firstBand = 0; + switch (order) { + case INVERTED: + l.pixelType |= DOSWAP; + firstBand = csm.getNumBands() - 1; + break; + case DIRECT: + // do nothing + break; + default: + // unable to create the image layout; + return null; + } + + l.nextRowOffset = br.getScanlineStride(); + l.offset = br.getDataOffset(firstBand); + l.dataArray = br.getDataStorage(); + l.dataType = DT_BYTE; + + l.width = br.getWidth(); + l.height = br.getHeight(); + + if (l.nextRowOffset == l.width * br.getPixelStride()) { + l.imageAtOnce = true; + } + return l; } - return false; + return null; } } diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java index aa9d0bf054f..de8a77c75f3 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java @@ -161,13 +161,18 @@ public class LCMSTransform implements ColorTransform { } public void colorConvert(BufferedImage src, BufferedImage dst) { - if (LCMSImageLayout.isSupported(src) && - LCMSImageLayout.isSupported(dst)) - { - doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst)); - return; - } LCMSImageLayout srcIL, dstIL; + + dstIL = LCMSImageLayout.createImageLayout(dst); + + if (dstIL != null) { + srcIL = LCMSImageLayout.createImageLayout(src); + if (srcIL != null) { + doTransform(srcIL, dstIL); + return; + } + } + Raster srcRas = src.getRaster(); WritableRaster dstRas = dst.getRaster(); ColorModel srcCM = src.getColorModel(); @@ -439,6 +444,14 @@ public class LCMSTransform implements ColorTransform { public void colorConvert(Raster src, WritableRaster dst) { LCMSImageLayout srcIL, dstIL; + dstIL = LCMSImageLayout.createImageLayout(dst); + if (dstIL != null) { + srcIL = LCMSImageLayout.createImageLayout(src); + if (srcIL != null) { + doTransform(srcIL, dstIL); + return; + } + } // Can't pass src and dst directly to CMM, so process per scanline SampleModel srcSM = src.getSampleModel(); SampleModel dstSM = dst.getSampleModel(); diff --git a/jdk/src/share/classes/sun/misc/ClassFileTransformer.java b/jdk/src/share/classes/sun/misc/ClassFileTransformer.java index 61524ba3b30..669b9e8aac8 100644 --- a/jdk/src/share/classes/sun/misc/ClassFileTransformer.java +++ b/jdk/src/share/classes/sun/misc/ClassFileTransformer.java @@ -25,43 +25,31 @@ package sun.misc; import java.util.ArrayList; +import java.util.List; /** - * This is an abstract base class which is called by java.lang.ClassLoader - * when ClassFormatError is thrown inside defineClass(). - * - * The purpose of this class is to allow applications (e.g. Java Plug-in) - * to have a chance to transform the byte code from one form to another - * if necessary. - * - * One application of this class is used by Java Plug-in to transform - * malformed JDK 1.1 class file into a well-formed Java 2 class file - * on-the-fly, so JDK 1.1 applets with malformed class file in the - * Internet may run in Java 2 after transformation. + * This is an abstract base class originally intended to be called by + * {@code java.lang.ClassLoader} when {@code ClassFormatError} is + * thrown inside {@code defineClass()}. It is no longer hooked into + * {@code ClassLoader} and will be removed in a future release. * * @author Stanley Man-Kit Ho */ -public abstract class ClassFileTransformer -{ - // Singleton of ClassFileTransformer - // - private static ArrayList transformerList +@Deprecated +public abstract class ClassFileTransformer { + + private static final List transformers = new ArrayList(); - private static ClassFileTransformer[] transformers - = new ClassFileTransformer[0]; /** * Add the class file transformer object. * * @param t Class file transformer instance */ - public static void add(ClassFileTransformer t) - { - synchronized(transformerList) - { - transformerList.add(t); - transformers = transformerList.toArray(new ClassFileTransformer[0]); + public static void add(ClassFileTransformer t) { + synchronized (transformers) { + transformers.add(t); } } @@ -70,13 +58,11 @@ public abstract class ClassFileTransformer * * @return ClassFileTransformer object array */ - public static ClassFileTransformer[] getTransformers() - { - // transformers is not intended to be changed frequently, - // so it is okay to not put synchronized block here - // to speed up performance. - // - return transformers; + public static ClassFileTransformer[] getTransformers() { + synchronized (transformers) { + ClassFileTransformer[] result = new ClassFileTransformer[transformers.size()]; + return transformers.toArray(result); + } } @@ -89,5 +75,5 @@ public abstract class ClassFileTransformer * @return Transformed byte array */ public abstract byte[] transform(byte[] b, int off, int len) - throws ClassFormatError; + throws ClassFormatError; } diff --git a/jdk/src/share/classes/sun/misc/JavaAWTAccess.java b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java index 6e3712592ce..e64a38b22c9 100644 --- a/jdk/src/share/classes/sun/misc/JavaAWTAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java @@ -26,6 +26,14 @@ package sun.misc; public interface JavaAWTAccess { + public Object getContext(); + public Object getExecutionContext(); + + public Object get(Object context, Object key); + public void put(Object context, Object key, Object value); + public void remove(Object context, Object key); + + // convenience methods whose context is the object returned by getContext() public Object get(Object key); public void put(Object key, Object value); public void remove(Object key); diff --git a/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java b/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java index 81654824c3a..9b09cd23b1a 100644 --- a/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java @@ -35,6 +35,7 @@ import java.util.jar.JarFile; public interface JavaUtilJarAccess { public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; + public boolean jarFileHasProfileAttribute(JarFile jar) throws IOException; public CodeSource[] getCodeSources(JarFile jar, URL url); public CodeSource getCodeSource(JarFile jar, URL url, String name); public Enumeration entryNames(JarFile jar, CodeSource[] cs); diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java index b8036ab3864..068bd72897c 100644 --- a/jdk/src/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java @@ -808,9 +808,6 @@ public class URLClassPath { /** * If the Profile attribute is present then this method checks that the runtime * supports that profile. - * - * ## Add a fast path like Class-Path to avoid reading the manifest when the attribute - * is not present. */ void checkProfileAttribute() throws IOException { Manifest man = jar.getManifest(); @@ -998,7 +995,8 @@ public class URLClassPath { parseExtensionsDependencies(); // check Profile attribute if present - if (!profileCheckSuppressedByLauncher) { + if (!profileCheckSuppressedByLauncher && + SharedSecrets.javaUtilJarAccess().jarFileHasProfileAttribute(jar)) { checkProfileAttribute(); } diff --git a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java index 4adab7d52ed..387ec1c8e62 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +++ b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java @@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOverInputStream { private boolean needToReadHeader = true; - static char CR = '\r'; - static char LF = '\n'; + final static char CR = '\r'; + final static char LF = '\n'; + /* + * Maximum chunk header size of 2KB + 2 bytes for CRLF + */ + private final static int MAX_CHUNK_HEADER_SIZE = 2050; private int numeric (char[] arr, int nchars) throws IOException { assert arr.length >= nchars; @@ -73,10 +77,14 @@ class ChunkedInputStream extends LeftOverInputStream { char[] len_arr = new char [16]; int len_size = 0; boolean end_of_len = false; + int read = 0; while ((c=in.read())!= -1) { char ch = (char) c; - if (len_size == len_arr.length -1) { + read++; + if ((len_size == len_arr.length -1) || + (read > MAX_CHUNK_HEADER_SIZE)) + { throw new IOException ("invalid chunk header"); } if (gotCR) { diff --git a/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java b/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java index 3dd445e7488..af45752206f 100644 --- a/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java +++ b/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java @@ -125,6 +125,11 @@ class ChunkedInputStream extends InputStream implements Hurryable { */ private boolean closed; + /* + * Maximum chunk header size of 2KB + 2 bytes for CRLF + */ + private final static int MAX_CHUNK_HEADER_SIZE = 2050; + /** * State to indicate that next field should be :- * chunk-size [ chunk-extension ] CRLF @@ -290,6 +295,10 @@ class ChunkedInputStream extends InputStream implements Hurryable { break; } pos++; + if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) { + error = true; + throw new IOException("Chunk header too long"); + } } if (pos >= rawCount) { return; diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 8003b5a5433..711a1b15a84 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -2637,7 +2637,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { multipleCookies = true; } - return retValue.length() == 0 ? null : retValue.toString(); + return retValue.length() == 0 ? "" : retValue.toString(); } return value; diff --git a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 3d60a38d74c..ff2ee589600 100644 --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -421,7 +421,7 @@ class DatagramChannelImpl synchronized (writeLock) { ensureOpen(); - InetSocketAddress isa = (InetSocketAddress)target; + InetSocketAddress isa = Net.checkAddress(target); InetAddress ia = isa.getAddress(); if (ia == null) throw new IOException("Target address not resolved"); @@ -432,9 +432,9 @@ class DatagramChannelImpl SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ia.isMulticastAddress()) { - sm.checkMulticast(isa.getAddress()); + sm.checkMulticast(ia); } else { - sm.checkConnect(isa.getAddress().getHostAddress(), + sm.checkConnect(ia.getHostAddress(), isa.getPort()); } } @@ -454,7 +454,7 @@ class DatagramChannelImpl return 0; writerThread = NativeThread.current(); do { - n = send(fd, src, target); + n = send(fd, src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); synchronized (stateLock) { @@ -471,7 +471,7 @@ class DatagramChannelImpl } } - private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) + private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) throws IOException { if (src instanceof DirectBuffer) @@ -502,7 +502,7 @@ class DatagramChannelImpl } private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, - SocketAddress target) + InetSocketAddress target) throws IOException { int pos = bb.position(); @@ -514,7 +514,7 @@ class DatagramChannelImpl int written; try { written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos, - rem, target); + rem, target.getAddress(), target.getPort()); } catch (PortUnreachableException pue) { if (isConnected()) throw pue; @@ -1116,8 +1116,8 @@ class DatagramChannelImpl boolean connected) throws IOException; - private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len, - SocketAddress sa) + private native int send0(boolean preferIPv6, FileDescriptor fd, long address, + int len, InetAddress addr, int port) throws IOException; static { diff --git a/jdk/src/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/share/classes/sun/print/RasterPrinterJob.java index 404f66cc26f..24bece595f8 100644 --- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java @@ -527,9 +527,92 @@ public abstract class RasterPrinterJob extends PrinterJob { } } + private PageFormat attributeToPageFormat(PrintService service, + PrintRequestAttributeSet attSet) { + PageFormat page = defaultPage(); + + if (service == null) { + return page; + } + + OrientationRequested orient = (OrientationRequested) + attSet.get(OrientationRequested.class); + if (orient == null) { + orient = (OrientationRequested) + service.getDefaultAttributeValue(OrientationRequested.class); + } + if (orient == OrientationRequested.REVERSE_LANDSCAPE) { + page.setOrientation(PageFormat.REVERSE_LANDSCAPE); + } else if (orient == OrientationRequested.LANDSCAPE) { + page.setOrientation(PageFormat.LANDSCAPE); + } else { + page.setOrientation(PageFormat.PORTRAIT); + } + + Media media = (Media)attSet.get(Media.class); + if (media == null) { + media = + (Media)service.getDefaultAttributeValue(Media.class); + } + if (!(media instanceof MediaSizeName)) { + media = MediaSizeName.NA_LETTER; + } + MediaSize size = + MediaSize.getMediaSizeForName((MediaSizeName)media); + if (size == null) { + size = MediaSize.NA.LETTER; + } + Paper paper = new Paper(); + float dim[] = size.getSize(1); //units == 1 to avoid FP error + double w = Math.rint((dim[0]*72.0)/Size2DSyntax.INCH); + double h = Math.rint((dim[1]*72.0)/Size2DSyntax.INCH); + paper.setSize(w, h); + MediaPrintableArea area = + (MediaPrintableArea) + attSet.get(MediaPrintableArea.class); + double ix, iw, iy, ih; + + if (area != null) { + // Should pass in same unit as updatePageAttributes + // to avoid rounding off errors. + ix = Math.rint( + area.getX(MediaPrintableArea.INCH) * DPI); + iy = Math.rint( + area.getY(MediaPrintableArea.INCH) * DPI); + iw = Math.rint( + area.getWidth(MediaPrintableArea.INCH) * DPI); + ih = Math.rint( + area.getHeight(MediaPrintableArea.INCH) * DPI); + } + else { + if (w >= 72.0 * 6.0) { + ix = 72.0; + iw = w - 2 * 72.0; + } else { + ix = w / 6.0; + iw = w * 0.75; + } + if (h >= 72.0 * 6.0) { + iy = 72.0; + ih = h - 2 * 72.0; + } else { + iy = h / 6.0; + ih = h * 0.75; + } + } + paper.setImageableArea(ix, iy, iw, ih); + page.setPaper(paper); + return page; + } protected void updatePageAttributes(PrintService service, PageFormat page) { + updateAttributesWithPageFormat(service, page, this.attributes); + } + + protected void updateAttributesWithPageFormat(PrintService service, + PageFormat page, + PrintRequestAttributeSet attributes) { if (service == null || page == null) { return; } @@ -659,6 +742,18 @@ public abstract class RasterPrinterJob extends PrinterJob { throw new HeadlessException(); } + DialogTypeSelection dlg = + (DialogTypeSelection)attributes.get(DialogTypeSelection.class); + + // Check for native, note that default dialog is COMMON. + if (dlg == DialogTypeSelection.NATIVE) { + PrintService pservice = getPrintService(); + PageFormat page = pageDialog(attributeToPageFormat(pservice, + attributes)); + updateAttributesWithPageFormat(pservice, page, attributes); + return page; + } + final GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); @@ -698,77 +793,7 @@ public abstract class RasterPrinterJob extends PrinterJob { attributes.remove(amCategory); } attributes.addAll(newas); - - PageFormat page = defaultPage(); - - OrientationRequested orient = - (OrientationRequested) - attributes.get(OrientationRequested.class); - int pfOrient = PageFormat.PORTRAIT; - if (orient != null) { - if (orient == OrientationRequested.REVERSE_LANDSCAPE) { - pfOrient = PageFormat.REVERSE_LANDSCAPE; - } else if (orient == OrientationRequested.LANDSCAPE) { - pfOrient = PageFormat.LANDSCAPE; - } - } - page.setOrientation(pfOrient); - - Media media = (Media)attributes.get(Media.class); - if (media == null) { - media = - (Media)service.getDefaultAttributeValue(Media.class); - } - if (!(media instanceof MediaSizeName)) { - media = MediaSizeName.NA_LETTER; - } - MediaSize size = - MediaSize.getMediaSizeForName((MediaSizeName)media); - if (size == null) { - size = MediaSize.NA.LETTER; - } - Paper paper = new Paper(); - float dim[] = size.getSize(1); //units == 1 to avoid FP error - double w = Math.rint((dim[0]*72.0)/Size2DSyntax.INCH); - double h = Math.rint((dim[1]*72.0)/Size2DSyntax.INCH); - paper.setSize(w, h); - MediaPrintableArea area = - (MediaPrintableArea) - attributes.get(MediaPrintableArea.class); - double ix, iw, iy, ih; - - if (area != null) { - // Should pass in same unit as updatePageAttributes - // to avoid rounding off errors. - ix = Math.rint( - area.getX(MediaPrintableArea.INCH) * DPI); - iy = Math.rint( - area.getY(MediaPrintableArea.INCH) * DPI); - iw = Math.rint( - area.getWidth(MediaPrintableArea.INCH) * DPI); - ih = Math.rint( - area.getHeight(MediaPrintableArea.INCH) * DPI); - } - else { - if (w >= 72.0 * 6.0) { - ix = 72.0; - iw = w - 2 * 72.0; - } else { - ix = w / 6.0; - iw = w * 0.75; - } - if (h >= 72.0 * 6.0) { - iy = 72.0; - ih = h - 2 * 72.0; - } else { - iy = h / 6.0; - ih = h * 0.75; - } - } - paper.setImageableArea(ix, iy, iw, ih); - page.setPaper(paper); - - return page; + return attributeToPageFormat(service, attributes); } else { return null; } @@ -795,7 +820,6 @@ public abstract class RasterPrinterJob extends PrinterJob { throw new HeadlessException(); } - DialogTypeSelection dlg = (DialogTypeSelection)attributes.get(DialogTypeSelection.class); @@ -816,7 +840,6 @@ public abstract class RasterPrinterJob extends PrinterJob { } - /* A security check has already been performed in the * java.awt.print.printerJob.getPrinterJob method. * So by the time we get here, it is OK for the current thread diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java index 5ca88f90202..ed1443a5c5a 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java @@ -86,11 +86,11 @@ public final class AnnotationSupport { Class containerClass = containerInstance.annotationType(); AnnotationType annoType = AnnotationType.getInstance(containerClass); if (annoType == null) - throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); + throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations"); Method m = annoType.members().get("value"); if (m == null) - throw new InvalidContainerAnnotationError(containerInstance + + throw new AnnotationFormatError(containerInstance + " is an invalid container for repeating annotations"); m.setAccessible(true); @@ -103,11 +103,9 @@ public final class AnnotationSupport { IllegalArgumentException | // parameters doesn't match InvocationTargetException | // the value method threw an exception ClassCastException e) { // well, a cast failed ... - throw new InvalidContainerAnnotationError( + throw new AnnotationFormatError( containerInstance + " is an invalid container for repeating annotations", - e, - containerInstance, - null); + e); } } @@ -129,12 +127,10 @@ public final class AnnotationSupport { return l; } catch (ClassCastException | NullPointerException e) { - throw new InvalidContainerAnnotationError( + throw new AnnotationFormatError( String.format("%s is an invalid container for repeating annotations of type: %s", containerInstance, annotationClass), - e, - containerInstance, - annotationClass); + e); } } } diff --git a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java index 0eade8de571..9d9c5ab6015 100644 --- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java @@ -252,6 +252,12 @@ public final class MethodUtil extends SecureClassLoader { public static Object invoke(Method m, Object obj, Object[] params) throws InvocationTargetException, IllegalAccessException { if (m.getDeclaringClass().equals(AccessController.class) || + (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.class) + && m.getName().equals("lookup")) || + (m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.Lookup.class) + && (m.getName().startsWith("find") || + m.getName().startsWith("bind") || + m.getName().startsWith("unreflect"))) || m.getDeclaringClass().equals(Method.class)) throw new InvocationTargetException( new UnsupportedOperationException("invocation not supported")); diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 38f84765b0f..0640d92e5d0 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -178,4 +178,31 @@ public final class ReflectUtil { return !isAncestor(from, to); } + + /** + * Access check on the interfaces that a proxy class implements and throw + * {@code SecurityException} if it accesses a restricted package. + * + * @param ccl the caller's class loader + * @param interfaces the list of interfaces that a proxy class implements + * + * @see Proxy#checkProxyAccess + */ + public static void checkProxyPackageAccess(ClassLoader ccl, + Class... interfaces) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + for (Class intf : interfaces) { + ClassLoader cl = intf.getClassLoader(); + if (needsPackageAccessCheck(ccl, cl)) { + checkPackageAccess(intf); + } + } + } + } + + // Note that bytecode instrumentation tools may exclude 'sun.*' + // classes but not generated proxy classes and so keep it in com.sun.* + public static final String PROXY_PACKAGE = "com.sun.proxy"; } diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java index 4ccdccdff0b..a60b23864af 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -153,7 +153,7 @@ public final class CGIHandler { returnServerError(e.getMessage()); } else - returnClientError("invalid command: " + command); + returnClientError("invalid command."); } catch (Exception e) { returnServerError("internal error: " + e.getMessage()); } @@ -225,7 +225,7 @@ final class CGIForwardCommand implements CGICommandHandler { try { port = Integer.parseInt(param); } catch (NumberFormatException e) { - throw new CGIClientException("invalid port number: " + param); + throw new CGIClientException("invalid port number."); } if (port <= 0 || port > 0xFFFF) throw new CGIClientException("invalid port: " + port); @@ -293,11 +293,14 @@ final class CGIForwardCommand implements CGICommandHandler { "unexpected EOF reading server response"); if (line.toLowerCase().startsWith(key)) { - // if contentLengthFound is true - // we should probably do something here - responseContentLength = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; + if (contentLengthFound) { + throw new CGIServerException( + "Multiple Content-length entries found."); + } else { + responseContentLength = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } } } while ((line.length() != 0) && (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java index 802b8233795..3a35bb02b25 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java @@ -70,11 +70,14 @@ class HttpInputStream extends FilterInputStream { throw new EOFException(); if (line.toLowerCase().startsWith(key)) { - // if contentLengthFound is true - // we should probably do something here - bytesLeft = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; + if (contentLengthFound) { + throw new IOException( + "Multiple Content-length entries found."); + } else { + bytesLeft = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } } // The idea here is to go past the first blank line. diff --git a/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java b/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java index 6330f71c1b0..584e1784c8a 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java @@ -29,6 +29,7 @@ import org.ietf.jgss.*; import sun.security.jgss.spi.*; import java.util.*; import com.sun.security.jgss.*; +import sun.security.jgss.spnego.SpNegoCredElement; public class GSSCredentialImpl implements ExtendedGSSCredential { @@ -87,6 +88,7 @@ public class GSSCredentialImpl implements ExtendedGSSCredential { throw new GSSException(GSSException.NO_CRED); } + // Wrap a mech cred into a GSS cred public GSSCredentialImpl(GSSManagerImpl gssManager, GSSCredentialSpi mechElement) throws GSSException { @@ -103,6 +105,11 @@ public class GSSCredentialImpl implements ExtendedGSSCredential { usage); tempCred = mechElement; hashtable.put(key, tempCred); + // More mechs that can use this cred, say, SPNEGO + if (!GSSUtil.isSpNegoMech(mechElement.getMechanism())) { + key = new SearchKey(GSSUtil.GSS_SPNEGO_MECH_OID, usage); + hashtable.put(key, new SpNegoCredElement(mechElement)); + } } void init(GSSManagerImpl gssManager) { diff --git a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java index 69116f56bd2..ee5999ced55 100644 --- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java +++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java @@ -44,7 +44,7 @@ public class SpNegoCredElement implements GSSCredentialSpi { private GSSCredentialSpi cred = null; - SpNegoCredElement(GSSCredentialSpi cred) throws GSSException { + public SpNegoCredElement(GSSCredentialSpi cred) throws GSSException { this.cred = cred; } diff --git a/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java b/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java index c5418c67d07..3caf6ca1941 100644 --- a/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java +++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java @@ -37,7 +37,7 @@ import java.security.Signature; import java.security.SignatureException; import java.security.PublicKey; -import sun.misc.BASE64Encoder; +import java.util.Base64; import sun.security.util.*; import sun.security.x509.AlgorithmId; @@ -289,10 +289,9 @@ public class PKCS10 { if (encoded == null) throw new SignatureException("Cert request was not signed"); - BASE64Encoder encoder = new BASE64Encoder(); out.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); - encoder.encodeBuffer(encoded, out); + out.println(Base64.getMimeEncoder().encodeToString(encoded)); out.println("-----END NEW CERTIFICATE REQUEST-----"); } diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java index dd7c3294649..11ce2b6126b 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java @@ -37,6 +37,7 @@ import javax.crypto.spec.*; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import sun.security.util.KeyUtil; /** * KeyAgreement implementation class. This class currently supports @@ -134,6 +135,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { BigInteger p, g, y; if (key instanceof DHPublicKey) { DHPublicKey dhKey = (DHPublicKey)key; + + // validate the Diffie-Hellman public key + KeyUtil.validate(dhKey); + y = dhKey.getY(); DHParameterSpec params = dhKey.getParams(); p = params.getP(); @@ -145,6 +150,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { try { DHPublicKeySpec spec = kf.engineGetKeySpec( key, DHPublicKeySpec.class); + + // validate the Diffie-Hellman public key + KeyUtil.validate(spec); + y = spec.getY(); p = spec.getP(); g = spec.getG(); diff --git a/jdk/src/share/classes/sun/security/provider/PolicyFile.java b/jdk/src/share/classes/sun/security/provider/PolicyFile.java index 5ea389b51e9..f92e1d5905c 100644 --- a/jdk/src/share/classes/sun/security/provider/PolicyFile.java +++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java @@ -1336,10 +1336,9 @@ public class PolicyFile extends java.security.Policy { if (pppe.isWildcardName()) { // a wildcard name matches any principal with the same class - for (Principal p : principals) { - if (pppe.principalClass.equals(p.getClass().getName())) { - continue; - } + if (wildcardPrincipalNameImplies(pppe.principalClass, + principals)) { + continue; } if (debug != null) { debug.println("evaluation (principal name wildcard) failed"); @@ -1414,6 +1413,21 @@ public class PolicyFile extends java.security.Policy { addPerms(perms, principals, entry); } + /** + * Returns true if the array of principals contains at least one + * principal of the specified class. + */ + private static boolean wildcardPrincipalNameImplies(String principalClass, + Principal[] principals) + { + for (Principal p : principals) { + if (principalClass.equals(p.getClass().getName())) { + return true; + } + } + return false; + } + private void addPerms(Permissions perms, Principal[] accPs, PolicyEntry entry) { diff --git a/jdk/src/share/classes/sun/security/provider/X509Factory.java b/jdk/src/share/classes/sun/security/provider/X509Factory.java index 28b7aa55666..3a491a1c080 100644 --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java @@ -35,7 +35,7 @@ import sun.security.provider.certpath.X509CertPath; import sun.security.provider.certpath.X509CertificatePair; import sun.security.util.DerValue; import sun.security.util.Cache; -import sun.misc.BASE64Decoder; +import java.util.Base64; import sun.security.pkcs.ParsingException; /** @@ -512,7 +512,7 @@ public class X509Factory extends CertificateFactorySpi { hyphen = 0; last = next; } - if (hyphen == 5 && (last==-1 || last=='\r' || last=='\n')) { + if (hyphen == 5 && (last == -1 || last == '\r' || last == '\n')) { break; } } @@ -575,8 +575,7 @@ public class X509Factory extends CertificateFactorySpi { checkHeaderFooter(header.toString(), footer.toString()); - BASE64Decoder decoder = new BASE64Decoder(); - return decoder.decodeBuffer(new String(data, 0, pos)); + return Base64.getMimeDecoder().decode(new String(data, 0, pos)); } } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java index f57c832bfa5..03c910b8897 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java @@ -89,7 +89,7 @@ public final class OCSP { new GetIntegerAction("com.sun.security.ocsp.timeout", DEFAULT_CONNECT_TIMEOUT)); if (tmp < 0) { - tmp = DEFAULT_CONNECT_TIMEOUT; + return DEFAULT_CONNECT_TIMEOUT; } // Convert to milliseconds, as the system property will be // specified in seconds diff --git a/jdk/src/share/classes/sun/security/ssl/CipherBox.java b/jdk/src/share/classes/sun/security/ssl/CipherBox.java index 362f9b5d904..52bb7d95863 100644 --- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java +++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -392,7 +392,8 @@ final class CipherBox { * uniformly use the bad_record_mac alert to hide the specific type of * the error. */ - int decrypt(byte[] buf, int offset, int len) throws BadPaddingException { + int decrypt(byte[] buf, int offset, int len, + int tagLen) throws BadPaddingException { if (cipher == null) { return len; } @@ -416,9 +417,10 @@ final class CipherBox { System.out); } catch (IOException e) { } } + if (blockSize != 0) { - newLen = removePadding(buf, offset, newLen, - blockSize, protocolVersion); + newLen = removePadding( + buf, offset, newLen, tagLen, blockSize, protocolVersion); if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (newLen < blockSize) { @@ -448,7 +450,7 @@ final class CipherBox { * * @see decrypt(byte[], int, int) */ - int decrypt(ByteBuffer bb) throws BadPaddingException { + int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException { int len = bb.remaining(); @@ -471,7 +473,6 @@ final class CipherBox { } if (debug != null && Debug.isOn("plaintext")) { - bb.position(pos); try { HexDumpEncoder hd = new HexDumpEncoder(); @@ -479,7 +480,8 @@ final class CipherBox { "Padded plaintext after DECRYPTION: len = " + newLen); - hd.encodeBuffer(bb, System.out); + hd.encodeBuffer( + (ByteBuffer)bb.duplicate().position(pos), System.out); } catch (IOException e) { } } @@ -488,7 +490,8 @@ final class CipherBox { */ if (blockSize != 0) { bb.position(pos); - newLen = removePadding(bb, blockSize, protocolVersion); + newLen = removePadding( + bb, tagLen, blockSize, protocolVersion); if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (newLen < blockSize) { @@ -590,6 +593,65 @@ final class CipherBox { return newlen; } + /* + * A constant-time check of the padding. + * + * NOTE that we are checking both the padding and the padLen bytes here. + * + * The caller MUST ensure that the len parameter is a positive number. + */ + private static int[] checkPadding( + byte[] buf, int offset, int len, byte pad) { + + if (len <= 0) { + throw new RuntimeException("padding len must be positive"); + } + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + for (int i = 0; i <= 256;) { + for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i + if (buf[offset + j] != pad) { + results[0]++; // mismatched padding data + } else { + results[1]++; // matched padding data + } + } + } + + return results; + } + + /* + * A constant-time check of the padding. + * + * NOTE that we are checking both the padding and the padLen bytes here. + * + * The caller MUST ensure that the bb parameter has remaining. + */ + private static int[] checkPadding(ByteBuffer bb, byte pad) { + + if (!bb.hasRemaining()) { + throw new RuntimeException("hasRemaining() must be positive"); + } + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + bb.mark(); + for (int i = 0; i <= 256; bb.reset()) { + for (; bb.hasRemaining() && i <= 256; i++) { + if (bb.get() != pad) { + results[0]++; // mismatched padding data + } else { + results[1]++; // matched padding data + } + } + } + + return results; + } /* * Typical TLS padding format for a 64 bit block cipher is as follows: @@ -602,86 +664,95 @@ final class CipherBox { * as it makes the data a multiple of the block size */ private static int removePadding(byte[] buf, int offset, int len, - int blockSize, ProtocolVersion protocolVersion) - throws BadPaddingException { + int tagLen, int blockSize, + ProtocolVersion protocolVersion) throws BadPaddingException { + // last byte is length byte (i.e. actual padding length - 1) int padOffset = offset + len - 1; - int pad = buf[padOffset] & 0x0ff; + int padLen = buf[padOffset] & 0xFF; - int newlen = len - (pad + 1); - if (newlen < 0) { - throw new BadPaddingException("Padding length invalid: " + pad); + int newLen = len - (padLen + 1); + if ((newLen - tagLen) < 0) { + // If the buffer is not long enough to contain the padding plus + // a MAC tag, do a dummy constant-time padding check. + // + // Note that it is a dummy check, so we won't care about what is + // the actual padding data. + checkPadding(buf, offset, len, (byte)(padLen & 0xFF)); + + throw new BadPaddingException("Invalid Padding length: " + padLen); } + // The padding data should be filled with the padding length value. + int[] results = checkPadding(buf, offset + newLen, + padLen + 1, (byte)(padLen & 0xFF)); if (protocolVersion.v >= ProtocolVersion.TLS10.v) { - for (int i = 1; i <= pad; i++) { - int val = buf[padOffset - i] & 0xff; - if (val != pad) { - throw new BadPaddingException - ("Invalid TLS padding: " + val); - } + if (results[0] != 0) { // padding data has invalid bytes + throw new BadPaddingException("Invalid TLS padding data"); } } else { // SSLv3 // SSLv3 requires 0 <= length byte < block size // some implementations do 1 <= length byte <= block size, // so accept that as well // v3 does not require any particular value for the other bytes - if (pad > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding: " + pad); + if (padLen > blockSize) { + throw new BadPaddingException("Invalid SSLv3 padding"); } } - return newlen; + return newLen; } /* * Position/limit is equal the removed padding. */ private static int removePadding(ByteBuffer bb, - int blockSize, ProtocolVersion protocolVersion) - throws BadPaddingException { + int tagLen, int blockSize, + ProtocolVersion protocolVersion) throws BadPaddingException { int len = bb.remaining(); int offset = bb.position(); // last byte is length byte (i.e. actual padding length - 1) int padOffset = offset + len - 1; - int pad = bb.get(padOffset) & 0x0ff; + int padLen = bb.get(padOffset) & 0xFF; - int newlen = len - (pad + 1); - if (newlen < 0) { - throw new BadPaddingException("Padding length invalid: " + pad); + int newLen = len - (padLen + 1); + if ((newLen - tagLen) < 0) { + // If the buffer is not long enough to contain the padding plus + // a MAC tag, do a dummy constant-time padding check. + // + // Note that it is a dummy check, so we won't care about what is + // the actual padding data. + checkPadding(bb.duplicate(), (byte)(padLen & 0xFF)); + + throw new BadPaddingException("Invalid Padding length: " + padLen); } - /* - * We could zero the padding area, but not much useful - * information there. - */ + // The padding data should be filled with the padding length value. + int[] results = checkPadding( + (ByteBuffer)bb.duplicate().position(offset + newLen), + (byte)(padLen & 0xFF)); if (protocolVersion.v >= ProtocolVersion.TLS10.v) { - bb.put(padOffset, (byte)0); // zero the padding. - for (int i = 1; i <= pad; i++) { - int val = bb.get(padOffset - i) & 0xff; - if (val != pad) { - throw new BadPaddingException - ("Invalid TLS padding: " + val); - } + if (results[0] != 0) { // padding data has invalid bytes + throw new BadPaddingException("Invalid TLS padding data"); } } else { // SSLv3 // SSLv3 requires 0 <= length byte < block size // some implementations do 1 <= length byte <= block size, // so accept that as well // v3 does not require any particular value for the other bytes - if (pad > blockSize) { - throw new BadPaddingException("Invalid SSLv3 padding: " + pad); + if (padLen > blockSize) { + throw new BadPaddingException("Invalid SSLv3 padding"); } } /* * Reset buffer limit to remove padding. */ - bb.position(offset + newlen); - bb.limit(offset + newlen); + bb.position(offset + newLen); + bb.limit(offset + newLen); - return newlen; + return newLen; } /* @@ -708,4 +779,45 @@ final class CipherBox { boolean isCBCMode() { return isCBCMode; } + + /** + * Is the cipher null? + * + * @return true if the cipher is null, false otherwise. + */ + boolean isNullCipher() { + return cipher == null; + } + + /** + * Sanity check the length of a fragment before decryption. + * + * In CBC mode, check that the fragment length is one or multiple times + * of the block size of the cipher suite, and is at least one (one is the + * smallest size of padding in CBC mode) bigger than the tag size of the + * MAC algorithm except the explicit IV size for TLS 1.1 or later. + * + * In non-CBC mode, check that the fragment length is not less than the + * tag size of the MAC algorithm. + * + * @return true if the length of a fragment matches above requirements + */ + boolean sanityCheck(int tagLen, int fragmentLen) { + if (!isCBCMode) { + return fragmentLen >= tagLen; + } + + if ((fragmentLen % blockSize) == 0) { + int minimal = tagLen + 1; + minimal = (minimal >= blockSize) ? minimal : blockSize; + if (protocolVersion.v >= ProtocolVersion.TLS11.v) { + minimal += blockSize; // plus the size of the explicit IV + } + + return (fragmentLen >= minimal); + } + + return false; + } + } diff --git a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java index 555304880b7..e0a081ad85d 100644 --- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java +++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -549,9 +549,18 @@ final class CipherSuite implements Comparable { // size of the MAC value (and MAC key) in bytes final int size; - MacAlg(String name, int size) { + // block size of the underlying hash algorithm + final int hashBlockSize; + + // minimal padding size of the underlying hash algorithm + final int minimalPaddingSize; + + MacAlg(String name, int size, + int hashBlockSize, int minimalPaddingSize) { this.name = name; this.size = size; + this.hashBlockSize = hashBlockSize; + this.minimalPaddingSize = minimalPaddingSize; } /** @@ -596,11 +605,11 @@ final class CipherSuite implements Comparable { new BulkCipher(CIPHER_AES, 32, 16, true); // MACs - final static MacAlg M_NULL = new MacAlg("NULL", 0); - final static MacAlg M_MD5 = new MacAlg("MD5", 16); - final static MacAlg M_SHA = new MacAlg("SHA", 20); - final static MacAlg M_SHA256 = new MacAlg("SHA256", 32); - final static MacAlg M_SHA384 = new MacAlg("SHA384", 48); + final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0); + final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9); + final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9); + final static MacAlg M_SHA256 = new MacAlg("SHA256", 32, 64, 9); + final static MacAlg M_SHA384 = new MacAlg("SHA384", 48, 128, 17); /** * PRFs (PseudoRandom Function) from TLS specifications. diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java index 1c0669fbeae..459a0aed7f8 100644 --- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java @@ -129,9 +129,8 @@ final class ClientHandshaker extends Handshaker { */ @Override void processMessage(byte type, int messageLen) throws IOException { - if (state > type - && (type != HandshakeMessage.ht_hello_request - && state != HandshakeMessage.ht_client_hello)) { + if (state >= type + && (type != HandshakeMessage.ht_hello_request)) { throw new SSLProtocolException( "Handshake message sequence violation, " + type); } @@ -194,8 +193,12 @@ final class ClientHandshaker extends Handshaker { } break; case K_DH_ANON: - this.serverKeyExchange(new DH_ServerKeyExchange( + try { + this.serverKeyExchange(new DH_ServerKeyExchange( input, protocolVersion)); + } catch (GeneralSecurityException e) { + throwSSLException("Server key", e); + } break; case K_DHE_DSS: case K_DHE_RSA: @@ -921,7 +924,7 @@ final class ClientHandshaker extends Handshaker { case K_DHE_RSA: case K_DHE_DSS: case K_DH_ANON: - preMasterSecret = dh.getAgreedSecret(serverDH); + preMasterSecret = dh.getAgreedSecret(serverDH, true); break; case K_ECDHE_RSA: case K_ECDHE_ECDSA: diff --git a/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java index f78bdc26420..94426f47d70 100644 --- a/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ package sun.security.ssl; import java.io.IOException; import java.io.PrintStream; import java.math.BigInteger; - +import javax.net.ssl.SSLHandshakeException; /* * Message used by clients to send their Diffie-Hellman public @@ -51,7 +51,7 @@ final class DHClientKeyExchange extends HandshakeMessage { private byte dh_Yc[]; // 1 to 2^16 -1 bytes BigInteger getClientPublicKey() { - return new BigInteger(1, dh_Yc); + return dh_Yc == null ? null : new BigInteger(1, dh_Yc); } /* @@ -73,7 +73,14 @@ final class DHClientKeyExchange extends HandshakeMessage { * but that's what the protocol spec requires.) */ DHClientKeyExchange(HandshakeInStream input) throws IOException { - dh_Yc = input.getBytes16(); + if (input.available() >= 2) { + dh_Yc = input.getBytes16(); + } else { + // currently, we don't support cipher suites that requires + // implicit public key of client. + throw new SSLHandshakeException( + "Unsupported implicit client DiffieHellman public key"); + } } @Override @@ -87,7 +94,9 @@ final class DHClientKeyExchange extends HandshakeMessage { @Override void send(HandshakeOutStream s) throws IOException { - s.putBytes16(dh_Yc); + if (dh_Yc != null && dh_Yc.length != 0) { + s.putBytes16(dh_Yc); + } } @Override diff --git a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java index d475ae8e978..ae9118f4ba5 100644 --- a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java +++ b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -28,12 +28,15 @@ package sun.security.ssl; import java.math.BigInteger; import java.security.*; - +import java.io.IOException; +import javax.net.ssl.SSLHandshakeException; import javax.crypto.SecretKey; import javax.crypto.KeyAgreement; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.*; +import sun.security.util.KeyUtil; + /** * This class implements the Diffie-Hellman key exchange algorithm. * D-H means combining your private key with your partners public key to @@ -54,7 +57,8 @@ import javax.crypto.spec.*; * . if we are server, call DHCrypt(keyLength,random). This generates * an ephemeral keypair of the request length. * . if we are client, call DHCrypt(modulus, base, random). This - * generates an ephemeral keypair using the parameters specified by the server. + * generates an ephemeral keypair using the parameters specified by + * the server. * . send parameters and public value to remote peer * . receive peers ephemeral public key * . call getAgreedSecret() to calculate the shared secret @@ -83,6 +87,9 @@ final class DHCrypt { // public component of our key, X = (g ^ x) mod p private BigInteger publicValue; // X (aka y) + // the times to recove from failure if public key validation + private static int MAX_FAILOVER_TIMES = 2; + /** * Generate a Diffie-Hellman keypair of the specified size. */ @@ -90,9 +97,12 @@ final class DHCrypt { try { KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); kpg.initialize(keyLength, random); - KeyPair kp = kpg.generateKeyPair(); - privateKey = kp.getPrivate(); - DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); + if (spec == null) { + throw new RuntimeException("Could not generate DH keypair"); + } + publicValue = spec.getY(); modulus = spec.getP(); base = spec.getG(); @@ -115,20 +125,25 @@ final class DHCrypt { KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); DHParameterSpec params = new DHParameterSpec(modulus, base); kpg.initialize(params, random); - KeyPair kp = kpg.generateKeyPair(); - privateKey = kp.getPrivate(); - DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + DHPublicKeySpec spec = generateDHPublicKeySpec(kpg); + if (spec == null) { + throw new RuntimeException("Could not generate DH keypair"); + } + publicValue = spec.getY(); } catch (GeneralSecurityException e) { throw new RuntimeException("Could not generate DH keypair", e); } } + static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) { if (key instanceof DHPublicKey) { DHPublicKey dhKey = (DHPublicKey)key; DHParameterSpec params = dhKey.getParams(); - return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG()); + return new DHPublicKeySpec(dhKey.getY(), + params.getP(), params.getG()); } try { KeyFactory factory = JsseJce.getKeyFactory("DH"); @@ -166,17 +181,32 @@ final class DHCrypt { *

    It is illegal to call this member function if the private key * has not been set (or generated). * - * @param peerPublicKey the peer's public key. - * @returns the secret, which is an unsigned big-endian integer - * the same size as the Diffie-Hellman modulus. + * @param peerPublicKey the peer's public key. + * @param keyIsValidated whether the {@code peerPublicKey} has beed + * validated + * @return the secret, which is an unsigned big-endian integer + * the same size as the Diffie-Hellman modulus. */ - SecretKey getAgreedSecret(BigInteger peerPublicValue) { + SecretKey getAgreedSecret(BigInteger peerPublicValue, + boolean keyIsValidated) throws IOException { try { KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); DHPublicKeySpec spec = new DHPublicKeySpec(peerPublicValue, modulus, base); PublicKey publicKey = kf.generatePublic(spec); KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); + + // validate the Diffie-Hellman public key + if (!keyIsValidated && + !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) { + try { + KeyUtil.validate(spec); + } catch (InvalidKeyException ike) { + // prefer handshake_failure alert to internal_error alert + throw new SSLHandshakeException(ike.getMessage()); + } + } + ka.init(privateKey); ka.doPhase(publicKey, true); return ka.generateSecret("TlsPremasterSecret"); @@ -185,4 +215,33 @@ final class DHCrypt { } } + // Generate and validate DHPublicKeySpec + private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg) + throws GeneralSecurityException { + + boolean doExtraValiadtion = + (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName())); + for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) { + KeyPair kp = kpg.generateKeyPair(); + privateKey = kp.getPrivate(); + DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); + + // validate the Diffie-Hellman public key + if (doExtraValiadtion) { + try { + KeyUtil.validate(spec); + } catch (InvalidKeyException ivke) { + if (i == MAX_FAILOVER_TIMES) { + throw ivke; + } + // otherwise, ignore the exception and try the next one + continue; + } + } + + return spec; + } + + return null; + } } diff --git a/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java b/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java index 6b064385203..9161d6de8ef 100644 --- a/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,71 +177,6 @@ final class EngineInputRecord extends InputRecord { return len; } - /* - * Verifies and removes the MAC value. Returns true if - * the MAC checks out OK. - * - * On entry: - * position = beginning of app/MAC data - * limit = end of MAC data. - * - * On return: - * position = beginning of app data - * limit = end of app data - */ - boolean checkMAC(MAC signer, ByteBuffer bb) { - if (internalData) { - return checkMAC(signer); - } - - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } - - /* - * Grab the original limit - */ - int lim = bb.limit(); - - /* - * Delineate the area to apply a MAC on. - */ - int macData = lim - len; - bb.limit(macData); - - byte[] mac = signer.compute(contentType(), bb); - - if (len != mac.length) { - throw new RuntimeException("Internal MAC error"); - } - - /* - * Delineate the MAC values, position was already set - * by doing the compute above. - * - * We could zero the MAC area, but not much useful information - * there anyway. - */ - bb.position(macData); - bb.limit(lim); - - try { - for (int i = 0; i < len; i++) { - if (bb.get() != mac[i]) { // No BB.equals(byte []); ! - return false; - } - } - return true; - } finally { - /* - * Position to the data. - */ - bb.rewind(); - bb.limit(macData); - } - } - /* * Pass the data down if it's internally cached, otherwise * do it here. @@ -251,20 +186,163 @@ final class EngineInputRecord extends InputRecord { * If external data(app), return a new ByteBuffer with data to * process. */ - ByteBuffer decrypt(CipherBox box, ByteBuffer bb) - throws BadPaddingException { + ByteBuffer decrypt(MAC signer, + CipherBox box, ByteBuffer bb) throws BadPaddingException { if (internalData) { - decrypt(box); + decrypt(signer, box); // MAC is checked during decryption return tmpBB; } - box.decrypt(bb); - bb.rewind(); + BadPaddingException reservedBPE = null; + int tagLen = signer.MAClen(); + int cipheredLength = bb.remaining(); + + if (!box.isNullCipher()) { + // sanity check length of the ciphertext + if (!box.sanityCheck(tagLen, cipheredLength)) { + throw new BadPaddingException( + "ciphertext sanity check failed"); + } + + try { + // Note that the CipherBox.decrypt() does not change + // the capacity of the buffer. + box.decrypt(bb, tagLen); + } catch (BadPaddingException bpe) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authentication code checking. + reservedBPE = bpe; + } finally { + bb.rewind(); + } + } + + if (tagLen != 0) { + int macOffset = bb.limit() - tagLen; + + // Note that although it is not necessary, we run the same MAC + // computation and comparison on the payload for both stream + // cipher and CBC block cipher. + if (bb.remaining() < tagLen) { + // negative data length, something is wrong + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record"); + } + + // set offset of the dummy MAC + macOffset = cipheredLength - tagLen; + bb.limit(cipheredLength); + } + + // Run MAC computation and comparison on the payload. + if (checkMacTags(contentType(), bb, signer, false)) { + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record MAC"); + } + } + + // Run MAC computation and comparison on the remainder. + // + // It is only necessary for CBC block cipher. It is used to get a + // constant time of MAC computation and comparison on each record. + if (box.isCBCMode()) { + int remainingLen = calculateRemainingLen( + signer, cipheredLength, macOffset); + + // NOTE: here we use the InputRecord.buf because I did not find + // an effective way to work on ByteBuffer when its capacity is + // less than remainingLen. + + // NOTE: remainingLen may be bigger (less than 1 block of the + // hash algorithm of the MAC) than the cipheredLength. However, + // We won't need to worry about it because we always use a + // maximum buffer for every record. We need a change here if + // we use small buffer size in the future. + if (remainingLen > buf.length) { + // unlikely to happen, just a placehold + throw new RuntimeException( + "Internal buffer capacity error"); + } + + // Won't need to worry about the result on the remainder. And + // then we won't need to worry about what's actual data to + // check MAC tag on. We start the check from the header of the + // buffer so that we don't need to construct a new byte buffer. + checkMacTags(contentType(), buf, 0, remainingLen, signer, true); + } + + bb.limit(macOffset); + } + + // Is it a failover? + if (reservedBPE != null) { + throw reservedBPE; + } return bb.slice(); } + /* + * Run MAC computation and comparison + * + * Please DON'T change the content of the ByteBuffer parameter! + */ + private static boolean checkMacTags(byte contentType, ByteBuffer bb, + MAC signer, boolean isSimulated) { + + int tagLen = signer.MAClen(); + int lim = bb.limit(); + int macData = lim - tagLen; + + bb.limit(macData); + byte[] hash = signer.compute(contentType, bb, isSimulated); + if (hash == null || tagLen != hash.length) { + // Something is wrong with MAC implementation. + throw new RuntimeException("Internal MAC error"); + } + + bb.position(macData); + bb.limit(lim); + try { + int[] results = compareMacTags(bb, hash); + return (results[0] != 0); + } finally { + bb.rewind(); + bb.limit(macData); + } + } + + /* + * A constant-time comparison of the MAC tags. + * + * Please DON'T change the content of the ByteBuffer parameter! + */ + private static int[] compareMacTags(ByteBuffer bb, byte[] tag) { + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + + // The caller ensures there are enough bytes available in the buffer. + // So we won't need to check the remaining of the buffer. + for (int i = 0; i < tag.length; i++) { + if (bb.get() != tag[i]) { + results[0]++; // mismatched bytes + } else { + results[1]++; // matched bytes + } + } + + return results; + } + /* * Override the actual write below. We do things this way to be * consistent with InputRecord. InputRecord may try to write out diff --git a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java index e9d39805b36..ae414c115f2 100644 --- a/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/EngineOutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,7 +118,7 @@ final class EngineOutputRecord extends OutputRecord { throws IOException { if (signer.MAClen() != 0) { - byte[] hash = signer.compute(contentType(), bb); + byte[] hash = signer.compute(contentType(), bb, false); /* * position was advanced to limit in compute above. diff --git a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java index 1a54b556c73..41908304eb8 100644 --- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java @@ -41,12 +41,14 @@ import javax.security.auth.x500.X500Principal; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import javax.crypto.spec.DHPublicKeySpec; import javax.net.ssl.*; import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; +import sun.security.util.KeyUtil; /** * Many data structures are involved in the handshake messages. These @@ -712,6 +714,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange this.protocolVersion = protocolVersion; this.preferableSignatureAlgorithm = null; + // The DH key has been validated in the constructor of DHCrypt. setValues(obj); signature = null; } @@ -728,6 +731,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange this.protocolVersion = protocolVersion; + // The DH key has been validated in the constructor of DHCrypt. setValues(obj); Signature sig; @@ -754,7 +758,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange * DH_anon key exchange */ DH_ServerKeyExchange(HandshakeInStream input, - ProtocolVersion protocolVersion) throws IOException { + ProtocolVersion protocolVersion) + throws IOException, GeneralSecurityException { this.protocolVersion = protocolVersion; this.preferableSignatureAlgorithm = null; @@ -762,6 +767,10 @@ class DH_ServerKeyExchange extends ServerKeyExchange dh_p = input.getBytes16(); dh_g = input.getBytes16(); dh_Ys = input.getBytes16(); + KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), + new BigInteger(1, dh_p), + new BigInteger(1, dh_g))); + signature = null; } @@ -782,6 +791,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange dh_p = input.getBytes16(); dh_g = input.getBytes16(); dh_Ys = input.getBytes16(); + KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys), + new BigInteger(1, dh_p), + new BigInteger(1, dh_g))); // read the signature and hash algorithm if (protocolVersion.v >= ProtocolVersion.TLS12.v) { diff --git a/jdk/src/share/classes/sun/security/ssl/InputRecord.java b/jdk/src/share/classes/sun/security/ssl/InputRecord.java index 78e866a07ca..45fdc62dd21 100644 --- a/jdk/src/share/classes/sun/security/ssl/InputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/InputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,43 +133,173 @@ class InputRecord extends ByteArrayInputStream implements Record { return handshakeHash; } + void decrypt(MAC signer, CipherBox box) throws BadPaddingException { + + BadPaddingException reservedBPE = null; + int tagLen = signer.MAClen(); + int cipheredLength = count - headerSize; + + if (!box.isNullCipher()) { + // sanity check length of the ciphertext + if (!box.sanityCheck(tagLen, cipheredLength)) { + throw new BadPaddingException( + "ciphertext sanity check failed"); + } + + try { + // Note that the CipherBox.decrypt() does not change + // the capacity of the buffer. + count = headerSize + + box.decrypt(buf, headerSize, cipheredLength, tagLen); + } catch (BadPaddingException bpe) { + // RFC 2246 states that decryption_failed should be used + // for this purpose. However, that allows certain attacks, + // so we just send bad record MAC. We also need to make + // sure to always check the MAC to avoid a timing attack + // for the same issue. See paper by Vaudenay et al and the + // update in RFC 4346/5246. + // + // Failover to message authentication code checking. + reservedBPE = bpe; + } + } + + if (tagLen != 0) { + int macOffset = count - tagLen; + int contentLen = macOffset - headerSize; + + // Note that although it is not necessary, we run the same MAC + // computation and comparison on the payload for both stream + // cipher and CBC block cipher. + if (contentLen < 0) { + // negative data length, something is wrong + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record"); + } + + // set offset of the dummy MAC + macOffset = headerSize + cipheredLength - tagLen; + contentLen = macOffset - headerSize; + } + + count -= tagLen; // Set the count before any MAC checking + // exception occurs, so that the following + // process can read the actual decrypted + // content (minus the MAC) in the fragment + // if necessary. + + // Run MAC computation and comparison on the payload. + if (checkMacTags(contentType(), + buf, headerSize, contentLen, signer, false)) { + if (reservedBPE == null) { + reservedBPE = new BadPaddingException("bad record MAC"); + } + } + + // Run MAC computation and comparison on the remainder. + // + // It is only necessary for CBC block cipher. It is used to get a + // constant time of MAC computation and comparison on each record. + if (box.isCBCMode()) { + int remainingLen = calculateRemainingLen( + signer, cipheredLength, contentLen); + + // NOTE: remainingLen may be bigger (less than 1 block of the + // hash algorithm of the MAC) than the cipheredLength. However, + // We won't need to worry about it because we always use a + // maximum buffer for every record. We need a change here if + // we use small buffer size in the future. + if (remainingLen > buf.length) { + // unlikely to happen, just a placehold + throw new RuntimeException( + "Internal buffer capacity error"); + } + + // Won't need to worry about the result on the remainder. And + // then we won't need to worry about what's actual data to + // check MAC tag on. We start the check from the header of the + // buffer so that we don't need to construct a new byte buffer. + checkMacTags(contentType(), buf, 0, remainingLen, signer, true); + } + } + + // Is it a failover? + if (reservedBPE != null) { + throw reservedBPE; + } + } + /* - * Verify and remove the MAC ... used for all records. + * Run MAC computation and comparison + * + * Please DON'T change the content of the byte buffer parameter! */ - boolean checkMAC(MAC signer) { - int len = signer.MAClen(); - if (len == 0) { // no mac - return true; - } + static boolean checkMacTags(byte contentType, byte[] buffer, + int offset, int contentLen, MAC signer, boolean isSimulated) { - int offset = count - len; - - if (offset < headerSize) { - // data length would be negative, something is wrong - return false; - } - - byte[] mac = signer.compute(contentType(), buf, - headerSize, offset - headerSize); - - if (len != mac.length) { + int tagLen = signer.MAClen(); + byte[] hash = signer.compute( + contentType, buffer, offset, contentLen, isSimulated); + if (hash == null || tagLen != hash.length) { + // Something is wrong with MAC implementation. throw new RuntimeException("Internal MAC error"); } - for (int i = 0; i < len; i++) { - if (buf[offset + i] != mac[i]) { - return false; + int[] results = compareMacTags(buffer, offset + contentLen, hash); + return (results[0] != 0); + } + + /* + * A constant-time comparison of the MAC tags. + * + * Please DON'T change the content of the byte buffer parameter! + */ + private static int[] compareMacTags( + byte[] buffer, int offset, byte[] tag) { + + // An array of hits is used to prevent Hotspot optimization for + // the purpose of a constant-time check. + int[] results = {0, 0}; // {missed #, matched #} + + // The caller ensures there are enough bytes available in the buffer. + // So we won't need to check the length of the buffer. + for (int i = 0; i < tag.length; i++) { + if (buffer[offset + i] != tag[i]) { + results[0]++; // mismatched bytes + } else { + results[1]++; // matched bytes } } - count -= len; - return true; + + return results; } - void decrypt(CipherBox box) throws BadPaddingException { - int len = count - headerSize; - count = headerSize + box.decrypt(buf, headerSize, len); - } + /* + * Calculate the length of a dummy buffer to run MAC computation + * and comparison on the remainder. + * + * The caller MUST ensure that the fullLen is not less than usedLen. + */ + static int calculateRemainingLen( + MAC signer, int fullLen, int usedLen) { + int blockLen = signer.hashBlockLen(); + int minimalPaddingLen = signer.minimalPaddingLen(); + + // (blockLen - minimalPaddingLen) is the maximum message size of + // the last block of hash function operation. See FIPS 180-4, or + // MD5 specification. + fullLen += 13 - (blockLen - minimalPaddingLen); + usedLen += 13 - (blockLen - minimalPaddingLen); + + // Note: fullLen is always not less than usedLen, and blockLen + // is always bigger than minimalPaddingLen, so we don't worry + // about negative values. 0x01 is added to the result to ensure + // that the return value is positive. The extra one byte does + // not impact the overall MAC compression function evaluations. + return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) - + Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen(); + } /* * Well ... hello_request messages are _never_ hashed since we can't diff --git a/jdk/src/share/classes/sun/security/ssl/MAC.java b/jdk/src/share/classes/sun/security/ssl/MAC.java index 753a8c57ac4..e491cc301da 100644 --- a/jdk/src/share/classes/sun/security/ssl/MAC.java +++ b/jdk/src/share/classes/sun/security/ssl/MAC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,8 @@ import static sun.security.ssl.CipherSuite.*; * provide integrity protection for SSL messages. The MAC is actually * one of several keyed hashes, as associated with the cipher suite and * protocol version. (SSL v3.0 uses one construct, TLS uses another.) - * - *

    NOTE: MAC computation is the only place in the SSL protocol that the + *

    + * NOTE: MAC computation is the only place in the SSL protocol that the * sequence number is used. It's also reset to zero with each change of * a cipher spec, so this is the only place this state is needed. * @@ -58,6 +58,9 @@ final class MAC { // Value of the null MAC is fixed private static final byte nullMAC[] = new byte[0]; + // internal identifier for the MAC algorithm + private final MacAlg macAlg; + // stuff defined by the kind of MAC algorithm private final int macSize; @@ -82,6 +85,7 @@ final class MAC { private MAC() { macSize = 0; + macAlg = M_NULL; mac = null; block = null; } @@ -91,6 +95,7 @@ final class MAC { */ MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException { + this.macAlg = macAlg; this.macSize = macAlg.size; String algorithm; @@ -127,6 +132,20 @@ final class MAC { return macSize; } + /** + * Returns the hash function block length of the MAC alorithm. + */ + int hashBlockLen() { + return macAlg.hashBlockSize; + } + + /** + * Returns the hash function minimal padding length of the MAC alorithm. + */ + int minimalPaddingLen() { + return macAlg.minimalPaddingSize; + } + /** * Computes and returns the MAC for the data in this byte array. * @@ -134,9 +153,11 @@ final class MAC { * @param buf compressed record on which the MAC is computed * @param offset start of compressed record data * @param len the size of the compressed record + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, byte buf[], int offset, int len) { - return compute(type, null, buf, offset, len); + final byte[] compute(byte type, byte buf[], + int offset, int len, boolean isSimulated) { + return compute(type, null, buf, offset, len, isSimulated); } /** @@ -149,9 +170,10 @@ final class MAC { * @param type record type * @param bb a ByteBuffer in which the position and limit * demarcate the data to be MAC'd. + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, ByteBuffer bb) { - return compute(type, bb, null, 0, bb.remaining()); + final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { + return compute(type, bb, null, 0, bb.remaining(), isSimulated); } /** @@ -204,18 +226,21 @@ final class MAC { * or buf/offset/len. */ private byte[] compute(byte type, ByteBuffer bb, byte[] buf, - int offset, int len) { + int offset, int len, boolean isSimulated) { if (macSize == 0) { return nullMAC; } - block[BLOCK_OFFSET_TYPE] = type; - block[block.length - 2] = (byte)(len >> 8); - block[block.length - 1] = (byte)(len ); + // MUST NOT increase the sequence number for a simulated computation. + if (!isSimulated) { + block[BLOCK_OFFSET_TYPE] = type; + block[block.length - 2] = (byte)(len >> 8); + block[block.length - 1] = (byte)(len ); - mac.update(block); - incrementSequenceNumber(); + mac.update(block); + incrementSequenceNumber(); + } // content if (bb != null) { diff --git a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java index 900003dfd0f..0ff27be460d 100644 --- a/jdk/src/share/classes/sun/security/ssl/OutputRecord.java +++ b/jdk/src/share/classes/sun/security/ssl/OutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record { } if (signer.MAClen() != 0) { byte[] hash = signer.compute(contentType, buf, - headerSize, count - headerSize); + headerSize, count - headerSize, false); write(hash); } } diff --git a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java index 2140214a059..d77229adb8d 100644 --- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -34,7 +34,7 @@ import javax.crypto.*; import javax.net.ssl.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * This is the client key exchange message (CLIENT --> SERVER) used with @@ -191,7 +191,7 @@ final class RSAClientKeyExchange extends HandshakeMessage { "unable to get the plaintext of the premaster secret"); } - int keySize = KeyLength.getKeySize(secretKey); + int keySize = KeyUtil.getKeySize(secretKey); if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 if (debug != null && Debug.isOn("handshake")) { System.out.println( diff --git a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java index 41415337ca1..5534cab0384 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine { * throw a fatal alert if the integrity check fails. */ try { - decryptedBB = inputRecord.decrypt(readCipher, readBB); + decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - // - // rewind the BB if necessary. - readBB.rewind(); - - inputRecord.checkMAC(readMAC, readBB); - - // use the same alert types as for MAC failure below byte alertType = (inputRecord.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!inputRecord.checkMAC(readMAC, decryptedBB)) { - if (inputRecord.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } // if (!inputRecord.decompress(c)) // fatal(Alerts.alert_decompression_failure, diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java index f807c4c58ce..cbc3db69b96 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -986,29 +986,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { * throw a fatal alert if the integrity check fails. */ try { - r.decrypt(readCipher); + r.decrypt(readMAC, readCipher); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - r.checkMAC(readMAC); - // use the same alert types as for MAC failure below byte alertType = (r.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!r.checkMAC(readMAC)) { - if (r.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } - // if (!r.decompress(c)) // fatal(Alerts.alert_decompression_failure, diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java index 89d5890b098..7865de9682b 100644 --- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -150,7 +150,7 @@ final class ServerHandshaker extends Handshaker { // In SSLv3 and TLS, messages follow strictly increasing // numerical order _except_ for one annoying special case. // - if ((state > type) + if ((state >= type) && (state != HandshakeMessage.ht_client_key_exchange && type != HandshakeMessage.ht_certificate_verify)) { throw new SSLProtocolException( @@ -250,13 +250,15 @@ final class ServerHandshaker extends Handshaker { } // - // Move the state machine forward except for that annoying - // special case. This means that clients could send extra - // cert verify messages; not a problem so long as all of - // them actually check out. + // Move state machine forward if the message handling + // code didn't already do so // - if (state < type && type != HandshakeMessage.ht_certificate_verify) { - state = type; + if (state < type) { + if(type == HandshakeMessage.ht_certificate_verify) { + state = type + 2; // an annoying special case + } else { + state = type; + } } } @@ -1406,7 +1408,7 @@ final class ServerHandshaker extends Handshaker { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } - return dh.getAgreedSecret(mesg.getClientPublicKey()); + return dh.getAgreedSecret(mesg.getClientPublicKey(), false); } private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg) diff --git a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index aeaa4f997a1..14a00d85a2b 100644 --- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -38,7 +38,7 @@ import java.util.Collection; import java.util.Collections; import java.util.ArrayList; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * Signature and hash algorithm. @@ -274,7 +274,7 @@ final class SignatureAndHashAlgorithm { * If key size is less than 512, the digest length should be * less than or equal to 20 bytes. */ - int keySize = KeyLength.getKeySize(signingKey); + int keySize = KeyUtil.getKeySize(signingKey); if (keySize >= 768) { maxDigestLength = HashAlgorithm.SHA512.length; } else if ((keySize >= 512) && (keySize < 768)) { diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java index 159de08695a..9828a1a9a1d 100644 --- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java +++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java @@ -57,7 +57,7 @@ import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.x509.*; import sun.security.util.*; -import sun.misc.BASE64Encoder; +import java.util.Base64; /** @@ -1120,7 +1120,6 @@ public class Main { * different, replace the hash in the manifest with the newly * generated one. (This may invalidate existing signatures!) */ - BASE64Encoder encoder = new JarBASE64Encoder(); Vector mfFiles = new Vector<>(); boolean wasSigned = false; @@ -1148,15 +1147,14 @@ public class Main { if (manifest.getAttributes(ze.getName()) != null) { // jar entry is contained in manifest, check and // possibly update its digest attributes - if (updateDigests(ze, zipFile, digests, encoder, + if (updateDigests(ze, zipFile, digests, manifest) == true) { mfModified = true; } } else if (!ze.isDirectory()) { // Add entry to manifest Attributes attrs = getDigestAttributes(ze, zipFile, - digests, - encoder); + digests); mfEntries.put(ze.getName(), attrs); mfModified = true; } @@ -1955,8 +1953,7 @@ public class Main { * of base64-encoded strings. */ private synchronized String[] getDigests(ZipEntry ze, ZipFile zf, - MessageDigest[] digests, - BASE64Encoder encoder) + MessageDigest[] digests) throws IOException { int n, i; @@ -1980,7 +1977,7 @@ public class Main { // complete the digests String[] base64Digests = new String[digests.length]; for (i=0; i= 0) { - return size; - } - } - - // try to parse the length from key specification - if (key instanceof SecretKey) { - SecretKey sk = (SecretKey)key; - String format = sk.getFormat(); - if ("RAW".equals(format) && sk.getEncoded() != null) { - size = (sk.getEncoded().length * 8); - } // Otherwise, it may be a unextractable key of PKCS#11, or - // a key we are not able to handle. - } else if (key instanceof RSAKey) { - RSAKey pubk = (RSAKey)key; - size = pubk.getModulus().bitLength(); - } else if (key instanceof ECKey) { - ECKey pubk = (ECKey)key; - size = pubk.getParams().getOrder().bitLength(); - } else if (key instanceof DSAKey) { - DSAKey pubk = (DSAKey)key; - size = pubk.getParams().getP().bitLength(); - } else if (key instanceof DHKey) { - DHKey pubk = (DHKey)key; - size = pubk.getParams().getP().bitLength(); - } // Otherwise, it may be a unextractable key of PKCS#11, or - // a key we are not able to handle. - - return size; - } -} - diff --git a/jdk/src/share/classes/sun/security/util/KeyUtil.java b/jdk/src/share/classes/sun/security/util/KeyUtil.java new file mode 100644 index 00000000000..6664dab38b6 --- /dev/null +++ b/jdk/src/share/classes/sun/security/util/KeyUtil.java @@ -0,0 +1,204 @@ +/* + * 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 sun.security.util; + +import java.security.Key; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.security.InvalidKeyException; +import java.security.interfaces.ECKey; +import java.security.interfaces.RSAKey; +import java.security.interfaces.DSAKey; +import java.security.spec.KeySpec; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.DHKey; +import javax.crypto.interfaces.DHPublicKey; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; +import java.math.BigInteger; + +/** + * A utility class to get key length, valiate keys, etc. + */ +public final class KeyUtil { + + /** + * Returns the key size of the given key object in bits. + * + * @param key the key object, cannot be null + * @return the key size of the given key object in bits, or -1 if the + * key size is not accessible + */ + public static final int getKeySize(Key key) { + int size = -1; + + if (key instanceof Length) { + try { + Length ruler = (Length)key; + size = ruler.length(); + } catch (UnsupportedOperationException usoe) { + // ignore the exception + } + + if (size >= 0) { + return size; + } + } + + // try to parse the length from key specification + if (key instanceof SecretKey) { + SecretKey sk = (SecretKey)key; + String format = sk.getFormat(); + if ("RAW".equals(format) && sk.getEncoded() != null) { + size = (sk.getEncoded().length * 8); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + } else if (key instanceof RSAKey) { + RSAKey pubk = (RSAKey)key; + size = pubk.getModulus().bitLength(); + } else if (key instanceof ECKey) { + ECKey pubk = (ECKey)key; + size = pubk.getParams().getOrder().bitLength(); + } else if (key instanceof DSAKey) { + DSAKey pubk = (DSAKey)key; + size = pubk.getParams().getP().bitLength(); + } else if (key instanceof DHKey) { + DHKey pubk = (DHKey)key; + size = pubk.getParams().getP().bitLength(); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + + return size; + } + + /** + * Returns whether the key is valid or not. + *

    + * Note that this method is only apply to DHPublicKey at present. + * + * @param publicKey + * the key object, cannot be null + * + * @throws NullPointerException if {@code publicKey} is null + * @throws InvalidKeyException if {@code publicKey} is invalid + */ + public static final void validate(Key key) + throws InvalidKeyException { + if (key == null) { + throw new NullPointerException( + "The key to be validated cannot be null"); + } + + if (key instanceof DHPublicKey) { + validateDHPublicKey((DHPublicKey)key); + } + } + + + /** + * Returns whether the key spec is valid or not. + *

    + * Note that this method is only apply to DHPublicKeySpec at present. + * + * @param keySpec + * the key spec object, cannot be null + * + * @throws NullPointerException if {@code keySpec} is null + * @throws InvalidKeyException if {@code keySpec} is invalid + */ + public static final void validate(KeySpec keySpec) + throws InvalidKeyException { + if (keySpec == null) { + throw new NullPointerException( + "The key spec to be validated cannot be null"); + } + + if (keySpec instanceof DHPublicKeySpec) { + validateDHPublicKey((DHPublicKeySpec)keySpec); + } + } + + /** + * Returns whether the specified provider is Oracle provider or not. + *

    + * Note that this method is only apply to SunJCE and SunPKCS11 at present. + * + * @param providerName + * the provider name + * @return true if, and only if, the provider of the specified + * {@code providerName} is Oracle provider + */ + public static final boolean isOracleJCEProvider(String providerName) { + return providerName != null && (providerName.equals("SunJCE") || + providerName.startsWith("SunPKCS11")); + } + + /** + * Returns whether the Diffie-Hellman public key is valid or not. + * + * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to + * validate Diffie-Hellman public keys: + * 1. Verify that y lies within the interval [2,p-1]. If it does not, + * the key is invalid. + * 2. Compute y^q mod p. If the result == 1, the key is valid. + * Otherwise the key is invalid. + */ + private static void validateDHPublicKey(DHPublicKey publicKey) + throws InvalidKeyException { + DHParameterSpec paramSpec = publicKey.getParams(); + + BigInteger p = paramSpec.getP(); + BigInteger g = paramSpec.getG(); + BigInteger y = publicKey.getY(); + + validateDHPublicKey(p, g, y); + } + + private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec) + throws InvalidKeyException { + validateDHPublicKey(publicKeySpec.getP(), + publicKeySpec.getG(), publicKeySpec.getY()); + } + + private static void validateDHPublicKey(BigInteger p, + BigInteger g, BigInteger y) throws InvalidKeyException { + + // For better interoperability, the interval is limited to [2, p-2]. + BigInteger leftOpen = BigInteger.ONE; + BigInteger rightOpen = p.subtract(BigInteger.ONE); + if (y.compareTo(leftOpen) <= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too small"); + } + if (y.compareTo(rightOpen) >= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too large"); + } + + // Don't bother to check against the y^q mod p if safe primes are used. + } +} + diff --git a/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java b/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java index 3d1b4733c30..548133cfa40 100644 --- a/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java +++ b/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java @@ -31,7 +31,7 @@ import java.security.CodeSigner; import java.util.*; import java.util.jar.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; import sun.security.jca.Providers; @@ -63,7 +63,6 @@ public class ManifestEntryVerifier { /** the manifest hashes for the digests in use */ ArrayList manifestHashes; - private BASE64Decoder decoder = null; private String name = null; private Manifest man; @@ -81,7 +80,6 @@ public class ManifestEntryVerifier { createdDigests = new HashMap(11); digests = new ArrayList(); manifestHashes = new ArrayList(); - decoder = new BASE64Decoder(); this.man = man; } @@ -147,7 +145,7 @@ public class ManifestEntryVerifier { digest.reset(); digests.add(digest); manifestHashes.add( - decoder.decodeBuffer((String)se.getValue())); + Base64.getMimeDecoder().decode((String)se.getValue())); } } } diff --git a/jdk/src/share/classes/sun/security/util/SecurityConstants.java b/jdk/src/share/classes/sun/security/util/SecurityConstants.java index c9d321f7c15..2b985ad0f65 100644 --- a/jdk/src/share/classes/sun/security/util/SecurityConstants.java +++ b/jdk/src/share/classes/sun/security/util/SecurityConstants.java @@ -70,31 +70,6 @@ public final class SecurityConstants { // sun.security.provider.PolicyFile public static final AllPermission ALL_PERMISSION = new AllPermission(); - /** - * Permission type used when AWT is not present. - */ - private static class FakeAWTPermission extends BasicPermission { - private static final long serialVersionUID = -1L; - public FakeAWTPermission(String name) { - super(name); - } - public String toString() { - return "(\"java.awt.AWTPermission\" \"" + getName() + "\")"; - } - } - - /** - * Permission factory used when AWT is not present. - */ - private static class FakeAWTPermissionFactory - implements PermissionFactory - { - @Override - public FakeAWTPermission newPermission(String name) { - return new FakeAWTPermission(name); - } - } - /** * AWT Permissions used in the JDK. */ @@ -107,37 +82,29 @@ public final class SecurityConstants { private static final String AWTFactory = "sun.awt.AWTPermissionFactory"; /** - * The PermissionFactory to create AWT permissions (or fake permissions - * if AWT is not present). + * The PermissionFactory to create AWT permissions (or null if AWT is + * not present) */ private static final PermissionFactory factory = permissionFactory(); private static PermissionFactory permissionFactory() { - Class c = AccessController - .doPrivileged(new PrivilegedAction>() { - public Class run() { - try { - return Class.forName(AWTFactory, true, null); - } catch (ClassNotFoundException e) { - // not available - return null; - } - }}); - if (c != null) { - // AWT present - try { - return (PermissionFactory)c.newInstance(); - } catch (ReflectiveOperationException x) { - throw new InternalError(x.getMessage(), x); - } - } else { - // AWT not present - return new FakeAWTPermissionFactory(); + Class c; + try { + c = Class.forName(AWTFactory, false, AWT.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // not available + return null; + } + // AWT present + try { + return (PermissionFactory)c.newInstance(); + } catch (ReflectiveOperationException x) { + throw new InternalError(x); } } private static Permission newAWTPermission(String name) { - return factory.newPermission(name); + return (factory == null) ? null : factory.newPermission(name); } // java.lang.SecurityManager diff --git a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java index 715a5da356b..e84cc2c37a8 100644 --- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java @@ -35,7 +35,7 @@ import java.util.*; import java.util.jar.*; import sun.security.pkcs.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; import sun.security.jca.Providers; @@ -220,7 +220,6 @@ public class SignatureFileVerifier { name); } - BASE64Decoder decoder = new BASE64Decoder(); CodeSigner[] newSigners = getSigners(infos, block); @@ -232,10 +231,10 @@ public class SignatureFileVerifier { sf.getEntries().entrySet().iterator(); // see if we can verify the whole manifest first - boolean manifestSigned = verifyManifestHash(sf, md, decoder, manifestDigests); + boolean manifestSigned = verifyManifestHash(sf, md, manifestDigests); // verify manifest main attributes - if (!manifestSigned && !verifyManifestMainAttrs(sf, md, decoder)) { + if (!manifestSigned && !verifyManifestMainAttrs(sf, md)) { throw new SecurityException ("Invalid signature file digest for Manifest main attributes"); } @@ -247,7 +246,7 @@ public class SignatureFileVerifier { String name = e.getKey(); if (manifestSigned || - (verifySection(e.getValue(), name, md, decoder))) { + (verifySection(e.getValue(), name, md))) { if (name.startsWith("./")) name = name.substring(2); @@ -275,7 +274,6 @@ public class SignatureFileVerifier { */ private boolean verifyManifestHash(Manifest sf, ManifestDigester md, - BASE64Decoder decoder, List manifestDigests) throws IOException { @@ -297,7 +295,7 @@ public class SignatureFileVerifier { if (digest != null) { byte[] computedHash = md.manifestDigest(digest); byte[] expectedHash = - decoder.decodeBuffer((String)se.getValue()); + Base64.getMimeDecoder().decode((String)se.getValue()); if (debug != null) { debug.println("Signature File: Manifest digest " + @@ -320,8 +318,7 @@ public class SignatureFileVerifier { } private boolean verifyManifestMainAttrs(Manifest sf, - ManifestDigester md, - BASE64Decoder decoder) + ManifestDigester md) throws IOException { Attributes mattr = sf.getMainAttributes(); @@ -342,7 +339,7 @@ public class SignatureFileVerifier { md.get(ManifestDigester.MF_MAIN_ATTRS, false); byte[] computedHash = mde.digest(digest); byte[] expectedHash = - decoder.decodeBuffer((String)se.getValue()); + Base64.getMimeDecoder().decode((String)se.getValue()); if (debug != null) { debug.println("Signature File: " + @@ -387,8 +384,7 @@ public class SignatureFileVerifier { private boolean verifySection(Attributes sfAttr, String name, - ManifestDigester md, - BASE64Decoder decoder) + ManifestDigester md) throws IOException { boolean oneDigestVerified = false; @@ -418,7 +414,7 @@ public class SignatureFileVerifier { boolean ok = false; byte[] expected = - decoder.decodeBuffer((String)se.getValue()); + Base64.getMimeDecoder().decode((String)se.getValue()); byte[] computed; if (workaround) { computed = mde.digestWorkaround(digest); diff --git a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java index 6aad34a73a4..03fdbc78332 100644 --- a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java +++ b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java @@ -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 @@ -737,5 +737,111 @@ public final class UntrustedCertificates { "B8WfedLHjFW/TMcnXlEWKz4=\n" + "-----END CERTIFICATE-----"); + // + // Revoked DigiCert code signing certificates used to sign malware + // + + // Subject: CN=Buster Paper Comercial Ltda, + // O=Buster Paper Comercial Ltda, + // L=S?o Jos? Dos Campos, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 + add("buster-paper-comercial-ltda-72A67312", + "-----BEGIN CERTIFICATE-----\n" + + "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" + + "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" + + "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" + + "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" + + "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" + + "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" + + "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" + + "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" + + "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" + + "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" + + "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" + + "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" + + "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" + + "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" + + "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" + + "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" + + "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" + + "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" + + "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" + + "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" + + "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" + + "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" + + "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" + + "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" + + "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" + + "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" + + "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" + + "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" + + "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" + + "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" + + "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" + + "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" + + "XMuKLxbh7g==\n" + + "-----END CERTIFICATE-----"); + + // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // L=S?o Paulo, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f + add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F", + "-----BEGIN CERTIFICATE-----\n" + + "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" + + "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" + + "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" + + "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" + + "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" + + "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" + + "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" + + "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" + + "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" + + "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" + + "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" + + "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" + + "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" + + "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" + + "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" + + "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" + + "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" + + "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" + + "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" + + "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" + + "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" + + "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" + + "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" + + "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" + + "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" + + "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" + + "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" + + "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" + + "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" + + "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" + + "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" + + "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" + + "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" + + "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + + "-----END CERTIFICATE-----"); + } } diff --git a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java index 64e06ceaebf..1593e5ed4ab 100644 --- a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java +++ b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java @@ -41,7 +41,7 @@ import java.util.*; import javax.security.auth.x500.X500Principal; import sun.misc.HexDumpEncoder; -import sun.misc.BASE64Decoder; +import java.util.Base64; import sun.security.util.*; import sun.security.provider.X509Factory; @@ -263,7 +263,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { } if (line.equals(X509Factory.BEGIN_CERT)) { /* stream appears to be hex-encoded bytes */ - BASE64Decoder decoder = new BASE64Decoder(); ByteArrayOutputStream decstream = new ByteArrayOutputStream(); try { while ((line = certBufferedReader.readLine()) != null) { @@ -271,7 +270,7 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { der = new DerValue(decstream.toByteArray()); break; } else { - decstream.write(decoder.decodeBuffer(line)); + decstream.write(Base64.getMimeDecoder().decode(line)); } } } catch (IOException ioe2) { diff --git a/jdk/src/share/classes/sun/swing/JLightweightFrame.java b/jdk/src/share/classes/sun/swing/JLightweightFrame.java new file mode 100644 index 00000000000..f7ea0aead1e --- /dev/null +++ b/jdk/src/share/classes/sun/swing/JLightweightFrame.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; + +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.LayoutFocusTraversalPolicy; +import javax.swing.RootPaneContainer; + +import sun.awt.LightweightFrame; + +/** + * The frame serves as a lightweight container which paints its content + * to an offscreen image and provides access to the image's data via the + * {@link LightweightContent} interface. Note, that it may not be shown + * as a standalone toplevel frame. Its purpose is to provide functionality + * for lightweight embedding. + * + * @author Artem Ananiev + * @author Anton Tarasov + */ +public final class JLightweightFrame extends LightweightFrame implements RootPaneContainer { + + private final JRootPane rootPane = new JRootPane(); + + private LightweightContent content; + + private Component component; + private JPanel contentPane; + + private BufferedImage bbImage; + + /** + * Constructs a new, initially invisible {@code JLightweightFrame} + * instance. + */ + public JLightweightFrame() { + super(); + add(rootPane, BorderLayout.CENTER); + setBackground(new Color(0, 0, 0, 0)); + setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); + } + + /** + * Sets the {@link LightweightContent} instance for this frame. + * The {@code JComponent} object returned by the + * {@link LightweightContent#getComponent()} method is immediately + * added to the frame's content pane. + * + * @param content the {@link LightweightContent} instance + */ + public void setContent(LightweightContent content) { + this.content = content; + this.component = content.getComponent(); + + initInterior(); + } + + @Override + public Graphics getGraphics() { + if (bbImage == null) return null; + + Graphics2D g = bbImage.createGraphics(); + g.setBackground(getBackground()); + g.setColor(getForeground()); + g.setFont(getFont()); + return g; + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusGrabbed() + */ + @Override + public void grabFocus() { + if (content != null) content.focusGrabbed(); + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusUngrabbed() + */ + @Override + public void ungrabFocus() { + if (content != null) content.focusUngrabbed(); + } + + private void initInterior() { + contentPane = new JPanel() { + @Override + public void paint(Graphics g) { + content.paintLock(); + try { + super.paint(g); + + final Rectangle clip = g.getClipBounds() != null ? + g.getClipBounds() : new Rectangle(0, 0, contentPane.getWidth(), contentPane.getHeight()); + + clip.x = Math.max(0, clip.x); + clip.y = Math.max(0, clip.y); + clip.width = Math.min(contentPane.getWidth(), clip.width); + clip.height = Math.min(contentPane.getHeight(), clip.height); + + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + content.imageUpdated(clip.x, clip.y, clip.width, clip.height); + } + }); + } finally { + content.paintUnlock(); + } + } + @Override + protected boolean isPaintingOrigin() { + return true; + } + }; + contentPane.setLayout(new BorderLayout()); + contentPane.add(component); + setContentPane(contentPane); + } + + @SuppressWarnings("deprecation") + @Override public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + + if (width == 0 || height == 0) { + return; + } + + content.paintLock(); + try { + if ((bbImage == null) || (width != bbImage.getWidth()) || (height != bbImage.getHeight())) { + boolean createBB = true; + int newW = width; + int newH = height; + if (bbImage != null) { + int oldW = bbImage.getWidth(); + int oldH = bbImage.getHeight(); + if ((oldW >= newW) && (oldH >= newH)) { + createBB = false; + } else { + if (oldW >= newW) { + newW = oldW; + } else { + newW = Math.max((int)(oldW * 1.2), width); + } + if (oldH >= newH) { + newH = oldH; + } else { + newH = Math.max((int)(oldH * 1.2), height); + } + } + } + if (createBB) { + BufferedImage oldBB = bbImage; + bbImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB_PRE); + if (oldBB != null) { + Graphics g = bbImage.getGraphics(); + try { + g.drawImage(oldBB, 0, 0, newW, newH, null); + } finally { + g.dispose(); + oldBB.flush(); + } + } + DataBufferInt dataBuf = (DataBufferInt)bbImage.getRaster().getDataBuffer(); + content.imageBufferReset(dataBuf.getData(), 0, 0, width, height, bbImage.getWidth()); + } else { + content.imageReshaped(0, 0, width, height); + } + } + } finally { + content.paintUnlock(); + } + } + + @Override + public JRootPane getRootPane() { + return rootPane; + } + + @Override + public void setContentPane(Container contentPane) { + getRootPane().setContentPane(contentPane); + } + + @Override + public Container getContentPane() { + return getRootPane().getContentPane(); + } + + @Override + public void setLayeredPane(JLayeredPane layeredPane) { + getRootPane().setLayeredPane(layeredPane); + } + + @Override + public JLayeredPane getLayeredPane() { + return getRootPane().getLayeredPane(); + } + + @Override + public void setGlassPane(Component glassPane) { + getRootPane().setGlassPane(glassPane); + } + + @Override + public Component getGlassPane() { + return getRootPane().getGlassPane(); + } +} diff --git a/jdk/src/share/classes/sun/swing/LightweightContent.java b/jdk/src/share/classes/sun/swing/LightweightContent.java new file mode 100644 index 00000000000..2d443fba23c --- /dev/null +++ b/jdk/src/share/classes/sun/swing/LightweightContent.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.swing; + +import javax.swing.JComponent; + +/** + * The interface by means of which the {@link JLightweightFrame} class + * communicates to its client application. + *

    + * The client application implements this interface so it can response + * to requests and process notifications from {@code JLightweightFrame}. + * An implementation of this interface is associated with a {@code + * JLightweightFrame} instance via the {@link JLightweightFrame#setContent} + * method. + * + * A hierarchy of components contained in the {@code JComponent} instance + * returned by the {@link #getComponent} method should not contain any + * heavyweight components, otherwise {@code JLightweightFrame} may fail + * to paint it. + * + * @author Artem Ananiev + * @author Anton Tarasov + * @author Jim Graham + */ +public interface LightweightContent { + + /** + * The client application overrides this method to return the {@code + * JComponent} instance which the {@code JLightweightFrame} container + * will paint as its lightweight content. A hierarchy of components + * contained in this component should not contain any heavyweight objects. + * + * @return the component to paint + */ + public JComponent getComponent(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that it acquires the paint lock. The client application + * should implement the locking mechanism in order to synchronize access + * to the content image data, shared between {@code JLightweightFrame} + * and the client application. + * + * @see #paintUnlock + */ + public void paintLock(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that it releases the paint lock. The client application + * should implement the locking mechanism in order to synchronize access + * to the content image data, shared between {@code JLightweightFrame} + * and the client application. + * + * @see #paintLock + */ + public void paintUnlock(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that a new data buffer has been set as a content pixel + * buffer. Typically this occurs when a buffer of a larger size is + * created in response to a content resize event. The method reports + * a reference to the pixel data buffer, the content image bounds + * within the buffer and the line stride of the buffer. These values + * have the following correlation. + *

    + * The {@code width} and {@code height} matches the size of the content + * (the component returned from the {@link #getComponent} method). The + * {@code x} and {@code y} is the origin of the content, {@code (0, 0)} + * in the coordinate space of the content, appearing at + * {@code data[y * linestride + x]} in the buffer. All indices + * {@code data[(y + j) * linestride + (x + i)]} where + * {@code (0 <= i < width)} and {@code (0 <= j < height)} will represent + * valid pixel data, {@code (i, j)} in the coordinate space of the content. + * + * @param data the content pixel data buffer of INT_ARGB_PRE type + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * @param linestride the line stride of the pixel buffer + */ + public void imageBufferReset(int[] data, + int x, int y, + int width, int height, + int linestride); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the content image bounds have been changed within the + * image's pixel buffer. + * + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * + * @see #imageBufferReset + */ + public void imageReshaped(int x, int y, int width, int height); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that a part of the content image, or the whole image has + * been updated. The method reports bounds of the rectangular dirty region. + * The {@code dirtyX} and {@code dirtyY} is the origin of the dirty + * rectangle, which is relative to the origin of the content, appearing + * at {@code data[(y + dirtyY] * linestride + (x + dirtyX)]} in the pixel + * buffer (see {@link #imageBufferReset}). All indices + * {@code data[(y + dirtyY + j) * linestride + (x + dirtyX + i)]} where + * {@code (0 <= i < dirtyWidth)} and {@code (0 <= j < dirtyHeight)} + * will represent valid pixel data, {@code (i, j)} in the coordinate space + * of the dirty rectangle. + * + * @param dirtyX the x coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyY the y coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyWidth the width of the dirty rectangle + * @param dirtyHeight the height of the dirty rectangle + * + * @see #imageBufferReset + * @see #imageReshaped + */ + public void imageUpdated(int dirtyX, int dirtyY, + int dirtyWidth, int dirtyHeight); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has grabbed focus. + */ + public void focusGrabbed(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has ungrabbed focus. + */ + public void focusUngrabbed(); +} diff --git a/jdk/src/share/classes/sun/tools/jar/Manifest.java b/jdk/src/share/classes/sun/tools/jar/Manifest.java index 7a8cf74a906..b1e23ce8e81 100644 --- a/jdk/src/share/classes/sun/tools/jar/Manifest.java +++ b/jdk/src/share/classes/sun/tools/jar/Manifest.java @@ -30,8 +30,7 @@ import java.util.*; import java.security.*; import sun.net.www.MessageHeader; -import sun.misc.BASE64Encoder; -import sun.misc.BASE64Decoder; +import java.util.Base64; /** * This is OBSOLETE. DO NOT USE THIS. Use java.util.jar.Manifest @@ -178,7 +177,6 @@ public class Manifest { return; } - BASE64Encoder enc = new BASE64Encoder(); /* compute hashes, write over any other "Hash-Algorithms" (?) */ for (int j = 0; j < hashes.length; ++j) { @@ -190,7 +188,7 @@ public class Manifest { while ((len = is.read(tmpbuf, 0, tmpbuf.length)) != -1) { dig.update(tmpbuf, 0, len); } - mh.set(hashes[j] + "-Digest", enc.encode(dig.digest())); + mh.set(hashes[j] + "-Digest", Base64.getMimeEncoder().encodeToString(dig.digest())); } catch (NoSuchAlgorithmException e) { throw new JarException("Digest algorithm " + hashes[j] + " not available."); diff --git a/jdk/src/share/classes/sun/tools/jar/SignatureFile.java b/jdk/src/share/classes/sun/tools/jar/SignatureFile.java index 8e7d3f59435..007b67962e5 100644 --- a/jdk/src/share/classes/sun/tools/jar/SignatureFile.java +++ b/jdk/src/share/classes/sun/tools/jar/SignatureFile.java @@ -30,8 +30,8 @@ import java.util.*; import java.security.*; import sun.net.www.MessageHeader; -import sun.misc.BASE64Encoder; -import sun.misc.BASE64Decoder; +import java.util.Base64; + import sun.security.pkcs.*; import sun.security.x509.AlgorithmId; @@ -305,7 +305,6 @@ public class SignatureFile { } smh.set("Name", name); - BASE64Encoder encoder = new BASE64Encoder(); try { for (int i = 0; i < hashes.length; ++i) { MessageDigest dig = getDigest(hashes[i]); @@ -314,7 +313,7 @@ public class SignatureFile { mh.print(ps); byte[] headerBytes = baos.toByteArray(); byte[] digest = dig.digest(headerBytes); - smh.set(hashes[i] + "-Digest", encoder.encode(digest)); + smh.set(hashes[i] + "-Digest", Base64.getMimeEncoder().encodeToString(digest)); } return smh; } catch (NoSuchAlgorithmException e) { diff --git a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index 2f12f6540ce..d7e32408cbc 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -33,6 +33,7 @@ import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.NumberFormatProvider; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; @@ -89,10 +90,7 @@ public abstract class LocaleProviderAdapter { * LocaleProviderAdapter preference list. The default list is intended * to behave the same manner in JDK7. */ - private static Type[] adapterPreference = { - Type.JRE, - Type.SPI, - }; + private static final List adapterPreference; /** * JRE Locale Data Adapter instance @@ -129,10 +127,11 @@ public abstract class LocaleProviderAdapter { static { String order = AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.locale.providers")); - // Override adapterPreference with the properties one + List typeList = new ArrayList<>(); + + // Check user specified adapter preference if (order != null && order.length() != 0) { String[] types = order.split(","); - List typeList = new ArrayList<>(); for (String type : types) { try { Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT)); @@ -153,18 +152,22 @@ public abstract class LocaleProviderAdapter { LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString()); } } - - if (!typeList.isEmpty()) { - if (!typeList.contains(Type.JRE)) { - // Append FALLBACK as the last resort. - fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter(); - typeList.add(Type.FALLBACK); - } - adapterPreference = typeList.toArray(new Type[0]); - } } - } + if (!typeList.isEmpty()) { + if (!typeList.contains(Type.JRE)) { + // Append FALLBACK as the last resort. + fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter(); + typeList.add(Type.FALLBACK); + } + } else { + // Default preference list + typeList.add(Type.JRE); + typeList.add(Type.SPI); + } + + adapterPreference = Collections.unmodifiableList(typeList); + } /** * Returns the singleton instance for each adapter type @@ -202,7 +205,7 @@ public abstract class LocaleProviderAdapter { /** * Returns the preference order of LocaleProviderAdapter.Type */ - public static Type[] getAdapterPreference() { + public static List getAdapterPreference() { return adapterPreference; } diff --git a/jdk/src/share/demo/java2d/J2DBench/build.xml b/jdk/src/share/demo/java2d/J2DBench/build.xml index a36aca8cec7..c29611d0f7a 100644 --- a/jdk/src/share/demo/java2d/J2DBench/build.xml +++ b/jdk/src/share/demo/java2d/J2DBench/build.xml @@ -52,7 +52,7 @@ - - + + + + - - diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg new file mode 100644 index 00000000000..6d61c9f120f Binary files /dev/null and b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg differ diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg new file mode 100644 index 00000000000..6b4ef3f38d1 Binary files /dev/null and b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg differ diff --git a/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg new file mode 100644 index 00000000000..41fb2eaccba Binary files /dev/null and b/jdk/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg differ diff --git a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java index e71b18857f1..4916929c32f 100644 --- a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java +++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java @@ -51,6 +51,7 @@ public class ColorConversionTests extends CMMTests { DataConversionTests.init(); ColorConvertOpTests.init(); + EmbeddedProfileTests.init(); } protected ColorConversionTests(Group parent, String nodeName, String description) { diff --git a/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java new file mode 100644 index 00000000000..3af6313eff1 --- /dev/null +++ b/jdk/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This source code is provided to illustrate the usage of a given feature + * or technique and has been deliberately simplified. Additional steps + * required for a production-quality application, such as security checks, + * input validation and proper error handling, might not be present in + * this sample code. + */ + +package j2dbench.tests.cmm; + +import j2dbench.Group; +import j2dbench.Option; +import j2dbench.Result; +import j2dbench.TestEnvironment; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +/* This benchmark verifies how changes in cmm library affects image decoding */ +public class EmbeddedProfileTests extends ColorConversionTests { + + protected static Group grpRoot; + protected static Group grpOptionsRoot; + + protected static Option inputImages; + + public static void init() { + grpRoot = new Group(colorConvRoot, "embed", "Embedded Profile Tests"); + + grpOptionsRoot = new Group(grpRoot, "embedOptions", "Options"); + + inputImages = createImageList(); + + new ReadImageTest(); + } + + private static enum IccImageResource { + SMALL("images/img_icc_small.jpg", "512x512", "Small: 512x512"), + MEDIUM("images/img_icc_medium.jpg", "2048x2048", "Medium: 2048x2048"), + LARGE("images/img_icc_large.jpg", "4096x4096", "Large: 4096x4096"); + + private IccImageResource(String file, String name, String description) { + this.url = CMMTests.class.getResource(file); + this.abbrev = name; + this.description = description; + } + + public final URL url; + public final String abbrev; + public final String description; + } + + private static Option createImageList() { + IccImageResource[] images = IccImageResource.values(); + + int num = images.length; + + String[] names = new String[num]; + String[] abbrev = new String[num]; + String[] descr = new String[num]; + + for (int i = 0; i < num; i++) { + names[i] = images[i].toString(); + abbrev[i] = images[i].abbrev; + descr[i] = images[i].description; + } + + Option list = new Option.ObjectList(grpOptionsRoot, + "Images", "Input Images", + names, images, abbrev, descr, 1); + + return list; + } + + public EmbeddedProfileTests(Group parent, String nodeName, String description) { + super(parent, nodeName, description); + addDependencies(grpOptionsRoot, true); + } + + private static class Context { + URL input; + + public Context(TestEnvironment env, Result res) { + + IccImageResource icc_input = (IccImageResource) + env.getModifier(inputImages); + + input = icc_input.url; + } + } + + public Object initTest(TestEnvironment env, Result res) { + return new Context(env, res); + } + + public void cleanupTest(TestEnvironment env, Object o) { + Context ctx = (Context)o; + ctx.input = null; + } + + private static class ReadImageTest extends EmbeddedProfileTests { + public ReadImageTest() { + super(grpRoot, "embd_img_read", "ImageReader.read()"); + } + + public void runTest(Object octx, int numReps) { + final Context ctx = (Context)octx; + final URL url = ctx.input; + ImageInputStream iis = null; + ImageReader reader = null; + + try { + iis = ImageIO.createImageInputStream(url.openStream()); + reader = ImageIO.getImageReaders(iis).next(); + } catch (IOException e) { + throw new RuntimeException("Unable to run the becnhmark", e); + } + + do { + try { + reader.setInput(iis); + BufferedImage img = reader.read(0); + reader.reset(); + + iis = ImageIO.createImageInputStream(url.openStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } while (--numReps >= 0); + } + } +} diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_init.c b/jdk/src/share/demo/jvmti/hprof/hprof_init.c index 328c474d410..aa3c820f1fc 100644 --- a/jdk/src/share/demo/jvmti/hprof/hprof_init.c +++ b/jdk/src/share/demo/jvmti/hprof/hprof_init.c @@ -1899,11 +1899,17 @@ load_library(char *name) */ getSystemProperty("sun.boot.library.path", &boot_path); md_build_library_name(lname, FILENAME_MAX, boot_path, name); + if ( strlen(lname) == 0 ) { + HPROF_ERROR(JNI_TRUE, "Could not find library"); + } jvmtiDeallocate(boot_path); handle = md_load_library(lname, err_buf, (int)sizeof(err_buf)); if ( handle == NULL ) { /* This may be necessary on Windows. */ md_build_library_name(lname, FILENAME_MAX, "", name); + if ( strlen(lname) == 0 ) { + HPROF_ERROR(JNI_TRUE, "Could not find library"); + } handle = md_load_library(lname, err_buf, (int)sizeof(err_buf)); if ( handle == NULL ) { HPROF_ERROR(JNI_TRUE, err_buf); @@ -1968,6 +1974,9 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) getSystemProperty("sun.boot.library.path", &boot_path); /* Load in NPT library for character conversions */ md_build_library_name(npt_lib, sizeof(npt_lib), boot_path, NPT_LIBNAME); + if ( strlen(npt_lib) == 0 ) { + HPROF_ERROR(JNI_TRUE, "Could not find npt library"); + } jvmtiDeallocate(boot_path); NPT_INITIALIZE(npt_lib, &(gdata->npt), NPT_VERSION, NULL); if ( gdata->npt == NULL ) { diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux index dd63fd4d1e2..8fc53d73677 100644 --- a/jdk/src/share/lib/security/java.security-linux +++ b/jdk/src/share/lib/security/java.security-linux @@ -145,7 +145,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -157,7 +169,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx index 00759d7b215..5a319fa5445 100644 --- a/jdk/src/share/lib/security/java.security-macosx +++ b/jdk/src/share/lib/security/java.security-macosx @@ -146,7 +146,20 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ + apple. # # List of comma-separated packages that start with or equal this string @@ -158,7 +171,20 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ + apple. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 241873676b7..2a781cff75d 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -147,7 +147,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -159,7 +171,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index 62b8b51fee6..a00f4628dd6 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -146,7 +146,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -158,7 +170,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp index 8ad5e556c41..f698c6d6cfb 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp @@ -187,6 +187,10 @@ void band::setIndexByTag(byte tag) { entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { CHECK_0; + if (ix_ == NULL) { + abort("no index"); + return NULL; + } assert(ix_->ixTag == ixTag || ((ixTag == CONSTANT_All || ixTag == CONSTANT_LoadableValue || @@ -354,7 +358,7 @@ const band_init all_band_inits[] = { BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_MethodParameters_NB, BYTE1_spec, 0), BAND_INIT(method_MethodParameters_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), - BAND_INIT(method_MethodParameters_flag_I, UNSIGNED5_spec, 0), + BAND_INIT(method_MethodParameters_flag_FH, UNSIGNED5_spec, 0), BAND_INIT(method_attr_bands, -1, -1), BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0), BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0), diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h index c555936d02e..c10b93d1888 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h @@ -99,8 +99,8 @@ struct band { int getByte() { assert(ix == null); return vs[0].getByte(); } int getInt() { assert(ix == null); return vs[0].getInt(); } - entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); } - entry* getRef() { assert(ix != null); return getRefCommon(ix, false); } + entry* getRefN() { return getRefCommon(ix, true); } + entry* getRef() { return getRefCommon(ix, false); } entry* getRefUsing(cpindex* ix2) { assert(ix == null); return getRefCommon(ix2, true); } entry* getRefCommon(cpindex* ix, bool nullOK); @@ -214,7 +214,7 @@ enum band_number { e_method_metadata_bands, e_method_MethodParameters_NB, e_method_MethodParameters_name_RUN, - e_method_MethodParameters_flag_I, + e_method_MethodParameters_flag_FH, e_method_attr_bands, e_class_flags_hi, @@ -393,7 +393,7 @@ enum band_number { #define method_Signature_RS all_bands[e_method_Signature_RS] #define method_MethodParameters_NB all_bands[e_method_MethodParameters_NB] #define method_MethodParameters_name_RUN all_bands[e_method_MethodParameters_name_RUN] -#define method_MethodParameters_flag_I all_bands[e_method_MethodParameters_flag_I] +#define method_MethodParameters_flag_FH all_bands[e_method_MethodParameters_flag_FH] #define method_attr_bands all_bands[e_method_attr_bands] #define class_flags_hi all_bands[e_class_flags_hi] #define class_flags_lo all_bands[e_class_flags_lo] diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h index 040d8edd55b..2f125e0d800 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h @@ -505,5 +505,9 @@ enum { bc_qldc = _xldc_op+7, bc_qldc_w = _xldc_op+8, _xldc_limit = _xldc_op+9, + _invoke_int_op = _xldc_limit, + _invokespecial_int = _invoke_int_op+0, + _invokestatic_int = _invoke_int_op+1, + _invoke_int_limit = _invoke_int_op+2, _xxx_3_end }; diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp index bedecda5391..26c683f0ae9 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp @@ -50,6 +50,7 @@ static jfieldID unpackerPtrFID; static jmethodID currentInstMID; static jmethodID readInputMID; static jclass NIclazz; +static jmethodID getUnpackerPtrMID; static char* dbg = null; @@ -60,8 +61,8 @@ static jlong read_input_via_jni(unpacker* self, static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) { unpacker* uPtr; - uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID)); - //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr); + jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID); + uPtr = (unpacker*)jlong2ptr(p); if (uPtr == null) { if (noCreate) return null; uPtr = new unpacker(); @@ -94,11 +95,15 @@ static unpacker* get_unpacker() { if (env == null) return null; jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID); - //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj); - if (pObj == null) - return null; - // Got pObj and env; now do it the easy way. - return get_unpacker(env, pObj); + //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj); + if (pObj != null) { + // Got pObj and env; now do it the easy way. + return get_unpacker(env, pObj); + } + // this should really not happen, if it does something is seriously + // wrong throw an exception + THROW_IOE(ERROR_INTERNAL); + return null; } static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) { @@ -127,18 +132,23 @@ static jlong read_input_via_jni(unpacker* self, JNIEXPORT void JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) { +#ifndef PRODUCT dbg = getenv("DEBUG_ATTACH"); while( dbg != null) { sleep(10); } +#endif NIclazz = (jclass) env->NewGlobalRef(clazz); unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J"); currentInstMID = env->GetStaticMethodID(clazz, "currentInstance", "()Ljava/lang/Object;"); readInputMID = env->GetMethodID(clazz, "readInputFn", "(Ljava/nio/ByteBuffer;J)J"); + getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J"); + if (unpackerPtrFID == null || currentInstMID == null || readInputMID == null || - NIclazz == null) { + NIclazz == null || + getUnpackerPtrMID == null) { THROW_IOE("cannot init class members"); } } @@ -146,8 +156,13 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, jobject pBuf, jlong offset) { - unpacker* uPtr = get_unpacker(env, pObj); - + // try to get the unpacker pointer the hard way first, we do this to ensure + // valid object pointers and env is intact, if not now is good time to bail. + unpacker* uPtr = get_unpacker(); + //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr); + if (uPtr == null) { + return -1; + } // redirect our io to the default log file or whatever. uPtr->redirect_stdio(); @@ -163,7 +178,12 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, else { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; } } - + // before we start off we make sure there is no other error by the time we + // get here + if (uPtr->aborting()) { + THROW_IOE(uPtr->get_abort_message()); + return 0; + } uPtr->start(buf, buflen); if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); @@ -230,11 +250,14 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject // We have fetched all the files. // Now swallow up any remaining input. - if (uPtr->input_remaining() == 0) + if (uPtr->input_remaining() == 0) { return null; - else - return env->NewDirectByteBuffer(uPtr->input_scan(), - uPtr->input_remaining()); + } else { + bytes remaining_bytes; + remaining_bytes.malloc(uPtr->input_remaining()); + remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining()); + return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len); + } } JNIEXPORT jlong JNICALL diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index 4b5e38a0de1..44ea89866f0 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -281,11 +281,13 @@ int entry::typeSize() { } inline cpindex* cpool::getFieldIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+0]; } inline cpindex* cpool::getMethodIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+1]; @@ -1291,6 +1293,7 @@ void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 2); e.refs[0] = cp_band1.getRef(); + CHECK; e.refs[1] = cp_band2.getRef(); CHECK; } @@ -1371,6 +1374,7 @@ void unpacker::read_method_type(entry* cpMap, int len) { entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 1); e.refs[0] = cp_MethodType.getRef(); + CHECK; } } @@ -2106,6 +2110,7 @@ void unpacker::read_attr_defs() { int attrc = ADH_BYTE_CONTEXT(header); int idx = ADH_BYTE_INDEX(header); entry* name = attr_definition_name.getRef(); + CHECK; entry* layout = attr_definition_layout.getRef(); CHECK; attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval()); @@ -2210,7 +2215,9 @@ void unpacker::read_ics() { if (ics[i].name == NO_ENTRY_YET) { // Long form. ics[i].outer = ic_outer_class.getRefN(); + CHECK; ics[i].name = ic_name.getRefN(); + CHECK; } else { // Fill in outer and name based on inner. bytes& n = ics[i].inner->value.b; @@ -2488,7 +2495,7 @@ void unpacker::read_attrs(int attrc, int obj_count) { method_MethodParameters_NB.readData(count); count = method_MethodParameters_NB.getIntTotal(); method_MethodParameters_name_RUN.readData(count); - method_MethodParameters_flag_I.readData(count); + method_MethodParameters_flag_FH.readData(count); CHECK; break; @@ -2733,6 +2740,7 @@ void unpacker::putlayout(band** body) { e = b.getRefUsing(cp.getKQIndex()); else e = b.getRefN(); + CHECK; switch (b.le_len) { case 0: break; case 1: putu1ref(e); break; @@ -2942,6 +2950,9 @@ band* unpacker::ref_band_for_op(int bc) { case bc_putfield: return &bc_fieldref; + case _invokespecial_int: + case _invokestatic_int: + return &bc_imethodref; case bc_invokevirtual: case bc_invokespecial: case bc_invokestatic: @@ -3118,7 +3129,7 @@ void unpacker::read_bcs() { void unpacker::read_bands() { byte* rp0 = rp; - + CHECK; read_file_header(); CHECK; @@ -3880,10 +3891,12 @@ void unpacker::dump_options() { // packed file and len is the length of the buffer. // If null, the callback is used to fill an internal buffer. void unpacker::start(void* packptr, size_t len) { + CHECK; NOT_PRODUCT(debug_u = this); if (packptr != null && len != 0) { inbytes.set((byte*) packptr, len); } + CHECK; read_bands(); } @@ -4015,6 +4028,7 @@ void unpacker::write_bc_ops() { NOT_PRODUCT(bc_superfield.setIndex(null)); NOT_PRODUCT(bc_supermethod.setIndex(null)); } + CHECK; for (int curIP = 0; ; curIP++) { int curPC = (int)(wpoffset() - codeBase); @@ -4128,7 +4142,8 @@ void unpacker::write_bc_ops() { int coding = bc_initref.getInt(); // Find the nth overloading of in classRef. entry* ref = null; - cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef); + cpindex* ix = cp.getMethodIndex(classRef); + CHECK; for (int j = 0, which_init = 0; ; j++) { ref = (ix == null)? null: ix->get(j); if (ref == null) break; // oops, bad input @@ -4177,6 +4192,12 @@ void unpacker::write_bc_ops() { } origBC = bc; switch (bc) { + case _invokestatic_int: + origBC = bc_invokestatic; + break; + case _invokespecial_int: + origBC = bc_invokespecial; + break; case bc_ildc: case bc_cldc: case bc_fldc: @@ -4405,6 +4426,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod): aname = cp.sym[cpool::s_EnclosingMethod]; putref(class_EnclosingMethod_RC.getRefN()); + CHECK_0; putref(class_EnclosingMethod_RDN.getRefN()); break; @@ -4423,6 +4445,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { putu2(count = method_Exceptions_N.getInt()); for (j = 0; j < count; j++) { putref(method_Exceptions_RC.getRefN()); + CHECK_0; } break; @@ -4431,7 +4454,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { putu1(count = method_MethodParameters_NB.getByte()); for (j = 0; j < count; j++) { putref(method_MethodParameters_name_RUN.getRefN()); - putu4(method_MethodParameters_flag_I.getInt()); + putu2(method_MethodParameters_flag_FH.getInt()); } break; @@ -4455,16 +4478,18 @@ int unpacker::write_attrs(int attrc, julong indexBits) { // (253) [(1)(2)(2)] // (254) [(1)(2)(2)(2)] putu2(code_StackMapTable_offset.getInt()); + CHECK_0; for (int k = (tag - 251); k > 0; k--) { put_stackmap_type(); + CHECK_0; } } else { // (255) [(1)NH[(2)]NH[(2)]] putu2(code_StackMapTable_offset.getInt()); putu2(j2 = code_StackMapTable_local_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} putu2(j2 = code_StackMapTable_stack_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} } } break; @@ -4488,7 +4513,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTable_slot.getInt()); } break; @@ -4503,7 +4530,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTypeTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTypeTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTypeTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTypeTable_slot.getInt()); } break; @@ -4531,7 +4560,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { break; } } - + CHECK_0; if (aname == null) { // Unparse a compressor-defined attribute. layout_definition* lo = ad.getLayout(idx); @@ -4687,7 +4716,9 @@ int unpacker::write_ics(int naOffset, int na) { flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero extra_ic.flags = flags; extra_ic.outer = class_InnerClasses_outer_RCN.getRefN(); + CHECK_0; extra_ic.name = class_InnerClasses_name_RUN.getRefN(); + CHECK_0; // Detect if this is an exact copy of the global tuple. if (global_ic != null) { if (global_ic->flags != extra_ic.flags || @@ -4797,6 +4828,7 @@ void unpacker::write_classfile_tail() { julong indexMask = ad.flagIndexMask(); cur_class = class_this.getRef(); + CHECK; cur_super = class_super.getRef(); CHECK; @@ -4810,6 +4842,7 @@ void unpacker::write_classfile_tail() { putu2(num = class_interface_count.getInt()); for (i = 0; i < num; i++) { putref(class_interface.getRef()); + CHECK; } write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); diff --git a/jdk/src/share/native/common/check_code.c b/jdk/src/share/native/common/check_code.c index c761a3d9158..e1170293f07 100644 --- a/jdk/src/share/native/common/check_code.c +++ b/jdk/src/share/native/common/check_code.c @@ -206,6 +206,10 @@ enum { #define LDC_METHOD_HANDLE_MAJOR_VERSION 51 +#define NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION 51 + +#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION 52 + #define ALLOC_STACK_SIZE 16 /* big enough */ typedef struct alloc_stack_type { @@ -1144,11 +1148,14 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) int *saved_operand; int keys; int k, delta; - /* 4639449, 4647081: Padding bytes must be zero. */ - unsigned char* bptr = (unsigned char*) (code + offset + 1); - for (; bptr < (unsigned char*)lpc; bptr++) { - if (*bptr != 0) { - CCerror(context, "Non zero padding bytes in switch"); + + if (context->major_version < NONZERO_PADDING_BYTES_IN_SWITCH_MAJOR_VERSION) { + /* 4639449, 4647081: Padding bytes must be zero. */ + unsigned char* bptr = (unsigned char*) (code + offset + 1); + for (; bptr < (unsigned char*)lpc; bptr++) { + if (*bptr != 0) { + CCerror(context, "Non zero padding bytes in switch"); + } } } if (opcode == JVM_OPC_tableswitch) { @@ -1246,11 +1253,24 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) jclass cb = context->class; fullinfo_type clazz_info; int is_constructor, is_internal, is_invokedynamic; - int kind = (opcode == JVM_OPC_invokeinterface - ? 1 << JVM_CONSTANT_InterfaceMethodref - : opcode == JVM_OPC_invokedynamic - ? 1 << JVM_CONSTANT_NameAndType - : 1 << JVM_CONSTANT_Methodref); + int kind; + + switch (opcode ) { + case JVM_OPC_invokestatic: + kind = ((context->major_version < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) + ? (1 << JVM_CONSTANT_Methodref) + : ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref))); + break; + case JVM_OPC_invokedynamic: + kind = 1 << JVM_CONSTANT_NameAndType; + break; + case JVM_OPC_invokeinterface: + kind = 1 << JVM_CONSTANT_InterfaceMethodref; + break; + default: + kind = 1 << JVM_CONSTANT_Methodref; + } + is_invokedynamic = opcode == JVM_OPC_invokedynamic; /* Make sure the constant pool item is the right type. */ verify_constant_pool_type(context, key, kind); diff --git a/jdk/src/share/native/java/lang/System.c b/jdk/src/share/native/java/lang/System.c index 8efd95e09b7..faef4b09314 100644 --- a/jdk/src/share/native/java/lang/System.c +++ b/jdk/src/share/native/java/lang/System.c @@ -212,6 +212,10 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) PUTPROP(props, "os.version", sprops->os_version); PUTPROP(props, "os.arch", sprops->os_arch); +#ifdef JDK_ARCH_ABI_PROP_NAME + PUTPROP(props, "sun.arch.abi", sprops->sun_arch_abi); +#endif + /* file system properties */ PUTPROP(props, "file.separator", sprops->file_separator); PUTPROP(props, "path.separator", sprops->path_separator); diff --git a/jdk/src/share/native/java/lang/java_props.h b/jdk/src/share/native/java/lang/java_props.h index e6c11c262c0..86a69d7a124 100644 --- a/jdk/src/share/native/java/lang/java_props.h +++ b/jdk/src/share/native/java/lang/java_props.h @@ -41,6 +41,10 @@ typedef struct { char *os_version; char *os_arch; +#ifdef JDK_ARCH_ABI_PROP_NAME + char *sun_arch_abi; +#endif + nchar *tmp_dir; nchar *font_dir; nchar *user_dir; diff --git a/jdk/src/share/native/java/util/zip/Inflater.c b/jdk/src/share/native/java/util/zip/Inflater.c index b67fff24f09..3778ff4e40c 100644 --- a/jdk/src/share/native/java/util/zip/Inflater.c +++ b/jdk/src/share/native/java/util/zip/Inflater.c @@ -27,6 +27,7 @@ * Native method support for java.util.zip.Inflater */ +#include #include #include #include @@ -60,12 +61,13 @@ Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) { z_stream *strm = calloc(1, sizeof(z_stream)); - if (strm == 0) { + if (strm == NULL) { JNU_ThrowOutOfMemoryError(env, 0); return jlong_zero; } else { - char *msg; - switch (inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS)) { + const char *msg; + int ret = inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS); + switch (ret) { case Z_OK: return ptr_to_jlong(strm); case Z_MEM_ERROR: @@ -73,7 +75,13 @@ Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) JNU_ThrowOutOfMemoryError(env, 0); return jlong_zero; default: - msg = strm->msg; + msg = ((strm->msg != NULL) ? strm->msg : + (ret == Z_VERSION_ERROR) ? + "zlib returned Z_VERSION_ERROR: " + "compile time and runtime zlib implementations differ" : + (ret == Z_STREAM_ERROR) ? + "inflateInit2 returned Z_STREAM_ERROR" : + "unknown error initializing zlib library"); free(strm); JNU_ThrowInternalError(env, msg); return jlong_zero; diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index d6f6d60d356..498ac717913 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -114,6 +114,62 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, return status; } +/* Verifies whether the channel offsets are sane and correspond to the type of + * the raster. + * + * Return value: + * 0: Failure: channel offsets are invalid + * 1: Success + */ +static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) { + int i, lastPixelOffset, lastScanOffset; + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) { + return 0; + } + if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) { + return 0; + } + + lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride; + lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride; + + + if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) { + return 0; + } + + lastPixelOffset += lastScanOffset; + + for (i = 0; i < rasterP->numDataElements; i++) { + int off = rasterP->chanOffsets[i]; + int size = lastPixelOffset + off; + + if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) { + return 0; + } + + if (size < lastPixelOffset || size >= dataArrayLength) { + // an overflow, or insufficient buffer capacity + return 0; + } + } + return 1; + case BANDED_RASTER_TYPE: + // NB:caller does not support the banded rasters yet, + // so this branch of the code must be re-defined in + // order to provide valid criteria for the data offsets + // verification, when/if banded rasters will be supported. + // At the moment, we prohibit banded rasters as well. + return 0; + default: + // PACKED_RASTER_TYPE: does not support channel offsets + // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error + return 0; + } +} + /* Parse the raster. All of the raster information is returned in the * rasterP structure. * @@ -125,7 +181,6 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { jobject joffs = NULL; /* int status;*/ - int isDiscrete = TRUE; if (JNU_IsNull(env, jraster)) { JNU_ThrowNullPointerException(env, "null Raster object"); @@ -155,6 +210,9 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return -1; } + // make sure that the raster type is initialized + rasterP->rasterType = UNKNOWN_RASTER_TYPE; + if (rasterP->numBands <= 0 || rasterP->numBands > MAX_NUMBANDS) { @@ -165,9 +223,14 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } + rasterP->sppsm.isUsed = 0; + if ((*env)->IsInstanceOf(env, rasterP->jsampleModel, (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) { jobject jmask, joffs, jnbits; + + rasterP->sppsm.isUsed = 1; + rasterP->sppsm.maxBitSize = (*env)->GetIntField(env, rasterP->jsampleModel, g_SPPSMmaxBitID); @@ -254,7 +317,6 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); rasterP->dataType = BYTE_DATA_TYPE; - isDiscrete = FALSE; } else { rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; @@ -265,7 +327,19 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } - if (isDiscrete) { + // do basic validation of the raster structure + if (rasterP->width <= 0 || rasterP->height <= 0 || + rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0) + { + // invalid raster + return -1; + } + + // channel (data) offsets + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment + // get channel (data) offsets rasterP->chanOffsets = NULL; if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { rasterP->chanOffsets = @@ -278,10 +352,21 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, rasterP->chanOffsets); + if (rasterP->jdata == NULL) { + // unable to verify the raster + return -1; + } + // verify whether channel offsets look sane + if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) { + return -1; + } + break; + default: + ; // PACKED_RASTER_TYPE does not use the channel offsets. } - /* additioanl check for sppsm fields validity: make sure that - * size of raster samples doesn't exceed the data type cpacity. + /* additional check for sppsm fields validity: make sure that + * size of raster samples doesn't exceed the data type capacity. */ if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */ rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */ @@ -696,6 +781,21 @@ setHints(JNIEnv *env, BufImageS_t *imageP) { } else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { int i; + + /* do some sanity check first: make sure that + * - sample model is SinglePixelPackedSampleModel + * - number of bands in the raster corresponds to the number + * of color components in the color model + */ + if (!rasterP->sppsm.isUsed || + rasterP->numBands != cmodelP->numComponents) + { + /* given raster is not compatible with the color model, + * so the operation has to be aborted. + */ + return -1; + } + if (cmodelP->maxNbits > 8) { hintP->needToExpand = TRUE; hintP->expandToNbits = cmodelP->maxNbits; diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.h b/jdk/src/share/native/sun/awt/image/awt_parseImage.h index f58adabb754..b92bb0c2833 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.h +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.h @@ -95,6 +95,7 @@ typedef struct { jint offsets[MAX_NUMBANDS]; jint nBits[MAX_NUMBANDS]; jint maxBitSize; + jint isUsed; // flag to indicate whether the raster sample model is SPPSM } SPPSampleModelS_t; /* Struct that holds information for the Raster object */ diff --git a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h index ce744af2c3b..579d98638dc 100644 --- a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h +++ b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h @@ -41,5 +41,10 @@ (((w) > 0) && ((h) > 0) && ((sz) > 0) && \ (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) +#define SAFE_TO_MULT(a, b) \ + (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b))) + +#define SAFE_TO_ADD(a, b) \ + (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b))) #endif // __SAFE_ALLOC_H__ diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c index fcd7de01639..b1a59098955 100644 --- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c @@ -133,6 +133,10 @@ SplashDecodeJpeg(Splash * splash, struct jpeg_decompress_struct *cinfo) ImageFormat srcFormat; jpeg_read_header(cinfo, TRUE); + + // SplashScreen jpeg converter expects data in RGB format only + cinfo->out_color_space = JCS_RGB; + jpeg_start_decompress(cinfo); SplashCleanup(splash); diff --git a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp index 60727aa3f3a..88e9f25ddeb 100644 --- a/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp +++ b/jdk/src/share/native/sun/font/layout/LookupProcessor.cpp @@ -125,6 +125,10 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt } const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); + if (lookupTable == NULL) { + success = LE_INTERNAL_ERROR; + return 0; + } le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); GlyphIterator tempIterator(*glyphIterator, lookupFlags); le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c index 7da0370baad..1340c82a822 100644 --- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c @@ -117,6 +117,7 @@ static jfieldID IL_offset_fID; static jfieldID IL_nextRowOffset_fID; static jfieldID IL_width_fID; static jfieldID IL_height_fID; +static jfieldID IL_imageAtOnce_fID; static jfieldID PF_ID_fID; JavaVM *javaVM; @@ -237,7 +238,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform * Method: loadProfile * Signature: ([B)J */ -JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile +JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative (JNIEnv *env, jobject obj, jbyteArray data) { jbyte* dataArray; @@ -284,7 +285,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile * Method: freeProfile * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfile +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative (JNIEnv *env, jobject obj, jlong id) { storeID_t sProf; @@ -369,48 +370,22 @@ static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); -/* - * Class: sun_java2d_cmm_lcms_LCMS - * Method: getTagSize - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize - (JNIEnv *env, jobject obj, jlong id, jint tagSig) -{ - storeID_t sProf; - TagSignature_t sig; - jint result = -1; - - sProf.j = id; - sig.j = tagSig; - - if (tagSig == SigHead) { - result = sizeof(cmsICCHeader); - } else { - if (cmsIsTag(sProf.pf, sig.cms)) { - result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); - } else { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "ICC profile tag not found"); - } - } - - return result; -} /* * Class: sun_java2d_cmm_lcms_LCMS * Method: getTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData - (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) +JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative + (JNIEnv *env, jobject obj, jlong id, jint tagSig) { storeID_t sProf; TagSignature_t sig; cmsInt32Number tagSize; - jbyte* dataArray; + jbyte* dataArray = NULL; + jbyteArray data = NULL; + jint bufSize; sProf.j = id; @@ -419,12 +394,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (tagSig == SigHead) { cmsBool status; - bufSize =(*env)->GetArrayLength(env, data); + // allocate java array + bufSize = sizeof(cmsICCHeader); + data = (*env)->NewByteArray(env, bufSize); - if (bufSize < sizeof(cmsICCHeader)) { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity"); - return; + if (data == NULL) { + JNU_ThrowByName(env, "java/awt/color/CMMException", + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -432,7 +409,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } status = _getHeaderInfo(sProf.pf, dataArray, bufSize); @@ -442,9 +419,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (!status) { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC Profile header not found"); + return NULL; } - return; + return data; } if (cmsIsTag(sProf.pf, sig.cms)) { @@ -452,16 +430,15 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData } else { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); - return; + return NULL; } - // verify data buffer capacity - bufSize = (*env)->GetArrayLength(env, data); - - if (tagSize < 0 || 0 > bufSize || tagSize > bufSize) { + // allocate java array + data = (*env)->NewByteArray(env, tagSize); + if (data == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity."); - return; + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -469,7 +446,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize); @@ -479,8 +456,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (bufSize != tagSize) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Can not get tag data."); + return NULL; } - return; + return data; } /* @@ -488,7 +466,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData * Method: setTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) { storeID_t sProf; @@ -586,6 +564,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert char* inputRow; char* outputRow; jobject srcData, dstData; + jboolean srcAtOnce = JNI_FALSE, dstAtOnce = JNI_FALSE; srcOffset = (*env)->GetIntField (env, src, IL_offset_fID); srcNextRowOffset = (*env)->GetIntField (env, src, IL_nextRowOffset_fID); @@ -594,6 +573,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert width = (*env)->GetIntField (env, src, IL_width_fID); height = (*env)->GetIntField (env, src, IL_height_fID); + srcAtOnce = (*env)->GetBooleanField(env, src, IL_imageAtOnce_fID); + dstAtOnce = (*env)->GetBooleanField(env, dst, IL_imageAtOnce_fID); + sTrans.j = (*env)->GetLongField (env, trans, Trans_ID_fID); if (sTrans.xf == NULL) { @@ -625,10 +607,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert inputRow = (char*)inputBuffer + srcOffset; outputRow = (char*)outputBuffer + dstOffset; - for (i = 0; i < height; i++) { - cmsDoTransform(sTrans.xf, inputRow, outputRow, width); - inputRow += srcNextRowOffset; - outputRow += dstNextRowOffset; + if (srcAtOnce && dstAtOnce) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width * height); + } else { + for (i = 0; i < height; i++) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width); + inputRow += srcNextRowOffset; + outputRow += dstNextRowOffset; + } } releaseILData(env, inputBuffer, srcDType, srcData); @@ -670,6 +656,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS IL_width_fID = (*env)->GetFieldID (env, IL, "width", "I"); IL_height_fID = (*env)->GetFieldID (env, IL, "height", "I"); IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I"); + IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z"); IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I"); PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); diff --git a/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h b/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h index abe7f230bee..3b1fa03b06a 100644 --- a/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h +++ b/jdk/src/share/native/sun/java2d/loops/AnyByteBinary.h @@ -153,7 +153,10 @@ jint PREFIX ## rgb; #define InitByteBinaryAlphaLoadData(TYPE, PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteBinaryFor4ByteArgb(TYPE, pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h b/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h index 3917c238e48..215cfc0e111 100644 --- a/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h +++ b/jdk/src/share/native/sun/java2d/loops/ByteIndexed.h @@ -202,7 +202,10 @@ typedef jubyte ByteIndexedBmDataType; jint PREFIX ## rgb; #define InitByteIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgb.h b/jdk/src/share/native/sun/java2d/loops/IntArgb.h index aec63431cb1..f4ec00524cc 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgb.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgb.h @@ -122,7 +122,8 @@ typedef jint IntArgbDataType; #define DeclareIntArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h b/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h index 81d551820a8..675fba1d228 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h @@ -133,7 +133,8 @@ typedef jint IntArgbBmDataType; #define DeclareIntArgbBmAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbBmFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h b/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h index 5ffb9dacb0b..c45013d0e00 100644 --- a/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h @@ -153,7 +153,8 @@ typedef jint IntArgbPreDataType; #define DeclareIntArgbPreAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbPreFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/TransformHelper.c b/jdk/src/share/native/sun/java2d/loops/TransformHelper.c index 23bba354756..72334550250 100644 --- a/jdk/src/share/native/sun/java2d/loops/TransformHelper.c +++ b/jdk/src/share/native/sun/java2d/loops/TransformHelper.c @@ -353,6 +353,9 @@ Java_sun_java2d_loops_TransformHelper_Transform pInterpFunc = pBicubicFunc; maxlinepix = LINE_SIZE / 16; break; + default: + // Should not happen, but just in case. + return; } srcInfo.bounds.x1 = sx1; diff --git a/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h b/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h index 348e03b7df4..aa50d8b0ff3 100644 --- a/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h +++ b/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h @@ -120,7 +120,8 @@ typedef jushort Ushort4444ArgbDataType; #define DeclareUshort4444ArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromUshort4444ArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h b/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h index 7786bda3829..6a4b5b13e5d 100644 --- a/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h +++ b/jdk/src/share/native/sun/java2d/loops/UshortIndexed.h @@ -170,7 +170,10 @@ typedef jushort UshortIndexedBmDataType; jint PREFIX ## rgb; #define InitUshortIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromUshortIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c index bd0eab3c113..7ec69fda633 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c @@ -687,8 +687,8 @@ CK_SSL3_KEY_MAT_PARAMS jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject if ((*env)->ExceptionCheck(env)) { free(ckParam.RandomInfo.pClientRandom); free(ckParam.RandomInfo.pServerRandom); - free(ckParam.pReturnedKeyMaterial); free(ckParam.pReturnedKeyMaterial->pIVClient); + free(ckParam.pReturnedKeyMaterial); return ckParam; } diff --git a/jdk/src/solaris/back/linker_md.c b/jdk/src/solaris/back/linker_md.c index a1cbcce3fcf..dbcfc04a40a 100644 --- a/jdk/src/solaris/back/linker_md.c +++ b/jdk/src/solaris/back/linker_md.c @@ -60,6 +60,7 @@ static void dll_build_name(char* buffer, size_t buflen, char *path_sep = PATH_SEPARATOR; char *pathname = (char *)pname; + *buffer = '\0'; while (strlen(pathname) > 0) { char *p = strchr(pathname, *path_sep); if (p == NULL) { @@ -69,13 +70,17 @@ static void dll_build_name(char* buffer, size_t buflen, if (p == pathname) { continue; } - (void)snprintf(buffer, buflen, "%.*s/lib%s." LIB_SUFFIX, (p - pathname), + (void)snprintf(buffer, buflen, "%.*s/lib%s." LIB_SUFFIX, (int)(p - pathname), pathname, fname); if (access(buffer, F_OK) == 0) { break; } - pathname = p + 1; + if (*p == '\0') { + pathname = p; + } else { + pathname = p + 1; + } *buffer = '\0'; } } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java b/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java index fdefb1047ce..0c540b17855 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XFramePeer.java @@ -641,4 +641,6 @@ class XFramePeer extends XDecoratedPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + public void emulateActivation(boolean doActivate) {} } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 7c40e8260ef..b4fb9c76f17 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -419,6 +419,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + return null; + } + public FramePeer createFrame(Frame target) { FramePeer peer = new XFramePeer(target); targetCreatedPeer(target, peer); diff --git a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 9035d0a44f8..f71345c84c3 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1026,13 +1026,21 @@ public class SctpChannelImpl extends SctpChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } + int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, -1 /*121*/, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, -1 /*121*/, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -1091,7 +1099,7 @@ public class SctpChannelImpl extends SctpChannel long address, int length, boolean peek) throws IOException; static native int send0(int fd, long address, int length, - SocketAddress target, int assocId, int streamNumber, + InetAddress addr, int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException; private static native int checkConnect(FileDescriptor fd, boolean block, diff --git a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index 6b42fcc02e3..84552ba042d 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -889,13 +889,20 @@ public class SctpMultiChannelImpl extends SctpMultiChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, assocId, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, assocId, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -976,13 +983,14 @@ public class SctpMultiChannelImpl extends SctpMultiChannel private static int send0(int fd, long address, int length, - SocketAddress target, + InetAddress addr, + int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException { - return SctpChannelImpl.send0(fd, address, length, target, assocId, + return SctpChannelImpl.send0(fd, address, length, addr, port, assocId, streamNumber, unordered, ppid); } diff --git a/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c b/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c index 1df2271ce4e..204636328f9 100644 --- a/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c +++ b/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c @@ -385,6 +385,7 @@ static void dll_build_name(char* buffer, size_t buflen, // Loosely based on os_solaris.cpp char *pathname = (char *)pname; + *buffer = '\0'; while (strlen(pathname) > 0) { char *p = strchr(pathname, ':'); if (p == NULL) { @@ -395,12 +396,16 @@ static void dll_build_name(char* buffer, size_t buflen, continue; } (void)snprintf(buffer, buflen, "%.*s/lib%s" JNI_LIB_SUFFIX, - (p - pathname), pathname, fname); + (int)(p - pathname), pathname, fname); if (access(buffer, F_OK) == 0) { - break; + break; + } + if (*p == '\0') { + pathname = p; + } else { + pathname = p + 1; } - pathname = p + 1; *buffer = '\0'; } } diff --git a/jdk/src/solaris/native/java/lang/java_props_md.c b/jdk/src/solaris/native/java/lang/java_props_md.c index c7d3ba6eff5..c8c18982585 100644 --- a/jdk/src/solaris/native/java/lang/java_props_md.c +++ b/jdk/src/solaris/native/java/lang/java_props_md.c @@ -514,6 +514,11 @@ GetJavaProperties(JNIEnv *env) } } + /* ABI property (optional) */ +#ifdef JDK_ARCH_ABI_PROP_NAME + sprops.sun_arch_abi = JDK_ARCH_ABI_PROP_NAME; +#endif + /* Determine the language, country, variant, and encoding from the host, * and store these in the user.language, user.country, user.variant and * file.encoding system properties. */ diff --git a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c index d8514a84126..cd2f4927bdb 100644 --- a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c @@ -46,8 +46,6 @@ #include "sun_nio_ch_DatagramChannelImpl.h" -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -212,15 +207,13 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, jlong address, - jint len, jobject dest) + jint len, jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKADDR sa; int sa_len = SOCKADDR_LEN; jint n = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (len > MAX_PACKET_LEN) { len = MAX_PACKET_LEN; diff --git a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c index b432403e9db..225556b4d9f 100644 --- a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c @@ -67,8 +67,6 @@ static jclass spc_class; /* sun.nio.ch.sctp.PeerAddressChanged */ static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged. */ static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */ static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown. */ -static jfieldID isa_addrID; /* java.net.InetSocketAddress.addr */ -static jfieldID isa_portID; /* java.net.InetSocketAddress.port */ /* defined in SctpNet.c */ jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr); @@ -138,13 +136,6 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs CHECK_NULL(ss_class); ss_ctrID = (*env)->GetMethodID(env, cls, "", "(I)V"); CHECK_NULL(ss_ctrID); - - /* InetSocketAddress */ - cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); - CHECK_NULL(cls); - isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL(isa_addrID); - isa_portID = (*env)->GetFieldID(env, cls, "port", "I"); } void getControlData @@ -509,12 +500,12 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0 /* * Class: sun_nio_ch_sctp_SctpChannelImpl * Method: send0 - * Signature: (IJILjava/net/SocketAddress;IIZI)I + * Signature: (IJILjava/net/InetAddress;IIIZI)I */ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 (JNIEnv *env, jclass klass, jint fd, jlong address, jint length, - jobject saTarget, jint assocId, jint streamNumber, jboolean unordered, - jint ppid) { + jobject targetAddress, jint targetPort, jint assocId, jint streamNumber, + jboolean unordered, jint ppid) { SOCKADDR sa; int sa_len = sizeof(sa); ssize_t rv = 0; @@ -526,17 +517,13 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 struct controlData cdata[1]; /* SctpChannel: - * saTarget may contain the preferred address or NULL to use primary, + * targetAddress may contain the preferred address or NULL to use primary, * assocId will always be -1 * SctpMultiChannell: - * Setup new association, saTarget will contain address, assocId = -1 - * Association already existing, assocId != -1, saTarget = preferred addr + * Setup new association, targetAddress will contain address, assocId = -1 + * Association already existing, assocId != -1, targetAddress = preferred addr */ - if (saTarget != NULL /*&& assocId <= 0*/) { - - jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID); - jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID); - + if (targetAddress != NULL /*&& assocId <= 0*/) { if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) { diff --git a/jdk/src/windows/back/linker_md.c b/jdk/src/windows/back/linker_md.c index e3ca2584cef..ad48d3d57c2 100644 --- a/jdk/src/windows/back/linker_md.c +++ b/jdk/src/windows/back/linker_md.c @@ -44,6 +44,7 @@ static void dll_build_name(char* buffer, size_t buflen, char *path_sep = PATH_SEPARATOR; char *pathname = (char *)pname; + *buffer = '\0'; while (strlen(pathname) > 0) { char *p = strchr(pathname, *path_sep); if (p == NULL) { @@ -54,16 +55,20 @@ static void dll_build_name(char* buffer, size_t buflen, continue; } if (*(p-1) == ':' || *(p-1) == '\\') { - (void)_snprintf(buffer, buflen, "%.*s%s.dll", (p - pathname), + (void)_snprintf(buffer, buflen, "%.*s%s.dll", (int)(p - pathname), pathname, fname); } else { - (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (p - pathname), + (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (int)(p - pathname), pathname, fname); } if (_access(buffer, 0) == 0) { break; } - pathname = p + 1; + if (*p == '\0') { + pathname = p; + } else { + pathname = p + 1; + } *buffer = '\0'; } } diff --git a/jdk/src/windows/bin/java_md.c b/jdk/src/windows/bin/java_md.c index e236cab1f2e..4078ecc754b 100644 --- a/jdk/src/windows/bin/java_md.c +++ b/jdk/src/windows/bin/java_md.c @@ -101,7 +101,6 @@ int awtPreloadD3D = -1; /* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */ #define D3D_PRELOAD_FUNC "preloadD3D" - /* Extracts value of a parameter with the specified name * from command line argument (returns pointer in the argument). * Returns NULL if the argument does not contains the parameter. @@ -276,7 +275,8 @@ LoadMSVCRT() #endif #ifdef CRT_DLL if (GetJREPath(crtpath, MAXPATHLEN)) { - if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { + if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { JLI_ReportErrorMessage(JRE_ERROR11); return JNI_FALSE; } @@ -347,7 +347,8 @@ GetJVMPath(const char *jrepath, const char *jvmtype, if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) { JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype); } else { - JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, + jrepath, jvmtype); } if (stat(jvmpath, &s) == 0) { return JNI_TRUE; @@ -525,6 +526,37 @@ jlong Counter2Micros(jlong counts) } return (counts * 1000 * 1000)/counterFrequency.QuadPart; } +/* + * windows snprintf does not guarantee a null terminator in the buffer, + * if the computed size is equal to or greater than the buffer size, + * as well as error conditions. This function guarantees a null terminator + * under all these conditions. An unreasonable buffer or size will return + * an error value. Under all other conditions this function will return the + * size of the bytes actually written minus the null terminator, similar + * to ansi snprintf api. Thus when calling this function the caller must + * ensure storage for the null terminator. + */ +int +JLI_Snprintf(char* buffer, size_t size, const char* format, ...) { + int rc; + va_list vl; + if (size == 0 || buffer == NULL) + return -1; + buffer[0] = '\0'; + va_start(vl, format); + rc = vsnprintf(buffer, size, format, vl); + va_end(vl); + /* force a null terminator, if something is amiss */ + if (rc < 0) { + /* apply ansi semantics */ + buffer[size - 1] = '\0'; + return size; + } else if (rc == size) { + /* force a null terminator */ + buffer[size - 1] = '\0'; + } + return rc; +} void JLI_ReportErrorMessage(const char* fmt, ...) { @@ -880,7 +912,7 @@ unquote(const char *s) { */ void ExecJRE(char *jre, char **argv) { - int len; + jint len; char path[MAXPATHLEN + 1]; const char *progname = GetProgramName(); @@ -1417,7 +1449,10 @@ CreateApplicationArgs(JNIEnv *env, char **strv, int argc) // we add the indicator tlen = 1 + JLI_StrLen(strv[i]) + 1; nargv[i] = (char *) JLI_MemAlloc(tlen); - JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]); + if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', + strv[i]) < 0) { + return NULL; + } JLI_TraceLauncher("%s\n", nargv[i]); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java index 6f788c2ac5d..37a257f1130 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -488,14 +488,15 @@ public abstract class WComponentPeer extends WObjectPeer try { replaceSurfaceData(); } catch (InvalidPipeException e) { - // REMIND : what do we do if our surface creation failed? + // REMIND : what do we do if our surface creation failed? } } } }; + Component c = (Component)target; // Fix 6255371. - if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r)); + if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { + postEvent(new InvocationEvent(c, r)); } } @@ -618,7 +619,7 @@ public abstract class WComponentPeer extends WObjectPeer } public void disposeLater() { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() { + postEvent(new InvocationEvent(target, new Runnable() { public void run() { dispose(); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java index b0f9cd3279d..ce02e045e31 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -27,6 +27,7 @@ package sun.awt.windows; import sun.awt.*; import java.awt.*; +import java.awt.event.InvocationEvent; import java.awt.peer.ComponentPeer; import java.awt.image.*; import sun.awt.image.ByteInterleavedRaster; @@ -226,17 +227,19 @@ public class WEmbeddedFrame extends EmbeddedFrame { } @SuppressWarnings("deprecation") - public void synthesizeWindowActivation(final boolean doActivate) { - if (!doActivate || EventQueue.isDispatchThread()) { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); + public void synthesizeWindowActivation(final boolean activate) { + if (!activate || EventQueue.isDispatchThread()) { + ((WFramePeer)getPeer()).emulateActivation(activate); } else { // To avoid focus concurrence b/w IE and EmbeddedFrame // activation is postponed by means of posting it to EDT. - EventQueue.invokeLater(new Runnable() { - public void run() { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); - } - }); + Runnable r = new Runnable() { + public void run() { + ((WFramePeer)getPeer()).emulateActivation(true); + } + }; + WToolkit.postEvent(WToolkit.targetToAppContext(this), + new InvocationEvent(this, r)); } } diff --git a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java index 3b6d298bda8..ec551e30ced 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java @@ -65,8 +65,6 @@ public class WEmbeddedFramePeer extends WFramePeer { public native Rectangle getBoundsPrivate(); - public native void synthesizeWmActivate(boolean doActivate); - @Override public boolean isAccelCapable() { // REMIND: Temp workaround for issues with using HW acceleration diff --git a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java index 368b8f60696..588b3caebdd 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java @@ -200,4 +200,11 @@ class WFramePeer extends WWindowPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + // TODO: implement it in peers. WLightweightFramePeer may implement lw version. + public void emulateActivation(boolean activate) { + synthesizeWmActivate(activate); + } + + private native void synthesizeWmActivate(boolean activate); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java new file mode 100644 index 00000000000..c2c1604bef4 --- /dev/null +++ b/jdk/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt.windows; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseEvent; + +import sun.awt.LightweightFrame; + +public class WLightweightFramePeer extends WFramePeer { + + public WLightweightFramePeer(LightweightFrame target) { + super(target); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)target; + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + public void show() { + super.show(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_SHOWN)); + } + + @Override + public void hide() { + super.hide(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_HIDDEN)); + } + + @Override + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_MOVED)); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_RESIZED)); + } + + @Override + public void handleEvent(java.awt.AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_PRESSED) { + emulateActivation(true); + } + super.handleEvent(e); + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java index afbdfa6c1f9..e87b0ad8c08 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java @@ -37,6 +37,7 @@ import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.PrivilegedAction; import sun.awt.AWTAutoShutdown; +import sun.awt.LightweightFrame; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; import sun.awt.Win32GraphicsEnvironment; @@ -398,6 +399,12 @@ public class WToolkit extends SunToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + FramePeer peer = new WLightweightFramePeer(target); + targetCreatedPeer(target, peer); + return peer; + } + public CanvasPeer createCanvas(Canvas target) { CanvasPeer peer = new WCanvasPeer(target); targetCreatedPeer(target, peer); diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index beb3e861f83..1034bb7d82f 100644 --- a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -35,6 +35,7 @@ import java.nio.channels.ClosedSelectorException; import java.nio.channels.Pipe; import java.nio.channels.SelectableChannel; import java.io.IOException; +import java.nio.channels.CancelledKeyException; import java.util.List; import java.util.ArrayList; import java.util.HashMap; @@ -561,17 +562,19 @@ final class WindowsSelectorImpl extends SelectorImpl { protected void implDereg(SelectionKeyImpl ski) throws IOException{ int i = ski.getIndex(); assert (i >= 0); - if (i != totalChannels - 1) { - // Copy end one over it - SelectionKeyImpl endChannel = channelArray[totalChannels-1]; - channelArray[i] = endChannel; - endChannel.setIndex(i); - pollWrapper.replaceEntry(pollWrapper, totalChannels - 1, + synchronized (closeLock) { + if (i != totalChannels - 1) { + // Copy end one over it + SelectionKeyImpl endChannel = channelArray[totalChannels-1]; + channelArray[i] = endChannel; + endChannel.setIndex(i); + pollWrapper.replaceEntry(pollWrapper, totalChannels - 1, pollWrapper, i); + } + ski.setIndex(-1); } channelArray[totalChannels - 1] = null; totalChannels--; - ski.setIndex(-1); if ( totalChannels != 1 && totalChannels % MAX_SELECTABLE_FDS == 1) { totalChannels--; threadsCount--; // The last thread has become redundant. @@ -589,7 +592,11 @@ final class WindowsSelectorImpl extends SelectorImpl { synchronized (closeLock) { if (pollWrapper == null) throw new ClosedSelectorException(); - pollWrapper.putEventOps(sk.getIndex(), ops); + // make sure this sk has not been removed yet + int index = sk.getIndex(); + if (index == -1) + throw new CancelledKeyException(); + pollWrapper.putEventOps(index, ops); } } diff --git a/jdk/src/windows/demo/jvmti/hprof/hprof_md.c b/jdk/src/windows/demo/jvmti/hprof/hprof_md.c index e5cbeda0f69..4bd4a40f049 100644 --- a/jdk/src/windows/demo/jvmti/hprof/hprof_md.c +++ b/jdk/src/windows/demo/jvmti/hprof/hprof_md.c @@ -372,6 +372,7 @@ static void dll_build_name(char* buffer, size_t buflen, // Loosley based on os_windows.cpp char *pathname = (char *)pname; + *buffer = '\0'; while (strlen(pathname) > 0) { char *p = strchr(pathname, ';'); if (p == NULL) { @@ -382,16 +383,20 @@ static void dll_build_name(char* buffer, size_t buflen, continue; } if (*(p-1) == ':' || *(p-1) == '\\') { - (void)_snprintf(buffer, buflen, "%.*s%s.dll", (p - pathname), + (void)_snprintf(buffer, buflen, "%.*s%s.dll", (int)(p - pathname), pathname, fname); } else { - (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (p - pathname), + (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (int)(p - pathname), pathname, fname); } if (_access(buffer, 0) == 0) { break; } - pathname = p + 1; + if (*p == '\0') { + pathname = p; + } else { + pathname = p + 1; + } *buffer = '\0'; } } diff --git a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c index f1eb449275e..60cc71e0aeb 100644 --- a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c +++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c @@ -36,9 +36,7 @@ #include #include -#include "jvm.h" #include "jni.h" -#include "jni_util.h" #include "io_util.h" #include "jlong.h" #include "io_util_md.h" @@ -115,13 +113,15 @@ static WCHAR* getFinalPath(const WCHAR *path) DWORD len = (*GetFinalPathNameByHandle_func)(h, result, MAX_PATH, 0); if (len >= MAX_PATH) { /* retry with a buffer of the right size */ - result = (WCHAR*)realloc(result, (len+1) * sizeof(WCHAR)); - if (result != NULL) { + WCHAR* newResult = (WCHAR*)realloc(result, (len+1) * sizeof(WCHAR)); + if (newResult != NULL) { + result = newResult; len = (*GetFinalPathNameByHandle_func)(h, result, len, 0); } else { len = 0; } } + if (len > 0) { /** * Strip prefix (should be \\?\ or \\?\UNC) diff --git a/jdk/src/windows/native/java/lang/ProcessImpl_md.c b/jdk/src/windows/native/java/lang/ProcessImpl_md.c index dfa59f99efd..5b45f8f24f2 100644 --- a/jdk/src/windows/native/java/lang/ProcessImpl_md.c +++ b/jdk/src/windows/native/java/lang/ProcessImpl_md.c @@ -120,10 +120,12 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, goto Catch; } si.hStdInput = inRead; - SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, FALSE); + SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, 0); handles[0] = (jlong) inWrite; } - SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, TRUE); + SetHandleInformation(si.hStdInput, + HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT); if (handles[1] != (jlong) -1) { si.hStdOutput = (HANDLE) handles[1]; @@ -134,10 +136,12 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, goto Catch; } si.hStdOutput = outWrite; - SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, FALSE); + SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, 0); handles[1] = (jlong) outRead; } - SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, TRUE); + SetHandleInformation(si.hStdOutput, + HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT); if (redirectErrorStream) { si.hStdError = si.hStdOutput; @@ -151,10 +155,12 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, goto Catch; } si.hStdError = errWrite; - SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE); + SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, 0); handles[2] = (jlong) errRead; } - SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE); + SetHandleInformation(si.hStdError, + HANDLE_FLAG_INHERIT, + HANDLE_FLAG_INHERIT); processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; ret = CreateProcessW(0, /* executable name */ diff --git a/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c b/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c index d3de6e7f024..cdd969cef79 100644 --- a/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c +++ b/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c @@ -89,6 +89,7 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCrea rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); if (rv == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); + closesocket(fd); return -1; } diff --git a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c index 9396cf82ea6..ab46f8d7faa 100644 --- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c +++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c @@ -34,8 +34,6 @@ #include "net_util.h" #include -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -50,9 +48,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -214,15 +209,14 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, - jlong address, jint len, jobject dest) + jlong address, jint len, + jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKETADDRESS sa; int sa_len; jint rv = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (NET_InetAddressToSockaddr(env, destAddress, destPort, (struct sockaddr *)&sa, diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.cpp b/jdk/src/windows/native/sun/windows/awt_Frame.cpp index da1df839535..41c5624f001 100644 --- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp @@ -105,6 +105,7 @@ AwtFrame::AwtFrame() { m_parentWnd = NULL; menuBar = NULL; m_isEmbedded = FALSE; + m_isLightweight = FALSE; m_ignoreWmSize = FALSE; m_isMenuDropped = FALSE; m_isInputMethodWindow = FALSE; @@ -170,14 +171,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) * area of the browser is a Java Frame for parenting purposes, but * really a Windows child window */ + BOOL isEmbeddedInstance = FALSE; + BOOL isEmbedded = FALSE; cls = env->FindClass("sun/awt/EmbeddedFrame"); - if (cls == NULL) { - return NULL; + if (cls) { + isEmbeddedInstance = env->IsInstanceOf(target, cls); } INT_PTR handle; - jboolean isEmbeddedInstance = env->IsInstanceOf(target, cls); - jboolean isEmbedded = FALSE; - if (isEmbeddedInstance) { handle = static_cast(env->GetLongField(target, AwtFrame::handleID)); if (handle != 0) { @@ -186,6 +186,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) } frame->m_isEmbedded = isEmbedded; + BOOL isLightweight = FALSE; + cls = env->FindClass("sun/awt/LightweightFrame"); + if (cls) { + isLightweight = env->IsInstanceOf(target, cls); + } + frame->m_isLightweight = isLightweight; + if (isEmbedded) { hwndParent = (HWND)handle; RECT rect; @@ -230,6 +237,23 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) rect.bottom-rect.top); frame->InitPeerGraphicsConfig(env, self); AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); + } else if (isLightweight) { + frame->m_isUndecorated = true; + frame->m_peerObject = env->NewGlobalRef(self); + frame->RegisterClass(); + + DWORD exStyle = 0; + DWORD style = WS_POPUP; + + frame->CreateHWnd(env, L"", + style, + exStyle, + 0, 0, 0, 0, + 0, + NULL, + ::GetSysColor(COLOR_WINDOWTEXT), + ::GetSysColor(COLOR_WINDOWFRAME), + self); } else { jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID); DWORD exStyle; @@ -345,16 +369,20 @@ LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, Ms case WM_SETFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtSetActiveWindow(); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtSetActiveWindow(); + } } mr = mrConsume; break; case WM_KILLFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + } } else if (sm_restoreFocusAndActivation) { if (AwtComponent::GetFocusedWindow() != NULL) { @@ -640,6 +668,10 @@ AwtFrame::Show() HWND hwnd = GetHWnd(); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + if (IsLightweightFrame()) { + return; + } + DTRACE_PRINTLN3("AwtFrame::Show:%s%s%s", m_iconic ? " iconic" : "", m_zoomed ? " zoomed" : "", @@ -992,6 +1024,9 @@ BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) // b) focus is requested to some of the frame's child. m_actualFocusedWindow = NULL; } + if (IsLightweightFrame()) { + return TRUE; + } return AwtWindow::AwtSetActiveWindow(isMouseEventCause); } @@ -1873,7 +1908,7 @@ Java_sun_awt_windows_WEmbeddedFramePeer_getBoundsPrivate(JNIEnv *env, jobject se } JNIEXPORT void JNICALL -Java_sun_awt_windows_WEmbeddedFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) +Java_sun_awt_windows_WFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) { TRY; diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.h b/jdk/src/windows/native/sun/windows/awt_Frame.h index f6d692b87eb..e151c17c2a5 100644 --- a/jdk/src/windows/native/sun/windows/awt_Frame.h +++ b/jdk/src/windows/native/sun/windows/awt_Frame.h @@ -72,6 +72,8 @@ public: /* Returns whether this frame is embedded in an external native frame. */ INLINE BOOL IsEmbeddedFrame() { return m_isEmbedded; } + /* Returns whether this frame is lightweight. */ + INLINE virtual BOOL IsLightweightFrame() { return m_isLightweight; } INLINE BOOL IsSimpleWindow() { return FALSE; } @@ -169,6 +171,9 @@ private: /* The frame is an EmbeddedFrame. */ BOOL m_isEmbedded; + /* The frame is a LightweightFrame */ + BOOL m_isLightweight; + /* used so that calls to ::MoveWindow in SetMenuBar don't propogate because they are immediately followed by calls to Component.resize */ BOOL m_ignoreWmSize; diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp index f16ba6c345c..eddcbca4088 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp @@ -53,14 +53,12 @@ struct EnableEditingStruct { * AwtTextComponent fields */ -/* java.awt.TextComponent fields */ -jfieldID AwtTextComponent::canAccessClipboardID; - - /************************************************************************ * AwtTextComponent methods */ +jmethodID AwtTextComponent::canAccessClipboardMID; + AwtTextComponent::AwtTextComponent() { m_synthetic = FALSE; m_lStartPos = -1; @@ -367,8 +365,7 @@ AwtTextComponent::WmPaste() } jobject target = GetTarget(env); jboolean canAccessClipboard = - env->GetBooleanField(target, - AwtTextComponent::canAccessClipboardID); + env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID); env->DeleteLocalRef(target); return (canAccessClipboard) ? mrDoDefault : mrConsume; } @@ -854,12 +851,13 @@ Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls) { TRY; - cls = env->FindClass("java/awt/TextComponent"); - if (cls != NULL) { - AwtTextComponent::canAccessClipboardID = - env->GetFieldID(cls, "canAccessClipboard", "Z"); - DASSERT(AwtTextComponent::canAccessClipboardID != NULL); - } + jclass textComponentClassID = env->FindClass("java/awt/TextComponent"); + AwtTextComponent::canAccessClipboardMID = + env->GetMethodID(textComponentClassID, + "canAccessClipboard", "()Z"); + env->DeleteLocalRef(textComponentClassID); + + DASSERT(AwtTextComponent::canAccessClipboardMID != NULL); CATCH_BAD_ALLOC; } diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.h b/jdk/src/windows/native/sun/windows/awt_TextComponent.h index e50219cd271..cc0fc97f780 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.h +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.h @@ -42,8 +42,7 @@ class AwtTextComponent : public AwtComponent { public: - /* java.awt.TextComponent canAccessClipboard field ID */ - static jfieldID canAccessClipboardID; + static jmethodID canAccessClipboardMID; AwtTextComponent(); diff --git a/jdk/src/windows/native/sun/windows/awt_Window.h b/jdk/src/windows/native/sun/windows/awt_Window.h index 8ad2b0902b2..0ee23322d4b 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.h +++ b/jdk/src/windows/native/sun/windows/awt_Window.h @@ -143,6 +143,7 @@ public: INLINE HICON GetHIcon() {return m_hIcon;}; INLINE HICON GetHIconSm() {return m_hIconSm;}; INLINE BOOL IsIconInherited() {return m_iconInherited;}; + INLINE virtual BOOL IsLightweightFrame() {return FALSE;} /* Post events to the EventQueue */ void SendComponentEvent(jint eventId); @@ -193,8 +194,10 @@ public: // Execute on Toolkit only. INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) { + AwtWindow *win = static_cast(AwtComponent::GetComponent(targetHWnd)); if (doActivate && - (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT)))) + (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT))) && + (win == NULL || !win->IsLightweightFrame())) { // The activation is rejected if either: // - The toplevel is not visible diff --git a/jdk/test/Makefile b/jdk/test/Makefile index 093d4649b21..69d5dac3d57 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -513,6 +513,7 @@ jdk_other: $(call TestDirs, \ javax/script \ java/sql javax/sql \ javax/smartcardio \ + javax/xml/soap \ javax/xml/ws com/sun/internal/ws \ jdk/asm \ com/sun/org/apache/xerces \ diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 3c4dc859980..842ffbe2532 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -134,6 +134,9 @@ java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java generic-all # 7196801 java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all +# 8008200 +java/lang/Class/asSubclass/BasicUnit.java generic-all + ############################################################################ # jdk_management @@ -324,9 +327,6 @@ tools/pack200/Pack200Test.java solaris-all, mac # 7150569 tools/launcher/UnicodeTest.java macosx-all -# 8006039 -tools/launcher/I18NJarTest.java macosx-all - # 8007410 tools/launcher/FXLauncherTest.java linux-all diff --git a/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html new file mode 100644 index 00000000000..7049e827033 --- /dev/null +++ b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html @@ -0,0 +1,43 @@ + + + + + + ManualYesNoTest + + + +

    ManualYesNoTest
    Bug ID:

    + +

    See the dialog box (usually in upper left corner) for instructions

    + + + + diff --git a/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java new file mode 100644 index 00000000000..8b509a12311 --- /dev/null +++ b/jdk/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 6243382 8006070 + @summary Dragging of mouse outside of a List and Choice area don't work properly on XAWT + @author Dmitry.Cherepanov@SUN.COM area=awt.list + @run applet/manual=yesno MouseDraggedOutCauseScrollingTest.html +*/ + +import java.applet.Applet; +import java.awt.*; + +public class MouseDraggedOutCauseScrollingTest extends Applet +{ + Choice choice; + List singleList; + List multipleList; + + public void init() + { + this.setLayout (new GridLayout (1, 3)); + + choice = new Choice(); + singleList = new List(3, false); + multipleList = new List(3, true); + + choice.add("Choice"); + for (int i = 1; i < 100; i++){ + choice.add(""+i); + } + + singleList.add("Single list"); + for (int i = 1; i < 100; i++) + singleList.add(""+i); + + multipleList.add("Multiple list"); + for (int i = 1; i < 100; i++) + multipleList.add(""+i); + + this.add(choice); + this.add(singleList); + this.add(multipleList); + + String toolkitName = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkitName.equals("sun.awt.X11.XToolkit")) { + String[] instructions = + { + "This test is not applicable to the current platform. Press PASS" + }; + Sysout.createDialogWithInstructions( instructions ); + } else { + String[] instructions = + { + "0) Please note, that this is only Motif/XAWT test. At first, make the applet active", + "1.1) Click on the choice", + "1.2) Press the left button of the mouse and keep on any item of the choice, for example 5", + "1.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "1.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "1.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "2.1) Click on the single list", + "2.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "2.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "2.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "2.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "3.1) Click on the multiple list", + "3.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "3.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "3.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the upper. If not, the test failed", + "3.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the lower. If not, the test failed", + "4) Test passed." + }; + Sysout.createDialogWithInstructions( instructions ); + } + + }//End init() + + public void start () + { + setSize (400,100); + setVisible(true); + validate(); + + }// start() + +}// class ManualYesNoTest + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class diff --git a/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java b/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java new file mode 100644 index 00000000000..156bfe5df0e --- /dev/null +++ b/jdk/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6430802 8008379 + @summary WM should not hang after show()/close() + @author anthony.petrov@sun.com: area=awt.modal + @run main/manual ModalDialogMultiscreenTest +*/ + + +/** + * ModalDialogMultiscreenTest.java + * + * summary: Tests whether a WM will hang on show()/close() a modal dialog in multiscreen mode + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + + +public class ModalDialogMultiscreenTest +{ + + private static class ButtonActionListener implements ActionListener { + JFrame frame; + JDialog dialog; + public ButtonActionListener(JFrame frame, JDialog dialog) { + this.frame = frame; + this.dialog = dialog; + } + public void actionPerformed(ActionEvent e) { + dialog.setLocationRelativeTo(frame); + dialog.setVisible(true); + } + } + public static class TestDialog extends JDialog { + public TestDialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) { + super(owner, title, modal, gc); + setSize(200, 100); + JButton button = new JButton("Close"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + getContentPane().add(button); + } + } + + private static void init() + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + + Sysout.createDialog( ); + + if (gs.length < 2) { + System.out.println("Not multi-head environment, test not valid!"); + ModalDialogMultiscreenTest.pass( ); + } + + String[] instructions = + { + "The test should be run on a multi-head X (non-xinerama) systems.", + "Otherwise click the Pass button right now.", + "You will see an open Frame on each screen your system has.", + "The frame has an 'Open dialog' button.", + "Clicking the button opens a modal dialog with a Close button.", + "The test procedure:", + "1. Open a dialog and close it with appropriate buttons.", + "2. Switch to another screen ($ DISPLAY=X.Y xprop)", + "3. Repeat steps 1-2 several times (about 3*)", + "If the test doesn't cause the window manager to hang, it's passed." + }; + Sysout.printInstructions( instructions ); + + + for (int i = 0; i < gs.length; i++) { + JFrame frame = new JFrame("Frame "+i,gs[i].getDefaultConfiguration()); + JButton button = new JButton("Open Dialog"); + button.setMinimumSize(new Dimension(200, 100)); + button.setPreferredSize(new Dimension(200, 100)); + button.setSize(new Dimension(200, 100)); + button.addActionListener(new ButtonActionListener(frame, new TestDialog(frame, "Dialog #"+i, true, gs[i].getDefaultConfiguration()))); + frame.getContentPane().add(button); + frame.pack(); + frame.setVisible(true); + } + + }//End init() + + + //ap203012: NO MORE CHANGES BELOW THIS LINE + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test-defined + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test passed nor test failed has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class ModalDialogMultiscreenTest + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// make listeners in a class defined here, and instantiate them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + ModalDialogMultiscreenTest.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + ModalDialogMultiscreenTest.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //ModalDialogMultiscreenTest + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + ModalDialogMultiscreenTest.pass(); + } + else + { + ModalDialogMultiscreenTest.fail(); + } + } + +}// TestDialog class diff --git a/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java b/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java index 9136e79f40e..5b927f8d520 100644 --- a/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java +++ b/jdk/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, 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 @@ -22,8 +22,8 @@ */ /* - @test %I% %E% - @bug 6572263 6571808 + @test + @bug 6572263 6571808 8005920 @summary PIT:FileDialog minimized to taskbar(through 'Show Desktop')selecting the fileDialog using windowList @author dmitry.cherepanov: area=awt.modal @run main/manual Winkey @@ -48,12 +48,14 @@ public class Winkey String[] instructions = { + " 0. This test is for MS Windows only, if you use other OS, press \"pass\" button.", " 1. there is a frame with a 'show modal' button, ", " 2. press the button to show a modal dialog, ", " 3. the modal dialog will be shown over the frame, ", " 4. please verify that all (5.1, 5.2.1, 5.2.2) the following tests pass: ", " ", " 5.1. press combination Windows Key and M key to minimize all windows, ", + " note that the modal dialog and modal blocked windows are NOT minimized", " 5.2. press combination Windows Key and D key to show desktop, ", " 5.2.1. restore the dialog by choosing this one in the ALT-TAB list, ", " 5.2.2. restore the dialog by mouse click on taskbar (on java or any other item)", diff --git a/jdk/test/java/beans/Introspector/Test7192955.java b/jdk/test/java/beans/Introspector/Test7192955.java index 13e874ba719..afce427bf30 100644 --- a/jdk/test/java/beans/Introspector/Test7192955.java +++ b/jdk/test/java/beans/Introspector/Test7192955.java @@ -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 @@ -23,17 +23,20 @@ /* * @test - * @bug 7192955 + * @bug 7192955 8000183 * @summary Tests that all properties are bound * @author Sergey Malenkov */ +import java.beans.IntrospectionException; +import java.beans.Introspector; import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; import java.util.List; public class Test7192955 { - public static void main(String[] args) { + public static void main(String[] args) throws IntrospectionException { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) { throw new Error("a simple property is not bound"); } @@ -43,6 +46,12 @@ public class Test7192955 { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) { throw new Error("a read-only property is not bound"); } + PropertyDescriptor[] pds = Introspector.getBeanInfo(MyBean.class, BaseBean.class).getPropertyDescriptors(); + for (PropertyDescriptor pd : pds) { + if (pd.getName().equals("test") && pd.isBound()) { + throw new Error("a simple property is bound without superclass"); + } + } } public static class BaseBean { diff --git a/jdk/test/java/lang/PrimitiveSumMinMaxTest.java b/jdk/test/java/lang/PrimitiveSumMinMaxTest.java index 1c44109c83f..56ab6740a83 100644 --- a/jdk/test/java/lang/PrimitiveSumMinMaxTest.java +++ b/jdk/test/java/lang/PrimitiveSumMinMaxTest.java @@ -50,20 +50,20 @@ public class PrimitiveSumMinMaxTest { BinaryOperator xor = Boolean::logicalXor; Comparator cmp = Boolean::compare; - assertTrue(and.operate(true, true)); - assertFalse(and.operate(true, false)); - assertFalse(and.operate(false, true)); - assertFalse(and.operate(false, false)); + assertTrue(and.apply(true, true)); + assertFalse(and.apply(true, false)); + assertFalse(and.apply(false, true)); + assertFalse(and.apply(false, false)); - assertTrue(or.operate(true, true)); - assertTrue(or.operate(true, false)); - assertTrue(or.operate(false, true)); - assertFalse(or.operate(false, false)); + assertTrue(or.apply(true, true)); + assertTrue(or.apply(true, false)); + assertTrue(or.apply(false, true)); + assertFalse(or.apply(false, false)); - assertFalse(xor.operate(true, true)); - assertTrue(xor.operate(true, false)); - assertTrue(xor.operate(false, true)); - assertFalse(xor.operate(false, false)); + assertFalse(xor.apply(true, true)); + assertTrue(xor.apply(true, false)); + assertTrue(xor.apply(false, true)); + assertFalse(xor.apply(false, false)); assertEquals(Boolean.TRUE.compareTo(Boolean.TRUE), cmp.compare(true, true)); assertEquals(Boolean.TRUE.compareTo(Boolean.FALSE), cmp.compare(true, false)); @@ -83,12 +83,12 @@ public class PrimitiveSumMinMaxTest { int[] numbers = { -1, 0, 1, 100, Integer.MAX_VALUE, Integer.MIN_VALUE }; for (int i : numbers) { for (int j : numbers) { - assertEquals(i+j, (int) sum1.operate(i, j)); - assertEquals(i+j, sum2.operateAsInt(i, j)); - assertEquals(Math.max(i,j), (int) max1.operate(i, j)); - assertEquals(Math.max(i,j), max2.operateAsInt(i, j)); - assertEquals(Math.min(i,j), (int) min1.operate(i, j)); - assertEquals(Math.min(i,j), min2.operateAsInt(i, j)); + assertEquals(i+j, (int) sum1.apply(i, j)); + assertEquals(i+j, sum2.applyAsInt(i, j)); + assertEquals(Math.max(i,j), (int) max1.apply(i, j)); + assertEquals(Math.max(i,j), max2.applyAsInt(i, j)); + assertEquals(Math.min(i,j), (int) min1.apply(i, j)); + assertEquals(Math.min(i,j), min2.applyAsInt(i, j)); assertEquals(((Integer) i).compareTo(j), cmp.compare(i, j)); } } @@ -106,12 +106,12 @@ public class PrimitiveSumMinMaxTest { long[] numbers = { -1, 0, 1, 100, Long.MAX_VALUE, Long.MIN_VALUE }; for (long i : numbers) { for (long j : numbers) { - assertEquals(i+j, (long) sum1.operate(i, j)); - assertEquals(i+j, sum2.operateAsLong(i, j)); - assertEquals(Math.max(i,j), (long) max1.operate(i, j)); - assertEquals(Math.max(i,j), max2.operateAsLong(i, j)); - assertEquals(Math.min(i,j), (long) min1.operate(i, j)); - assertEquals(Math.min(i,j), min2.operateAsLong(i, j)); + assertEquals(i+j, (long) sum1.apply(i, j)); + assertEquals(i+j, sum2.applyAsLong(i, j)); + assertEquals(Math.max(i,j), (long) max1.apply(i, j)); + assertEquals(Math.max(i,j), max2.applyAsLong(i, j)); + assertEquals(Math.min(i,j), (long) min1.apply(i, j)); + assertEquals(Math.min(i,j), min2.applyAsLong(i, j)); assertEquals(((Long) i).compareTo(j), cmp.compare(i, j)); } } @@ -126,9 +126,9 @@ public class PrimitiveSumMinMaxTest { float[] numbers = { -1, 0, 1, 100, Float.MAX_VALUE, Float.MIN_VALUE }; for (float i : numbers) { for (float j : numbers) { - assertEquals(i+j, (float) sum1.operate(i, j)); - assertEquals(Math.max(i,j), (float) max1.operate(i, j)); - assertEquals(Math.min(i,j), (float) min1.operate(i, j)); + assertEquals(i+j, (float) sum1.apply(i, j)); + assertEquals(Math.max(i,j), (float) max1.apply(i, j)); + assertEquals(Math.min(i,j), (float) min1.apply(i, j)); assertEquals(((Float) i).compareTo(j), cmp.compare(i, j)); } } @@ -146,12 +146,12 @@ public class PrimitiveSumMinMaxTest { double[] numbers = { -1, 0, 1, 100, Double.MAX_VALUE, Double.MIN_VALUE }; for (double i : numbers) { for (double j : numbers) { - assertEquals(i+j, (double) sum1.operate(i, j)); - assertEquals(i+j, sum2.operateAsDouble(i, j)); - assertEquals(Math.max(i,j), (double) max1.operate(i, j)); - assertEquals(Math.max(i,j), max2.operateAsDouble(i, j)); - assertEquals(Math.min(i,j), (double) min1.operate(i, j)); - assertEquals(Math.min(i,j), min2.operateAsDouble(i, j)); + assertEquals(i+j, (double) sum1.apply(i, j)); + assertEquals(i+j, sum2.applyAsDouble(i, j)); + assertEquals(Math.max(i,j), (double) max1.apply(i, j)); + assertEquals(Math.max(i,j), max2.applyAsDouble(i, j)); + assertEquals(Math.min(i,j), (double) min1.apply(i, j)); + assertEquals(Math.min(i,j), min2.applyAsDouble(i, j)); assertEquals(((Double) i).compareTo(j), cmp.compare(i, j)); } } diff --git a/jdk/test/java/lang/SecurityManager/NoAWT.java b/jdk/test/java/lang/SecurityManager/NoAWT.java index 3224af46dd4..d55e05c1027 100644 --- a/jdk/test/java/lang/SecurityManager/NoAWT.java +++ b/jdk/test/java/lang/SecurityManager/NoAWT.java @@ -22,14 +22,43 @@ */ /* @test - * @bug 8004502 + * @bug 8004502 8008793 * @summary Sanity check that SecurityManager methods that check AWTPermission * behave as expected when AWT is not present */ +import java.security.AllPermission; +import java.security.Permission; + public class NoAWT { + + static class MySecurityManager extends SecurityManager { + Class expectedClass; + + void setExpectedPermissionClass(Class c) { + expectedClass = c; + } + + @Override + public void checkPermission(Permission perm) { + if (perm.getClass() != expectedClass) + throw new RuntimeException("Got: " + perm.getClass() + ", expected: " + expectedClass); + super.checkPermission(perm); + } + } + public static void main(String[] args) { - SecurityManager sm = new SecurityManager(); + Class awtPermissionClass = null; + try { + awtPermissionClass = Class.forName("java.awt.AWTPermission"); + } catch (ClassNotFoundException ignore) { } + + MySecurityManager sm = new MySecurityManager(); + if (awtPermissionClass != null) { + sm.setExpectedPermissionClass(awtPermissionClass); + } else { + sm.setExpectedPermissionClass(AllPermission.class); + } try { sm.checkAwtEventQueueAccess(); diff --git a/jdk/test/java/lang/instrument/RedefineMethodInBacktrace.sh b/jdk/test/java/lang/instrument/RedefineMethodInBacktrace.sh new file mode 100644 index 00000000000..20167bf8330 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktrace.sh @@ -0,0 +1,87 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 7174978 +# @summary Redefine a class with a method stored in a backtrace. +# @author Stefan Karlsson +# +# @run shell MakeJAR3.sh RedefineMethodInBacktraceAgent 'Can-Redefine-Classes: true' +# @run build RedefineMethodInBacktraceTarget RedefineMethodInBacktraceApp +# @run shell RedefineMethodInBacktrace.sh +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +JAVAC="${COMPILEJAVA}"/bin/javac +JAVA="${TESTJAVA}"/bin/java + +cp "${TESTSRC}"/RedefineMethodInBacktraceTarget_2.java \ + RedefineMethodInBacktraceTarget.java +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTarget.java + +"${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodInBacktraceAgent.jar \ + -classpath "${TESTCLASSES}" RedefineMethodInBacktraceApp > output.log 2>&1 +RUN_RESULT=$? + +if [ $RUN_RESULT != 0 ]; then + echo "FAIL: the run failed with exit code '$RUN_RESULT'" + exit $RUN_RESULT +fi + +cat output.log + +MESG="Exception" +grep "$MESG" output.log +result=$? +if [ "$result" = 0 ]; then + echo "FAIL: found '$MESG' in the test output" + result=1 +else + echo "PASS: did NOT find '$MESG' in the test output" + result=0 +fi + +exit $result diff --git a/jdk/test/java/lang/instrument/RedefineMethodInBacktraceAgent.java b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceAgent.java new file mode 100644 index 00000000000..a4cc182bf23 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceAgent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.instrument.Instrumentation; + +public class RedefineMethodInBacktraceAgent { + private static Instrumentation instrumentation; + + private RedefineMethodInBacktraceAgent() {} + + public static void premain(String agentArgs, Instrumentation inst) { + System.out.println("Hello from RedefineMethodInBacktraceAgent!"); + System.out.println("isRedefineClassesSupported()=" + + inst.isRedefineClassesSupported()); + + instrumentation = inst; + } + + public static Instrumentation getInstrumentation() { + return instrumentation; + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java new file mode 100644 index 00000000000..a4ad0884661 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.instrument.ClassDefinition; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * When an exception is thrown, the JVM collects just enough information + * about the stack trace to be able to create a full fledged stack trace + * (StackTraceElement[]). The backtrace contains this information and the + * JVM must make sure that the data in the backtrace is still usable after + * a class redefinition. + * + * After the PermGen removal there was a bug when the last reference to a Method + * was in the backtrace. The class of the method was kept alive, because of the + * mirror stored in the backtrace, but the old versions of the redefined method + * could be freed, since class redefinition didn't know about the backtraces. + */ +public class RedefineMethodInBacktraceApp { + public static void main(String args[]) throws Exception { + System.out.println("Hello from RedefineMethodInBacktraceApp!"); + + new RedefineMethodInBacktraceApp().doTest(); + + System.exit(0); + } + + private void doTest() throws Exception { + doMethodInBacktraceTest(); + } + + private void doMethodInBacktraceTest() throws Exception { + Throwable t = getThrowableFromMethodToRedefine(); + + doRedefine(RedefineMethodInBacktraceTarget.class); + + doClassUnloading(); + + touchRedefinedMethodInBacktrace(t); + } + + private static Throwable getThrowableFromMethodToRedefine() throws Exception { + Class c = + RedefineMethodInBacktraceTarget.class; + Method method = c.getMethod("methodToRedefine"); + + Throwable thrownFromMethodToRedefine = null; + try { + method.invoke(null); + } catch (InvocationTargetException e) { + thrownFromMethodToRedefine = e.getCause(); + if (!(thrownFromMethodToRedefine instanceof RuntimeException)) { + throw e; + } + } + method = null; + c = null; + + return thrownFromMethodToRedefine; + } + + private static void doClassUnloading() { + // This will clean out old, unused redefined methods. + System.gc(); + } + + private static void touchRedefinedMethodInBacktrace(Throwable throwable) { + // Make sure that we can convert the backtrace, which is referring to + // the redefined method, to a StrackTraceElement[] without crashing. + throwable.getStackTrace(); + } + + private static void doRedefine(Class clazz) throws Exception { + // Load the second version of this class. + File f = new File(clazz.getName() + ".class"); + System.out.println("Reading test class from " + f.getAbsolutePath()); + InputStream redefineStream = new FileInputStream(f); + + byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream); + + ClassDefinition redefineParamBlock = new ClassDefinition( + clazz, redefineBuffer); + + RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses( + new ClassDefinition[] {redefineParamBlock}); + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget.java b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget.java new file mode 100644 index 00000000000..fad881137c8 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The first version of this class. The second version is in + * RedefineMethodInBacktraceTarget_2.java. + */ +public class RedefineMethodInBacktraceTarget { + public static void methodToRedefine() { + throw new RuntimeException("Test exception"); + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget_2.java b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget_2.java new file mode 100644 index 00000000000..d2ba2259932 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget_2.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This is the second version of this class. The first version is in + * RedefineMethodInBacktraceTarget.java. + */ +public class RedefineMethodInBacktraceTarget { + public static void methodToRedefine() { + throw new RuntimeException("Test exception 2"); + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotations.sh b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotations.sh new file mode 100644 index 00000000000..9bde206f17a --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotations.sh @@ -0,0 +1,85 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 7022100 +# @summary Method annotations are incorrectly set when redefining classes. +# @author Stefan Karlsson +# +# @run shell MakeJAR3.sh RedefineMethodWithAnnotationsAgent 'Can-Redefine-Classes: true' +# @run build RedefineMethodWithAnnotationsTarget RedefineMethodWithAnnotationsApp RedefineMethodWithAnnotationsAnnotations +# @run shell RedefineMethodWithAnnotations.sh +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +JAVAC="${COMPILEJAVA}"/bin/javac +JAVA="${TESTJAVA}"/bin/java + +cp "${TESTSRC}"/RedefineMethodWithAnnotationsTarget_2.java \ + RedefineMethodWithAnnotationsTarget.java +cp "${TESTSRC}"/RedefineMethodWithAnnotationsAnnotations.java \ + RedefineMethodWithAnnotationsAnnotations.java + +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ + RedefineMethodWithAnnotationsTarget.java \ + RedefineMethodWithAnnotationsAnnotations.java + +"${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodWithAnnotationsAgent.jar \ + -cp "${TESTCLASSES}" RedefineMethodWithAnnotationsApp > output.log 2>&1 +cat output.log + +MESG="Exception" +grep "$MESG" output.log +result=$? +if [ "$result" = 0 ]; then + echo "FAIL: found '$MESG' in the test output" + result=1 +else + echo "PASS: did NOT find '$MESG' in the test output" + result=0 +fi + +exit $result diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAgent.java b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAgent.java new file mode 100644 index 00000000000..c160be8756b --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAgent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.instrument.Instrumentation; + +public class RedefineMethodWithAnnotationsAgent { + private static Instrumentation instrumentation; + + private RedefineMethodWithAnnotationsAgent() {} + + public static void premain(String agentArgs, Instrumentation inst) { + System.out.println("Hello from RedefineMethodWithAnnotationsAgent!"); + System.out.println("isRedefineClassesSupported()=" + + inst.isRedefineClassesSupported()); + + instrumentation = inst; + } + + public static Instrumentation getInstrumentation() { + return instrumentation; + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAnnotations.java b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAnnotations.java new file mode 100644 index 00000000000..a215e96b8b9 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAnnotations.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@interface ParameterAnnotation { + // Values used for the annotations in the first version of the target class. + static final String STRING_VALUE_1 = "String1"; + static final String INT_VALUE_1 = "Int1"; + + // Values used for the annotations in the second version of the target class. + static final String STRING_VALUE_2 = "String2"; + static final String INT_VALUE_2 = "Int2"; + + String value(); +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsApp.java b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsApp.java new file mode 100644 index 00000000000..ebc6ac503b8 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsApp.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.instrument.ClassDefinition; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; + +public class RedefineMethodWithAnnotationsApp { + public static void main(String args[]) throws Exception { + System.out.println("Hello from RedefineMethodWithAnnotationsApp!"); + + new RedefineMethodWithAnnotationsApp().doTest(); + + System.exit(0); + } + + private void doTest() throws Exception { + doMethodParameterAnnotationsTest(); + } + + private void doMethodParameterAnnotationsTest() throws Exception { + verifyMethodParameterAnnotationsValue( + ParameterAnnotation.STRING_VALUE_1); + + doRedefine(RedefineMethodWithAnnotationsTarget.class); + + verifyMethodParameterAnnotationsValue( + ParameterAnnotation.STRING_VALUE_2); + } + + private static void verifyMethodParameterAnnotationsValue( + String expectedValue) throws Exception { + Class c = + RedefineMethodWithAnnotationsTarget.class; + Method method = c.getMethod("annotatedMethod", String.class); + + Annotation [][] parametersAnnotations = + method.getParameterAnnotations(); + if (parametersAnnotations.length != 1) { + throw new Exception("Incorrect number of parameters to method: " + + method.getName() + "." + + " Expected: 1," + + " got: " + parametersAnnotations.length); + } + + Annotation[] parameterAnnotations = parametersAnnotations[0]; + if (parameterAnnotations.length != 1) { + throw new Exception("Incorrect number of annotations." + + " Expected: 1" + + ", got " + parameterAnnotations.length); + } + + Annotation parameterAnnotation = parameterAnnotations[0]; + if (!(parameterAnnotation instanceof ParameterAnnotation)) { + throw new Exception("Incorrect Annotation class." + + " Expected: " + ParameterAnnotation.class.getName() + + ", got: " + parameterAnnotation.getClass().getName()); + } + + ParameterAnnotation pa = (ParameterAnnotation)parameterAnnotation; + String annotationValue = pa.value(); + if (!expectedValue.equals(annotationValue)) { + throw new Exception("Incorrect parameter annotation value." + + " Expected: " + expectedValue + + ", got: " + annotationValue); + } + } + + private static void doRedefine(Class clazz) throws Exception { + // Load the second version of this class. + File f = new File(clazz.getName() + ".class"); + System.out.println("Reading test class from " + f); + InputStream redefineStream = new FileInputStream(f); + + byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream); + + ClassDefinition redefineParamBlock = new ClassDefinition( + clazz, redefineBuffer); + + RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses( + new ClassDefinition[] {redefineParamBlock}); + } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget.java b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget.java new file mode 100644 index 00000000000..6cfbe21eb89 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * The first version of this class. The second version is in + * RedefineMethodWithAnnotationsTarget_2.java. + */ +public class RedefineMethodWithAnnotationsTarget { + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.STRING_VALUE_1) String parameter) { } + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.INT_VALUE_1) int parameter) { } +} diff --git a/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget_2.java b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget_2.java new file mode 100644 index 00000000000..85c43047231 --- /dev/null +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget_2.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This is the second version of this class. The first version is in + * RedefineMethodWithAnnotationsTarget.java. + *

    + * It has the same methods but with different annotations and order. + */ +public class RedefineMethodWithAnnotationsTarget { + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.INT_VALUE_2) int parameter) { } + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.STRING_VALUE_2) String parameter) { } +} diff --git a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh index 6deb7ce6e44..850fac252a1 100644 --- a/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh +++ b/jdk/test/java/lang/instrument/RedefineSubclassWithTwoInterfaces.sh @@ -141,32 +141,30 @@ else fi PASS1_MESG="before any redefines" -cnt=`grep "$PASS1_MESG" output.log | grep 'version-0' | wc -l | sed 's/^ *//'` -case "$cnt" in -2) +cnt=`grep "$PASS1_MESG" output.log | grep 'version-0' | wc -l` +# no quotes around $cnt so any whitespace from 'wc -l' is ignored +if [ $cnt = 2 ]; then echo "INFO: found 2 version-0 '$PASS1_MESG' mesgs." - ;; -*) +else echo "FAIL: did NOT find 2 version-0 '$PASS1_MESG' mesgs." + echo "INFO: cnt='$cnt'" echo "INFO: grep '$PASS1_MESG' output:" grep "$PASS1_MESG" output.log result=1 - ;; -esac +fi PASS2_MESG="after redefine" -cnt=`grep "$PASS2_MESG" output.log | grep 'version-1' | wc -l | sed 's/^ *//'` -case "$cnt" in -2) +cnt=`grep "$PASS2_MESG" output.log | grep 'version-1' | wc -l` +# no quotes around $cnt so any whitespace from 'wc -l' is ignored +if [ $cnt = 2 ]; then echo "INFO: found 2 version-1 '$PASS2_MESG' mesgs." - ;; -*) +else echo "FAIL: did NOT find 2 version-1 '$PASS2_MESG' mesgs." + echo "INFO: cnt='$cnt'" echo "INFO: grep '$PASS2_MESG' output:" grep "$PASS2_MESG" output.log result=1 - ;; -esac +fi if [ "$result" = 0 ]; then echo "PASS: test passed both positive and negative output checks." diff --git a/jdk/test/java/lang/invoke/7087570/Test7087570.java b/jdk/test/java/lang/invoke/7087570/Test7087570.java new file mode 100644 index 00000000000..572faccdf5a --- /dev/null +++ b/jdk/test/java/lang/invoke/7087570/Test7087570.java @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* @test + * @bug 7087570 + * @summary REF_invokeSpecial DMHs (which are unusual) get marked explicitly; tweak the MHI to use this bit + * + * @run main Test7087570 + */ + +import java.lang.invoke.*; +import java.lang.reflect.*; +import java.util.*; + +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; + +public class Test7087570 { + // XXX may remove the following constant declarations when MethodHandleInfo is made public + private static final int + REF_getField = 1, + REF_getStatic = 2, + REF_putField = 3, + REF_putStatic = 4, + REF_invokeVirtual = 5, + REF_invokeStatic = 6, + REF_invokeSpecial = 7, + REF_newInvokeSpecial = 8, + REF_invokeInterface = 9, + REF_LIMIT = 10; + + private static final TestMethodData[] TESTS = new TestMethodData[] { + // field accessors + data(DummyFieldHolder.class, "instanceField", getterMethodType(String.class), DummyFieldHolder.class, REF_getField), + data(DummyFieldHolder.class, "instanceField", setterMethodType(String.class), DummyFieldHolder.class, REF_putField), + data(DummyFieldHolder.class, "staticField", getterMethodType(Integer.class), DummyFieldHolder.class, REF_getStatic), + data(DummyFieldHolder.class, "staticField", setterMethodType(Integer.class), DummyFieldHolder.class, REF_putStatic), + data(DummyFieldHolder.class, "instanceByteField", getterMethodType(byte.class), DummyFieldHolder.class, REF_getField), + data(DummyFieldHolder.class, "instanceByteField", setterMethodType(byte.class), DummyFieldHolder.class, REF_putField), + + // REF_invokeVirtual + data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeVirtual), + + // REF_invokeVirtual strength-reduced to REF_invokeSpecial, + // test if it normalizes back to REF_invokeVirtual in MethodHandleInfo as expected + data(String.class, "hashCode", methodType(int.class), String.class, REF_invokeVirtual), + + // REF_invokeStatic + data(Collections.class, "sort", methodType(void.class, List.class), Collections.class, REF_invokeStatic), + data(Arrays.class, "asList", methodType(List.class, Object[].class), Arrays.class, REF_invokeStatic), // varargs case + + // REF_invokeSpecial + data(Object.class, "hashCode", methodType(int.class), Object.class, REF_invokeSpecial), + + // REF_newInvokeSpecial + data(String.class, "", methodType(void.class, char[].class), String.class, REF_newInvokeSpecial), + data(DummyFieldHolder.class, "", methodType(void.class, byte.class, Long[].class), DummyFieldHolder.class, REF_newInvokeSpecial), // varargs case + + // REF_invokeInterface + data(List.class, "size", methodType(int.class), List.class, REF_invokeInterface) + }; + + public static void main(String... args) throws Throwable { + testWithLookup(); + testWithUnreflect(); + } + + private static void doTest(MethodHandle mh, TestMethodData testMethod) { + Object mhi = newMethodHandleInfo(mh); + + System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n", + testMethod.clazz.getName(), testMethod.name, testMethod.methodType, + REF_KIND_NAMES[testMethod.referenceKind], + REF_KIND_NAMES[getReferenceKind(mhi)]); + assertEquals(testMethod.name, getName(mhi)); + assertEquals(testMethod.methodType, getMethodType(mhi)); + assertEquals(testMethod.declaringClass, getDeclaringClass(mhi)); + assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh)); + assertRefKindEquals(testMethod.referenceKind, getReferenceKind(mhi)); + } + + private static void testWithLookup() throws Throwable { + for (TestMethodData testMethod : TESTS) { + MethodHandle mh = lookupFrom(testMethod); + doTest(mh, testMethod); + } + } + + private static void testWithUnreflect() throws Throwable { + for (TestMethodData testMethod : TESTS) { + MethodHandle mh = unreflectFrom(testMethod); + doTest(mh, testMethod); + } + } + + private static MethodType getterMethodType(Class clazz) { + return methodType(clazz); + } + + private static MethodType setterMethodType(Class clazz) { + return methodType(void.class, clazz); + } + + private static final String[] REF_KIND_NAMES = { + "MH::invokeBasic", + "REF_getField", "REF_getStatic", "REF_putField", "REF_putStatic", + "REF_invokeVirtual", "REF_invokeStatic", "REF_invokeSpecial", + "REF_newInvokeSpecial", "REF_invokeInterface" + }; + + private static final Lookup LOOKUP = lookup(); + + // XXX may remove the following reflective logic when MethodHandleInfo is made public + private static final MethodHandle MH_IS_INVOKESPECIAL; + private static final MethodHandle MHI_CONSTRUCTOR; + private static final MethodHandle MHI_GET_NAME; + private static final MethodHandle MHI_GET_METHOD_TYPE; + private static final MethodHandle MHI_GET_DECLARING_CLASS; + private static final MethodHandle MHI_GET_REFERENCE_KIND; + + static { + try { + // This is white box testing. Use reflection to grab private implementation bits. + String magicName = "IMPL_LOOKUP"; + Field magicLookup = MethodHandles.Lookup.class.getDeclaredField(magicName); + // This unit test will fail if a security manager is installed. + magicLookup.setAccessible(true); + // Forbidden fruit... + Lookup directInvokeLookup = (Lookup) magicLookup.get(null); + Class mhiClass = Class.forName("java.lang.invoke.MethodHandleInfo", false, MethodHandle.class.getClassLoader()); + MH_IS_INVOKESPECIAL = directInvokeLookup + .findVirtual(MethodHandle.class, "isInvokeSpecial", methodType(boolean.class)); + MHI_CONSTRUCTOR = directInvokeLookup + .findConstructor(mhiClass, methodType(void.class, MethodHandle.class)); + MHI_GET_NAME = directInvokeLookup + .findVirtual(mhiClass, "getName", methodType(String.class)); + MHI_GET_METHOD_TYPE = directInvokeLookup + .findVirtual(mhiClass, "getMethodType", methodType(MethodType.class)); + MHI_GET_DECLARING_CLASS = directInvokeLookup + .findVirtual(mhiClass, "getDeclaringClass", methodType(Class.class)); + MHI_GET_REFERENCE_KIND = directInvokeLookup + .findVirtual(mhiClass, "getReferenceKind", methodType(int.class)); + } catch (ReflectiveOperationException ex) { + throw new Error(ex); + } + } + + private static class TestMethodData { + final Class clazz; + final String name; + final MethodType methodType; + final Class declaringClass; + final int referenceKind; // the nominal refKind + + public TestMethodData(Class clazz, String name, + MethodType methodType, Class declaringClass, + int referenceKind) { + this.clazz = clazz; + this.name = name; + this.methodType = methodType; + this.declaringClass = declaringClass; + this.referenceKind = referenceKind; + } + } + + private static TestMethodData data(Class clazz, String name, + MethodType methodType, Class declaringClass, + int referenceKind) { + return new TestMethodData(clazz, name, methodType, declaringClass, referenceKind); + } + + private static MethodHandle lookupFrom(TestMethodData testMethod) + throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { + switch (testMethod.referenceKind) { + case REF_getField: + return LOOKUP.findGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType()); + case REF_putField: + return LOOKUP.findSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0)); + case REF_getStatic: + return LOOKUP.findStaticGetter(testMethod.clazz, testMethod.name, testMethod.methodType.returnType()); + case REF_putStatic: + return LOOKUP.findStaticSetter(testMethod.clazz, testMethod.name, testMethod.methodType.parameterType(0)); + case REF_invokeVirtual: + case REF_invokeInterface: + return LOOKUP.findVirtual(testMethod.clazz, testMethod.name, testMethod.methodType); + case REF_invokeStatic: + return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType); + case REF_invokeSpecial: + Class thisClass = LOOKUP.lookupClass(); + return LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass); + case REF_newInvokeSpecial: + return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType); + default: + throw new Error("ERROR: unexpected referenceKind in test data"); + } + } + + private static MethodHandle unreflectFrom(TestMethodData testMethod) + throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException { + switch (testMethod.referenceKind) { + case REF_getField: + case REF_getStatic: { + Field f = testMethod.clazz.getDeclaredField(testMethod.name); + return LOOKUP.unreflectGetter(f); + } + case REF_putField: + case REF_putStatic: { + Field f = testMethod.clazz.getDeclaredField(testMethod.name); + return LOOKUP.unreflectSetter(f); + } + case REF_invokeVirtual: + case REF_invokeStatic: + case REF_invokeInterface: { + Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray()); + return LOOKUP.unreflect(m); + } + case REF_invokeSpecial: { + Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray()); + Class thisClass = LOOKUP.lookupClass(); + return LOOKUP.unreflectSpecial(m, thisClass); + } + case REF_newInvokeSpecial: { + Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray()); + return LOOKUP.unreflectConstructor(c); + } + default: + throw new Error("ERROR: unexpected referenceKind in test data"); + } + } + + private static Object newMethodHandleInfo(MethodHandle mh) { + try { + return MHI_CONSTRUCTOR.invoke(mh); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static boolean isInvokeSpecial(MethodHandle mh) { + try { + return (boolean) MH_IS_INVOKESPECIAL.invokeExact(mh); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static String getName(Object mhi) { + try { + return (String) MHI_GET_NAME.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static MethodType getMethodType(Object mhi) { + try { + return (MethodType) MHI_GET_METHOD_TYPE.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static Class getDeclaringClass(Object mhi) { + try { + return (Class) MHI_GET_DECLARING_CLASS.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static int getReferenceKind(Object mhi) { + try { + return (int) MHI_GET_REFERENCE_KIND.invoke(mhi); + } catch (Throwable ex) { + throw new Error(ex); + } + } + + private static void assertRefKindEquals(int expect, int observed) { + if (expect == observed) return; + + String msg = "expected " + REF_KIND_NAMES[(int) expect] + + " but observed " + REF_KIND_NAMES[(int) observed]; + System.out.println("FAILED: " + msg); + throw new AssertionError(msg); + } + + private static void assertEquals(Object expect, Object observed) { + if (java.util.Objects.equals(expect, observed)) return; + + String msg = "expected " + expect + " but observed " + observed; + System.out.println("FAILED: " + msg); + throw new AssertionError(msg); + } +} + +class DummyFieldHolder { + public static Integer staticField; + public String instanceField; + public byte instanceByteField; + + public DummyFieldHolder(byte unused1, Long... unused2) { + } +} + diff --git a/jdk/test/java/lang/invoke/lambda/LUtils.java b/jdk/test/java/lang/invoke/lambda/LUtils.java new file mode 100644 index 00000000000..a7b013e3a6c --- /dev/null +++ b/jdk/test/java/lang/invoke/lambda/LUtils.java @@ -0,0 +1,171 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/* + * support infrastructure to invoke a java class from the command line + */ +class LUtils { + static final sun.tools.jar.Main jarTool = + new sun.tools.jar.Main(System.out, System.err, "jar-tool"); + static final com.sun.tools.javac.Main javac = + new com.sun.tools.javac.Main(); + static final File cwd = new File(".").getAbsoluteFile(); + static final String JAVAHOME = System.getProperty("java.home"); + static final boolean isWindows = + System.getProperty("os.name", "unknown").startsWith("Windows"); + //static final boolean isSDK = JAVAHOME.endsWith("jre"); + static final File JAVA_BIN_FILE = new File(JAVAHOME, "bin"); + static final File JAVA_CMD = new File(JAVA_BIN_FILE, + isWindows ? "java.exe" : "java"); + + protected LUtils() { + } + + public static void compile(String... args) { + if (javac.compile(args) != 0) { + throw new RuntimeException("compilation fails"); + } + } + + static void createFile(File outFile, List content) { + try { + Files.write(outFile.getAbsoluteFile().toPath(), content, + Charset.defaultCharset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + static File getClassFile(File javaFile) { + return javaFile.getName().endsWith(".java") + ? new File(javaFile.getName().replace(".java", ".class")) + : null; + } + + static String getSimpleName(File inFile) { + String fname = inFile.getName(); + return fname.substring(0, fname.indexOf(".")); + } + + static TestResult doExec(String... cmds) { + return doExec(null, null, cmds); + } + + /* + * A method which executes a java cmd and returns the results in a container + */ + static TestResult doExec(Map envToSet, + java.util.Set envToRemove, String... cmds) { + String cmdStr = ""; + for (String x : cmds) { + cmdStr = cmdStr.concat(x + " "); + } + ProcessBuilder pb = new ProcessBuilder(cmds); + Map env = pb.environment(); + if (envToRemove != null) { + for (String key : envToRemove) { + env.remove(key); + } + } + if (envToSet != null) { + env.putAll(envToSet); + } + BufferedReader rdr = null; + try { + List outputList = new ArrayList<>(); + pb.redirectErrorStream(true); + Process p = pb.start(); + rdr = new BufferedReader(new InputStreamReader(p.getInputStream())); + String in = rdr.readLine(); + while (in != null) { + outputList.add(in); + in = rdr.readLine(); + } + p.waitFor(); + p.destroy(); + + return new TestResult(cmdStr, p.exitValue(), outputList, + env, new Throwable("current stack of the test")); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + } + + static class TestResult { + String cmd; + int exitValue; + List testOutput; + Map env; + Throwable t; + + public TestResult(String str, int rv, List oList, + Map env, Throwable t) { + cmd = str; + exitValue = rv; + testOutput = oList; + this.env = env; + this.t = t; + } + + void assertZero(String message) { + if (exitValue != 0) { + System.err.println(this); + throw new RuntimeException(message); + } + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + PrintWriter status = new PrintWriter(sw); + status.println("Cmd: " + cmd); + status.println("Return code: " + exitValue); + status.println("Environment variable:"); + for (String x : env.keySet()) { + status.println("\t" + x + "=" + env.get(x)); + } + status.println("Output:"); + for (String x : testOutput) { + status.println("\t" + x); + } + status.println("Exception:"); + status.println(t.getMessage()); + t.printStackTrace(status); + + return sw.getBuffer().toString(); + } + } +} diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java index 8c3d1c5ed5b..e9e5cbcd1c2 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java @@ -26,20 +26,12 @@ * @bug 8003881 * @summary tests DoPrivileged action (implemented as lambda expressions) by * inserting them into the BootClassPath. - * @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java + * @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java LUtils.java * @run main/othervm LambdaAccessControlDoPrivilegedTest */ -import java.io.BufferedReader; import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.charset.Charset; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.Map; public class LambdaAccessControlDoPrivilegedTest extends LUtils { public static void main(String... args) { @@ -87,140 +79,3 @@ public class LambdaAccessControlDoPrivilegedTest extends LUtils { jarFile.delete(); } } - -/* - * support infrastructure to invoke a java class from the command line - */ -class LUtils { - static final sun.tools.jar.Main jarTool = - new sun.tools.jar.Main(System.out, System.err, "jar-tool"); - static final com.sun.tools.javac.Main javac = - new com.sun.tools.javac.Main(); - static final File cwd = new File(".").getAbsoluteFile(); - static final String JAVAHOME = System.getProperty("java.home"); - static final boolean isWindows = - System.getProperty("os.name", "unknown").startsWith("Windows"); - //static final boolean isSDK = JAVAHOME.endsWith("jre"); - static final File JAVA_BIN_FILE = new File(JAVAHOME, "bin"); - static final File JAVA_CMD = new File(JAVA_BIN_FILE, - isWindows ? "java.exe" : "java"); - - protected LUtils() { - } - - public static void compile(String... args) { - if (javac.compile(args) != 0) { - throw new RuntimeException("compilation fails"); - } - } - - static void createFile(File outFile, List content) { - try { - Files.write(outFile.getAbsoluteFile().toPath(), content, - Charset.defaultCharset()); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - } - - static File getClassFile(File javaFile) { - return javaFile.getName().endsWith(".java") - ? new File(javaFile.getName().replace(".java", ".class")) - : null; - } - - static String getSimpleName(File inFile) { - String fname = inFile.getName(); - return fname.substring(0, fname.indexOf(".")); - } - - static TestResult doExec(String... cmds) { - return doExec(null, null, cmds); - } - - /* - * A method which executes a java cmd and returns the results in a container - */ - static TestResult doExec(Map envToSet, - java.util.Set envToRemove, String... cmds) { - String cmdStr = ""; - for (String x : cmds) { - cmdStr = cmdStr.concat(x + " "); - } - ProcessBuilder pb = new ProcessBuilder(cmds); - Map env = pb.environment(); - if (envToRemove != null) { - for (String key : envToRemove) { - env.remove(key); - } - } - if (envToSet != null) { - env.putAll(envToSet); - } - BufferedReader rdr = null; - try { - List outputList = new ArrayList<>(); - pb.redirectErrorStream(true); - Process p = pb.start(); - rdr = new BufferedReader(new InputStreamReader(p.getInputStream())); - String in = rdr.readLine(); - while (in != null) { - outputList.add(in); - in = rdr.readLine(); - } - p.waitFor(); - p.destroy(); - - return new TestResult(cmdStr, p.exitValue(), outputList, - env, new Throwable("current stack of the test")); - } catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException(ex.getMessage()); - } - } - - static class TestResult { - String cmd; - int exitValue; - List testOutput; - Map env; - Throwable t; - - public TestResult(String str, int rv, List oList, - Map env, Throwable t) { - cmd = str; - exitValue = rv; - testOutput = oList; - this.env = env; - this.t = t; - } - - void assertZero(String message) { - if (exitValue != 0) { - System.err.println(this); - throw new RuntimeException(message); - } - } - - @Override - public String toString() { - StringWriter sw = new StringWriter(); - PrintWriter status = new PrintWriter(sw); - status.println("Cmd: " + cmd); - status.println("Return code: " + exitValue); - status.println("Environment variable:"); - for (String x : env.keySet()) { - status.println("\t" + x + "=" + env.get(x)); - } - status.println("Output:"); - for (String x : testOutput) { - status.println("\t" + x); - } - status.println("Exception:"); - status.println(t.getMessage()); - t.printStackTrace(status); - - return sw.getBuffer().toString(); - } - } -} diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlTest.java b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlTest.java index 361a4cffcce..6ca9fb0beb2 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlTest.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlTest.java @@ -25,7 +25,7 @@ * @test * @bug 8003881 * @summary tests Lambda expression with a a security manager at top level - * @compile -XDignore.symbol.file LambdaAccessControlTest.java + * @compile -XDignore.symbol.file LambdaAccessControlTest.java LUtils.java * * @run main/othervm LambdaAccessControlTest */ diff --git a/jdk/test/java/lang/invoke/lambda/LambdaClassLoaderSerialization.java b/jdk/test/java/lang/invoke/lambda/LambdaClassLoaderSerialization.java new file mode 100644 index 00000000000..9d38102b14a --- /dev/null +++ b/jdk/test/java/lang/invoke/lambda/LambdaClassLoaderSerialization.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +@test +@bug 8004970 +@summary Lambda serialization in the presence of class loaders +@author Peter Levart +*/ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Arrays; + +public class LambdaClassLoaderSerialization { + + public interface SerializableRunnable extends Runnable, Serializable {} + + public static class MyCode implements SerializableRunnable { + + private byte[] serialize(Object o) { + ByteArrayOutputStream baos; + try ( + ObjectOutputStream oos = + new ObjectOutputStream(baos = new ByteArrayOutputStream()) + ) { + oos.writeObject(o); + } + catch (IOException e) { + throw new RuntimeException(e); + } + return baos.toByteArray(); + } + + private T deserialize(byte[] bytes) { + try ( + ObjectInputStream ois = + new ObjectInputStream(new ByteArrayInputStream(bytes)) + ) { + return (T) ois.readObject(); + } + catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public void run() { + System.out.println(" this: " + this); + + SerializableRunnable deSerializedThis = deserialize(serialize(this)); + System.out.println(" deSerializedThis: " + deSerializedThis); + + SerializableRunnable runnable = () -> {System.out.println("HELLO");}; + System.out.println(" runnable: " + runnable); + + SerializableRunnable deSerializedRunnable = deserialize(serialize(runnable)); + System.out.println("deSerializedRunnable: " + deSerializedRunnable); + } + } + + public static void main(String[] args) throws Exception { + ClassLoader myCl = new MyClassLoader( + LambdaClassLoaderSerialization.class.getClassLoader() + ); + Class myCodeClass = Class.forName( + LambdaClassLoaderSerialization.class.getName() + "$MyCode", + true, + myCl + ); + Runnable myCode = (Runnable) myCodeClass.newInstance(); + myCode.run(); + } + + static class MyClassLoader extends ClassLoader { + MyClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.indexOf('.') < 0) { + synchronized (getClassLoadingLock(name)) { + Class c = findLoadedClass(name); + if (c == null) { + c = findClass(name); + } + if (resolve) { + resolveClass(c); + } + return c; + } + } else { + return super.loadClass(name, resolve); + } + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + String path = name.replace('.', '/').concat(".class"); + try (InputStream is = getResourceAsStream(path)) { + if (is != null) { + byte[] bytes = readFully(is); + return defineClass(name, bytes, 0, bytes.length); + } else { + throw new ClassNotFoundException(name); + } + } + catch (IOException e) { + throw new ClassNotFoundException(name, e); + } + } + + static byte[] readFully(InputStream is) throws IOException { + byte[] output = {}; + int pos = 0; + while (true) { + int bytesToRead; + if (pos >= output.length) { // Only expand when there's no room + bytesToRead = output.length + 1024; + if (output.length < pos + bytesToRead) { + output = Arrays.copyOf(output, pos + bytesToRead); + } + } else { + bytesToRead = output.length - pos; + } + int cc = is.read(output, pos, bytesToRead); + if (cc < 0) { + if (output.length != pos) { + output = Arrays.copyOf(output, pos); + } + break; + } + pos += cc; + } + return output; + } + } +} diff --git a/jdk/test/java/lang/invoke/lambda/LambdaSerialization.java b/jdk/test/java/lang/invoke/lambda/LambdaSerialization.java new file mode 100644 index 00000000000..6d681c35a66 --- /dev/null +++ b/jdk/test/java/lang/invoke/lambda/LambdaSerialization.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* +@test +@bug 8004970 +@summary Lambda serialization +*/ + +import java.io.*; + +public class LambdaSerialization { + + static int assertionCount = 0; + + static void assertTrue(boolean cond) { + assertionCount++; + if (!cond) + throw new AssertionError(); + } + + public static void main(String[] args) throws Exception { + try { + // Write lambdas out + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(baos); + + write(out, z -> "[" + z + "]" ); + write(out, z -> z + z ); + write(out, z -> "blah" ); + out.flush(); + out.close(); + + // Read them back + ByteArrayInputStream bais = + new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + readAssert(in, "[X]"); + readAssert(in, "XX"); + readAssert(in, "blah"); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } + assertTrue(assertionCount == 3); + } + + static void write(ObjectOutput out, LSI lamb) throws IOException { + out.writeObject(lamb); + } + + static void readAssert(ObjectInputStream in, String expected) throws IOException, ClassNotFoundException { + LSI ls = (LSI) in.readObject(); + String result = ls.convert("X"); + System.out.printf("Result: %s\n", result); + assertTrue(result.equals(expected)); + } +} + +interface LSI extends Serializable { + String convert(String x); +} diff --git a/jdk/test/java/lang/reflect/OldenCompilingWithDefaults.java b/jdk/test/java/lang/reflect/OldenCompilingWithDefaults.java new file mode 100644 index 00000000000..c8609b35f9d --- /dev/null +++ b/jdk/test/java/lang/reflect/OldenCompilingWithDefaults.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8009267 + * @summary Verify uses of isAnnotationPresent compile under older source versions + * @compile -source 1.5 -target 1.5 OldenCompilingWithDefaults.java + * @compile -source 1.6 -target 1.6 OldenCompilingWithDefaults.java + * @compile -source 1.7 -target 1.7 OldenCompilingWithDefaults.java + * @compile OldenCompilingWithDefaults.java + */ + +import java.lang.reflect.*; + +public class OldenCompilingWithDefaults { + public OldenCompilingWithDefaults(){} + static Object f; + + public static void main(String... args) throws Exception { + Class clazz = OldenCompilingWithDefaults.class; + Package pkg = clazz.getPackage(); + Constructor ctor = clazz.getConstructor(); + Method m = clazz.getMethod("main", String[].class); + Field f = clazz.getField("f"); + + if(clazz.isAnnotationPresent(SuppressWarnings.class) || + pkg.isAnnotationPresent(SuppressWarnings.class) || + ctor.isAnnotationPresent(SuppressWarnings.class) || + m.isAnnotationPresent(SuppressWarnings.class) || + f.isAnnotationPresent(SuppressWarnings.class)) + System.out.println("An annotation is present."); + } +} diff --git a/jdk/test/java/lang/reflect/Parameter/WithParameters.java b/jdk/test/java/lang/reflect/Parameter/WithParameters.java index c4ffec6de30..bddebf1c782 100644 --- a/jdk/test/java/lang/reflect/Parameter/WithParameters.java +++ b/jdk/test/java/lang/reflect/Parameter/WithParameters.java @@ -22,7 +22,6 @@ */ /* - * @ignore * @test * @compile -parameters WithParameters.java * @run main WithParameters @@ -85,8 +84,8 @@ public class WithParameters { error++; } } - if(parameters[0].toString().equals("int quux")) { - System.err.println("toString for quux is wrong"); + if(!parameters[0].toString().equals("final int quux")) { + System.err.println("toString for quux is wrong, expected \"final int quux\", got \"" + parameters[0] + "\""); error++; } if(parameters[0].getModifiers() != Modifier.FINAL) { @@ -101,8 +100,8 @@ public class WithParameters { System.err.println("getParameterizedType for quux is wrong"); error++; } - if(parameters[1].toString().equals("WithParameters$Foo quuux")) { - System.err.println("toString for quuux is wrong"); + if(!parameters[1].toString().equals("WithParameters$Foo quuux")) { + System.err.println("toString for quuux is wrong, expected \"WithParameters$Foo quuux\", got \"" + parameters[1] + "\""); error++; } if(parameters[1].isVarArgs()) { @@ -121,8 +120,8 @@ public class WithParameters { System.err.println("getAnnotations has the wrong annotation"); error++; } - if(parameters[2].toString().equals("java.util.List quuux")) { - System.err.println("toString for l is wrong"); + if(!parameters[2].toString().equals("java.util.List l")) { + System.err.println("toString for l is wrong, expected \"java.util.List l\", got \"" + parameters[2] + "\""); error++; } if(parameters[2].isVarArgs()) { @@ -149,8 +148,8 @@ public class WithParameters { error++; } } - if(parameters[3].toString().equals("java.util.List l")) { - System.err.println("toString for l2 is wrong"); + if(!parameters[3].toString().equals("java.util.List l2")) { + System.err.println("toString for l2 is wrong, expected \"java.util.List l2\", got \"" + parameters[3] + "\""); error++; } if(parameters[3].isVarArgs()) { @@ -177,8 +176,8 @@ public class WithParameters { error++; } } - if(parameters[4].toString().equals("java.util.List l")) { - System.err.println("toString for l3 is wrong"); + if(!parameters[4].toString().equals("java.util.List l3")) { + System.err.println("toString for l3 is wrong, expected \"java.util.List l3\", got \"" + parameters[3] + "\""); error++; } if(parameters[4].isVarArgs()) { @@ -212,8 +211,8 @@ public class WithParameters { } } } - if(parameters[5].toString().equals("java.lang.String... rest")) { - System.err.println("toString for l is wrong"); + if(!parameters[5].toString().equals("java.lang.String... rest")) { + System.err.println("toString for rest is wrong, expected \"java.lang.String... rest\", got \"" + parameters[5] + "\""); error++; } if(!parameters[5].isVarArgs()) { diff --git a/jdk/test/java/net/BindException/Test.java b/jdk/test/java/net/BindException/Test.java index 19bba9af90b..11d37e4b9c9 100644 --- a/jdk/test/java/net/BindException/Test.java +++ b/jdk/test/java/net/BindException/Test.java @@ -46,7 +46,7 @@ public class Test { static int failures; static void doTest(Object test[], InetAddress ia1, InetAddress ia2, - boolean silent) { + boolean silent) throws Exception { String s1_type = (String)test[0]; String s2_type = (String)test[1]; int port = 0; @@ -64,11 +64,10 @@ public class Test { boolean failed = false; Exception failed_exc = null; + Socket sock1 = null; + ServerSocket ss = null; + DatagramSocket dsock1 = null; try { - Socket sock1, sock2; - ServerSocket ss; - DatagramSocket dsock1, dsock2; - /* bind the first socket */ if (s1_type.equals("Socket")) { @@ -90,16 +89,18 @@ public class Test { /* bind the second socket */ if (s2_type.equals("Socket")) { - sock2 = new Socket(); - sock2.bind( new InetSocketAddress(ia2, port)); + try (Socket sock2 = new Socket()) { + sock2.bind( new InetSocketAddress(ia2, port)); + } } if (s2_type.equals("ServerSocket")) { - ss = new ServerSocket(port, 0, ia2); + try (ServerSocket ss2 = new ServerSocket(port, 0, ia2)) { } } if (s2_type.equals("DatagramSocket")) { - dsock2 = new DatagramSocket( new InetSocketAddress(ia2, port) ); + try (DatagramSocket ds = + new DatagramSocket(new InetSocketAddress(ia2, port))) { } } } catch (BindException be) { @@ -107,6 +108,10 @@ public class Test { } catch (Exception e) { failed = true; failed_exc = e; + } finally { + if (sock1 != null) sock1.close(); + if (ss != null) ss.close(); + if (dsock1 != null) dsock1.close(); } /* diff --git a/jdk/test/java/net/Socket/HttpProxy.java b/jdk/test/java/net/Socket/HttpProxy.java new file mode 100644 index 00000000000..92f14d2d32a --- /dev/null +++ b/jdk/test/java/net/Socket/HttpProxy.java @@ -0,0 +1,281 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6370908 + * @summary Add support for HTTP_CONNECT proxy in Socket class + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import static java.lang.System.out; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ServerSocket; +import java.net.Socket; +import sun.net.www.MessageHeader; + +public class HttpProxy { + final String proxyHost; + final int proxyPort; + static final int SO_TIMEOUT = 15000; + + public static void main(String[] args) throws Exception { + String host; + int port; + if (args.length == 0) { + // Start internal proxy + ConnectProxyTunnelServer proxy = new ConnectProxyTunnelServer(); + proxy.start(); + host = "localhost"; + port = proxy.getLocalPort(); + out.println("Running with internal proxy: " + host + ":" + port); + } else if (args.length == 2) { + host = args[0]; + port = Integer.valueOf(args[1]); + out.println("Running against specified proxy server: " + host + ":" + port); + } else { + System.err.println("Usage: java HttpProxy [ ]"); + return; + } + + HttpProxy p = new HttpProxy(host, port); + p.test(); + } + + public HttpProxy(String proxyHost, int proxyPort) { + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + } + + void test() throws Exception { + InetSocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort); + Proxy httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress); + + try (ServerSocket ss = new ServerSocket(0); + Socket sock = new Socket(httpProxy)) { + sock.setSoTimeout(SO_TIMEOUT); + sock.setTcpNoDelay(false); + + InetSocketAddress externalAddress = + new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort()); + + out.println("Trying to connect to server socket on " + externalAddress); + sock.connect(externalAddress); + try (Socket externalSock = ss.accept()) { + // perform some simple checks + check(sock.isBound(), "Socket is not bound"); + check(sock.isConnected(), "Socket is not connected"); + check(!sock.isClosed(), "Socket should not be closed"); + check(sock.getSoTimeout() == SO_TIMEOUT, + "Socket should have a previously set timeout"); + check(sock.getTcpNoDelay() == false, "NODELAY should be false"); + + simpleDataExchange(sock, externalSock); + } + } + } + + static void check(boolean condition, String message) { + if (!condition) out.println(message); + } + + static Exception unexpected(Exception e) { + out.println("Unexcepted Exception: " + e); + e.printStackTrace(); + return e; + } + + // performs a simple exchange of data between the two sockets + // and throws an exception if there is any problem. + void simpleDataExchange(Socket s1, Socket s2) throws Exception { + try (final InputStream i1 = s1.getInputStream(); + final InputStream i2 = s2.getInputStream(); + final OutputStream o1 = s1.getOutputStream(); + final OutputStream o2 = s2.getOutputStream()) { + startSimpleWriter("simpleWriter1", o1, 100); + startSimpleWriter("simpleWriter2", o2, 200); + simpleRead(i2, 100); + simpleRead(i1, 200); + } + } + + void startSimpleWriter(String threadName, final OutputStream os, final int start) { + (new Thread(new Runnable() { + public void run() { + try { simpleWrite(os, start); } + catch (Exception e) {unexpected(e); } + }}, threadName)).start(); + } + + void simpleWrite(OutputStream os, int start) throws Exception { + byte b[] = new byte[2]; + for (int i=start; iCONNECT server-name:server-port HTTP/1.x + */ + static InetSocketAddress getConnectInfo(String connectStr) + throws Exception + { + try { + int starti = connectStr.indexOf(' '); + int endi = connectStr.lastIndexOf(' '); + String connectInfo = connectStr.substring(starti+1, endi).trim(); + // retrieve server name and port + endi = connectInfo.indexOf(':'); + String name = connectInfo.substring(0, endi); + int port = Integer.parseInt(connectInfo.substring(endi+1)); + return new InetSocketAddress(name, port); + } catch (Exception e) { + out.println("Proxy recieved a request: " + connectStr); + throw unexpected(e); + } + } + } + + /* Reads from the given InputStream and writes to the given OutputStream */ + static class Forwarder implements Runnable + { + private final InputStream in; + private final OutputStream os; + + Forwarder(InputStream in, OutputStream os) { + this.in = in; + this.os = os; + } + + @Override + public void run() { + try { + byte[] ba = new byte[1024]; + int count; + while ((count = in.read(ba)) != -1) { + os.write(ba, 0, count); + } + } catch (IOException e) { + unexpected(e); + } + } + } +} diff --git a/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java b/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java index c916b2ef8af..7b9ec6a9a36 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java @@ -42,7 +42,7 @@ public class SendToUnresolved { try { dc.send(bb, sa); throw new RuntimeException("Expected exception not thrown"); - } catch (IOException e) { + } catch (IOException | UnresolvedAddressException e) { // Correct result } dc.close(); diff --git a/jdk/test/java/nio/channels/Selector/RacyDeregister.java b/jdk/test/java/nio/channels/Selector/RacyDeregister.java new file mode 100644 index 00000000000..5a72df18107 --- /dev/null +++ b/jdk/test/java/nio/channels/Selector/RacyDeregister.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +/* + * @test + * @bug 6429204 + * @summary SelectionKey.interestOps does not update interest set on Windows. + * @author Frank Ding + */ +public class RacyDeregister { + + static boolean notified; + static final Object selectorLock = new Object(); + static final Object notifyLock = new Object(); + /** + * null: not terminated + * true: passed + * false: failed + */ + static volatile Boolean succTermination = null; + + public static void main(String[] args) throws Exception { + InetAddress addr = InetAddress.getByName(null); + ServerSocketChannel sc = ServerSocketChannel.open(); + sc.socket().bind(new InetSocketAddress(addr, 0)); + + SocketChannel.open(new InetSocketAddress(addr, + sc.socket().getLocalPort())); + + SocketChannel accepted = sc.accept(); + accepted.configureBlocking(false); + + SocketChannel.open(new InetSocketAddress(addr, + sc.socket().getLocalPort())); + SocketChannel accepted2 = sc.accept(); + accepted2.configureBlocking(false); + + final Selector sel = Selector.open(); + SelectionKey key2 = accepted2.register(sel, SelectionKey.OP_READ); + final SelectionKey[] key = new SelectionKey[]{ + accepted.register(sel, SelectionKey.OP_READ)}; + + + // thread that will be changing key[0].interestOps to OP_READ | OP_WRITE + new Thread() { + + public void run() { + try { + for (int k = 0; k < 15; k++) { + for (int i = 0; i < 10000; i++) { + synchronized (notifyLock) { + synchronized (selectorLock) { + sel.wakeup(); + key[0].interestOps(SelectionKey.OP_READ + | SelectionKey.OP_WRITE); + } + notified = false; + long beginTime = System.currentTimeMillis(); + while (true) { + notifyLock.wait(5000); + if (notified) { + break; + } + long endTime = System.currentTimeMillis(); + if (endTime - beginTime > 5000) { + succTermination = false; + // wake up main thread doing select() + sel.wakeup(); + return; + } + } + } + } + } + succTermination = true; + // wake up main thread doing select() + sel.wakeup(); + } catch (Exception e) { + System.out.println(e); + succTermination = true; + // wake up main thread doing select() + sel.wakeup(); + } + } + }.start(); + + // main thread will be doing registering/deregistering with the sel + while (true) { + sel.select(); + if (Boolean.TRUE.equals(succTermination)) { + System.out.println("Test passed"); + sel.close(); + sc.close(); + break; + } else if (Boolean.FALSE.equals(succTermination)) { + System.out.println("Failed to pass the test"); + sel.close(); + sc.close(); + throw new RuntimeException("Failed to pass the test"); + } + synchronized (selectorLock) { + } + if (sel.selectedKeys().contains(key[0]) && key[0].isWritable()) { + synchronized (notifyLock) { + notified = true; + notifyLock.notify(); + key[0].cancel(); + sel.selectNow(); + key2 = accepted2.register(sel, SelectionKey.OP_READ); + key[0] = accepted.register(sel, SelectionKey.OP_READ); + } + } + key2.cancel(); + sel.selectedKeys().clear(); + } + } +} diff --git a/jdk/test/java/nio/file/Files/CopyAndMove.java b/jdk/test/java/nio/file/Files/CopyAndMove.java index 48ecb0dfcbc..4853b0dcdf4 100644 --- a/jdk/test/java/nio/file/Files/CopyAndMove.java +++ b/jdk/test/java/nio/file/Files/CopyAndMove.java @@ -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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6917021 7006126 6950237 + * @bug 4313887 6838333 6917021 7006126 6950237 8006645 * @summary Unit test for java.nio.file.Files copy and move methods * @library .. * @build CopyAndMove PassThroughFileSystem @@ -37,6 +37,7 @@ import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; import java.io.*; import java.util.*; +import java.util.concurrent.TimeUnit; public class CopyAndMove { static final Random rand = new Random(); @@ -94,8 +95,8 @@ public class CopyAndMove { // check last modified time if not a symbolic link if (!attrs1.isSymbolicLink()) { - long time1 = attrs1.lastModifiedTime().toMillis(); - long time2 = attrs2.lastModifiedTime().toMillis(); + long time1 = attrs1.lastModifiedTime().to(TimeUnit.SECONDS); + long time2 = attrs2.lastModifiedTime().to(TimeUnit.SECONDS); if (time1 != time2) { System.err.format("File time for %s is %s\n", attrs1.fileKey(), attrs1.lastModifiedTime()); diff --git a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy index f6e312ec696..3ba44491aca 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy +++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy @@ -13,6 +13,7 @@ grant { permission java.io.FilePermission ".${/}-", "read,write,delete"; permission java.lang.RuntimePermission "createClassLoader"; + permission java.lang.RuntimePermission "getClassLoader"; permission java.lang.RuntimePermission "setContextClassLoader"; // used by TestLibrary to determine test environment diff --git a/jdk/test/java/rmi/testlibrary/JavaVM.java b/jdk/test/java/rmi/testlibrary/JavaVM.java index c363f8e4420..a1b169823cd 100644 --- a/jdk/test/java/rmi/testlibrary/JavaVM.java +++ b/jdk/test/java/rmi/testlibrary/JavaVM.java @@ -110,6 +110,14 @@ public class JavaVM { return TestLibrary.getExtraProperty("jcov.options",""); } + public void start(Runnable runnable) throws IOException { + if (runnable == null) { + throw new NullPointerException("Runnable cannot be null."); + } + + start(); + new JavaVMCallbackHandler(runnable).start(); + } /** * Exec the VM as specified in this object's constructor. @@ -183,4 +191,35 @@ public class JavaVM { start(); return waitFor(); } + + /** + * Handles calling the callback. + */ + private class JavaVMCallbackHandler extends Thread { + Runnable runnable; + + JavaVMCallbackHandler(Runnable runnable) { + this.runnable = runnable; + } + + + /** + * Wait for the Process to terminate and notify the callback. + */ + @Override + public void run() { + if (vm != null) { + try { + vm.waitFor(); + } catch(InterruptedException ie) { + // Restore the interrupted status + Thread.currentThread().interrupt(); + } + } + + if (runnable != null) { + runnable.run(); + } + } + } } diff --git a/jdk/test/java/util/Calendar/JavatimeTest.java b/jdk/test/java/util/Calendar/JavatimeTest.java index 5b9a7101805..d7b211705f4 100644 --- a/jdk/test/java/util/Calendar/JavatimeTest.java +++ b/jdk/test/java/util/Calendar/JavatimeTest.java @@ -23,7 +23,7 @@ /* *@test - *@bug 8007520 + *@bug 8007520 8008254 *@summary Test those bridge methods to/from java.time date/time classes */ @@ -53,13 +53,10 @@ public class JavatimeTest { int nanos = r.nextInt(NANOS_PER_SECOND); int nanos_ms = nanos / 1000000 * 1000000; // millis precision long millis = secs * 1000 + r.nextInt(1000); - LocalDateTime ldt = LocalDateTime.ofEpochSecond(secs, nanos, ZoneOffset.UTC); LocalDateTime ldt_ms = LocalDateTime.ofEpochSecond(secs, nanos_ms, ZoneOffset.UTC); Instant inst = Instant.ofEpochSecond(secs, nanos); Instant inst_ms = Instant.ofEpochSecond(secs, nanos_ms); - //System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); - ///////////// java.util.Date ///////////////////////// Date jud = new java.util.Date(millis); Instant inst0 = jud.toInstant(); @@ -77,6 +74,8 @@ public class JavatimeTest { } //////////// java.util.GregorianCalendar ///////////// GregorianCalendar cal = new GregorianCalendar(); + // non-roundtrip of tz name between j.u.tz and j.t.zid + cal.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault())); cal.setGregorianChange(new java.util.Date(Long.MIN_VALUE)); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setMinimalDaysInFirstWeek(4); @@ -84,6 +83,9 @@ public class JavatimeTest { ZonedDateTime zdt0 = cal.toZonedDateTime(); if (cal.getTimeInMillis() != zdt0.toInstant().toEpochMilli() || !cal.equals(GregorianCalendar.from(zdt0))) { + System.out.println("cal:" + cal); + System.out.println("zdt:" + zdt0); + System.out.println("calNew:" + GregorianCalendar.from(zdt0)); System.out.printf("ms: %16d ns: %10d ldt:[%s]%n", millis, nanos, ldt); throw new RuntimeException("FAILED: gcal -> zdt -> gcal"); } diff --git a/jdk/test/java/util/Collections/ReverseOrder.java b/jdk/test/java/util/Collections/ReverseOrder.java index d4fed080783..9831b57c5a5 100644 --- a/jdk/test/java/util/Collections/ReverseOrder.java +++ b/jdk/test/java/util/Collections/ReverseOrder.java @@ -23,23 +23,56 @@ /* * @test - * @bug 4593209 + * @bug 4593209 8001667 * @summary Reverse comparator was subtly broken * @author Josh bloch */ import java.util.*; +import java.io.*; public class ReverseOrder { + static byte[] serialBytes(Object o) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + oos.flush(); + oos.close(); + return bos.toByteArray(); + } catch (Throwable t) { + throw new Error(t); + } + } + + @SuppressWarnings("unchecked") + static T serialClone(T o) { + try { + ObjectInputStream ois = new ObjectInputStream + (new ByteArrayInputStream(serialBytes(o))); + T clone = (T) ois.readObject(); + return clone; + } catch (Throwable t) { + throw new Error(t); + } + } + public static void main(String[] args) throws Exception { Foo[] a = { new Foo(2), new Foo(3), new Foo(1) }; List list = Arrays.asList(a); - Collections.sort(list, Collections.reverseOrder()); + Comparator cmp = Collections.reverseOrder(); + Collections.sort(list, cmp); Foo[] golden = { new Foo(3), new Foo(2), new Foo(1) }; List goldenList = Arrays.asList(golden); if (!list.equals(goldenList)) throw new Exception(list.toString()); + + Comparator clone = serialClone(cmp); + List list2 = Arrays.asList(a); + Collections.sort(list2, clone); + if (!list2.equals(goldenList)) + throw new Exception(list.toString()); } } diff --git a/jdk/test/java/util/ComparatorsTest.java b/jdk/test/java/util/ComparatorsTest.java new file mode 100644 index 00000000000..1640c2d657a --- /dev/null +++ b/jdk/test/java/util/ComparatorsTest.java @@ -0,0 +1,353 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8001667 + * @run testng ComparatorsTest + */ + +import java.util.Comparator; +import java.util.Comparators; +import java.util.AbstractMap; +import java.util.Map; +import org.testng.annotations.Test; + +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import java.util.function.ToDoubleFunction; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertSame; + +/** + * Unit tests for helper methods in Comparators + */ +@Test(groups = "unit") +public class ComparatorsTest { + private static class Thing { + public final int intField; + public final long longField; + public final double doubleField; + public final String stringField; + + private Thing(int intField, long longField, double doubleField, String stringField) { + this.intField = intField; + this.longField = longField; + this.doubleField = doubleField; + this.stringField = stringField; + } + + public int getIntField() { + return intField; + } + + public long getLongField() { + return longField; + } + + public double getDoubleField() { + return doubleField; + } + + public String getStringField() { + return stringField; + } + } + + private final int[] intValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 }; + private final long[] longValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 }; + private final double[] doubleValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 }; + private final String[] stringValues = { "a", "a", "b", "b", "c", "c", "d", "d", "e", "e" }; + private final int[] comparisons = { 0, -1, 0, -1, 0, -1, 0, -1, 0 }; + + private void assertComparisons(T[] things, Comparator comp, int[] comparisons) { + for (int i=0; i comp = Comparators.comparing(new ToIntFunction() { + @Override + public int applyAsInt(Thing thing) { + return thing.getIntField(); + } + }); + + assertComparisons(things, comp, comparisons); + } + + public void testLongComparator() { + Thing[] things = new Thing[longValues.length]; + for (int i=0; i comp = Comparators.comparing(new ToLongFunction() { + @Override + public long applyAsLong(Thing thing) { + return thing.getLongField(); + } + }); + + assertComparisons(things, comp, comparisons); + } + + public void testDoubleComparator() { + Thing[] things = new Thing[doubleValues.length]; + for (int i=0; i comp = Comparators.comparing(new ToDoubleFunction() { + @Override + public double applyAsDouble(Thing thing) { + return thing.getDoubleField(); + } + }); + + assertComparisons(things, comp, comparisons); + } + + public void testComparing() { + Thing[] things = new Thing[doubleValues.length]; + for (int i=0; i comp = Comparators.comparing(new Function() { + @Override + public String apply(Thing thing) { + return thing.getStringField(); + } + }); + + assertComparisons(things, comp, comparisons); + } + + public void testNaturalOrderComparator() { + Comparator comp = Comparators.naturalOrder(); + + assertComparisons(stringValues, comp, comparisons); + } + + public void testReverseComparator() { + Comparator cmpr = Comparators.reverseOrder(); + Comparator cmp = cmpr.reverseOrder(); + + assertEquals(cmp.reverseOrder(), cmpr); + assertEquals(0, cmp.compare("a", "a")); + assertEquals(0, cmpr.compare("a", "a")); + assertTrue(cmp.compare("a", "b") < 0); + assertTrue(cmpr.compare("a", "b") > 0); + assertTrue(cmp.compare("b", "a") > 0); + assertTrue(cmpr.compare("b", "a") < 0); + } + + public void testReverseComparator2() { + Comparator cmp = (s1, s2) -> s1.length() - s2.length(); + Comparator cmpr = cmp.reverseOrder(); + + assertEquals(cmpr.reverseOrder(), cmp); + assertEquals(0, cmp.compare("abc", "def")); + assertEquals(0, cmpr.compare("abc", "def")); + assertTrue(cmp.compare("abcd", "def") > 0); + assertTrue(cmpr.compare("abcd", "def") < 0); + assertTrue(cmp.compare("abc", "defg") < 0); + assertTrue(cmpr.compare("abc", "defg") > 0); + } + + @Test(expectedExceptions=NullPointerException.class) + public void testReverseComparatorNPE() { + Comparator cmp = Comparators.reverseOrder(null); + } + + public void testComposeComparator() { + // Longer string in front + Comparator first = (s1, s2) -> s2.length() - s1.length(); + Comparator second = Comparators.naturalOrder(); + Comparator composed = Comparators.compose(first, second); + + assertTrue(composed.compare("abcdefg", "abcdef") < 0); + assertTrue(composed.compare("abcdef", "abcdefg") > 0); + assertTrue(composed.compare("abcdef", "abcdef") == 0); + assertTrue(composed.compare("abcdef", "ghijkl") < 0); + assertTrue(composed.compare("ghijkl", "abcdefg") > 0); + } + + private void assertPairComparison(K k1, V v1, K k2, V v2, + Comparator> ck, + Comparator> cv) { + final Map.Entry p11 = new AbstractMap.SimpleImmutableEntry<>(k1, v1); + final Map.Entry p12 = new AbstractMap.SimpleImmutableEntry<>(k1, v2); + final Map.Entry p21 = new AbstractMap.SimpleImmutableEntry<>(k2, v1); + final Map.Entry p22 = new AbstractMap.SimpleImmutableEntry<>(k2, v2); + + assertTrue(ck.compare(p11, p11) == 0); + assertTrue(ck.compare(p12, p11) == 0); + assertTrue(ck.compare(p11, p12) == 0); + assertTrue(ck.compare(p12, p22) < 0); + assertTrue(ck.compare(p12, p21) < 0); + assertTrue(ck.compare(p21, p11) > 0); + assertTrue(ck.compare(p21, p12) > 0); + + assertTrue(cv.compare(p11, p11) == 0); + assertTrue(cv.compare(p12, p11) > 0); + assertTrue(cv.compare(p11, p12) < 0); + assertTrue(cv.compare(p12, p22) == 0); + assertTrue(cv.compare(p12, p21) > 0); + assertTrue(cv.compare(p21, p11) == 0); + assertTrue(cv.compare(p21, p12) < 0); + + Comparator> cmp = Comparators.compose(ck, cv); + assertTrue(cmp.compare(p11, p11) == 0); + assertTrue(cmp.compare(p12, p11) > 0); + assertTrue(cmp.compare(p11, p12) < 0); + assertTrue(cmp.compare(p12, p22) < 0); + assertTrue(cmp.compare(p12, p21) < 0); + assertTrue(cmp.compare(p21, p11) > 0); + assertTrue(cmp.compare(p21, p12) > 0); + + cmp = Comparators.compose(cv, ck); + assertTrue(cmp.compare(p11, p11) == 0); + assertTrue(cmp.compare(p12, p11) > 0); + assertTrue(cmp.compare(p11, p12) < 0); + assertTrue(cmp.compare(p12, p22) < 0); + assertTrue(cmp.compare(p12, p21) > 0); + assertTrue(cmp.compare(p21, p11) > 0); + assertTrue(cmp.compare(p21, p12) < 0); + } + + public void testKVComparatorable() { + assertPairComparison(1, "ABC", 2, "XYZ", + Comparators.naturalOrderKeys(), + Comparators.naturalOrderValues()); + } + + private static class People { + final String firstName; + final String lastName; + final int age; + + People(String first, String last, int age) { + firstName = first; + lastName = last; + this.age = age; + } + + String getFirstName() { return firstName; } + String getLastName() { return lastName; } + int getAge() { return age; } + long getAgeAsLong() { return (long) age; }; + double getAgeAsDouble() { return (double) age; }; + } + + private final People people[] = { + new People("John", "Doe", 34), + new People("Mary", "Doe", 30), + new People("Maria", "Doe", 14), + new People("Jonah", "Doe", 10), + new People("John", "Cook", 54), + new People("Mary", "Cook", 50), + }; + + public void testKVComparators() { + // Comparator cmp = Comparators.naturalOrder(); // Should fail to compiler as People is not comparable + // We can use simple comparator, but those have been tested above. + // Thus choose to do compose for some level of interation. + Comparator cmp1 = Comparators.comparing((Function) People::getFirstName); + Comparator cmp2 = Comparators.comparing((Function) People::getLastName); + Comparator cmp = Comparators.compose(cmp1, cmp2); + + assertPairComparison(people[0], people[0], people[1], people[1], + Comparators.byKey(cmp), + Comparators.byValue(cmp)); + + } + + private void assertComparison(Comparator cmp, T less, T greater) { + assertTrue(cmp.compare(less, greater) < 0, "less"); + assertTrue(cmp.compare(less, less) == 0, "equal"); + assertTrue(cmp.compare(greater, less) > 0, "greater"); + } + + public void testComparatorDefaultMethods() { + Comparator cmp = Comparators.comparing((Function) People::getFirstName); + Comparator cmp2 = Comparators.comparing((Function) People::getLastName); + // reverseOrder + assertComparison(cmp.reverseOrder(), people[1], people[0]); + // thenComparing(Comparator) + assertComparison(cmp.thenComparing(cmp2), people[0], people[1]); + assertComparison(cmp.thenComparing(cmp2), people[4], people[0]); + // thenComparing(Function) + assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]); + assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]); + // thenComparing(ToIntFunction) + assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]); + assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]); + // thenComparing(ToLongFunction) + assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]); + assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]); + // thenComparing(ToDoubleFunction) + assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]); + assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]); + } + + public void testGreaterOf() { + // lesser + assertSame(Comparators.greaterOf(Comparators.comparing( + (Function) People::getFirstName)) + .apply(people[0], people[1]), + people[1]); + // euqal + assertSame(Comparators.greaterOf(Comparators.comparing( + (Function) People::getLastName)) + .apply(people[0], people[1]), + people[0]); + // greater + assertSame(Comparators.greaterOf(Comparators.comparing( + (ToIntFunction) People::getAge)) + .apply(people[0], people[1]), + people[0]); + } + + public void testLesserOf() { + // lesser + assertSame(Comparators.lesserOf(Comparators.comparing( + (Function) People::getFirstName)) + .apply(people[0], people[1]), + people[0]); + // euqal + assertSame(Comparators.lesserOf(Comparators.comparing( + (Function) People::getLastName)) + .apply(people[0], people[1]), + people[0]); + // greater + assertSame(Comparators.lesserOf(Comparators.comparing( + (ToIntFunction) People::getAge)) + .apply(people[0], people[1]), + people[1]); + } +} \ No newline at end of file diff --git a/jdk/test/java/util/Locale/Bug8004240.java b/jdk/test/java/util/Locale/Bug8004240.java new file mode 100644 index 00000000000..84f291b93ba --- /dev/null +++ b/jdk/test/java/util/Locale/Bug8004240.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004240 + * @summary Verify that getAdapterPreference returns an unmodifiable list. + * @compile -XDignore.symbol.file Bug8004240.java + * @run main Bug8004240 + */ + +import java.util.List; +import sun.util.locale.provider.LocaleProviderAdapter; + +public class Bug8004240 { + + public static void main(String[] args) { + List types = LocaleProviderAdapter.getAdapterPreference(); + + try { + types.set(0, null); + } catch (UnsupportedOperationException e) { + // success + return; + } + + throw new RuntimeException("LocaleProviderAdapter.getAdapterPrefence() returned a modifiable list."); + } +} diff --git a/jdk/test/java/util/Map/ToArray.java b/jdk/test/java/util/Map/ToArray.java new file mode 100644 index 00000000000..f7a8de716cf --- /dev/null +++ b/jdk/test/java/util/Map/ToArray.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8008785 + * @summary Ensure toArray() implementations return correct results. + * @author Mike Duigou + */ +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; + +public class ToArray { + + /** + * Number of elements per map. + */ + private static final int TEST_SIZE = 5000; + + private static void realMain(String[] args) throws Throwable { + Map[] maps = (Map[]) new Map[]{ + new HashMap<>(), + new Hashtable<>(), + new IdentityHashMap<>(), + new LinkedHashMap<>(), + new TreeMap<>(), + new WeakHashMap<>(), + new ConcurrentHashMap<>(), + new ConcurrentSkipListMap<>() + }; + + // for each map type. + for (Map map : maps) { + try { + testMap(map); + } catch(Exception all) { + unexpected("Failed for " + map.getClass().getName(), all); + } + } + } + + private static final Integer[] KEYS = new Integer[TEST_SIZE]; + + private static final Long[] VALUES = new Long[TEST_SIZE]; + + static { + for (int each = 0; each < TEST_SIZE; each++) { + KEYS[each] = Integer.valueOf(each); + VALUES[each] = Long.valueOf(each + TEST_SIZE); + } + } + + + private static void testMap(Map map) { + System.out.println("Testing " + map.getClass()); + System.out.flush(); + + // Fill the map + for (int each = 0; each < TEST_SIZE; each++) { + map.put(KEYS[each], VALUES[each]); + } + + // check the keys + Object[] keys = map.keySet().toArray(); + Arrays.sort(keys); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected key", keys[each] == KEYS[each]); + } + + // check the values + Object[] values = map.values().toArray(); + Arrays.sort(values); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected value", values[each] == VALUES[each]); + } + + // check the entries + Map.Entry[] entries = map.entrySet().toArray(new Map.Entry[TEST_SIZE]); + Arrays.sort( entries,new Comparator>() { + public int compare(Map.Entry o1, Map.Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + }}); + + for(int each = 0; each < TEST_SIZE; each++) { + check( "unexpected entry", entries[each].getKey() == KEYS[each] && entries[each].getValue() == VALUES[each]); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + + static void pass() { + passed++; + } + + static void fail() { + failed++; + (new Error("Failure")).printStackTrace(System.err); + } + + static void fail(String msg) { + failed++; + (new Error("Failure: " + msg)).printStackTrace(System.err); + } + + static void abort() { + fail(); + System.exit(1); + } + + static void abort(String msg) { + fail(msg); + System.exit(1); + } + + static void unexpected(String msg, Throwable t) { + System.err.println("Unexpected: " + msg); + unexpected(t); + } + + static void unexpected(Throwable t) { + failed++; + t.printStackTrace(System.err); + } + + static void check(boolean cond) { + if (cond) { + pass(); + } else { + fail(); + } + } + + static void check(String desc, boolean cond) { + if (cond) { + pass(); + } else { + fail(desc); + } + } + + static void equal(Object x, Object y) { + if (Objects.equals(x, y)) { + pass(); + } else { + fail(x + " not equal to " + y); + } + } + + public static void main(String[] args) throws Throwable { + Thread.currentThread().setName(ToArray.class.getName()); +// Thread.currentThread().setPriority(Thread.MAX_PRIORITY); + try { + realMain(args); + } catch (Throwable t) { + unexpected(t); + } + + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) { + throw new Error("Some tests failed"); + } + } +} diff --git a/jdk/test/java/util/concurrent/forkjoin/ThreadLessCommon.java b/jdk/test/java/util/concurrent/forkjoin/ThreadLessCommon.java new file mode 100644 index 00000000000..1dd3b660f60 --- /dev/null +++ b/jdk/test/java/util/concurrent/forkjoin/ThreadLessCommon.java @@ -0,0 +1,135 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8008378 + * @summary Basic checks for parallelism 0, and null returning factory + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 ThreadLessCommon + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.threadFactory=ThreadLessCommon$NullForkJoinWorkerThreadFactory ThreadLessCommon + * @author Chris Hegarty + */ + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.RecursiveTask; + +public class ThreadLessCommon { + + static final int THRESHOLD = 1000; + static final boolean debug = true; + + private static void realMain(String[] args) throws Throwable { + if (debug) { + String pp = System.getProperty( + "java.util.concurrent.ForkJoinPool.common.parallelism"); + System.out.println( + "java.util.concurrent.ForkJoinPool.common.parallelism:" + pp); + String tf = System.getProperty( + "java.util.concurrent.ForkJoinPool.common.threadFactory"); + System.out.println( + "java.util.concurrent.ForkJoinPool.common.threadFactory:" + tf); + } + + long from = 0, to = 50000; + RecursiveTask task = new SumTask(from, to, Thread.currentThread()); + long sum = task.invoke(); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + + task.fork(); + sum = task.join(); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + + sum = ForkJoinPool.commonPool().invoke(task.fork()); + System.out.printf("%nSum: from [%d] to [%d] = [%d]%n", from, to, sum); + } + + static class SumTask extends RecursiveTask { + final Thread expectedThread; + final long from; + final long to; + SumTask(long from, long to, Thread thread) { + this.from = from; this.to = to; expectedThread = thread; + } + + @Override + public Long compute() { + check(Thread.currentThread() == expectedThread, + "Expected " + expectedThread + ", got " + Thread.currentThread()); + long range = to - from; + if (range < THRESHOLD) { + long acc = 0; + for (long i = from; i <= to; i++) + acc = acc + i; + return acc; + } else { + long half = from + range / 2; + SumTask t1 = new SumTask(from, half ,expectedThread); + SumTask t2 = new SumTask(half+1, to ,expectedThread); + if (half % 2 == 0) { + t1.fork(); + return t2.compute() + t1.join(); + } else { + invokeAll(t1, t2); + try { return t1.get() + t2.get(); } + catch (Exception x) { unexpected(x); return 0L;} + } + } + } + } + + public static class NullForkJoinWorkerThreadFactory + implements ForkJoinWorkerThreadFactory + { + @Override + public ForkJoinWorkerThread newThread(ForkJoinPool pool) { + return null; + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; /*Thread.dumpStack();*/} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond, String msg) {if (cond) pass(); else fail(msg);} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/concurrent/forkjoin/ThrowingRunnable.java b/jdk/test/java/util/concurrent/forkjoin/ThrowingRunnable.java new file mode 100644 index 00000000000..47e6f3543db --- /dev/null +++ b/jdk/test/java/util/concurrent/forkjoin/ThrowingRunnable.java @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* + * @test + * @bug 8008378 + * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.exceptionHandler=ThrowingRunnable + * ThrowingRunnable + * @summary FJP.execute(Runnable), uncaught exception should cause worker thread + * to die. + * @author Chris Hegarty + */ + +import java.lang.Thread.UncaughtExceptionHandler; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; + +public class ThrowingRunnable implements Runnable, UncaughtExceptionHandler { + + static final Phaser phaser = new Phaser(2); + + private static void realMain(String[] args) throws Throwable { + ThrowingRunnable r = new ThrowingRunnable(); + ForkJoinPool.commonPool().execute(r); + phaser.awaitAdvanceInterruptibly(phaser.arrive(), 10, TimeUnit.SECONDS); + pass(); + } + + @Override + public void run() { + throw new RuntimeException("This is an exception."); + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + pass(); + phaser.arrive(); + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; /*Thread.dumpStack();*/} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond, String msg) {if (cond) pass(); else fail(msg);} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/logging/CustomLogManager.java b/jdk/test/java/util/logging/CustomLogManager.java new file mode 100644 index 00000000000..9542e54ec02 --- /dev/null +++ b/jdk/test/java/util/logging/CustomLogManager.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; +import java.util.logging.*; + +/* + * Custom LogManager implementation to verify that the implementation delegates + * to the LogManager subclass to register both system logger and user logger. + * + * The LogManager implementation is the one configuring the logger's property + * such as level, handler, etc. + */ +public class CustomLogManager extends LogManager { + static LogManager INSTANCE; + Map namedLoggers = new HashMap<>(); + Properties props = initConfig(); + public CustomLogManager() { + if (INSTANCE != null) { + throw new RuntimeException("CustomLogManager already created"); + } + INSTANCE = this; + } + + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + namedLoggers.put(name, logger); + // set level + if (props.get(name + ".level") != null) { + logger.setLevel(Level.parse(props.getProperty(name + ".level"))); + } + // add handlers + if (props.get(name + ".handlers") != null && logger.getHandlers().length == 0) { + logger.addHandler(new CustomHandler()); + } + // add parent loggers + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (props.get(pname + ".level") != null || + props.get(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + // + // The test doesn't set the parent for simplicity. + if (!namedLoggers.containsKey(pname)) { + Logger.getLogger(pname); + } + } + ix = ix2 + 1; + } + return true; + } + + public synchronized Logger getLogger(String name) { + return namedLoggers.get(name); + } + + public synchronized Enumeration getLoggerNames() { + return Collections.enumeration(namedLoggers.keySet()); + } + + public String getProperty(String name) { + return props.getProperty(name); + } + + public void readConfiguration() { + // do nothing + } + + public void readConfiguration(InputStream ins) { + // do nothing + } + + private Properties initConfig() { + Properties props = new Properties(); + props.put(".level", "CONFIG"); + props.put("CustomLogManagerTest.level", "WARNING"); + props.put("CustomLogManagerTest.handlers", "CustomLogManager$CustomHandler"); + props.put("SimpleLogManager.level", "INFO"); + props.put("SimpleLogManager.handlers", "CustomLogManager$CustomHandler"); + props.put("CustomLogManager$CustomHandler.level", "WARNING"); + props.put(".handlers", "CustomLogManager$CustomHandler"); + props.put("org.foo.bar.level", "SEVERE"); + props.put("org.foo.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.level", "SEVERE"); + props.put("org.openjdk.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.core.level", "INFO"); + + return props; + } + + public static void checkLogger(String name) { + checkLogger(name, null); + } + + public static void checkLogger(String name, String resourceBundleName) { + Logger logger = INSTANCE.getLogger(name); + if (logger == null) { + throw new RuntimeException("Logger \"" + name + "\" not exist"); + } + System.out.format("Logger \"%s\" level=%s handlers=%s resourcebundle=%s%n", + name, logger.getLevel(), + Arrays.toString(logger.getHandlers()), + logger.getResourceBundleName()); + String rb = logger.getResourceBundleName(); + if (rb != resourceBundleName && (rb == null || rb.equals(resourceBundleName))) { + throw new RuntimeException("Logger \"" + name + + "\" unexpected resource bundle: " + rb); + } + + String value = INSTANCE.getProperty(name + ".level"); + String level = logger.getLevel() != null ? logger.getLevel().getName() : null; + if (level != value && (level == null || level.equals(value))) { + throw new RuntimeException("Logger \"" + name + "\" unexpected level: " + level); + } + + Handler[] handlers = logger.getHandlers(); + String hdl = INSTANCE.getProperty(name + ".handlers"); + if ((hdl == null && handlers.length != 0) || + (hdl != null && handlers.length != 1)) { + throw new RuntimeException("Logger \"" + name + "\" unexpected handler: " + + Arrays.toString(handlers)); + } + checkParents(name); + } + + private static void checkParents(String name) { + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (INSTANCE.getProperty(pname + ".level") != null || + INSTANCE.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + checkLogger(pname); + } + ix = ix2 + 1; + } + } + + // only CustomLogManager can create an instance of CustomHandler + private class CustomHandler extends StreamHandler { + } +} diff --git a/jdk/test/java/util/logging/CustomLogManagerTest.java b/jdk/test/java/util/logging/CustomLogManagerTest.java new file mode 100644 index 00000000000..2fa89a9a47b --- /dev/null +++ b/jdk/test/java/util/logging/CustomLogManagerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; + +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary Add loggers to custom log manager + * + * @compile -XDignore.symbol.file CustomLogManagerTest.java CustomLogManager.java + * @run main/othervm -Djava.util.logging.manager=CustomLogManager CustomLogManagerTest + */ +public class CustomLogManagerTest { + private static final String RESOURCE_BUNDLE = "sun.util.logging.resources.logging"; + public static void main(String[] args) { + String mgr = System.getProperty("java.util.logging.manager"); + if (!mgr.equals("CustomLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger.getLogger(CustomLogManagerTest.class.getName()); + Logger.getLogger("org.foo.Foo"); + Logger.getLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + // platform logger will be set with the default system resource bundle + PlatformLogger.getLogger("org.openjdk.core.logger"); + + if (LogManager.getLogManager() != CustomLogManager.INSTANCE) { + throw new RuntimeException(LogManager.getLogManager() + " not CustomLogManager"); + } + + CustomLogManager.checkLogger(CustomLogManagerTest.class.getName()); + CustomLogManager.checkLogger("org.foo.Foo"); + CustomLogManager.checkLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + CustomLogManager.checkLogger(Logger.GLOBAL_LOGGER_NAME); + CustomLogManager.checkLogger(""); + CustomLogManager.checkLogger("org.openjdk.core.logger", RESOURCE_BUNDLE); + } +} diff --git a/jdk/test/java/util/logging/SimpleLogManager.java b/jdk/test/java/util/logging/SimpleLogManager.java new file mode 100644 index 00000000000..f469727654f --- /dev/null +++ b/jdk/test/java/util/logging/SimpleLogManager.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.*; +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary A LogManager subclass overrides its own implementation of named + * logger (see the subclassing information in the Logger class specification) + * + * @compile -XDignore.symbol.file CustomLogManager.java SimpleLogManager.java + * @run main/othervm -Djava.util.logging.manager=SimpleLogManager SimpleLogManager + */ +public class SimpleLogManager extends CustomLogManager { + public static void main(String[] args) { + String classname = System.getProperty("java.util.logging.manager"); + if (!classname.equals("SimpleLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger logger = Logger.getLogger(SimpleLogManager.class.getName()); + Logger.getLogger("org.foo.bar.Foo"); + + // a platform logger used by the system code is just a Logger instance. + PlatformLogger.getLogger("org.openjdk.core.logger"); + + LogManager mgr = LogManager.getLogManager(); + if (mgr != CustomLogManager.INSTANCE || !(mgr instanceof SimpleLogManager)) { + throw new RuntimeException(LogManager.getLogManager() + " not SimpleLogManager"); + } + + checkCustomLogger(SimpleLogManager.class.getName(), null); + checkCustomLogger("org.foo.bar.Foo", null); + checkCustomLogger("org.openjdk.core.logger", "sun.util.logging.resources.logging"); + + // ## The LogManager.demandLogger method does not handle custom log manager + // ## that overrides the getLogger method to return a custom logger + // ## (see the test case in 8005640). Logger.getLogger may return + // ## a Logger instance but LogManager overrides it with a custom Logger + // ## instance like this case. + // + // However, the specification of LogManager and Logger subclassing is + // not clear whether this is supported or not. The following check + // just captures the current behavior. + if (logger instanceof CustomLogger) { + throw new RuntimeException(logger + " not CustomLogger"); + } + } + + private static void checkCustomLogger(String name, String resourceBundleName) { + CustomLogManager.checkLogger(name, resourceBundleName); + Logger logger1 = Logger.getLogger(name); + Logger logger2 = LogManager.getLogManager().getLogger(name); + if (logger1 != logger2) { + throw new RuntimeException(logger1 + " != " + logger2); + } + if (!(logger1 instanceof CustomLogger)) { + throw new RuntimeException(logger1 + " not CustomLogger"); + } + } + + /* + * This SimpleLogManager overrides the addLogger method to replace + * the given logger with a custom logger. + * + * It's unclear what the recommended way to use custom logger is. + * A LogManager subclass might override the getLogger method to return + * a custom Logger and create a new custom logger if not exist so that + * Logger.getLogger() can return a custom Logger instance but that violates + * the LogManager.getLogger() spec which should return null if not found. + */ + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + CustomLogger newLogger = new CustomLogger(logger); + super.addLogger(newLogger); + return true; + } + + public class CustomLogger extends Logger { + CustomLogger(Logger logger) { + super(logger.getName(), logger.getResourceBundleName()); + } + CustomLogger(String name) { + super(name, null); + } + } +} diff --git a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java index ff56c46fbd2..d91ae14ba57 100644 --- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java +++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java @@ -119,9 +119,6 @@ public class SubjectDelegation2Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("monitorRole"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -132,6 +129,9 @@ public class SubjectDelegation2Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); diff --git a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java index b3a004e0467..de169987796 100644 --- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java +++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java @@ -120,9 +120,6 @@ public class SubjectDelegation3Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("delegate"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -133,6 +130,9 @@ public class SubjectDelegation3Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); diff --git a/jdk/test/javax/script/CauseExceptionTest.java b/jdk/test/javax/script/CauseExceptionTest.java index f1ff708bc1e..41fa5e4b493 100644 --- a/jdk/test/javax/script/CauseExceptionTest.java +++ b/jdk/test/javax/script/CauseExceptionTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 6869617 - * @summary RhinoScriptEngine bug : ScriptException cause not set (with fix) + * @summary ScriptEngine bug : ScriptException cause not set (with fix) */ import javax.script.*; @@ -33,12 +33,12 @@ import java.io.*; public class CauseExceptionTest { public static void main(String[] args) throws ScriptException, NoSuchMethodException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { System.out.println("Warning: No js engine found; test vacuously passes."); return; } - engine.eval("function hello_world() { println('hello world'); throw 'out of here'; } "); + engine.eval("function hello_world() { print('hello world'); throw 'out of here'; } "); Invocable invocable = (Invocable) engine; try { invocable.invokeFunction("hello_world", (Object[])null); diff --git a/jdk/test/javax/script/RhinoExceptionTest.java b/jdk/test/javax/script/ExceptionTest.java similarity index 96% rename from jdk/test/javax/script/RhinoExceptionTest.java rename to jdk/test/javax/script/ExceptionTest.java index 22d5f0fd6fb..9ea2d4e3f7a 100644 --- a/jdk/test/javax/script/RhinoExceptionTest.java +++ b/jdk/test/javax/script/ExceptionTest.java @@ -24,14 +24,14 @@ /* * @test * @bug 6474943 6705893 - * @summary Test that Rhino exception messages are + * @summary Test that script engine exception messages are * available from ScriptException. */ import java.io.*; import javax.script.*; -public class RhinoExceptionTest { +public class ExceptionTest { private static final String ERROR_MSG = "error from JavaScript"; public static void main(String[] args) throws Exception { diff --git a/jdk/test/javax/script/GetInterfaceTest.java b/jdk/test/javax/script/GetInterfaceTest.java index d780a6db08b..dffc74ea3b4 100644 --- a/jdk/test/javax/script/GetInterfaceTest.java +++ b/jdk/test/javax/script/GetInterfaceTest.java @@ -22,6 +22,7 @@ */ /* + * @run ignore * @test * @bug 6960211 * @summary JavaScript engine allows creation of interface although methods not available. @@ -32,10 +33,10 @@ import javax.script.*; public class GetInterfaceTest { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("js"); + ScriptEngine engine = manager.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No engine engine found; test vacuously passes."); + System.out.println("Warning: No js engine engine found; test vacuously passes."); return; } diff --git a/jdk/test/javax/script/Helper.java b/jdk/test/javax/script/Helper.java index 73617bf5e93..fc132a457d1 100644 --- a/jdk/test/javax/script/Helper.java +++ b/jdk/test/javax/script/Helper.java @@ -24,13 +24,13 @@ import javax.script.*; /** * Helper class to consolidate testing requirements for a js engine. - * A js engine is required as part of Sun's product JDK. + * A js engine is required as part of Oracle's product JDK. */ public class Helper { private Helper() {}; // Don't instantiate public static ScriptEngine getJsEngine(ScriptEngineManager m) { - ScriptEngine e = m.getEngineByName("js"); + ScriptEngine e = m.getEngineByName("nashorn"); if (e == null && System.getProperty("java.runtime.name").startsWith("Java(TM)")) { // A js engine is requied for Sun's product JDK diff --git a/jdk/test/javax/script/StringWriterPrintTest.java b/jdk/test/javax/script/StringWriterPrintTest.java index 42345791878..7a75b6f0396 100644 --- a/jdk/test/javax/script/StringWriterPrintTest.java +++ b/jdk/test/javax/script/StringWriterPrintTest.java @@ -33,9 +33,9 @@ import java.io.*; public class StringWriterPrintTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No js engine found; test vacuously passes."); + System.out.println("Warning: No nashorn engine found; test vacuously passes."); return; } StringWriter sw = new StringWriter(); diff --git a/jdk/test/javax/script/Test3.js b/jdk/test/javax/script/Test3.js index 4cdb8286843..5f7aba45e93 100644 --- a/jdk/test/javax/script/Test3.js +++ b/jdk/test/javax/script/Test3.js @@ -1,22 +1,24 @@ +var ScriptContext = javax.script.ScriptContext; + if (key == undefined || key != 'engine value') { throw "unexpected engine scope value"; } // pre-defined context variable refers to current ScriptContext -if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') { +if (context.getAttribute('key', ScriptContext.GLOBAL_SCOPE) != 'global value') { throw "unexpected global scope value"; } // change the engine scope value key = 'new engine value'; -if (context.getAttribute('key', context.GLOBAL_SCOPE) != 'global value') { +if (context.getAttribute('key', ScriptContext.GLOBAL_SCOPE) != 'global value') { throw "global scope should not change here"; } // delete engine scope value delete key; -if (key == undefined && key != 'xglobal value') { +if (key == undefined && key != 'global value') { throw 'global scope should be visible after engine scope removal'; } diff --git a/jdk/test/javax/script/Test5.java b/jdk/test/javax/script/Test5.java index 107bd148b63..acdd3a47448 100644 --- a/jdk/test/javax/script/Test5.java +++ b/jdk/test/javax/script/Test5.java @@ -48,16 +48,24 @@ public class Test5 { System.out.println("engine scope only"); e.put("count", new Integer(1)); - Reader reader = new FileReader( - new File(System.getProperty("test.src", "."), "Test5.js")); - engine.eval(reader,ctxt); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } + System.out.println("both scopes"); ctxt.setBindings(g, ScriptContext.GLOBAL_SCOPE); e.put("count", new Integer(2)); - engine.eval(reader,ctxt); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } System.out.println("only global"); e.put("count", new Integer(3)); - ctxt.setAttribute("key", null, ScriptContext.ENGINE_SCOPE); - engine.eval(reader,ctxt); + ctxt.removeAttribute("key", ScriptContext.ENGINE_SCOPE); + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test5.js"))) { + engine.eval(reader,ctxt); + } } } diff --git a/jdk/test/javax/script/Test5.js b/jdk/test/javax/script/Test5.js index c607cbc8604..708b482d00c 100644 --- a/jdk/test/javax/script/Test5.js +++ b/jdk/test/javax/script/Test5.js @@ -1,6 +1,5 @@ -var key; -var count; +var ScriptContext = javax.script.ScriptContext; print(count); switch (count) { @@ -9,7 +8,7 @@ switch (count) { if (key != 'value in engine') { throw "unexpected engine scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != null) { + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != null) { throw "unexpected global scope value"; } break; @@ -19,7 +18,7 @@ switch (count) { if (key != 'value in engine') { throw "unexpected engine scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != "value in global") { throw "unexpected global scope value"; } @@ -30,7 +29,7 @@ switch (count) { if (key != 'value in global') { throw "unexpected global scope value"; } - if (context.getAttribute("key", context.GLOBAL_SCOPE ) != + if (context.getAttribute("key", ScriptContext.GLOBAL_SCOPE ) != "value in global") { throw "unexpected global scope value"; } diff --git a/jdk/test/javax/script/Test6.java b/jdk/test/javax/script/Test6.java index 82758879fdb..5582b0a9025 100644 --- a/jdk/test/javax/script/Test6.java +++ b/jdk/test/javax/script/Test6.java @@ -40,11 +40,23 @@ public class Test6 { System.out.println("Warning: No js engine found; test vacuously passes."); return; } - Reader reader = new FileReader( - new File(System.getProperty("test.src", "."), "Test6.js")); - engine.eval(reader); + + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test6.js"))) { + engine.eval(reader); + } Object res = engine.get("res"); - CompiledScript scr = ((Compilable)engine).compile(reader); + + CompiledScript scr = null; + try (Reader reader = new FileReader( + new File(System.getProperty("test.src", "."), "Test6.js"))) { + scr = ((Compilable)engine).compile(reader); + } + + if (scr == null) { + throw new RuntimeException("compilation failed!"); + } + scr.eval(); Object res1 = engine.get("res"); if (! res.equals(res1)) { diff --git a/jdk/test/javax/script/Test7.js b/jdk/test/javax/script/Test7.js index b1ec2a8fd9f..d79db96067d 100644 --- a/jdk/test/javax/script/Test7.js +++ b/jdk/test/javax/script/Test7.js @@ -1,9 +1,14 @@ //this is the first line of Test7.js var filename; +try { + load("nashorn:mozilla_compat.js"); +} catch (e) { + //ignored +} importPackage(java.io); importPackage(java); var f = new File(filename); var r = new BufferedReader(new InputStreamReader(new FileInputStream(f))); -var firstLine = r.readLine() + ''; +var firstLine = r.readLine(); print(firstLine); diff --git a/jdk/test/javax/script/UnescapedBracketRegExTest.java b/jdk/test/javax/script/UnescapedBracketRegExTest.java index f2a807065f7..472ae107ed9 100644 --- a/jdk/test/javax/script/UnescapedBracketRegExTest.java +++ b/jdk/test/javax/script/UnescapedBracketRegExTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 7012701 - * @summary 7012701 Add a test to check that Rhino's RegExp parser accepts unescaped '[' + * @summary 7012701 Add a test to check that RegExp parser accepts unescaped '[' */ import javax.script.*; @@ -33,9 +33,9 @@ import java.io.*; public class UnescapedBracketRegExTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine engine = sem.getEngineByName("js"); + ScriptEngine engine = sem.getEngineByName("nashorn"); if (engine == null) { - System.out.println("Warning: No js engine found; test vacuously passes."); + System.out.println("Warning: No nashorn engine found; test vacuously passes."); return; } // the following throws exception diff --git a/jdk/test/javax/script/VersionTest.java b/jdk/test/javax/script/VersionTest.java index 374f43be51c..87fa8bcfa51 100644 --- a/jdk/test/javax/script/VersionTest.java +++ b/jdk/test/javax/script/VersionTest.java @@ -31,9 +31,7 @@ import javax.script.*; import java.io.*; public class VersionTest { - - private static final String JS_LANG_VERSION = "1.8"; - private static final String JS_ENGINE_VERSION = "1.7 release 3 PRERELEASE"; + private static final String JS_LANG_VERSION = "ECMA - 262 Edition 5.1"; public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); @@ -48,9 +46,18 @@ public class VersionTest { JS_LANG_VERSION); } String engineVersion = jsengine.getFactory().getEngineVersion(); - if (! engineVersion.equals(JS_ENGINE_VERSION)) { - throw new RuntimeException("Expected Rhino version is " + - JS_ENGINE_VERSION); + String expectedVersion = getNashornVersion(); + if (! engineVersion.equals(expectedVersion)) { + throw new RuntimeException("Expected version is " + expectedVersion); + } + } + + private static String getNashornVersion() { + try { + Class versionClass = Class.forName("jdk.nashorn.internal.runtime.Version"); + return (String) versionClass.getMethod("version").invoke(null); + } catch (Exception e) { + return "Version Unknown!"; } } } diff --git a/jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java b/jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java index c2f9e619ac4..00ee727401c 100644 --- a/jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java +++ b/jdk/test/javax/security/auth/kerberos/KerberosTixDateTest.java @@ -34,7 +34,7 @@ import java.io.*; import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.KerberosTicket; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class KerberosTixDateTest { @@ -127,7 +127,7 @@ public class KerberosTixDateTest { System.out.println("Testing against KerberosTicket from JDK6..."); byte[] serializedBytes = - new BASE64Decoder().decodeBuffer(serializedKerberosTix); + Base64.getMimeDecoder().decode(serializedKerberosTix); checkEqualsAndHashCode(serializedBytes, t); System.out.println("Testing against KerberosTicket from current rel..."); diff --git a/jdk/test/javax/swing/text/html/7189299/bug7189299.java b/jdk/test/javax/swing/text/html/7189299/bug7189299.java new file mode 100644 index 00000000000..70d2057c89f --- /dev/null +++ b/jdk/test/javax/swing/text/html/7189299/bug7189299.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2013 IBM Corporation + */ +import java.awt.BorderLayout; +import java.awt.Toolkit; + +import java.awt.event.ActionListener; +import javax.swing.DefaultButtonModel; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.html.HTMLEditorKit; +import sun.awt.SunToolkit; + + +/* + * @test + * @bug 8008289 + * @summary Shared ButtonModel instance should deregister previous listeners. + * @author Frank Ding + */ +public class bug7189299 { + + private static JEditorPane html; + private static JFrame frame; + + private static void setup() { + /** + * Note the input type is not restricted to "submit". Types "image", + * "checkbox", "radio" have the same problem. + */ + html = new JEditorPane("text/html", + "

    " + + "" + + "
    "); + frame = new JFrame(); + frame.setLayout(new BorderLayout()); + frame.add(html, BorderLayout.CENTER); + frame.setSize(200, 100); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + private static void doTest() { + /* + * Calling updateComponentTreeUI creates a new FormView instance with + * its own associated JButton instance. The same DefaultButtonModel + * instance is used for both FormView's. + * + * The action listeners associated with (the JButton for) the first + * FormView should be unregistered from this common DefaultButtonModel, + * such that only those for the new FormView remain. + */ + SwingUtilities.updateComponentTreeUI(html); + } + + private static void verifySingleDefaultButtonModelListener() { + HTMLEditorKit htmlEditorKit = (HTMLEditorKit) html.getEditorKit(); + StyleContext.NamedStyle style = ((StyleContext.NamedStyle) htmlEditorKit + .getInputAttributes()); + DefaultButtonModel model = ((DefaultButtonModel) style + .getAttribute(StyleConstants.ModelAttribute)); + ActionListener[] listeners = model.getActionListeners(); + int actionListenerNum = listeners.length; + if (actionListenerNum != 1) { + throw new RuntimeException( + "Expected single ActionListener object registered with " + + "DefaultButtonModel; found " + actionListenerNum + + " listeners registered."); + } + + int changeListenerNum = model.getChangeListeners().length; + if (changeListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ChangeListener object registered " + + "with DefaultButtonModel; found " + changeListenerNum + + " listeners registered."); + } + int itemListenerNum = model.getItemListeners().length; + if (itemListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ItemListener object registered " + + "with DefaultButtonModel; found " + itemListenerNum + + " listeners registered."); + } + } + + public static void main(String[] args) throws Exception { + final SunToolkit toolkit = ((SunToolkit) Toolkit.getDefaultToolkit()); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + setup(); + } + }); + toolkit.realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + verifySingleDefaultButtonModelListener(); + doTest(); + verifySingleDefaultButtonModelListener(); + } finally { + frame.dispose(); + } + } + }); + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java index fa038faccd4..d109778f22a 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JdkFinder.java @@ -38,10 +38,6 @@ public final class JdkFinder { } binPath += File.separatorChar + "bin" + File.separatorChar + executable; - File toolFile = new File(binPath); - if (!toolFile.exists()) { - throw new RuntimeException(binPath + " does not exist"); - } return binPath; } diff --git a/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java new file mode 100644 index 00000000000..75f63496bfa --- /dev/null +++ b/jdk/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6877495 + @summary JTextField and JTextArea does not support supplementary characters + @author Alexander Scherbatiy + @run main SuplementaryCharactersTransferTest +*/ + + +import java.io.*; +import java.util.*; +import java.awt.*; +import java.awt.datatransfer.*; +import sun.awt.datatransfer.*; +import sun.awt.datatransfer.DataTransferer.ReencodingInputStream; + +public class SuplementaryCharactersTransferTest { + + public static final long TEXT_FORMAT = 13; + + public static void main(String[] args) throws Exception { + + DataTransferer dataTransferer = new TestDataTransferer(); + dataTransferer.registerTextFlavorProperties("UNICODE TEXT", "utf-16le", "\r\n", "2"); + ByteTransferable transferable = new ByteTransferable(); + ReencodingInputStream is = dataTransferer.new ReencodingInputStream(transferable.getByteInputStream(), TEXT_FORMAT, + DataTransferer.getTextCharset(transferable.getDataFlavor()), transferable); + + byte[] bytes = transferable.getBytes(); + byte[] result = new byte[bytes.length]; + + is.read(result); + + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] != result[i]) { + throw new RuntimeException("Characters are not equal!"); + } + } + + } + + static class ByteTransferable implements Transferable, ClipboardOwner { + + private final DataFlavor dataFlavor; + + public ByteTransferable() throws Exception { + dataFlavor = DataFlavor.getTextPlainUnicodeFlavor(); + } + + public DataFlavor getDataFlavor() { + return dataFlavor; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{dataFlavor}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(dataFlavor); + } + + public byte[] getBytes() { + return new byte[]{97, 0, 64, -40, 32, -36, 98, 0}; + } + + public InputStream getByteInputStream() { + return new ByteArrayInputStream(getBytes()); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + if (flavor.equals(dataFlavor)) { + return getByteInputStream(); + } else { + throw new UnsupportedFlavorException(flavor); + } + } + + public void lostOwnership(Clipboard clipboard, Transferable contents) { + } + } + + static class TestDataTransferer extends DataTransferer { + + @Override + public String getDefaultUnicodeEncoding() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isLocaleDependentTextFormat(long format) { + return false; + } + + @Override + public boolean isFileFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isImageFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Long getFormatForNativeAsLong(String str) { + return TEXT_FORMAT; + } + + @Override + protected String getNativeForFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected ByteArrayOutputStream convertFileListToBytes( + ArrayList fileList) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected String[] dragQueryFile(byte[] bytes) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Image platformImageBytesOrStreamToImage(InputStream str, + byte[] bytes, long format) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected byte[] imageToPlatformBytes(Image image, long format) + throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} \ No newline at end of file diff --git a/jdk/test/sun/misc/Cleaner/ExitOnThrow.java b/jdk/test/sun/misc/Cleaner/ExitOnThrow.java index 03ea83d9d45..f4fd8021748 100644 --- a/jdk/test/sun/misc/Cleaner/ExitOnThrow.java +++ b/jdk/test/sun/misc/Cleaner/ExitOnThrow.java @@ -28,21 +28,17 @@ import sun.misc.*; public class ExitOnThrow { - private static volatile boolean ran = false; - public static void main(String[] args) throws Exception { Cleaner.create(new Object(), new Runnable() { public void run() { - ran = true; throw new RuntimeException("Foo!"); } }); - while (!ran) { + while (true) { System.gc(); Thread.sleep(100); } - System.exit(0); } } diff --git a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh index 7506ce4403f..4a22114ab18 100644 --- a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh +++ b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh @@ -25,7 +25,7 @@ # # @test -# @bug 4954921 +# @bug 4954921 8009259 # @summary Ensure that if a cleaner throws an exception then the VM exits # # @build ExitOnThrow diff --git a/jdk/test/sun/net/www/protocol/http/HttpOnly.java b/jdk/test/sun/net/www/protocol/http/HttpOnly.java index 60596bad219..6a2ce8256d9 100644 --- a/jdk/test/sun/net/www/protocol/http/HttpOnly.java +++ b/jdk/test/sun/net/www/protocol/http/HttpOnly.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 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 @@ -22,7 +22,7 @@ */ /** * @test - * @bug 7095980 + * @bug 7095980 8007315 * @summary Ensure HttpURLConnection (and supporting APIs) don't expose * HttpOnly cookies */ @@ -52,6 +52,8 @@ import com.sun.net.httpserver.HttpServer; * 4) check HttpOnly cookies received by server * 5) server reply with Set-Cookie containing HttpOnly cookie * 6) check HttpOnly cookies are not accessible from Http client + * 7) check that non-null (empty string) values are returned for + scenario where all values are stripped from original key values */ public class HttpOnly { @@ -177,6 +179,36 @@ public class HttpOnly { " value " + val); } } + + // TEST 7 : check that header keys containing empty key values don't return null + int i = 1; + String key = ""; + String value = ""; + + while (true) { + key = uc.getHeaderFieldKey(i); + value = uc.getHeaderField(i++); + if (key == null && value == null) + break; + + if (key != null) + check(value != null, + "Encountered a null value for key value : " + key); + } + + // TEST 7.5 similar test but use getHeaderFields + respHeaders = uc.getHeaderFields(); + respEntries = respHeaders.entrySet(); + for (Map.Entry> entry : respEntries) { + String header = entry.getKey(); + if (header != null) { + List listValues = entry.getValue(); + for (String value1 : listValues) + check(value1 != null, + "getHeaderFields returned null values for header:, " + + header); + } + } } // HTTP Server diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java index aae14f46bd3..738f2c3d4e3 100644 --- a/jdk/test/sun/security/krb5/auto/Context.java +++ b/jdk/test/sun/security/krb5/auto/Context.java @@ -296,6 +296,13 @@ public class Context { return s; } + /** + * Returns the cred inside, if there is one + */ + public GSSCredential cred() { + return cred; + } + /** * Disposes the GSSContext within * @throws org.ietf.jgss.GSSException diff --git a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java index 19f3355ce09..82333d7783b 100644 --- a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java +++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java @@ -55,6 +55,7 @@ import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSManager; import sun.security.jgss.GSSUtil; import sun.security.krb5.Config; +import java.util.Base64; /** * Basic JGSS/krb5 test with 3 parties: client, server, backend server. Each @@ -341,12 +342,11 @@ public class HttpNegotiateServer { exch.getHttpContext().getAttributes().put("GSSContext", c); return new com.sun.net.httpserver.Authenticator.Retry(err); } else { // Later requests - byte[] token = new sun.misc.BASE64Decoder() - .decodeBuffer(auth.split(" ")[1]); + byte[] token = Base64.getMimeDecoder().decode(auth.split(" ")[1]); token = c.acceptSecContext(token, 0, token.length); Headers map = exch.getResponseHeaders(); - map.set (reqHdr, scheme + " " + new sun.misc.BASE64Encoder() - .encode(token).replaceAll("\\s", "")); + map.set (reqHdr, scheme + " " + Base64.getMimeEncoder() + .encodeToString(token).replaceAll("\\s", "")); if (c.isEstablished()) { return new com.sun.net.httpserver.Authenticator.Success( new HttpPrincipal(c.getSrcName().toString(), "")); diff --git a/jdk/test/sun/security/krb5/auto/SpnegoLifeTime.java b/jdk/test/sun/security/krb5/auto/SpnegoLifeTime.java new file mode 100644 index 00000000000..906cfbee786 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/SpnegoLifeTime.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8000653 + * @summary SPNEGO tests fail at context.getDelegCred().getRemainingInitLifetime(mechOid) + * @compile -XDignore.symbol.file SpnegoLifeTime.java + * @run main/othervm SpnegoLifeTime + */ + +import org.ietf.jgss.Oid; +import org.ietf.jgss.GSSCredential; +import sun.security.jgss.GSSUtil; + +public class SpnegoLifeTime { + + public static void main(String[] args) throws Exception { + + Oid oid = GSSUtil.GSS_SPNEGO_MECH_OID; + new OneKDC(null).writeJAASConf(); + + Context c, s; + c = Context.fromJAAS("client"); + s = Context.fromJAAS("server"); + + c.startAsClient(OneKDC.SERVER, oid); + c.x().requestCredDeleg(true); + s.startAsServer(oid); + + Context.handshake(c, s); + + GSSCredential cred = s.delegated().cred(); + cred.getRemainingInitLifetime(oid); + cred.getUsage(oid); + } +} + diff --git a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java index e4f7eb1a773..8958718ae7a 100644 --- a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java +++ b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java @@ -29,7 +29,7 @@ import javax.net.*; import javax.net.ssl.*; import java.lang.reflect.*; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; public class ShortRSAKeyWithinTLS { @@ -175,13 +175,13 @@ public class ShortRSAKeyWithinTLS { privateKey = (PrivateKey)ks.getKey(keyAlias, null); publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey(); - int privateKeySize = KeyLength.getKeySize(privateKey); + int privateKeySize = KeyUtil.getKeySize(privateKey); if (privateKeySize != keySize) { throw new Exception("Expected key size is " + keySize + ", but the private key size is " + privateKeySize); } - int publicKeySize = KeyLength.getKeySize(publicKey); + int publicKeySize = KeyUtil.getKeySize(publicKey); if (publicKeySize != keySize) { throw new Exception("Expected key size is " + keySize + ", but the public key size is " + publicKeySize); diff --git a/jdk/test/sun/security/provider/PolicyFile/WildcardPrincipalName.java b/jdk/test/sun/security/provider/PolicyFile/WildcardPrincipalName.java new file mode 100644 index 00000000000..d81149d036f --- /dev/null +++ b/jdk/test/sun/security/provider/PolicyFile/WildcardPrincipalName.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8008908 + * @summary wildcard principal names are not processed correctly + * @run main/othervm/policy=wildcard.policy WildcardPrincipalName + */ + +import java.security.AccessController; +import java.security.Permission; +import java.security.Principal; +import java.security.PrivilegedAction; +import java.util.HashSet; +import java.util.PropertyPermission; +import java.util.Set; +import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; + +public class WildcardPrincipalName { + + public static void main(String[] args) throws Exception { + + X500Principal duke = new X500Principal("CN=Duke"); + PropertyPermission pp = new PropertyPermission("user.home", "read"); + RunAsPrivilegedUserAction runAsPrivilegedUserAction + = new RunAsPrivilegedUserAction(duke, + new CheckPermissionAction(pp)); + AccessController.doPrivileged(runAsPrivilegedUserAction); + System.out.println("test PASSED"); + } + + private static class RunAsPrivilegedUserAction + implements PrivilegedAction { + private final PrivilegedAction action; + private final Principal principal; + + RunAsPrivilegedUserAction(Principal principal, + PrivilegedAction action) { + this.principal = principal; + this.action = action; + } + + @Override public Void run() { + Set principals = new HashSet<>(); + Set publicCredentials = new HashSet<>(); + Set privateCredentials = new HashSet<>(); + + principals.add(principal); + Subject subject = new Subject(true, + principals, + publicCredentials, + privateCredentials); + + Subject.doAsPrivileged(subject, action, null); + return null; + } + } + + private static class CheckPermissionAction + implements PrivilegedAction { + private final Permission permission; + + CheckPermissionAction(Permission permission) { + this.permission = permission; + } + + @Override public Void run() { + AccessController.checkPermission(permission); + return null; + } + } +} diff --git a/jdk/test/sun/security/provider/PolicyFile/wildcard.policy b/jdk/test/sun/security/provider/PolicyFile/wildcard.policy new file mode 100644 index 00000000000..55e942db37a --- /dev/null +++ b/jdk/test/sun/security/provider/PolicyFile/wildcard.policy @@ -0,0 +1,7 @@ +grant principal javax.security.auth.x500.X500Principal * { + permission java.util.PropertyPermission "user.home", "read"; +}; + +grant { + permission javax.security.auth.AuthPermission "doAsPrivileged"; +}; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java index 0a25f7f21ce..9cf0fbb7185 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/MD2InTrustAnchor.java @@ -46,8 +46,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.*; import java.security.interfaces.*; -import sun.misc.BASE64Decoder; - +import java.util.Base64; public class MD2InTrustAnchor { @@ -238,7 +237,7 @@ public class MD2InTrustAnchor { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java index 3aeeb081b34..ff8887c212a 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/TrustTrustedCert.java @@ -44,7 +44,7 @@ import java.security.*; import java.security.cert.*; import java.security.spec.*; import java.security.interfaces.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class TrustTrustedCert { @@ -230,7 +230,7 @@ public class TrustTrustedCert { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(targetPrivateKey)); + Base64.getMimeDecoder().decode(targetPrivateKey)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java index 1756ba0cacd..8f1e71622c4 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/BasicConstraints.java @@ -44,7 +44,7 @@ import java.security.spec.*; import java.security.interfaces.*; import java.math.BigInteger; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class BasicConstraints { @@ -400,11 +400,11 @@ public class BasicConstraints { PKCS8EncodedKeySpec priKeySpec = null; if (isServer) { priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(serverPrivateKey)); + Base64.getMimeDecoder().decode(serverPrivateKey)); is = new ByteArrayInputStream(serverCertStr.getBytes()); } else { priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(clientPrivateKey)); + Base64.getMimeDecoder().decode(clientPrivateKey)); is = new ByteArrayInputStream(clientCertStr.getBytes()); } KeyFactory kf = KeyFactory.getInstance("RSA"); diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java index 0037b6f379f..1f8f7298383 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SelfIssuedCert.java @@ -45,7 +45,7 @@ import java.security.spec.*; import java.security.interfaces.*; import java.math.BigInteger; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class SelfIssuedCert { @@ -242,7 +242,7 @@ public class SelfIssuedCert { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java index 9d77078f12e..e5fa754391e 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsClient/ProxyTunnelServer.java @@ -33,6 +33,7 @@ import java.net.*; import javax.net.ssl.*; import javax.net.ServerSocketFactory; import sun.net.www.*; +import java.util.Base64; public class ProxyTunnelServer extends Thread { @@ -292,12 +293,12 @@ public class ProxyTunnelServer extends Thread { authInfo.trim(); int ind = authInfo.indexOf(' '); String recvdUserPlusPass = authInfo.substring(ind + 1).trim(); + // extract encoded (username:passwd if (userPlusPass.equals( - new String( - (new sun.misc.BASE64Decoder()). - decodeBuffer(recvdUserPlusPass) - ))) { + new String( Base64.getMimeDecoder() + .decode(recvdUserPlusPass)))) + { matched = true; } } catch (Exception e) { diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java b/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java index 03a841bfd85..1b93237a544 100644 --- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java +++ b/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/SSLSocketSNISensitive.java @@ -51,7 +51,7 @@ import java.security.cert.X509Certificate; import java.security.cert.CertificateFactory; import java.security.spec.*; import java.security.interfaces.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class SSLSocketSNISensitive { @@ -391,7 +391,7 @@ public class SSLSocketSNISensitive { // generate the private key. String keySpecStr = keyStrs[i]; PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java index 4a7130964b8..f92d7f69c05 100644 --- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java +++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/DisabledShortRSAKeys.java @@ -53,7 +53,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.*; import java.security.interfaces.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class DisabledShortRSAKeys { @@ -244,7 +244,7 @@ public class DisabledShortRSAKeys { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java index c3c170205a4..8370f9d3525 100644 --- a/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java +++ b/jdk/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKey512.java @@ -48,7 +48,7 @@ import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.*; import java.security.interfaces.*; -import sun.misc.BASE64Decoder; +import java.util.Base64; public class ShortRSAKey512 { @@ -229,7 +229,7 @@ public class ShortRSAKey512 { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - new BASE64Decoder().decodeBuffer(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java index a70eb7fb680..f2f3430e12e 100644 --- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ProxyTunnelServer.java @@ -35,6 +35,7 @@ import java.net.*; import javax.net.ssl.*; import javax.net.ServerSocketFactory; import sun.net.www.*; +import java.util.Base64; public class ProxyTunnelServer extends Thread { @@ -296,10 +297,9 @@ public class ProxyTunnelServer extends Thread { String recvdUserPlusPass = authInfo.substring(ind + 1).trim(); // extract encoded (username:passwd if (userPlusPass.equals( - new String( - (new sun.misc.BASE64Decoder()). - decodeBuffer(recvdUserPlusPass) - ))) { + new String( Base64.getMimeDecoder() + .decode(recvdUserPlusPass)))) + { matched = true; } } catch (Exception e) { diff --git a/jdk/test/sun/tools/jrunscript/CheckEngine.java b/jdk/test/sun/tools/jrunscript/CheckEngine.java index 023e5e0920a..752411da2ac 100644 --- a/jdk/test/sun/tools/jrunscript/CheckEngine.java +++ b/jdk/test/sun/tools/jrunscript/CheckEngine.java @@ -33,7 +33,7 @@ public class CheckEngine { public static void main(String... args) { int exitCode = 0; ScriptEngine engine = - (new ScriptEngineManager()).getEngineByName("js"); + (new ScriptEngineManager()).getEngineByName("nashorn"); if (engine == null && !(System.getProperty("java.runtime.name").startsWith("Java(TM)"))) { diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh index 4d9e792c43f..b2102ef6a62 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh @@ -43,7 +43,7 @@ fi # to script as java.lang.System property. sysProps is # jrunscript shell built-in variable for System properties. -${JRUNSCRIPT} -Djrunscript.foo=bar </dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -e "println('hello')" > jrunscript-eTest.out 2>&1 - -$golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out -if [ $? != 0 ] -then - echo "Output of jrunscript -e differ from expected output. Failed." - rm -f jrunscript-eTest.out 2>/dev/null - exit 1 -fi - # -e option with JavaScript explicitly choosen as language rm -f jrunscript-eTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js -e "println('hello')" > jrunscript-eTest.out 2>&1 +${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn -e "println('hello')" > jrunscript-eTest.out 2>&1 $golden_diff jrunscript-eTest.out ${TESTSRC}/dash-e.out if [ $? != 0 ] diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh index 170a7dd0d11..8c402a316ea 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh @@ -39,22 +39,11 @@ if [ $? -eq 2 ]; then exit 0 fi -rm -f jrunscript-fTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 - -$golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out -if [ $? != 0 ] -then - echo "Output of jrunscript -f differ from expected output. Failed." - rm -f jrunscript-fTest.out 2>/dev/null - exit 1 -fi - # -f option used with JavaScript as language chosen explicitly # with -l option rm -f jrunscript-fTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 +${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn -f ${TESTSRC}/hello.js > jrunscript-fTest.out 2>&1 $golden_diff jrunscript-fTest.out ${TESTSRC}/dash-f.out if [ $? != 0 ] diff --git a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh index 0a3237536db..921524be9e0 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -40,7 +40,7 @@ if [ $? -eq 2 ]; then fi rm -f jrunscriptTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true > jrunscriptTest.out 2>&1 < jrunscriptTest.out 2>&1 </dev/null - exit 1 -fi - -rm -f jrunscriptTest.out 2>/dev/null -${JRUNSCRIPT} -J-Djava.awt.headless=true -l js > jrunscriptTest.out 2>&1 </dev/null exit 1 fi diff --git a/jdk/test/sun/tools/jrunscript/repl.out b/jdk/test/sun/tools/jrunscript/repl.out index 13b390fc29b..156b8263fce 100644 --- a/jdk/test/sun/tools/jrunscript/repl.out +++ b/jdk/test/sun/tools/jrunscript/repl.out @@ -1,7 +1,7 @@ -js> 7.0 -js> 35.0 -js> 35 is the value -js> yes v != 0 -js> hello world from script -js> I am runnable -js> \ No newline at end of file +nashorn> 7 +nashorn> 35.0 +nashorn> 35 is the value +nashorn> yes v != 0 +nashorn> hello world from script +nashorn> I am runnable +nashorn> \ No newline at end of file diff --git a/jdk/test/tools/launcher/I18NJarTest.java b/jdk/test/tools/launcher/I18NJarTest.java index 9c033b47f8f..ad94abcce64 100644 --- a/jdk/test/tools/launcher/I18NJarTest.java +++ b/jdk/test/tools/launcher/I18NJarTest.java @@ -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 @@ -52,6 +52,8 @@ public class I18NJarTest extends TestHelper { private static final File cwd = new File("."); private static final File dir = new File("\uFF66\uFF67\uFF68\uFF69"); private static final String encoding = System.getProperty("sun.jnu.encoding", ""); + private static final String LANG = System.getenv("LANG"); + private static final String LC_ALL = System.getenv("LC_ALL"); public static void main(String... args) throws Exception { boolean localeAvailable = false; @@ -63,7 +65,16 @@ public class I18NJarTest extends TestHelper { } if (!localeAvailable) { System.out.println("Warning: locale: " + Locale.JAPAN - + " not found, test passes vacuosly"); + + " not found, test passes vacuously"); + return; + } + if ("C".equals(LC_ALL) || "C".equals(LANG)) { + System.out.println("Warning: The LANG and/or LC_ALL env vars are " + + "set to \"C\":\n" + + " LANG=" + LANG + "\n" + + " LC_ALL=" + LC_ALL + "\n" + + "This test requires support for multi-byte filenames.\n" + + "Test passes vacuously."); return; } if (encoding.equals("MS932") || encoding.equals("UTF-8")) { @@ -73,7 +84,7 @@ public class I18NJarTest extends TestHelper { } else { System.out.println("Warning: current encoding is " + encoding + "this test requires MS932 or UTF-8," + - " test passes vacuosly"); + " test passes vacuously"); return; } dir.mkdir(); diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java index 4535990dbca..f01931d5482 100644 --- a/jdk/test/tools/launcher/ToolsOpts.java +++ b/jdk/test/tools/launcher/ToolsOpts.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8002091 * @summary Test options patterns for javac,javah,javap and javadoc using * javac as a test launcher. Create a dummy javac and intercept options to check * reception of options as passed through the launcher without having to launch diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index 11f65cb2e9a..64f0e6adfb8 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -74,6 +74,7 @@ public class VersionCheck extends TestHelper { "jmap", "jps", "jrunscript", + "jjs", "jsadebugd", "jstack", "jstat", diff --git a/jdk/test/tools/pack200/AttributeTests.java b/jdk/test/tools/pack200/AttributeTests.java index d4a40a90cc5..c12891829e7 100644 --- a/jdk/test/tools/pack200/AttributeTests.java +++ b/jdk/test/tools/pack200/AttributeTests.java @@ -29,7 +29,7 @@ import java.util.List; import static java.nio.file.StandardOpenOption.*; /* * @test - * @bug 6746111 8005252 + * @bug 6746111 8005252 8008262 * @summary tests various classfile format and attribute handling by pack200 * @compile -XDignore.symbol.file Utils.java AttributeTests.java * @run main AttributeTests @@ -67,17 +67,7 @@ public class AttributeTests { File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); Utils.jar("cvf", testjarFile.getName(), javaClassName); - // pack using --repack - File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT); - scratch.clear(); - scratch.add(Utils.getPack200Cmd()); - scratch.add("--repack"); - scratch.add("--unknown-attribute=error"); - scratch.add(outjarFile.getName()); - scratch.add(testjarFile.getName()); - Utils.runExec(scratch); - - Utils.doCompareVerify(testjarFile, outjarFile); + Utils.testWithRepack(testjarFile, "--unknown-attribute=error"); } /* * this test checks to see if we get the expected strings for output diff --git a/jdk/test/tools/pack200/InstructionTests.java b/jdk/test/tools/pack200/InstructionTests.java index ce92c0ed558..7015ae9a11f 100644 --- a/jdk/test/tools/pack200/InstructionTests.java +++ b/jdk/test/tools/pack200/InstructionTests.java @@ -26,11 +26,10 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import static java.nio.file.StandardOpenOption.*; -import java.util.regex.Pattern; /* * @test - * @bug 8003549 + * @bug 8003549 8007297 * @summary tests class files instruction formats introduced in JSR-335 * @compile -XDignore.symbol.file Utils.java InstructionTests.java * @run main InstructionTests @@ -48,52 +47,34 @@ public class InstructionTests { List scratch = new ArrayList<>(); final String fname = "A"; String javaFileName = fname + Utils.JAVA_FILE_EXT; - scratch.add("interface IntIterator {"); + scratch.add("interface I {"); scratch.add(" default void forEach(){}"); scratch.add(" static void next() {}"); scratch.add("}"); - scratch.add("class A implements IntIterator {"); - scratch.add("public void forEach(Object o){"); - scratch.add("IntIterator.super.forEach();"); - scratch.add("IntIterator.next();"); - scratch.add("}"); + scratch.add("class A implements I {"); + scratch.add(" public void forEach(Object o){"); + scratch.add(" I.super.forEach();"); + scratch.add(" I.next();"); + scratch.add(" }"); scratch.add("}"); File cwd = new File("."); File javaFile = new File(cwd, javaFileName); Files.write(javaFile.toPath(), scratch, Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING); - // make sure we have -g so that we compare LVT and LNT entries + // -g to compare LVT and LNT entries Utils.compiler("-g", javaFile.getName()); + File propsFile = new File("pack.props"); + scratch.clear(); + scratch.add("com.sun.java.util.jar.pack.class.format.error=error"); + scratch.add("pack.unknown.attribute=error"); + Files.write(propsFile.toPath(), scratch, Charset.defaultCharset(), + CREATE, TRUNCATE_EXISTING); // jar the file up File testjarFile = new File(cwd, "test" + Utils.JAR_FILE_EXT); Utils.jar("cvf", testjarFile.getName(), "."); - // pack using --repack - File outjarFile = new File(cwd, "out" + Utils.JAR_FILE_EXT); - scratch.clear(); - scratch.add(Utils.getPack200Cmd()); - scratch.add("-J-ea"); - scratch.add("-J-esa"); - scratch.add("--repack"); - scratch.add(outjarFile.getName()); - scratch.add(testjarFile.getName()); - List output = Utils.runExec(scratch); - // TODO remove this when we get bc escapes working correctly - // this test anyhow would fail at that time - findString("WARNING: Passing.*" + fname + Utils.CLASS_FILE_EXT, - output); - - Utils.doCompareVerify(testjarFile, outjarFile); - } - - static boolean findString(String str, List list) { - Pattern p = Pattern.compile(str); - for (String x : list) { - if (p.matcher(x).matches()) - return true; - } - throw new RuntimeException("Error: " + str + " not found in output"); + Utils.testWithRepack(testjarFile, "--config-file=" + propsFile.getName()); } } diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index 0e2269822f5..f3d1d4666b8 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -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 @@ -315,6 +315,41 @@ class Utils { } } + static void testWithRepack(File inFile, String... repackOpts) throws IOException { + File cwd = new File("."); + // pack using --repack in native mode + File nativejarFile = new File(cwd, "out-n" + Utils.JAR_FILE_EXT); + repack(inFile, nativejarFile, false, repackOpts); + doCompareVerify(inFile, nativejarFile); + + // ensure bit compatibility between the unpacker variants + File javajarFile = new File(cwd, "out-j" + Utils.JAR_FILE_EXT); + repack(inFile, javajarFile, true, repackOpts); + doCompareBitWise(javajarFile, nativejarFile); + } + + static List repack(File inFile, File outFile, + boolean disableNative, String... extraOpts) { + List cmdList = new ArrayList<>(); + cmdList.clear(); + cmdList.add(Utils.getJavaCmd()); + cmdList.add("-ea"); + cmdList.add("-esa"); + if (disableNative) { + cmdList.add("-Dcom.sun.java.util.jar.pack.disable.native=true"); + } + cmdList.add("com.sun.java.util.jar.pack.Driver"); + cmdList.add("--repack"); + if (extraOpts != null) { + for (String opt: extraOpts) { + cmdList.add(opt); + } + } + cmdList.add(outFile.getName()); + cmdList.add(inFile.getName()); + return Utils.runExec(cmdList); + } + // given a jar file foo.jar will write to foo.pack static void pack(JarFile jarFile, File packFile) throws IOException { Pack200.Packer packer = Pack200.newPacker(); diff --git a/jdk/test/vm/verifier/TestStaticIF.java b/jdk/test/vm/verifier/TestStaticIF.java new file mode 100644 index 00000000000..5a6776f3fc6 --- /dev/null +++ b/jdk/test/vm/verifier/TestStaticIF.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8007736 + * @summary Test static interface method. + * @run main/othervm -Xverify:all -XX:-UseSplitVerifier TestStaticIF + */ + +public class TestStaticIF implements StaticMethodInInterface { + + public static void main(String[] args) { + System.out.printf("main: %s%n", StaticMethodInInterface.get()); + } +} + +interface StaticMethodInInterface { + + public static String get() { + return "Hello from StaticMethodInInterface.get()"; + } +}