# HG changeset patch # User lana # Date 1366260484 25200 # Node ID 4b8e606f8afb9343d47bb93f09eccf3f5a33b4e8 # Parent bb098a221d85561b945d7246462bf54901d65133# Parent 674880648db489fb568d6db19a10491cb67918e5 Merge diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/FILES_c.gmk --- a/make/java/java/FILES_c.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/FILES_c.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -48,7 +48,6 @@ Proxy.c \ RandomAccessFile.c \ RandomAccessFile_md.c \ - ResourceBundle.c \ Runtime.c \ SecurityManager.c \ Shutdown.c \ diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/Makefile --- a/make/java/java/Makefile Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/Makefile Wed Apr 17 21:48:04 2013 -0700 @@ -313,6 +313,12 @@ CAL_PROPS = calendars.properties # +# Rule to copy Hijrah-umalqura calendar properties file. +# +HIJRAH_UMALQURA_PROPS = hijrah-config-umalqura.properties + + +# # Rule to copy tzmappings file on Windows # ifeq ($(PLATFORM), windows) @@ -324,7 +330,7 @@ $(call chmod-file, 444) endif -build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(TZMAP) +build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(LIBDIR)/$(HIJRAH_UMALQURA_PROPS) $(TZMAP) $(LIBDIR)/$(PROPS): $(PLATFORM_SRC)/lib/$(PROPS) $(install-file) @@ -332,6 +338,9 @@ $(LIBDIR)/$(CAL_PROPS): $(SHARE_SRC)/lib/$(CAL_PROPS) $(install-file) +$(LIBDIR)/$(HIJRAH_UMALQURA_PROPS): $(SHARE_SRC)/lib/$(HIJRAH_UMALQURA_PROPS) + $(install-file) + clean:: $(RM) -r $(LIBDIR)/$(PROPS) $(TZMAP) diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/mapfile-vers --- a/make/java/java/mapfile-vers Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/mapfile-vers Wed Apr 17 21:48:04 2013 -0700 @@ -134,7 +134,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; - Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_registerNatives; Java_java_lang_Compiler_registerNatives; Java_java_lang_Double_longBitsToDouble; @@ -217,7 +216,7 @@ Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_lang_UNIXProcess_initIDs; + Java_java_lang_UNIXProcess_init; Java_java_lang_UNIXProcess_waitForProcessExit; Java_java_lang_UNIXProcess_forkAndExec; Java_java_lang_UNIXProcess_destroyProcess; @@ -233,7 +232,6 @@ Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext; - Java_java_util_ResourceBundle_getClassContext; Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/reorder-i586 --- a/make/java/java/reorder-i586 Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/reorder-i586 Wed Apr 17 21:48:04 2013 -0700 @@ -73,7 +73,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/reorder-sparc --- a/make/java/java/reorder-sparc Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/reorder-sparc Wed Apr 17 21:48:04 2013 -0700 @@ -78,7 +78,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb make/java/java/reorder-sparcv9 --- a/make/java/java/reorder-sparcv9 Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/java/reorder-sparcv9 Wed Apr 17 21:48:04 2013 -0700 @@ -74,7 +74,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb make/java/text/base/FILES_java.gmk --- a/make/java/text/base/FILES_java.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/text/base/FILES_java.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -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 @@ -105,5 +105,7 @@ sun/text/resources/CollationData.java \ \ sun/text/resources/FormatData.java \ + sun/text/resources/JavaTimeSupplementary.java \ sun/text/resources/en/FormatData_en.java \ - sun/text/resources/en/FormatData_en_US.java + sun/text/resources/en/FormatData_en_US.java \ + sun/text/resources/en/JavaTimeSupplementary_en.java \ diff -r bb098a221d85 -r 4b8e606f8afb make/java/util/FILES_java.gmk --- a/make/java/util/FILES_java.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/make/java/util/FILES_java.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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,6 +26,7 @@ FILES_java = \ sun/util/resources/LocaleData.java \ sun/util/resources/OpenListResourceBundle.java \ + sun/util/resources/ParallelListResourceBundle.java \ sun/util/resources/LocaleNamesBundle.java \ sun/util/resources/TimeZoneNamesBundle.java \ sun/util/resources/TimeZoneNames.java \ diff -r bb098a221d85 -r 4b8e606f8afb make/sun/font/FILES_c.gmk --- a/make/sun/font/FILES_c.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/make/sun/font/FILES_c.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -106,7 +106,21 @@ OpenTypeLayoutEngine.cpp \ ThaiLayoutEngine.cpp \ ScriptAndLanguageTags.cpp \ - FontInstanceAdapter.cpp + FontInstanceAdapter.cpp \ + ContextualGlyphInsertionProc2.cpp \ + ContextualGlyphSubstProc2.cpp \ + GXLayoutEngine2.cpp \ + IndicRearrangementProcessor2.cpp \ + LigatureSubstProc2.cpp \ + MorphTables2.cpp \ + NonContextualGlyphSubstProc2.cpp \ + SegmentArrayProcessor2.cpp \ + SegmentSingleProcessor2.cpp \ + SimpleArrayProcessor2.cpp \ + SingleTableProcessor2.cpp \ + StateTableProcessor2.cpp \ + SubtableProcessor2.cpp \ + TrimmedArrayProcessor2.cpp ifeq ($(PLATFORM),windows) diff -r bb098a221d85 -r 4b8e606f8afb make/sun/splashscreen/Makefile --- a/make/sun/splashscreen/Makefile Wed Apr 17 21:32:11 2013 -0700 +++ b/make/sun/splashscreen/Makefile Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -83,21 +83,17 @@ -framework JavaNativeFoundation else ifneq ($(PLATFORM), windows) CFLAGS += -DWITH_X11 - ifeq ($(PLATFORM), macosx)) - OTHER_LDLIBS += -liconv - CPPFLAGS += -I$(OPENWIN_HOME)/include \ - -I$(OPENWIN_HOME)/include/X11/extensions - OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -pthread - else - CPPFLAGS += -I$(OPENWIN_HOME)/include -I$(OPENWIN_HOME)/include/X11/extensions - OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -lpthread - endif + CPPFLAGS += -I$(OPENWIN_HOME)/include -I$(OPENWIN_HOME)/include/X11/extensions + OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -lpthread else # PLATFORM CFLAGS += -DWITH_WIN32 OTHER_LDLIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib /DELAYLOAD:user32.dll #$(JVMLIB) $(OBJDIR)/../../jpeg/$(OBJDIRNAME)/jpeg$(SUFFIX).lib endif # PLATFORM +# Add giflib include path for all platforms +CPPFLAGS += -I$(SHARE_SRC)/native/sun/awt/giflib + # # Add to ambient vpath to get files in a subdirectory # diff -r bb098a221d85 -r 4b8e606f8afb make/sun/text/FILES_java.gmk --- a/make/sun/text/FILES_java.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/make/sun/text/FILES_java.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -227,5 +227,54 @@ sun/util/resources/sv/TimeZoneNames_sv.java \ sun/util/resources/zh/TimeZoneNames_zh_CN.java \ sun/util/resources/zh/TimeZoneNames_zh_TW.java \ - sun/util/resources/zh/TimeZoneNames_zh_HK.java + sun/util/resources/zh/TimeZoneNames_zh_HK.java \ + \ + sun/text/resources/ar/JavaTimeSupplementary_ar.java \ + sun/text/resources/be/JavaTimeSupplementary_be.java \ + sun/text/resources/bg/JavaTimeSupplementary_bg.java \ + sun/text/resources/ca/JavaTimeSupplementary_ca.java \ + sun/text/resources/cs/JavaTimeSupplementary_cs.java \ + sun/text/resources/da/JavaTimeSupplementary_da.java \ + sun/text/resources/de/JavaTimeSupplementary_de.java \ + sun/text/resources/el/JavaTimeSupplementary_el.java \ + sun/text/resources/en/JavaTimeSupplementary_en_GB.java \ + sun/text/resources/en/JavaTimeSupplementary_en_SG.java \ + sun/text/resources/es/JavaTimeSupplementary_es.java \ + sun/text/resources/et/JavaTimeSupplementary_et.java \ + sun/text/resources/fi/JavaTimeSupplementary_fi.java \ + sun/text/resources/fr/JavaTimeSupplementary_fr.java \ + sun/text/resources/ga/JavaTimeSupplementary_ga.java \ + sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java \ + sun/text/resources/hr/JavaTimeSupplementary_hr.java \ + sun/text/resources/hu/JavaTimeSupplementary_hu.java \ + sun/text/resources/is/JavaTimeSupplementary_is.java \ + sun/text/resources/it/JavaTimeSupplementary_it.java \ + sun/text/resources/iw/JavaTimeSupplementary_iw.java \ + sun/text/resources/iw/JavaTimeSupplementary_iw_IL.java \ + sun/text/resources/ja/JavaTimeSupplementary_ja.java \ + sun/text/resources/ko/JavaTimeSupplementary_ko.java \ + sun/text/resources/lt/JavaTimeSupplementary_lt.java \ + sun/text/resources/lv/JavaTimeSupplementary_lv.java \ + sun/text/resources/mk/JavaTimeSupplementary_mk.java \ + sun/text/resources/ms/JavaTimeSupplementary_ms.java \ + sun/text/resources/mt/JavaTimeSupplementary_mt.java \ + sun/text/resources/nl/JavaTimeSupplementary_nl.java \ + sun/text/resources/no/JavaTimeSupplementary_no.java \ + sun/text/resources/pl/JavaTimeSupplementary_pl.java \ + sun/text/resources/pt/JavaTimeSupplementary_pt.java \ + sun/text/resources/pt/JavaTimeSupplementary_pt_PT.java \ + sun/text/resources/ro/JavaTimeSupplementary_ro.java \ + sun/text/resources/ru/JavaTimeSupplementary_ru.java \ + sun/text/resources/sk/JavaTimeSupplementary_sk.java \ + sun/text/resources/sl/JavaTimeSupplementary_sl.java \ + sun/text/resources/sq/JavaTimeSupplementary_sq.java \ + sun/text/resources/sr/JavaTimeSupplementary_sr.java \ + sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java \ + sun/text/resources/sv/JavaTimeSupplementary_sv.java \ + sun/text/resources/th/JavaTimeSupplementary_th.java \ + sun/text/resources/tr/JavaTimeSupplementary_tr.java \ + sun/text/resources/uk/JavaTimeSupplementary_uk.java \ + sun/text/resources/vi/JavaTimeSupplementary_vi.java \ + sun/text/resources/zh/JavaTimeSupplementary_zh.java \ + sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java diff -r bb098a221d85 -r 4b8e606f8afb make/sun/tzdb/Makefile --- a/make/sun/tzdb/Makefile Wed Apr 17 21:32:11 2013 -0700 +++ b/make/sun/tzdb/Makefile Wed Apr 17 21:48:04 2013 -0700 @@ -42,7 +42,6 @@ # Time zone data file creation # TZDATA_DIR := ../javazic/tzdata -TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION)) TZFILE := \ africa antarctica asia australasia europe northamerica \ pacificnew southamerica backward etcetera \ @@ -50,9 +49,7 @@ TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZFILE)) - - -TZDB_JAR = tzdb.jar +TZDB_DAT = $(LIBDIR)/tzdb.dat # # Rules @@ -62,13 +59,12 @@ # # Add to the build rule # -build: $(LIBDIR)/$(TZDB_JAR) +build: $(TZDB_DAT) -$(LIBDIR)/$(TZDB_JAR): $(TZFILES) +$(TZDB_DAT): $(TZFILES) $(prep-target) - echo build tzdb from version $(TZDATA_VER) $(BOOT_JAVA_CMD) -jar $(BUILDTOOLJARDIR)/tzdb.jar \ - -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(LIBDIR) $(TZFILE) + -srcdir $(TZDATA_DIR) -dstfile $(TZDB_DAT) $(TZFILE) clean clobber:: - $(RM) $(LIBDIR)/$(TZDB_JAR) + $(RM) $(TZDB_DAT) diff -r bb098a221d85 -r 4b8e606f8afb make/tools/src/build/tools/cldrconverter/AbstractLDMLHandler.java --- a/make/tools/src/build/tools/cldrconverter/AbstractLDMLHandler.java Wed Apr 17 21:32:11 2013 -0700 +++ b/make/tools/src/build/tools/cldrconverter/AbstractLDMLHandler.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package build.tools.cldrconverter; +import build.tools.cldrconverter.CLDRConverter.DraftType; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -88,7 +89,7 @@ } String draftValue = attributes.getValue("draft"); if (draftValue != null) { - return CLDRConverter.draftType > CLDRConverter.DRAFT_MAP.get(draftValue); + return DraftType.getDefault().ordinal() > DraftType.forKeyword(draftValue).ordinal(); } return false; } diff -r bb098a221d85 -r 4b8e606f8afb make/tools/src/build/tools/cldrconverter/Bundle.java --- a/make/tools/src/build/tools/cldrconverter/Bundle.java Wed Apr 17 21:32:11 2013 -0700 +++ b/make/tools/src/build/tools/cldrconverter/Bundle.java Wed Apr 17 21:48:04 2013 -0700 @@ -266,6 +266,9 @@ handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows"); adjustEraNames(myMap, calendarType); @@ -484,25 +487,33 @@ for (String k : patternKeys) { if (myMap.containsKey(calendarPrefix + k)) { int len = patternKeys.length; - List rawPatterns = new ArrayList<>(); - List patterns = new ArrayList<>(); + List rawPatterns = new ArrayList<>(len); + List patterns = new ArrayList<>(len); for (int i = 0; i < len; i++) { String key = calendarPrefix + patternKeys[i]; String pattern = (String) myMap.remove(key); if (pattern == null) { pattern = (String) parentsMap.remove(key); } + rawPatterns.add(i, pattern); if (pattern != null) { - rawPatterns.add(i, pattern); patterns.add(i, translateDateFormatLetters(calendarType, pattern)); + } else { + patterns.add(i, null); } } + // If patterns is empty or has any nulls, discard patterns. if (patterns.isEmpty()) { return; } + for (String p : patterns) { + if (p == null) { + return; + } + } String key = calendarPrefix + name; if (!rawPatterns.equals(patterns)) { - myMap.put("cldr." + key, rawPatterns.toArray(new String[len])); + myMap.put("java.time." + key, rawPatterns.toArray(new String[len])); } myMap.put(key, patterns.toArray(new String[len])); break; diff -r bb098a221d85 -r 4b8e606f8afb make/tools/src/build/tools/cldrconverter/CLDRConverter.java --- a/make/tools/src/build/tools/cldrconverter/CLDRConverter.java Wed Apr 17 21:32:11 2013 -0700 +++ b/make/tools/src/build/tools/cldrconverter/CLDRConverter.java Wed Apr 17 21:48:04 2013 -0700 @@ -68,25 +68,43 @@ static MetaZonesParseHandler handlerMetaZones; private static BundleGenerator bundleGenerator; - static int draftType; - private static final String DRAFT_UNCONFIRMED = "unconfirmed"; - private static final String DRAFT_PROVISIONAL = "provisional"; - private static final String DRAFT_CONTRIBUTED = "contributed"; - private static final String DRAFT_APPROVED = "approved"; - private static final String DRAFT_TRUE = "true"; - private static final String DRAFT_FALSE = "false"; - private static final String DRAFT_DEFAULT = DRAFT_APPROVED; - static final Map DRAFT_MAP = new HashMap<>(); + static enum DraftType { + UNCONFIRMED, + PROVISIONAL, + CONTRIBUTED, + APPROVED; + + private static final Map map = new HashMap<>(); + static { + for (DraftType dt : values()) { + map.put(dt.getKeyword(), dt); + } + } + static private DraftType defaultType = CONTRIBUTED; + + private final String keyword; + + private DraftType() { + keyword = this.name().toLowerCase(Locale.ROOT); - static { - DRAFT_MAP.put(DRAFT_UNCONFIRMED, 0); - DRAFT_MAP.put(DRAFT_PROVISIONAL, 1); - DRAFT_MAP.put(DRAFT_CONTRIBUTED, 2); - DRAFT_MAP.put(DRAFT_APPROVED, 3); - DRAFT_MAP.put(DRAFT_TRUE, 0); - DRAFT_MAP.put(DRAFT_FALSE, 2); - draftType = DRAFT_MAP.get(DRAFT_DEFAULT); - }; + } + + static DraftType forKeyword(String keyword) { + return map.get(keyword); + } + + static DraftType getDefault() { + return defaultType; + } + + static void setDefault(String keyword) { + defaultType = Objects.requireNonNull(forKeyword(keyword)); + } + + String getKeyword() { + return keyword; + } + } static boolean USE_UTF8 = false; private static boolean verbose; @@ -106,7 +124,7 @@ case "-draft": String draftDataType = args[++i]; try { - draftType = DRAFT_MAP.get(draftDataType); + DraftType.setDefault(draftDataType); } catch (NullPointerException e) { severe("Error: incorrect draft value: %s%n", draftDataType); System.exit(1); @@ -525,7 +543,7 @@ "standalone.MonthNames", "MonthAbbreviations", "standalone.MonthAbbreviations", - "MonthNarrow", + "MonthNarrows", "standalone.MonthNarrows", "DayNames", "standalone.DayNames", @@ -533,6 +551,12 @@ "standalone.DayAbbreviations", "DayNarrows", "standalone.DayNarrows", + "QuarterNames", + "standalone.QuarterNames", + "QuarterAbbreviations", + "standalone.QuarterAbbreviations", + "QuarterNarrows", + "standalone.QuarterNarrows", "AmPmMarkers", "narrow.AmPmMarkers", "long.Eras", @@ -560,7 +584,7 @@ String prefix = calendarType.keyElementName(); for (String element : FORMAT_DATA_ELEMENTS) { String key = prefix + element; - copyIfPresent(map, "cldr." + key, formatData); + copyIfPresent(map, "java.time." + key, formatData); copyIfPresent(map, key, formatData); } } diff -r bb098a221d85 -r 4b8e606f8afb make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java --- a/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java Wed Apr 17 21:32:11 2013 -0700 +++ b/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java Wed Apr 17 21:48:04 2013 -0700 @@ -356,6 +356,44 @@ } } break; + case "quarterContext": + { + // for FormatData + // need to keep stand-alone and format, to allow for inheritance in CLDR + String type = attributes.getValue("type"); + if ("stand-alone".equals(type) || "format".equals(type)) { + pushKeyContainer(qName, attributes, type); + } else { + pushIgnoredContainer(qName); + } + } + break; + case "quarterWidth": + { + // for FormatData + // keep info about the context type so we can sort out inheritance later + String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName(); + switch (attributes.getValue("type")) { + case "wide": + pushStringArrayEntry(qName, attributes, prefix + "QuarterNames/" + getContainerKey(), 4); + break; + case "abbreviated": + pushStringArrayEntry(qName, attributes, prefix + "QuarterAbbreviations/" + getContainerKey(), 4); + break; + case "narrow": + pushStringArrayEntry(qName, attributes, prefix + "QuarterNarrows/" + getContainerKey(), 4); + break; + default: + pushIgnoredContainer(qName); + break; + } + } + break; + case "quarter": + // for FormatData + // add to string array entry of quarterWidth element + pushStringArrayElement(qName, attributes, Integer.parseInt(attributes.getValue("type")) - 1); + break; // // Time zone names diff -r bb098a221d85 -r 4b8e606f8afb make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java --- a/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java Wed Apr 17 21:32:11 2013 -0700 +++ b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java Wed Apr 17 21:48:04 2013 -0700 @@ -58,12 +58,12 @@ import static build.tools.tzdb.Utils.*; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.ParsePosition; import java.util.ArrayList; import java.util.Arrays; @@ -71,132 +71,131 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.NoSuchElementException; +import java.util.Scanner; import java.util.SortedMap; -import java.util.StringTokenizer; import java.util.TreeMap; -import java.util.TreeSet; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; import java.util.regex.Matcher; +import java.util.regex.MatchResult; import java.util.regex.Pattern; /** - * A builder that can read the TZDB time-zone files and build {@code ZoneRules} instances. + * A compiler that reads a set of TZDB time-zone files and builds a single + * combined TZDB data file. * * @since 1.8 */ public final class TzdbZoneRulesCompiler { - private static final Matcher YEAR = Pattern.compile("(?i)(?min)|(?max)|(?only)|(?[0-9]+)").matcher(""); - private static final Matcher MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)").matcher(""); - private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher(""); - private static final Matcher TIME = Pattern.compile("(?-)?+(?[0-9]{1,2})(:(?[0-5][0-9]))?+(:(?[0-5][0-9]))?+").matcher(""); + public static void main(String[] args) { + new TzdbZoneRulesCompiler().compile(args); + } - /** - * Constant for MJD 1972-01-01. - */ - private static final long MJD_1972_01_01 = 41317L; - - /** - * Reads a set of TZDB files and builds a single combined data file. - * - * @param args the arguments - */ - public static void main(String[] args) { + private void compile(String[] args) { if (args.length < 2) { outputHelp(); return; } - - // parse args + Path srcDir = null; + Path dstFile = null; String version = null; - File baseSrcDir = null; - File dstDir = null; - boolean verbose = false; - - // parse options + // parse args/options int i; for (i = 0; i < args.length; i++) { String arg = args[i]; - if (arg.startsWith("-") == false) { + if (!arg.startsWith("-")) { break; } if ("-srcdir".equals(arg)) { - if (baseSrcDir == null && ++i < args.length) { - baseSrcDir = new File(args[i]); + if (srcDir == null && ++i < args.length) { + srcDir = Paths.get(args[i]); continue; } - } else if ("-dstdir".equals(arg)) { - if (dstDir == null && ++i < args.length) { - dstDir = new File(args[i]); - continue; - } - } else if ("-version".equals(arg)) { - if (version == null && ++i < args.length) { - version = args[i]; + } else if ("-dstfile".equals(arg)) { + if (dstFile == null && ++i < args.length) { + dstFile = Paths.get(args[i]); continue; } } else if ("-verbose".equals(arg)) { - if (verbose == false) { + if (!verbose) { verbose = true; continue; } - } else if ("-help".equals(arg) == false) { + } else if (!"-help".equals(arg)) { System.out.println("Unrecognised option: " + arg); } outputHelp(); return; } - // check source directory - if (baseSrcDir == null) { - System.out.println("Source directory must be specified using -srcdir: " + baseSrcDir); - return; + if (srcDir == null) { + System.err.println("Source directory must be specified using -srcdir"); + System.exit(1); } - if (baseSrcDir.isDirectory() == false) { - System.out.println("Source does not exist or is not a directory: " + baseSrcDir); - return; + if (!Files.isDirectory(srcDir)) { + System.err.println("Source does not exist or is not a directory: " + srcDir); + System.exit(1); } - dstDir = (dstDir != null ? dstDir : baseSrcDir); - // parse source file names - List srcFileNames = Arrays.asList(Arrays.copyOfRange(args, i, args.length)); - if (srcFileNames.isEmpty()) { - System.out.println("Source filenames not specified, using default set"); - System.out.println("(africa antarctica asia australasia backward etcetera europe northamerica southamerica)"); - srcFileNames = Arrays.asList("africa", "antarctica", "asia", "australasia", "backward", - "etcetera", "europe", "northamerica", "southamerica"); + if (i == args.length) { + i = 0; + args = new String[] {"africa", "antarctica", "asia", "australasia", "europe", + "northamerica","southamerica", "backward", "etcetera" }; + System.out.println("Source filenames not specified, using default set ( "); + for (String name : args) { + System.out.printf(name + " "); + } + System.out.println(")"); } - - // find source directories to process - List srcDirs = new ArrayList<>(); - if (version != null) { - // if the "version" specified, as in jdk repo, the "baseSrcDir" is - // the "srcDir" that contains the tzdb data. - srcDirs.add(baseSrcDir); - } else { - File[] dirs = baseSrcDir.listFiles(); - for (File dir : dirs) { - if (dir.isDirectory() && dir.getName().matches("[12][0-9]{3}[A-Za-z0-9._-]+")) { - srcDirs.add(dir); - } + // source files in this directory + List srcFiles = new ArrayList<>(); + for (; i < args.length; i++) { + Path file = srcDir.resolve(args[i]); + if (Files.exists(file)) { + srcFiles.add(file); + } else { + System.err.println("Source directory does not contain source file: " + args[i]); + System.exit(1); } } - if (srcDirs.isEmpty()) { - System.out.println("Source directory contains no valid source folders: " + baseSrcDir); - return; + // check destination file + if (dstFile == null) { + dstFile = srcDir.resolve("tzdb.dat"); + } else { + Path parent = dstFile.getParent(); + if (parent != null && !Files.exists(parent)) { + System.err.println("Destination directory does not exist: " + parent); + System.exit(1); + } } - // check destination directory - if (dstDir.exists() == false && dstDir.mkdirs() == false) { - System.out.println("Destination directory could not be created: " + dstDir); - return; + try { + // get tzdb source version + Matcher m = Pattern.compile("tzdata(?[0-9]{4}[A-z])") + .matcher(new String(Files.readAllBytes(srcDir.resolve("VERSION")), + "ISO-8859-1")); + if (m.find()) { + version = m.group("ver"); + } else { + System.exit(1); + System.err.println("Source directory does not contain file: VERSION"); + } + printVerbose("Compiling TZDB version " + version); + // parse source files + for (Path file : srcFiles) { + printVerbose("Parsing file: " + file); + parseFile(file); + } + // build zone rules + printVerbose("Building rules"); + buildZoneRules(); + // output to file + printVerbose("Outputting tzdb file: " + dstFile); + outputFile(dstFile, version, builtZones, links); + } catch (Exception ex) { + System.out.println("Failed: " + ex.toString()); + ex.printStackTrace(); + System.exit(1); } - if (dstDir.isDirectory() == false) { - System.out.println("Destination is not a directory: " + dstDir); - return; - } - process(srcDirs, srcFileNames, dstDir, version, verbose); System.exit(0); } @@ -206,145 +205,35 @@ private static void outputHelp() { System.out.println("Usage: TzdbZoneRulesCompiler "); System.out.println("where options include:"); - System.out.println(" -srcdir Where to find source directories (required)"); - System.out.println(" -dstdir Where to output generated files (default srcdir)"); - System.out.println(" -version Specify the version, such as 2009a (optional)"); + System.out.println(" -srcdir Where to find tzdb source directory (required)"); + System.out.println(" -dstfile Where to output generated file (default srcdir/tzdb.dat)"); System.out.println(" -help Print this usage message"); System.out.println(" -verbose Output verbose information during compilation"); - System.out.println(" There must be one directory for each version in srcdir"); - System.out.println(" Each directory must have the name of the version, such as 2009a"); - System.out.println(" Each directory must contain the unpacked tzdb files, such as asia or europe"); - System.out.println(" Directories must match the regex [12][0-9][0-9][0-9][A-Za-z0-9._-]+"); - System.out.println(" There will be one jar file for each version and one combined jar in dstdir"); - System.out.println(" If the version is specified, only that version is processed"); - } - - /** - * Process to create the jar files. - */ - private static void process(List srcDirs, List srcFileNames, File dstDir, String version, boolean verbose) { - // build actual jar files - Map> allBuiltZones = new TreeMap<>(); - Set allRegionIds = new TreeSet(); - Set allRules = new HashSet(); - Map> allLinks = new TreeMap<>(); - - for (File srcDir : srcDirs) { - // source files in this directory - List srcFiles = new ArrayList<>(); - for (String srcFileName : srcFileNames) { - File file = new File(srcDir, srcFileName); - if (file.exists()) { - srcFiles.add(file); - } - } - if (srcFiles.isEmpty()) { - continue; // nothing to process - } - - // compile - String loopVersion = (srcDirs.size() == 1 && version != null) - ? version : srcDir.getName(); - TzdbZoneRulesCompiler compiler = new TzdbZoneRulesCompiler(loopVersion, srcFiles, verbose); - try { - // compile - compiler.compile(); - SortedMap builtZones = compiler.getZones(); - - // output version-specific file - File dstFile = version == null ? new File(dstDir, "tzdb" + loopVersion + ".jar") - : new File(dstDir, "tzdb.jar"); - if (verbose) { - System.out.println("Outputting file: " + dstFile); - } - outputFile(dstFile, loopVersion, builtZones, compiler.links); - - // create totals - allBuiltZones.put(loopVersion, builtZones); - allRegionIds.addAll(builtZones.keySet()); - allRules.addAll(builtZones.values()); - allLinks.put(loopVersion, compiler.links); - } catch (Exception ex) { - System.out.println("Failed: " + ex.toString()); - ex.printStackTrace(); - System.exit(1); - } - } - - // output merged file - if (version == null) { - File dstFile = new File(dstDir, "tzdb-all.jar"); - if (verbose) { - System.out.println("Outputting combined file: " + dstFile); - } - outputFile(dstFile, allBuiltZones, allRegionIds, allRules, allLinks); - } + System.out.println(" The source directory must contain the unpacked tzdb files, such as asia or europe"); } /** * Outputs the file. */ - private static void outputFile(File dstFile, - String version, - SortedMap builtZones, - Map links) { - Map> loopAllBuiltZones = new TreeMap<>(); - loopAllBuiltZones.put(version, builtZones); - Set loopAllRegionIds = new TreeSet(builtZones.keySet()); - Set loopAllRules = new HashSet(builtZones.values()); - Map> loopAllLinks = new TreeMap<>(); - loopAllLinks.put(version, links); - outputFile(dstFile, loopAllBuiltZones, loopAllRegionIds, loopAllRules, loopAllLinks); - } - - /** - * Outputs the file. - */ - private static void outputFile(File dstFile, - Map> allBuiltZones, - Set allRegionIds, - Set allRules, - Map> allLinks) { - try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(dstFile))) { - outputTZEntry(jos, allBuiltZones, allRegionIds, allRules, allLinks); - } catch (Exception ex) { - System.out.println("Failed: " + ex.toString()); - ex.printStackTrace(); - System.exit(1); - } - } - - /** - * Outputs the timezone entry in the JAR file. - */ - private static void outputTZEntry(JarOutputStream jos, - Map> allBuiltZones, - Set allRegionIds, - Set allRules, - Map> allLinks) { - // this format is not publicly specified - try { - jos.putNextEntry(new ZipEntry("TZDB.dat")); - DataOutputStream out = new DataOutputStream(jos); - + private void outputFile(Path dstFile, String version, + SortedMap builtZones, + Map links) { + try (DataOutputStream out = new DataOutputStream(Files.newOutputStream(dstFile))) { // file version out.writeByte(1); // group out.writeUTF("TZDB"); // versions - String[] versionArray = allBuiltZones.keySet().toArray(new String[allBuiltZones.size()]); - out.writeShort(versionArray.length); - for (String version : versionArray) { - out.writeUTF(version); - } + out.writeShort(1); + out.writeUTF(version); // regions - String[] regionArray = allRegionIds.toArray(new String[allRegionIds.size()]); + String[] regionArray = builtZones.keySet().toArray(new String[builtZones.size()]); out.writeShort(regionArray.length); for (String regionId : regionArray) { out.writeUTF(regionId); } - // rules - List rulesList = new ArrayList<>(allRules); + // rules -- hashset -> remove the dup + List rulesList = new ArrayList<>(new HashSet<>(builtZones.values())); out.writeShort(rulesList.size()); ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); for (ZoneRules rules : rulesList) { @@ -357,27 +246,22 @@ out.write(bytes); } // link version-region-rules - for (String version : allBuiltZones.keySet()) { - out.writeShort(allBuiltZones.get(version).size()); - for (Map.Entry entry : allBuiltZones.get(version).entrySet()) { - int regionIndex = Arrays.binarySearch(regionArray, entry.getKey()); - int rulesIndex = rulesList.indexOf(entry.getValue()); - out.writeShort(regionIndex); - out.writeShort(rulesIndex); - } + out.writeShort(builtZones.size()); + for (Map.Entry entry : builtZones.entrySet()) { + int regionIndex = Arrays.binarySearch(regionArray, entry.getKey()); + int rulesIndex = rulesList.indexOf(entry.getValue()); + out.writeShort(regionIndex); + out.writeShort(rulesIndex); } // alias-region - for (String version : allLinks.keySet()) { - out.writeShort(allLinks.get(version).size()); - for (Map.Entry entry : allLinks.get(version).entrySet()) { - int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey()); - int regionIndex = Arrays.binarySearch(regionArray, entry.getValue()); - out.writeShort(aliasIndex); - out.writeShort(regionIndex); - } + out.writeShort(links.size()); + for (Map.Entry entry : links.entrySet()) { + int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey()); + int regionIndex = Arrays.binarySearch(regionArray, entry.getValue()); + out.writeShort(aliasIndex); + out.writeShort(regionIndex); } out.flush(); - jos.closeEntry(); } catch (Exception ex) { System.out.println("Failed: " + ex.toString()); ex.printStackTrace(); @@ -385,76 +269,30 @@ } } - //----------------------------------------------------------------------- + private static final Pattern YEAR = Pattern.compile("(?i)(?min)|(?max)|(?only)|(?[0-9]+)"); + private static final Pattern MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)"); + private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher(""); + private static final Matcher TIME = Pattern.compile("(?-)?+(?[0-9]{1,2})(:(?[0-5][0-9]))?+(:(?[0-5][0-9]))?+").matcher(""); + /** The TZDB rules. */ private final Map> rules = new HashMap<>(); /** The TZDB zones. */ private final Map> zones = new HashMap<>(); + /** The TZDB links. */ - private final Map links = new HashMap<>(); /** The built zones. */ private final SortedMap builtZones = new TreeMap<>(); - - /** The version to produce. */ - private final String version; - - /** The source files. */ - - private final List sourceFiles; - - /** The version to produce. */ - private final boolean verbose; - - /** - * Creates an instance if you want to invoke the compiler manually. - * - * @param version the version, such as 2009a, not null - * @param sourceFiles the list of source files, not empty, not null - * @param verbose whether to output verbose messages - */ - public TzdbZoneRulesCompiler(String version, List sourceFiles, boolean verbose) { - this.version = version; - this.sourceFiles = sourceFiles; - this.verbose = verbose; - } + /** Whether to output verbose messages. */ + private boolean verbose; /** - * Compile the rules file. - *

- * Use {@link #getZones()} to retrieve the parsed data. - * - * @throws Exception if an error occurs + * private contructor */ - public void compile() throws Exception { - printVerbose("Compiling TZDB version " + version); - parseFiles(); - buildZoneRules(); - printVerbose("Compiled TZDB version " + version); - } - - /** - * Gets the parsed zone rules. - * - * @return the parsed zone rules, not null - */ - public SortedMap getZones() { - return builtZones; - } - - /** - * Parses the source files. - * - * @throws Exception if an error occurs - */ - private void parseFiles() throws Exception { - for (File file : sourceFiles) { - printVerbose("Parsing file: " + file); - parseFile(file); - } + private TzdbZoneRulesCompiler() { } /** @@ -463,14 +301,14 @@ * @param file the file being read, not null * @throws Exception if an error occurs */ - private void parseFile(File file) throws Exception { + private void parseFile(Path file) throws Exception { int lineNumber = 1; String line = null; - BufferedReader in = null; try { - in = new BufferedReader(new FileReader(file)); + List lines = Files.readAllLines(file, StandardCharsets.ISO_8859_1); List openZone = null; - for ( ; (line = in.readLine()) != null; lineNumber++) { + for (; lineNumber < lines.size(); lineNumber++) { + line = lines.get(lineNumber); int index = line.indexOf('#'); // remove comments (doesn't handle # in quotes) if (index >= 0) { line = line.substring(0, index); @@ -478,41 +316,43 @@ if (line.trim().length() == 0) { // ignore blank lines continue; } - StringTokenizer st = new StringTokenizer(line, " \t"); - if (openZone != null && Character.isWhitespace(line.charAt(0)) && st.hasMoreTokens()) { - if (parseZoneLine(st, openZone)) { + Scanner s = new Scanner(line); + if (openZone != null && Character.isWhitespace(line.charAt(0)) && s.hasNext()) { + if (parseZoneLine(s, openZone)) { openZone = null; } } else { - if (st.hasMoreTokens()) { - String first = st.nextToken(); + if (s.hasNext()) { + String first = s.next(); if (first.equals("Zone")) { - if (st.countTokens() < 3) { + openZone = new ArrayList<>(); + try { + zones.put(s.next(), openZone); + if (parseZoneLine(s, openZone)) { + openZone = null; + } + } catch (NoSuchElementException x) { printVerbose("Invalid Zone line in file: " + file + ", line: " + line); throw new IllegalArgumentException("Invalid Zone line"); } - openZone = new ArrayList<>(); - zones.put(st.nextToken(), openZone); - if (parseZoneLine(st, openZone)) { - openZone = null; - } } else { openZone = null; if (first.equals("Rule")) { - if (st.countTokens() < 9) { + try { + parseRuleLine(s); + } catch (NoSuchElementException x) { printVerbose("Invalid Rule line in file: " + file + ", line: " + line); throw new IllegalArgumentException("Invalid Rule line"); } - parseRuleLine(st); - } else if (first.equals("Link")) { - if (st.countTokens() < 2) { + try { + String realId = s.next(); + String aliasId = s.next(); + links.put(aliasId, realId); + } catch (NoSuchElementException x) { printVerbose("Invalid Link line in file: " + file + ", line: " + line); throw new IllegalArgumentException("Invalid Link line"); } - String realId = st.nextToken(); - String aliasId = st.nextToken(); - links.put(aliasId, realId); } else { throw new IllegalArgumentException("Unknown line"); @@ -522,52 +362,44 @@ } } } catch (Exception ex) { - throw new Exception("Failed while processing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex); - } finally { - try { - if (in != null) { - in.close(); - } - } catch (Exception ex) { - // ignore NPE and IOE - } + throw new Exception("Failed while parsing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex); } } /** * Parses a Rule line. * - * @param st the tokenizer, not null + * @param s the line scanner, not null */ - private void parseRuleLine(StringTokenizer st) { + private void parseRuleLine(Scanner s) { TZDBRule rule = new TZDBRule(); - String name = st.nextToken(); + String name = s.next(); if (rules.containsKey(name) == false) { rules.put(name, new ArrayList()); } rules.get(name).add(rule); - rule.startYear = parseYear(st.nextToken(), 0); - rule.endYear = parseYear(st.nextToken(), rule.startYear); + rule.startYear = parseYear(s, 0); + rule.endYear = parseYear(s, rule.startYear); if (rule.startYear > rule.endYear) { throw new IllegalArgumentException("Year order invalid: " + rule.startYear + " > " + rule.endYear); } - parseOptional(st.nextToken()); // type is unused - parseMonthDayTime(st, rule); - rule.savingsAmount = parsePeriod(st.nextToken()); - rule.text = parseOptional(st.nextToken()); + parseOptional(s.next()); // type is unused + parseMonthDayTime(s, rule); + rule.savingsAmount = parsePeriod(s.next()); + rule.text = parseOptional(s.next()); } /** * Parses a Zone line. * - * @param st the tokenizer, not null + * @param s the line scanner, not null * @return true if the zone is complete */ - private boolean parseZoneLine(StringTokenizer st, List zoneList) { + private boolean parseZoneLine(Scanner s, List zoneList) { TZDBZone zone = new TZDBZone(); zoneList.add(zone); - zone.standardOffset = parseOffset(st.nextToken()); - String savingsRule = parseOptional(st.nextToken()); + zone.standardOffset = parseOffset(s.next()); + String savingsRule = parseOptional(s.next()); if (savingsRule == null) { zone.fixedSavingsSecs = 0; zone.savingsRule = null; @@ -580,11 +412,11 @@ zone.savingsRule = savingsRule; } } - zone.text = st.nextToken(); - if (st.hasMoreTokens()) { - zone.year = Integer.parseInt(st.nextToken()); - if (st.hasMoreTokens()) { - parseMonthDayTime(st, zone); + zone.text = s.next(); + if (s.hasNext()) { + zone.year = Integer.parseInt(s.next()); + if (s.hasNext()) { + parseMonthDayTime(s, zone); } return false; } else { @@ -595,13 +427,13 @@ /** * Parses a Rule line. * - * @param st the tokenizer, not null + * @param s the line scanner, not null * @param mdt the object to parse into, not null */ - private void parseMonthDayTime(StringTokenizer st, TZDBMonthDayTime mdt) { - mdt.month = parseMonth(st.nextToken()); - if (st.hasMoreTokens()) { - String dayRule = st.nextToken(); + private void parseMonthDayTime(Scanner s, TZDBMonthDayTime mdt) { + mdt.month = parseMonth(s); + if (s.hasNext()) { + String dayRule = s.next(); if (dayRule.startsWith("last")) { mdt.dayOfMonth = -1; mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(4)); @@ -621,8 +453,8 @@ } mdt.dayOfMonth = Integer.parseInt(dayRule); } - if (st.hasMoreTokens()) { - String timeStr = st.nextToken(); + if (s.hasNext()) { + String timeStr = s.next(); int secsOfDay = parseSecs(timeStr); if (secsOfDay == 86400) { mdt.endOfDay = true; @@ -635,30 +467,43 @@ } } - private int parseYear(String str, int defaultYear) { - if (YEAR.reset(str).matches()) { - if (YEAR.group("min") != null) { - //return YEAR_MIN_VALUE; + private int parseYear(Scanner s, int defaultYear) { + if (s.hasNext(YEAR)) { + s.next(YEAR); + MatchResult mr = s.match(); + if (mr.group(1) != null) { return 1900; // systemv has min - } else if (YEAR.group("max") != null) { + } else if (mr.group(2) != null) { return YEAR_MAX_VALUE; - } else if (YEAR.group("only") != null) { + } else if (mr.group(3) != null) { return defaultYear; } - return Integer.parseInt(YEAR.group("year")); + return Integer.parseInt(mr.group(4)); + /* + if (mr.group("min") != null) { + //return YEAR_MIN_VALUE; + return 1900; // systemv has min + } else if (mr.group("max") != null) { + return YEAR_MAX_VALUE; + } else if (mr.group("only") != null) { + return defaultYear; + } + return Integer.parseInt(mr.group("year")); + */ } - throw new IllegalArgumentException("Unknown year: " + str); + throw new IllegalArgumentException("Unknown year: " + s.next()); } - private int parseMonth(String str) { - if (MONTH.reset(str).matches()) { + private int parseMonth(Scanner s) { + if (s.hasNext(MONTH)) { + s.next(MONTH); for (int moy = 1; moy < 13; moy++) { - if (MONTH.group(moy) != null) { + if (s.match().group(moy) != null) { return moy; } } } - throw new IllegalArgumentException("Unknown month: " + str); + throw new IllegalArgumentException("Unknown month: " + s.next()); } private int parseDayOfWeek(String str) { @@ -729,7 +574,6 @@ } } - //----------------------------------------------------------------------- /** * Build the rules, zones and links into real zones. * @@ -744,8 +588,7 @@ for (TZDBZone tzdbZone : tzdbZones) { bld = tzdbZone.addToBuilder(bld, rules); } - ZoneRules buildRules = bld.toRules(zoneId); - builtZones.put(zoneId, buildRules); + builtZones.put(zoneId, bld.toRules(zoneId)); } // build aliases @@ -758,25 +601,25 @@ printVerbose("Relinking alias " + aliasId + " to " + realId); realRules = builtZones.get(realId); if (realRules == null) { - throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId + "' for '" + version + "'"); + throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId); } links.put(aliasId, realId); - } builtZones.put(aliasId, realRules); } - // remove UTC and GMT - //builtZones.remove("UTC"); - //builtZones.remove("GMT"); - //builtZones.remove("GMT0"); + // builtZones.remove("UTC"); + // builtZones.remove("GMT"); + // builtZones.remove("GMT0"); builtZones.remove("GMT+0"); builtZones.remove("GMT-0"); links.remove("GMT+0"); links.remove("GMT-0"); + // remove ROC, which is not supported in j.u.tz + builtZones.remove("ROC"); + links.remove("ROC"); } - //----------------------------------------------------------------------- /** * Prints a verbose message. * @@ -788,7 +631,6 @@ } } - //----------------------------------------------------------------------- /** * Class representing a month-day-time in the TZDB file. */ @@ -893,5 +735,4 @@ return ldt; } } - } diff -r bb098a221d85 -r 4b8e606f8afb makefiles/CopyFiles.gmk --- a/makefiles/CopyFiles.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/CopyFiles.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -174,6 +174,13 @@ COPY_FILES += $(LIBDIR)/calendars.properties +$(LIBDIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties + $(MKDIR) -p $(@D) + $(RM) $@ + $(CP) $< $@ + +COPY_FILES += $(LIBDIR)/hijrah-config-umalqura.properties + ########################################################################################## ifeq ($(OPENJDK_TARGET_OS),windows) diff -r bb098a221d85 -r 4b8e606f8afb makefiles/CreateJars.gmk --- a/makefiles/CreateJars.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/CreateJars.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -73,11 +73,6 @@ ########################################################################################## -$(IMAGES_OUTPUTDIR)/lib/tzdb.jar: $(JDK_OUTPUTDIR)/lib/tzdb.jar - $(install-file) - -########################################################################################## - LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in is it \ iw ja ko lt lv mk ms mt nl no pl pt ro ru sk sl sq sr sv \ th tr uk vi zh diff -r bb098a221d85 -r 4b8e606f8afb makefiles/GendataTZDB.gmk --- a/makefiles/GendataTZDB.gmk Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/GendataTZDB.gmk Wed Apr 17 21:48:04 2013 -0700 @@ -29,16 +29,13 @@ # Time zone data file creation # TZDATA_DIR := $(JDK_TOPDIR)/make/sun/javazic/tzdata -TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION)) TZDATA_TZFILE := africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera gmt jdk11_backward TZDATA_TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZDATA_TZFILE)) -GENDATA_TZDB_DST := $(JDK_OUTPUTDIR)/lib -GENDATA_TZDB_JAR := tzdb.jar +GENDATA_TZDB_DAT := $(JDK_OUTPUTDIR)/lib/tzdb.dat -$(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) : $(TZDATA_TZFILES) - $(RM) $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) - echo building tzdb from version $(TZDATA_VER) - $(TOOL_TZDB) -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(GENDATA_TZDB_DST) $(TZDATA_TZFILE) +$(GENDATA_TZDB_DAT) : $(TZDATA_TZFILES) + $(RM) $(GENDATA_TZDB_DAT) + $(TOOL_TZDB) -srcdir $(TZDATA_DIR) -dstfile $(GENDATA_TZDB_DAT) $(TZDATA_TZFILE) -GENDATA_TZDB += $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) +GENDATA_TZDB += $(GENDATA_TZDB_DAT) diff -r bb098a221d85 -r 4b8e606f8afb makefiles/mapfiles/libjava/mapfile-vers --- a/makefiles/mapfiles/libjava/mapfile-vers Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/mapfiles/libjava/mapfile-vers Wed Apr 17 21:48:04 2013 -0700 @@ -134,7 +134,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; - Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_registerNatives; Java_java_lang_Compiler_registerNatives; Java_java_lang_Double_longBitsToDouble; @@ -217,7 +216,7 @@ Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_lang_UNIXProcess_initIDs; + Java_java_lang_UNIXProcess_init; Java_java_lang_UNIXProcess_waitForProcessExit; Java_java_lang_UNIXProcess_forkAndExec; Java_java_lang_UNIXProcess_destroyProcess; @@ -233,7 +232,6 @@ Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext; - Java_java_util_ResourceBundle_getClassContext; Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; diff -r bb098a221d85 -r 4b8e606f8afb makefiles/mapfiles/libjava/reorder-sparc --- a/makefiles/mapfiles/libjava/reorder-sparc Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/mapfiles/libjava/reorder-sparc Wed Apr 17 21:48:04 2013 -0700 @@ -78,7 +78,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb makefiles/mapfiles/libjava/reorder-sparcv9 --- a/makefiles/mapfiles/libjava/reorder-sparcv9 Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/mapfiles/libjava/reorder-sparcv9 Wed Apr 17 21:48:04 2013 -0700 @@ -74,7 +74,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb makefiles/mapfiles/libjava/reorder-x86 --- a/makefiles/mapfiles/libjava/reorder-x86 Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/mapfiles/libjava/reorder-x86 Wed Apr 17 21:48:04 2013 -0700 @@ -73,7 +73,6 @@ # Test Sleep # Test IntToString # Test LoadToolkit -text: .text%Java_java_util_ResourceBundle_getClassContext; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%JNU_GetEnv; text: .text%Java_java_io_UnixFileSystem_checkAccess; diff -r bb098a221d85 -r 4b8e606f8afb makefiles/profile-includes.txt --- a/makefiles/profile-includes.txt Wed Apr 17 21:32:11 2013 -0700 +++ b/makefiles/profile-includes.txt Wed Apr 17 21:48:04 2013 -0700 @@ -66,6 +66,7 @@ ext/sunec.jar \ ext/sunjce_provider.jar \ ext/sunpkcs11.jar \ + hijrah-config-umalqura.properties \ jce.jar \ jsse.jar \ logging.properties \ @@ -80,7 +81,7 @@ security/java.security \ security/local_policy.jar \ security/trusted.libraries \ - tzdb.jar + tzdb.dat PROFILE_1_JRE_OTHER_FILES := \ COPYRIGHT \ @@ -100,9 +101,7 @@ resources.jar \ rt.jar \ security/US_export_policy.jar \ - security/local_policy.jar \ - tzdb.jar - + security/local_policy.jar PROFILE_2_JRE_BIN_FILES := \ rmid$(EXE_SUFFIX) \ diff -r bb098a221d85 -r 4b8e606f8afb src/macosx/classes/sun/lwawt/LWWindowPeer.java --- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Apr 17 21:48:04 2013 -0700 @@ -170,7 +170,7 @@ setTitle(((Dialog) getTarget()).getTitle()); } - setAlwaysOnTop(getTarget().isAlwaysOnTop()); + updateAlwaysOnTopState(); updateMinimumSize(); final Shape shape = getTarget().getShape(); @@ -357,8 +357,8 @@ } @Override - public void setAlwaysOnTop(boolean value) { - platformWindow.setAlwaysOnTop(value); + public void updateAlwaysOnTopState() { + platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop()); } @Override diff -r bb098a221d85 -r 4b8e606f8afb src/macosx/classes/sun/lwawt/macosx/CFileDialog.java --- a/src/macosx/classes/sun/lwawt/macosx/CFileDialog.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/CFileDialog.java Wed Apr 17 21:48:04 2013 -0700 @@ -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 @@ -180,7 +180,7 @@ } @Override - public void setAlwaysOnTop(boolean alwaysOnTop) { + public void updateAlwaysOnTopState() { } @Override diff -r bb098a221d85 -r 4b8e606f8afb src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java --- a/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java Wed Apr 17 21:48:04 2013 -0700 @@ -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 @@ -87,7 +87,7 @@ } // 1.6 peer method - public void setAlwaysOnTop(boolean value) { + public void updateAlwaysOnTopState() { // no-op, since we just show the native print dialog } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/CipherCore.java --- a/src/share/classes/com/sun/crypto/provider/CipherCore.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java Wed Apr 17 21:48:04 2013 -0700 @@ -426,17 +426,13 @@ } } try { - params = AlgorithmParameters.getInstance(algName, "SunJCE"); + params = AlgorithmParameters.getInstance(algName, + SunJCE.getInstance()); + params.init(spec); } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("Cannot find " + algName + " AlgorithmParameters implementation in SunJCE provider"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("Cannot find SunJCE provider"); - } - try { - params.init(spec); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException(spec.getClass() + " not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java --- a/src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -169,7 +169,8 @@ try { KeyFactory keyFactory = - KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE"); + KeyFactory.getInstance(encodedKeyAlgorithm, + SunJCE.getInstance()); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey); key = keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException nsae) { @@ -191,8 +192,6 @@ } } catch (InvalidKeySpecException ikse) { // Should never happen. - } catch (NoSuchProviderException nspe) { - // Should never happen. } return key; @@ -215,7 +214,8 @@ try { KeyFactory keyFactory = - KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE"); + KeyFactory.getInstance(encodedKeyAlgorithm, + SunJCE.getInstance()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException nsae) { @@ -237,8 +237,6 @@ } } catch (InvalidKeySpecException ikse) { // Should never happen. - } catch (NoSuchProviderException nspe) { - // Should never happen. } return key; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/ConstructKeys.java --- a/src/share/classes/com/sun/crypto/provider/ConstructKeys.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/ConstructKeys.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -30,7 +30,6 @@ import java.security.PrivateKey; import java.security.KeyFactory; import java.security.InvalidKeyException; -import java.security.NoSuchProviderException; import java.security.NoSuchAlgorithmException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; @@ -66,7 +65,8 @@ try { KeyFactory keyFactory = - KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE"); + KeyFactory.getInstance(encodedKeyAlgorithm, + SunJCE.getInstance()); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey); key = keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException nsae) { @@ -94,8 +94,6 @@ new InvalidKeyException("Cannot construct public key"); ike.initCause(ikse); throw ike; - } catch (NoSuchProviderException nspe) { - // Should never happen. } return key; @@ -118,7 +116,8 @@ try { KeyFactory keyFactory = - KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE"); + KeyFactory.getInstance(encodedKeyAlgorithm, + SunJCE.getInstance()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException nsae) { @@ -146,8 +145,6 @@ new InvalidKeyException("Cannot construct private key"); ike.initCause(ikse); throw ike; - } catch (NoSuchProviderException nspe) { - // Should never happen. } return key; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java --- a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java Wed Apr 17 21:48:04 2013 -0700 @@ -389,17 +389,13 @@ if (iv != null) { String algo = cipherKey.getAlgorithm(); try { - params = AlgorithmParameters.getInstance(algo, "SunJCE"); + params = AlgorithmParameters.getInstance(algo, + SunJCE.getInstance()); + params.init(new IvParameterSpec(iv)); } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("Cannot find " + algo + " AlgorithmParameters implementation in SunJCE provider"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("Cannot find SunJCE provider"); - } - try { - params.init(new IvParameterSpec(iv)); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("IvParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java --- a/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java Wed Apr 17 21:48:04 2013 -0700 @@ -151,7 +151,8 @@ dhParamSpec = new DHParameterSpec(dsaParamSpec.getP(), dsaParamSpec.getG()); } - algParams = AlgorithmParameters.getInstance("DH", "SunJCE"); + algParams = AlgorithmParameters.getInstance("DH", + SunJCE.getInstance()); algParams.init(dhParamSpec); } catch (InvalidParameterSpecException e) { // this should never happen @@ -159,11 +160,7 @@ } catch (NoSuchAlgorithmException e) { // this should never happen, because we provide it throw new RuntimeException(e.getMessage()); - } catch (NoSuchProviderException e) { - // this should never happen, because we provide it - throw new RuntimeException(e.getMessage()); } - return algParams; } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/KeyProtector.java --- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java Wed Apr 17 21:48:04 2013 -0700 @@ -81,8 +81,6 @@ // key protector private char[] password; - private static final Provider PROV = Security.getProvider("SunJCE"); - KeyProtector(char[] password) { if (password == null) { throw new IllegalArgumentException("password can't be null"); @@ -119,7 +117,7 @@ // wrap encrypted private key in EncryptedPrivateKeyInfo // (as defined in PKCS#8) AlgorithmParameters pbeParams = - AlgorithmParameters.getInstance("PBE", PROV); + AlgorithmParameters.getInstance("PBE", SunJCE.getInstance()); pbeParams.init(pbeSpec); AlgorithmId encrAlg = new AlgorithmId @@ -299,7 +297,7 @@ PBEWithMD5AndTripleDESCipher cipherSpi; cipherSpi = new PBEWithMD5AndTripleDESCipher(); - cipher = new CipherForKeyProtector(cipherSpi, PROV, + cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(), "PBEWithMD5AndTripleDES"); cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec); return new SealedObjectForKeyProtector(key, cipher); @@ -330,8 +328,9 @@ } PBEWithMD5AndTripleDESCipher cipherSpi; cipherSpi = new PBEWithMD5AndTripleDESCipher(); - Cipher cipher = new CipherForKeyProtector(cipherSpi, PROV, - "PBEWithMD5AndTripleDES"); + Cipher cipher = new CipherForKeyProtector(cipherSpi, + SunJCE.getInstance(), + "PBEWithMD5AndTripleDES"); cipher.init(Cipher.DECRYPT_MODE, skey, params); return (Key)soForKeyProtector.getObject(cipher); } catch (NoSuchAlgorithmException ex) { diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/PBECipherCore.java --- a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java Wed Apr 17 21:48:04 2013 -0700 @@ -169,16 +169,12 @@ PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount); try { params = AlgorithmParameters.getInstance("PBEWithMD5And" + - (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), "SunJCE"); + (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), + SunJCE.getInstance()); + params.init(pbeSpec); } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("SunJCE called, but not configured"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("SunJCE called, but not configured"); - } - try { - params.init(pbeSpec); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("PBEParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/PBES1Core.java --- a/src/share/classes/com/sun/crypto/provider/PBES1Core.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java Wed Apr 17 21:48:04 2013 -0700 @@ -169,16 +169,12 @@ PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount); try { params = AlgorithmParameters.getInstance("PBEWithMD5And" + - (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), "SunJCE"); + (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), + SunJCE.getInstance()); + params.init(pbeSpec); } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("SunJCE called, but not configured"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("SunJCE called, but not configured"); - } - try { - params.init(pbeSpec); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("PBEParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/PBES2Core.java --- a/src/share/classes/com/sun/crypto/provider/PBES2Core.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/PBES2Core.java Wed Apr 17 21:48:04 2013 -0700 @@ -25,11 +25,9 @@ package com.sun.crypto.provider; -import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.*; import javax.crypto.*; -import javax.crypto.interfaces.*; import javax.crypto.spec.*; /** @@ -145,16 +143,12 @@ } PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec); try { - params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE"); + params = AlgorithmParameters.getInstance(pbeAlgo, + SunJCE.getInstance()); + params.init(pbeSpec); } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("SunJCE called, but not configured"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("SunJCE called, but not configured"); - } - try { - params.init(pbeSpec); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("PBEParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java --- a/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -33,7 +33,6 @@ import java.security.KeyRep; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.spec.InvalidKeySpecException; import javax.crypto.Mac; import javax.crypto.SecretKey; @@ -102,21 +101,16 @@ int keyLength = keySpec.getKeyLength(); if (keyLength == 0) { throw new InvalidKeySpecException("Key length not found"); - } else if (keyLength == 0) { + } else if (keyLength < 0) { throw new InvalidKeySpecException("Key length is negative"); } try { - this.prf = Mac.getInstance(prfAlgo, "SunJCE"); + this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance()); } catch (NoSuchAlgorithmException nsae) { // not gonna happen; re-throw just in case InvalidKeySpecException ike = new InvalidKeySpecException(); ike.initCause(nsae); throw ike; - } catch (NoSuchProviderException nspe) { - // Again, not gonna happen; re-throw just in case - InvalidKeySpecException ike = new InvalidKeySpecException(); - ike.initCause(nspe); - throw ike; } this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength); } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java --- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java Wed Apr 17 21:48:04 2013 -0700 @@ -25,7 +25,6 @@ package com.sun.crypto.provider; -import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.*; import java.security.spec.*; @@ -232,14 +231,13 @@ } PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount); try { - params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE"); - } catch (GeneralSecurityException gse) { + params = AlgorithmParameters.getInstance(pbeAlgo, + SunJCE.getInstance()); + params.init(pbeSpec); + } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException( "SunJCE provider is not configured properly"); - } - try { - params.init(pbeSpec); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("PBEParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/RSACipher.java --- a/src/share/classes/com/sun/crypto/provider/RSACipher.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/RSACipher.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -178,16 +178,14 @@ if (spec != null) { try { AlgorithmParameters params = - AlgorithmParameters.getInstance("OAEP", "SunJCE"); + AlgorithmParameters.getInstance("OAEP", + SunJCE.getInstance()); params.init(spec); return params; } catch (NoSuchAlgorithmException nsae) { // should never happen throw new RuntimeException("Cannot find OAEP " + " AlgorithmParameters implementation in SunJCE provider"); - } catch (NoSuchProviderException nspe) { - // should never happen - throw new RuntimeException("Cannot find SunJCE provider"); } catch (InvalidParameterSpecException ipse) { // should never happen throw new RuntimeException("OAEPParameterSpec not supported"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java --- a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -46,14 +46,15 @@ AlgorithmParameters params = null; if (super.encodedParams != null) { try { - params = AlgorithmParameters.getInstance("PBE", "SunJCE"); + params = AlgorithmParameters.getInstance("PBE", + SunJCE.getInstance()); params.init(super.encodedParams); - } catch (NoSuchProviderException nspe) { - // eat. } catch (NoSuchAlgorithmException nsae) { - //eat. - } catch (IOException ioe) { - //eat. + throw new RuntimeException( + "SunJCE provider is not configured properly"); + } catch (IOException io) { + throw new RuntimeException("Parameter failure: "+ + io.getMessage()); } } return params; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/SunJCE.java --- a/src/share/classes/com/sun/crypto/provider/SunJCE.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java Wed Apr 17 21:48:04 2013 -0700 @@ -91,6 +91,10 @@ /* Are we debugging? -- for developers */ static final boolean debug = false; + // Instance of this provider, so we don't have to call the provider list + // to find ourselves or run the risk of not being in the list. + private static volatile SunJCE instance = null; + // lazy initialize SecureRandom to avoid potential recursion if Sun // provider has not been installed yet private static class SecureRandomHolder { @@ -770,5 +774,17 @@ return null; } }); + + if (instance == null) { + instance = this; + } + } + + // Return the instance of this class or create one if needed. + static SunJCE getInstance() { + if (instance == null) { + return new SunJCE(); + } + return instance; } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java --- a/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -165,16 +165,18 @@ // partition keyblock into individual secrets int ofs = 0; - byte[] tmp = new byte[macLength]; + if (macLength != 0) { + byte[] tmp = new byte[macLength]; - // mac keys - System.arraycopy(keyBlock, ofs, tmp, 0, macLength); - ofs += macLength; - clientMacKey = new SecretKeySpec(tmp, "Mac"); + // mac keys + System.arraycopy(keyBlock, ofs, tmp, 0, macLength); + ofs += macLength; + clientMacKey = new SecretKeySpec(tmp, "Mac"); - System.arraycopy(keyBlock, ofs, tmp, 0, macLength); - ofs += macLength; - serverMacKey = new SecretKeySpec(tmp, "Mac"); + System.arraycopy(keyBlock, ofs, tmp, 0, macLength); + ofs += macLength; + serverMacKey = new SecretKeySpec(tmp, "Mac"); + } if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites return new TlsKeyMaterialSpec(clientMacKey, serverMacKey); @@ -198,7 +200,7 @@ // IV keys if needed. if (ivLength != 0) { - tmp = new byte[ivLength]; + byte[] tmp = new byte[ivLength]; System.arraycopy(keyBlock, ofs, tmp, 0, ivLength); ofs += ivLength; @@ -220,8 +222,8 @@ // TLS 1.0 byte[] seed = concat(clientRandom, serverRandom); - tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed, - expandedKeyLength, md5, sha); + byte[] tmp = doTLS10PRF(clientKeyBytes, + LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha); clientCipherKey = new SecretKeySpec(tmp, alg); tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed, @@ -239,7 +241,7 @@ } } else { // SSLv3 - tmp = new byte[expandedKeyLength]; + byte[] tmp = new byte[expandedKeyLength]; md5.update(clientKeyBytes); md5.update(clientRandom); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java --- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Wed Apr 17 21:48:04 2013 -0700 @@ -243,12 +243,17 @@ * sending warnings to listeners. */ protected void warningOccurred(int code) { - if ((code < 0) || (code > MAX_WARNING)){ - throw new InternalError("Invalid warning index"); + cbLock.lock(); + try { + if ((code < 0) || (code > MAX_WARNING)){ + throw new InternalError("Invalid warning index"); + } + processWarningOccurred + ("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources", + Integer.toString(code)); + } finally { + cbLock.unlock(); } - processWarningOccurred - ("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources", - Integer.toString(code)); } /** @@ -265,7 +270,12 @@ * library warnings from being printed to stderr. */ protected void warningWithMessage(String msg) { - processWarningOccurred(msg); + cbLock.lock(); + try { + processWarningOccurred(msg); + } finally { + cbLock.unlock(); + } } public void setInput(Object input, @@ -274,18 +284,55 @@ { setThreadLock(); try { + cbLock.check(); + super.setInput(input, seekForwardOnly, ignoreMetadata); this.ignoreMetadata = ignoreMetadata; resetInternalState(); iis = (ImageInputStream) input; // Always works - setSource(structPointer, iis); + setSource(structPointer); } finally { clearThreadLock(); } } - private native void setSource(long structPointer, - ImageInputStream source); + /** + * This method is called from native code in order to fill + * native input buffer. + * + * We block any attempt to change the reading state during this + * method, in order to prevent a corruption of the native decoder + * state. + * + * @return number of bytes read from the stream. + */ + private int readInputData(byte[] buf, int off, int len) throws IOException { + cbLock.lock(); + try { + return iis.read(buf, off, len); + } finally { + cbLock.unlock(); + } + } + + /** + * This method is called from the native code in order to + * skip requested number of bytes in the input stream. + * + * @param n + * @return + * @throws IOException + */ + private long skipInputBytes(long n) throws IOException { + cbLock.lock(); + try { + return iis.skipBytes(n); + } finally { + cbLock.unlock(); + } + } + + private native void setSource(long structPointer); private void checkTablesOnly() throws IOException { if (debug) { @@ -337,6 +384,8 @@ public int getNumImages(boolean allowSearch) throws IOException { setThreadLock(); try { // locked thread + cbLock.check(); + return getNumImagesOnThread(allowSearch); } finally { clearThreadLock(); @@ -536,8 +585,13 @@ if (debug) { System.out.println("pushing back " + num + " bytes"); } - iis.seek(iis.getStreamPosition()-num); - // The buffer is clear after this, so no need to set haveSeeked. + cbLock.lock(); + try { + iis.seek(iis.getStreamPosition()-num); + // The buffer is clear after this, so no need to set haveSeeked. + } finally { + cbLock.unlock(); + } } /** @@ -644,7 +698,12 @@ * Ignore this profile. */ iccCS = null; - warningOccurred(WARNING_IGNORE_INVALID_ICC); + cbLock.lock(); + try { + warningOccurred(WARNING_IGNORE_INVALID_ICC); + } finally { + cbLock.unlock(); + } } } } @@ -653,6 +712,7 @@ setThreadLock(); try { if (currentImage != imageIndex) { + cbLock.check(); readHeader(imageIndex, true); } return width; @@ -665,6 +725,7 @@ setThreadLock(); try { if (currentImage != imageIndex) { + cbLock.check(); readHeader(imageIndex, true); } return height; @@ -693,6 +754,8 @@ setThreadLock(); try { if (currentImage != imageIndex) { + cbLock.check(); + readHeader(imageIndex, true); } @@ -716,6 +779,7 @@ private Iterator getImageTypesOnThread(int imageIndex) throws IOException { if (currentImage != imageIndex) { + cbLock.check(); readHeader(imageIndex, true); } @@ -931,6 +995,7 @@ setThreadLock(); try { if (!tablesOnlyChecked) { + cbLock.check(); checkTablesOnly(); } return streamMetadata; @@ -951,6 +1016,8 @@ return imageMetadata; } + cbLock.check(); + gotoImage(imageIndex); imageMetadata = new JPEGMetadata(false, false, iis, this); @@ -967,6 +1034,7 @@ throws IOException { setThreadLock(); try { + cbLock.check(); try { readInternal(imageIndex, param, false); } catch (RuntimeException e) { @@ -1196,58 +1264,63 @@ } target.setRect(destROI.x, destROI.y + y, raster); - processImageUpdate(image, - destROI.x, destROI.y+y, - raster.getWidth(), 1, - 1, 1, - destinationBands); - if ((y > 0) && (y%progInterval == 0)) { - int height = target.getHeight()-1; - float percentOfPass = ((float)y)/height; - if (progressive) { - if (knownPassCount != UNKNOWN) { - processImageProgress((pass + percentOfPass)*100.0F - / knownPassCount); - } else if (maxProgressivePass != Integer.MAX_VALUE) { - // Use the range of allowed progressive passes - processImageProgress((pass + percentOfPass)*100.0F - / (maxProgressivePass - minProgressivePass + 1)); + cbLock.lock(); + try { + processImageUpdate(image, + destROI.x, destROI.y+y, + raster.getWidth(), 1, + 1, 1, + destinationBands); + if ((y > 0) && (y%progInterval == 0)) { + int height = target.getHeight()-1; + float percentOfPass = ((float)y)/height; + if (progressive) { + if (knownPassCount != UNKNOWN) { + processImageProgress((pass + percentOfPass)*100.0F + / knownPassCount); + } else if (maxProgressivePass != Integer.MAX_VALUE) { + // Use the range of allowed progressive passes + processImageProgress((pass + percentOfPass)*100.0F + / (maxProgressivePass - minProgressivePass + 1)); + } else { + // Assume there are a minimum of MIN_ESTIMATED_PASSES + // and that there is always one more pass + // Compute the percentage as the percentage at the end + // of the previous pass, plus the percentage of this + // pass scaled to be the percentage of the total remaining, + // assuming a minimum of MIN_ESTIMATED_PASSES passes and + // that there is always one more pass. This is monotonic + // and asymptotic to 1.0, which is what we need. + int remainingPasses = // including this one + Math.max(2, MIN_ESTIMATED_PASSES-pass); + int totalPasses = pass + remainingPasses-1; + progInterval = Math.max(height/20*totalPasses, + totalPasses); + if (y%progInterval == 0) { + percentToDate = previousPassPercentage + + (1.0F - previousPassPercentage) + * (percentOfPass)/remainingPasses; + if (debug) { + System.out.print("pass= " + pass); + System.out.print(", y= " + y); + System.out.print(", progInt= " + progInterval); + System.out.print(", % of pass: " + percentOfPass); + System.out.print(", rem. passes: " + + remainingPasses); + System.out.print(", prev%: " + + previousPassPercentage); + System.out.print(", %ToDate: " + percentToDate); + System.out.print(" "); + } + processImageProgress(percentToDate*100.0F); + } + } } else { - // Assume there are a minimum of MIN_ESTIMATED_PASSES - // and that there is always one more pass - // Compute the percentage as the percentage at the end - // of the previous pass, plus the percentage of this - // pass scaled to be the percentage of the total remaining, - // assuming a minimum of MIN_ESTIMATED_PASSES passes and - // that there is always one more pass. This is monotonic - // and asymptotic to 1.0, which is what we need. - int remainingPasses = // including this one - Math.max(2, MIN_ESTIMATED_PASSES-pass); - int totalPasses = pass + remainingPasses-1; - progInterval = Math.max(height/20*totalPasses, - totalPasses); - if (y%progInterval == 0) { - percentToDate = previousPassPercentage + - (1.0F - previousPassPercentage) - * (percentOfPass)/remainingPasses; - if (debug) { - System.out.print("pass= " + pass); - System.out.print(", y= " + y); - System.out.print(", progInt= " + progInterval); - System.out.print(", % of pass: " + percentOfPass); - System.out.print(", rem. passes: " - + remainingPasses); - System.out.print(", prev%: " - + previousPassPercentage); - System.out.print(", %ToDate: " + percentToDate); - System.out.print(" "); - } - processImageProgress(percentToDate*100.0F); - } + processImageProgress(percentOfPass * 100.0F); } - } else { - processImageProgress(percentOfPass * 100.0F); } + } finally { + cbLock.unlock(); } } @@ -1260,33 +1333,58 @@ } private void passStarted (int pass) { - this.pass = pass; - previousPassPercentage = percentToDate; - processPassStarted(image, - pass, - minProgressivePass, - maxProgressivePass, - 0, 0, - 1,1, - destinationBands); + cbLock.lock(); + try { + this.pass = pass; + previousPassPercentage = percentToDate; + processPassStarted(image, + pass, + minProgressivePass, + maxProgressivePass, + 0, 0, + 1,1, + destinationBands); + } finally { + cbLock.unlock(); + } } private void passComplete () { - processPassComplete(image); + cbLock.lock(); + try { + processPassComplete(image); + } finally { + cbLock.unlock(); + } } void thumbnailStarted(int thumbnailIndex) { - processThumbnailStarted(currentImage, thumbnailIndex); + cbLock.lock(); + try { + processThumbnailStarted(currentImage, thumbnailIndex); + } finally { + cbLock.unlock(); + } } // Provide access to protected superclass method void thumbnailProgress(float percentageDone) { - processThumbnailProgress(percentageDone); + cbLock.lock(); + try { + processThumbnailProgress(percentageDone); + } finally { + cbLock.unlock(); + } } // Provide access to protected superclass method void thumbnailComplete() { - processThumbnailComplete(); + cbLock.lock(); + try { + processThumbnailComplete(); + } finally { + cbLock.unlock(); + } } /** @@ -1310,6 +1408,11 @@ public void abort() { setThreadLock(); try { + /** + * NB: we do not check the call back lock here, + * we allow to abort the reader any time. + */ + super.abort(); abortRead(structPointer); } finally { @@ -1332,6 +1435,7 @@ setThreadLock(); Raster retval = null; try { + cbLock.check(); /* * This could be further optimized by not resetting the dest. * offset and creating a translated raster in readInternal() @@ -1371,6 +1475,8 @@ public int getNumThumbnails(int imageIndex) throws IOException { setThreadLock(); try { + cbLock.check(); + getImageMetadata(imageIndex); // checks iis state for us // Now check the jfif segments JFIFMarkerSegment jfif = @@ -1391,6 +1497,8 @@ throws IOException { setThreadLock(); try { + cbLock.check(); + if ((thumbnailIndex < 0) || (thumbnailIndex >= getNumThumbnails(imageIndex))) { throw new IndexOutOfBoundsException("No such thumbnail"); @@ -1409,6 +1517,8 @@ throws IOException { setThreadLock(); try { + cbLock.check(); + if ((thumbnailIndex < 0) || (thumbnailIndex >= getNumThumbnails(imageIndex))) { throw new IndexOutOfBoundsException("No such thumbnail"); @@ -1428,6 +1538,8 @@ throws IOException { setThreadLock(); try { + cbLock.check(); + if ((thumbnailIndex < 0) || (thumbnailIndex >= getNumThumbnails(imageIndex))) { throw new IndexOutOfBoundsException("No such thumbnail"); @@ -1468,6 +1580,7 @@ public void reset() { setThreadLock(); try { + cbLock.check(); super.reset(); } finally { clearThreadLock(); @@ -1479,6 +1592,8 @@ public void dispose() { setThreadLock(); try { + cbLock.check(); + if (structPointer != 0) { disposerRecord.dispose(); structPointer = 0; @@ -1540,6 +1655,36 @@ theThread = null; } } + + private CallBackLock cbLock = new CallBackLock(); + + private static class CallBackLock { + + private State lockState; + + CallBackLock() { + lockState = State.Unlocked; + } + + void check() { + if (lockState != State.Unlocked) { + throw new IllegalStateException("Access to the reader is not allowed"); + } + } + + private void lock() { + lockState = State.Locked; + } + + private void unlock() { + lockState = State.Unlocked; + } + + private static enum State { + Unlocked, + Locked + } + } } /** diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java --- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Wed Apr 17 21:48:04 2013 -0700 @@ -183,8 +183,7 @@ return null; } }); - initWriterIDs(ImageOutputStream.class, - JPEGQTable.class, + initWriterIDs(JPEGQTable.class, JPEGHuffmanTable.class); } @@ -200,11 +199,13 @@ public void setOutput(Object output) { setThreadLock(); try { + cbLock.check(); + super.setOutput(output); // validates output resetInternalState(); ios = (ImageOutputStream) output; // so this will always work // Set the native destination - setDest(structPointer, ios); + setDest(structPointer); } finally { clearThreadLock(); } @@ -359,6 +360,8 @@ ImageWriteParam param) throws IOException { setThreadLock(); try { + cbLock.check(); + writeOnThread(streamMetadata, image, param); } finally { clearThreadLock(); @@ -1082,13 +1085,18 @@ haveMetadata, restartInterval); - if (aborted) { - processWriteAborted(); - } else { - processImageComplete(); + cbLock.lock(); + try { + if (aborted) { + processWriteAborted(); + } else { + processImageComplete(); + } + + ios.flush(); + } finally { + cbLock.unlock(); } - - ios.flush(); currentImage++; // After a successful write } @@ -1096,6 +1104,8 @@ throws IOException { setThreadLock(); try { + cbLock.check(); + prepareWriteSequenceOnThread(streamMetadata); } finally { clearThreadLock(); @@ -1175,6 +1185,8 @@ throws IOException { setThreadLock(); try { + cbLock.check(); + if (sequencePrepared == false) { throw new IllegalStateException("sequencePrepared not called!"); } @@ -1188,6 +1200,8 @@ public void endWriteSequence() throws IOException { setThreadLock(); try { + cbLock.check(); + if (sequencePrepared == false) { throw new IllegalStateException("sequencePrepared not called!"); } @@ -1200,6 +1214,10 @@ public synchronized void abort() { setThreadLock(); try { + /** + * NB: we do not check the call back lock here, we allow to abort + * the reader any time. + */ super.abort(); abortWrite(structPointer); } finally { @@ -1223,6 +1241,8 @@ public void reset() { setThreadLock(); try { + cbLock.check(); + super.reset(); } finally { clearThreadLock(); @@ -1232,6 +1252,8 @@ public void dispose() { setThreadLock(); try { + cbLock.check(); + if (structPointer != 0) { disposerRecord.dispose(); structPointer = 0; @@ -1251,13 +1273,18 @@ * sending warnings to listeners. */ void warningOccurred(int code) { - if ((code < 0) || (code > MAX_WARNING)){ - throw new InternalError("Invalid warning index"); + cbLock.lock(); + try { + if ((code < 0) || (code > MAX_WARNING)){ + throw new InternalError("Invalid warning index"); + } + processWarningOccurred + (currentImage, + "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources", + Integer.toString(code)); + } finally { + cbLock.unlock(); } - processWarningOccurred - (currentImage, - "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources", - Integer.toString(code)); } /** @@ -1274,21 +1301,41 @@ * library warnings from being printed to stderr. */ void warningWithMessage(String msg) { - processWarningOccurred(currentImage, msg); + cbLock.lock(); + try { + processWarningOccurred(currentImage, msg); + } finally { + cbLock.unlock(); + } } void thumbnailStarted(int thumbnailIndex) { - processThumbnailStarted(currentImage, thumbnailIndex); + cbLock.lock(); + try { + processThumbnailStarted(currentImage, thumbnailIndex); + } finally { + cbLock.unlock(); + } } // Provide access to protected superclass method void thumbnailProgress(float percentageDone) { - processThumbnailProgress(percentageDone); + cbLock.lock(); + try { + processThumbnailProgress(percentageDone); + } finally { + cbLock.unlock(); + } } // Provide access to protected superclass method void thumbnailComplete() { - processThumbnailComplete(); + cbLock.lock(); + try { + processThumbnailComplete(); + } finally { + cbLock.unlock(); + } } ///////// End of Package-access API @@ -1615,16 +1662,14 @@ ////////////// Native methods and callbacks /** Sets up static native structures. */ - private static native void initWriterIDs(Class iosClass, - Class qTableClass, + private static native void initWriterIDs(Class qTableClass, Class huffClass); /** Sets up per-writer native structure and returns a pointer to it. */ private native long initJPEGImageWriter(); /** Sets up native structures for output stream */ - private native void setDest(long structPointer, - ImageOutputStream ios); + private native void setDest(long structPointer); /** * Returns true if the write was aborted. @@ -1749,7 +1794,12 @@ } raster.setRect(sourceLine); if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines - processImageProgress((float) y / (float) sourceHeight * 100.0F); + cbLock.lock(); + try { + processImageProgress((float) y / (float) sourceHeight * 100.0F); + } finally { + cbLock.unlock(); + } } } @@ -1777,6 +1827,25 @@ } } + /** + * This method is called from native code in order to write encoder + * output to the destination. + * + * We block any attempt to change the writer state during this + * method, in order to prevent a corruption of the native encoder + * state. + */ + private void writeOutputData(byte[] data, int offset, int len) + throws IOException + { + cbLock.lock(); + try { + ios.write(data, offset, len); + } finally { + cbLock.unlock(); + } + } + private Thread theThread = null; private int theLockCount = 0; @@ -1811,4 +1880,34 @@ theThread = null; } } + + private CallBackLock cbLock = new CallBackLock(); + + private static class CallBackLock { + + private State lockState; + + CallBackLock() { + lockState = State.Unlocked; + } + + void check() { + if (lockState != State.Unlocked) { + throw new IllegalStateException("Access to the writer is not allowed"); + } + } + + private void lock() { + lockState = State.Locked; + } + + private void unlock() { + lockState = State.Unlocked; + } + + private static enum State { + Unlocked, + Locked + } + } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, 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 @@ -32,6 +32,7 @@ import java.io.ObjectInputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.security.Permission; import java.util.Map; import java.util.logging.Level; @@ -213,7 +214,6 @@ Object moi; - // ------------------------------ // ------------------------------ Constructor cons = findConstructor(theClass, null); @@ -224,6 +224,7 @@ // Instantiate the new object try { ReflectUtil.checkPackageAccess(theClass); + ensureClassAccess(theClass); moi= cons.newInstance(); } catch (InvocationTargetException e) { // Wrap the exception. @@ -270,7 +271,6 @@ checkMBeanPermission(theClass, null, null, "instantiate"); // Instantiate the new object - // ------------------------------ // ------------------------------ final Class[] tab; @@ -300,6 +300,7 @@ } try { ReflectUtil.checkPackageAccess(theClass); + ensureClassAccess(theClass); moi = cons.newInstance(params); } catch (NoSuchMethodError error) { @@ -741,4 +742,13 @@ sm.checkPermission(perm); } } + + private static void ensureClassAccess(Class clazz) + throws IllegalAccessException + { + int mod = clazz.getModifiers(); + if (!Modifier.isPublic(mod)) { + throw new IllegalAccessException("Class is not public and can't be instantiated"); + } + } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/media/sound/AbstractMidiDevice.java --- a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java Wed Apr 17 21:48:04 2013 -0700 @@ -56,7 +56,7 @@ // from simultaneous creation and destruction // reduces possibility of deadlock, compared to // synchronizing to the class instance - private Object traRecLock = new Object(); + private final Object traRecLock = new Object(); // DEVICE ATTRIBUTES @@ -474,7 +474,7 @@ This is necessary for Receivers retrieved via MidiSystem.getReceiver() (which opens the device implicitely). */ - protected abstract class AbstractReceiver implements MidiDeviceReceiver { + abstract class AbstractReceiver implements MidiDeviceReceiver { private boolean open = true; @@ -483,24 +483,24 @@ Receiver. Therefore, subclasses should not override this method. Instead, they should implement implSend(). */ - public synchronized void send(MidiMessage message, long timeStamp) { - if (open) { - implSend(message, timeStamp); - } else { + @Override + public final synchronized void send(final MidiMessage message, + final long timeStamp) { + if (!open) { throw new IllegalStateException("Receiver is not open"); } + implSend(message, timeStamp); } - - protected abstract void implSend(MidiMessage message, long timeStamp); - + abstract void implSend(MidiMessage message, long timeStamp); /** Close the Receiver. * Here, the call to the magic method closeInternal() takes place. * Therefore, subclasses that override this method must call * 'super.close()'. */ - public void close() { + @Override + public final void close() { open = false; synchronized (AbstractMidiDevice.this.traRecLock) { AbstractMidiDevice.this.getReceiverList().remove(this); @@ -508,11 +508,12 @@ AbstractMidiDevice.this.closeInternal(this); } - public MidiDevice getMidiDevice() { + @Override + public final MidiDevice getMidiDevice() { return AbstractMidiDevice.this; } - protected boolean isOpen() { + final boolean isOpen() { return open; } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/media/sound/FastShortMessage.java --- a/src/share/classes/com/sun/media/sound/FastShortMessage.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/media/sound/FastShortMessage.java Wed Apr 17 21:48:04 2013 -0700 @@ -32,7 +32,7 @@ * * @author Florian Bomers */ -class FastShortMessage extends ShortMessage { +final class FastShortMessage extends ShortMessage { private int packedMsg; public FastShortMessage(int packedMsg) throws InvalidMidiDataException { diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/media/sound/FastSysexMessage.java --- a/src/share/classes/com/sun/media/sound/FastSysexMessage.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/media/sound/FastSysexMessage.java Wed Apr 17 21:48:04 2013 -0700 @@ -32,7 +32,7 @@ * * @author Florian Bomers */ -class FastSysexMessage extends SysexMessage { +final class FastSysexMessage extends SysexMessage { FastSysexMessage(byte[] data) throws InvalidMidiDataException { super(data); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/media/sound/MidiOutDevice.java --- a/src/share/classes/com/sun/media/sound/MidiOutDevice.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/media/sound/MidiOutDevice.java Wed Apr 17 21:48:04 2013 -0700 @@ -103,9 +103,9 @@ class MidiOutReceiver extends AbstractReceiver { - protected void implSend(MidiMessage message, long timeStamp) { - int length = message.getLength(); - int status = message.getStatus(); + void implSend(final MidiMessage message, final long timeStamp) { + final int length = message.getLength(); + final int status = message.getStatus(); if (length <= 3 && status != 0xF0 && status != 0xF7) { int packedMsg; if (message instanceof ShortMessage) { @@ -140,11 +140,15 @@ } nSendShortMessage(id, packedMsg, timeStamp); } else { + final byte[] data; if (message instanceof FastSysexMessage) { - nSendLongMessage(id, ((FastSysexMessage) message).getReadOnlyMessage(), - length, timeStamp); + data = ((FastSysexMessage) message).getReadOnlyMessage(); } else { - nSendLongMessage(id, message.getMessage(), length, timeStamp); + data = message.getMessage(); + } + final int dataLength = Math.min(length, data.length); + if (dataLength > 0) { + nSendLongMessage(id, data, dataLength, timeStamp); } } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/media/sound/RealTimeSequencer.java --- a/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/media/sound/RealTimeSequencer.java Wed Apr 17 21:48:04 2013 -0700 @@ -1026,7 +1026,7 @@ class SequencerReceiver extends AbstractReceiver { - protected void implSend(MidiMessage message, long timeStamp) { + void implSend(MidiMessage message, long timeStamp) { if (recording) { long tickPos = 0; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/com/sun/tools/jdi/EventSetImpl.java --- a/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/com/sun/tools/jdi/EventSetImpl.java Wed Apr 17 21:48:04 2013 -0700 @@ -851,6 +851,11 @@ } } + @Override + public Spliterator spliterator() { + return Spliterators.spliterator(this, Spliterator.DISTINCT); + } + /* below make this unmodifiable */ public boolean add(Event o){ diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/awt/Window.java --- a/src/share/classes/java/awt/Window.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/awt/Window.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, 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 @@ -2234,7 +2234,7 @@ WindowPeer peer = (WindowPeer)this.peer; synchronized(getTreeLock()) { if (peer != null) { - peer.setAlwaysOnTop(alwaysOnTop); + peer.updateAlwaysOnTopState(); } } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/awt/peer/WindowPeer.java --- a/src/share/classes/java/awt/peer/WindowPeer.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/awt/peer/WindowPeer.java Wed Apr 17 21:48:04 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2009, 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 @@ -53,15 +53,14 @@ void toBack(); /** - * Sets if the window should always stay on top of all other windows or - * not. + * Updates the window's always-on-top state. + * Sets if the window should always stay + * on top of all other windows or not. * - * @param alwaysOnTop if the window should always stay on top of all other - * windows or not - * + * @see Window#getAlwaysOnTop() * @see Window#setAlwaysOnTop(boolean) */ - void setAlwaysOnTop(boolean alwaysOnTop); + void updateAlwaysOnTopState(); /** * Updates the window's focusable state. diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/beans/ThreadGroupContext.java --- a/src/share/classes/java/beans/ThreadGroupContext.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/beans/ThreadGroupContext.java Wed Apr 17 21:48:04 2013 -0700 @@ -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 @@ -29,7 +29,6 @@ import com.sun.beans.finder.PropertyEditorFinder; import java.awt.GraphicsEnvironment; -import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; @@ -42,7 +41,7 @@ */ final class ThreadGroupContext { - private static final Map contexts = new WeakHashMap<>(); + private static final WeakIdentityMap contexts = new WeakIdentityMap<>(); /** * Returns the appropriate {@code AppContext} for the caller, @@ -69,6 +68,8 @@ private BeanInfoFinder beanInfoFinder; private PropertyEditorFinder propertyEditorFinder; + private ThreadGroupContext() { + } boolean isDesignTime() { return this.isDesignTime; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/beans/WeakIdentityMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/beans/WeakIdentityMap.java Wed Apr 17 21:48:04 2013 -0700 @@ -0,0 +1,181 @@ +/* + * 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.beans; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; + +/** + * Hash table based mapping, which uses weak references to store keys + * and reference-equality in place of object-equality to compare them. + * An entry will automatically be removed when its key is no longer + * in ordinary use. Both null values and the null key are supported. + * + * @see java.util.IdentityHashMap + * @see java.util.WeakHashMap + */ +final class WeakIdentityMap { + + private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two + private static final Object NULL = new Object(); // special object for null key + + private final ReferenceQueue queue = new ReferenceQueue(); + + private Entry[] table = newTable(1<<3); // table's length MUST be a power of two + private int threshold = 6; // the next size value at which to resize + private int size = 0; // the number of key-value mappings + + public T get(Object key) { + removeStaleEntries(); + if (key == null) { + key = NULL; + } + int hash = key.hashCode(); + int index = getIndex(this.table, hash); + for (Entry entry = this.table[index]; entry != null; entry = entry.next) { + if (entry.isMatched(key, hash)) { + return entry.value; + } + } + return null; + } + + public T put(Object key, T value) { + removeStaleEntries(); + if (key == null) { + key = NULL; + } + int hash = key.hashCode(); + int index = getIndex(this.table, hash); + for (Entry entry = this.table[index]; entry != null; entry = entry.next) { + if (entry.isMatched(key, hash)) { + T oldValue = entry.value; + entry.value = value; + return oldValue; + } + } + this.table[index] = new Entry(key, hash, value, this.queue, this.table[index]); + if (++this.size >= this.threshold) { + if (this.table.length == MAXIMUM_CAPACITY) { + this.threshold = Integer.MAX_VALUE; + } + else { + removeStaleEntries(); + Entry[] table = newTable(this.table.length * 2); + transfer(this.table, table); + + // If ignoring null elements and processing ref queue caused massive + // shrinkage, then restore old table. This should be rare, but avoids + // unbounded expansion of garbage-filled tables. + if (this.size >= this.threshold / 2) { + this.table = table; + this.threshold *= 2; + } + else { + transfer(table, this.table); + } + } + } + return null; + } + + private void removeStaleEntries() { + for (Object ref = this.queue.poll(); ref != null; ref = this.queue.poll()) { + @SuppressWarnings("unchecked") + Entry entry = (Entry) ref; + int index = getIndex(this.table, entry.hash); + + Entry prev = this.table[index]; + Entry current = prev; + while (current != null) { + Entry next = current.next; + if (current == entry) { + if (prev == entry) { + this.table[index] = next; + } + else { + prev.next = next; + } + entry.value = null; // Help GC + entry.next = null; // Help GC + this.size--; + break; + } + prev = current; + current = next; + } + } + } + + private void transfer(Entry[] oldTable, Entry[] newTable) { + for (int i = 0; i < oldTable.length; i++) { + Entry entry = oldTable[i]; + oldTable[i] = null; + while (entry != null) { + Entry next = entry.next; + Object key = entry.get(); + if (key == null) { + entry.value = null; // Help GC + entry.next = null; // Help GC + this.size--; + } + else { + int index = getIndex(newTable, entry.hash); + entry.next = newTable[index]; + newTable[index] = entry; + } + entry = next; + } + } + } + + + @SuppressWarnings("unchecked") + private Entry[] newTable(int length) { + return (Entry[]) new Entry[length]; + } + + private static int getIndex(Entry[] table, int hash) { + return hash & (table.length - 1); + } + + private static class Entry extends WeakReference { + private final int hash; + private T value; + private Entry next; + + Entry(Object key, int hash, T value, ReferenceQueue queue, Entry next) { + super(key, queue); + this.hash = hash; + this.value = value; + this.next = next; + } + + boolean isMatched(Object key, int hash) { + return (this.hash == hash) && (key == get()); + } + } +} diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/io/ObjectInputStream.java --- a/src/share/classes/java/io/ObjectInputStream.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/io/ObjectInputStream.java Wed Apr 17 21:48:04 2013 -0700 @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import static java.io.ObjectStreamClass.processQueue; +import sun.reflect.misc.ReflectUtil; /** * An ObjectInputStream deserializes primitive data and objects previously @@ -1519,6 +1520,12 @@ } } + private boolean isCustomSubclass() { + // Return true if this class is a custom subclass of ObjectInputStream + return getClass().getClassLoader() + != ObjectInputStream.class.getClassLoader(); + } + /** * Reads in and returns class descriptor for a dynamic proxy class. Sets * passHandle to proxy class descriptor's assigned handle. If proxy class @@ -1548,6 +1555,15 @@ try { if ((cl = resolveProxyClass(ifaces)) == null) { resolveEx = new ClassNotFoundException("null class"); + } else if (!Proxy.isProxyClass(cl)) { + throw new InvalidClassException("Not a proxy"); + } else { + // ReflectUtil.checkProxyPackageAccess makes a test + // equivalent to isCustomSubclass so there's no need + // to condition this call to isCustomSubclass == true here. + ReflectUtil.checkProxyPackageAccess( + getClass().getClassLoader(), + cl.getInterfaces()); } } catch (ClassNotFoundException ex) { resolveEx = ex; @@ -1589,9 +1605,12 @@ Class cl = null; ClassNotFoundException resolveEx = null; bin.setBlockDataMode(true); + final boolean checksRequired = isCustomSubclass(); try { if ((cl = resolveClass(readDesc)) == null) { resolveEx = new ClassNotFoundException("null class"); + } else if (checksRequired) { + ReflectUtil.checkPackageAccess(cl); } } catch (ClassNotFoundException ex) { resolveEx = ex; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Class.java --- a/src/share/classes/java/lang/Class.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Class.java Wed Apr 17 21:48:04 2013 -0700 @@ -53,6 +53,7 @@ import java.util.HashMap; import java.util.Objects; import sun.misc.Unsafe; +import sun.reflect.CallerSensitive; import sun.reflect.ConstantPool; import sun.reflect.Reflection; import sun.reflect.ReflectionFactory; @@ -250,9 +251,11 @@ * by this method fails * @exception ClassNotFoundException if the class cannot be located */ + @CallerSensitive public static Class forName(String className) throws ClassNotFoundException { - return forName0(className, true, ClassLoader.getCallerClassLoader()); + return forName0(className, true, + ClassLoader.getClassLoader(Reflection.getCallerClass())); } @@ -317,6 +320,7 @@ * @see java.lang.ClassLoader * @since 1.2 */ + @CallerSensitive public static Class forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException @@ -324,7 +328,7 @@ if (sun.misc.VM.isSystemDomainLoader(loader)) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ClassLoader ccl = ClassLoader.getCallerClassLoader(); + ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass()); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); @@ -386,18 +390,14 @@ * * */ + @CallerSensitive public T newInstance() throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); } - return newInstance0(); - } - private T newInstance0() - throws InstantiationException, IllegalAccessException - { // NOTE: the following code may not be strictly correct under // the current Java memory model. @@ -432,7 +432,7 @@ // Security check (same as in java.lang.reflect.Constructor) int modifiers = tmpConstructor.getModifiers(); if (!Reflection.quickCheckMemberAccess(this, modifiers)) { - Class caller = Reflection.getCallerClass(3); + Class caller = Reflection.getCallerClass(); if (newInstanceCallerCache != caller) { Reflection.ensureMemberAccess(caller, this, null, modifiers); newInstanceCallerCache = caller; @@ -674,16 +674,14 @@ * @see SecurityManager#checkPermission * @see java.lang.RuntimePermission */ + @CallerSensitive public ClassLoader getClassLoader() { ClassLoader cl = getClassLoader0(); if (cl == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ClassLoader ccl = ClassLoader.getCallerClassLoader(); - if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } + ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass()); } return cl; } @@ -1392,11 +1390,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Class[] getClasses() { - // 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(), false); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here @@ -1467,11 +1463,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Field[] getFields() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyFields(privateGetPublicFields(null)); } @@ -1518,11 +1512,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Method[] getMethods() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyMethods(privateGetPublicMethods()); } @@ -1567,11 +1559,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Constructor[] getConstructors() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(true)); } @@ -1625,12 +1615,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Field getField(String name) throws NoSuchFieldException, SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); @@ -1710,12 +1698,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -1764,12 +1750,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Constructor getConstructor(Class... parameterTypes) throws NoSuchMethodException, SecurityException { - // 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(), true); + checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.PUBLIC); } @@ -1807,11 +1791,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Class[] getDeclaredClasses() throws SecurityException { - // 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(), false); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false); return getDeclaredClasses0(); } @@ -1851,11 +1833,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Field[] getDeclaredFields() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyFields(privateGetDeclaredFields(false)); } @@ -1899,11 +1879,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Method[] getDeclaredMethods() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyMethods(privateGetDeclaredMethods(false)); } @@ -1944,11 +1922,9 @@ * * @since JDK1.1 */ + @CallerSensitive public Constructor[] getDeclaredConstructors() throws SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return copyConstructors(privateGetDeclaredConstructors(false)); } @@ -1987,12 +1963,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); @@ -2042,12 +2016,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Method getDeclaredMethod(String name, Class... parameterTypes) throws NoSuchMethodException, SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); @@ -2092,12 +2064,10 @@ * * @since JDK1.1 */ + @CallerSensitive public Constructor getDeclaredConstructor(Class... parameterTypes) throws NoSuchMethodException, SecurityException { - // 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(), true); + checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); return getConstructor0(parameterTypes, Member.DECLARED); } @@ -2255,23 +2225,40 @@ */ static native Class getPrimitiveClass(String name); + private static boolean isCheckMemberAccessOverridden(SecurityManager smgr) { + if (smgr.getClass() == SecurityManager.class) return false; + + Class[] paramTypes = new Class[] {Class.class, int.class}; + return smgr.getClass().getMethod0("checkMemberAccess", paramTypes). + getDeclaringClass() != SecurityManager.class; + } /* * Check if client is allowed to access members. If access is denied, * throw a SecurityException. * - * Be very careful not to change the stack depth of this checkMemberAccess - * call for security reasons. - * See java.lang.SecurityManager.checkMemberAccess. - * *

Default policy: allow all clients access with normal Java access * control. */ - private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { - SecurityManager s = System.getSecurityManager(); + private void checkMemberAccess(int which, Class caller, boolean checkProxyInterfaces) { + final SecurityManager s = System.getSecurityManager(); if (s != null) { - s.checkMemberAccess(this, which); - ClassLoader cl = getClassLoader0(); + final ClassLoader ccl = ClassLoader.getClassLoader(caller); + final ClassLoader cl = getClassLoader0(); + if (!isCheckMemberAccessOverridden(s)) { + // Inlined SecurityManager.checkMemberAccess + if (which != Member.PUBLIC) { + if (ccl != cl) { + s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + } + } + } else { + // Don't refactor; otherwise break the stack depth for + // checkMemberAccess of subclasses of SecurityManager as specified. + s.checkMemberAccess(this, which); + } + + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/ClassLoader.java --- a/src/share/classes/java/lang/ClassLoader.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/ClassLoader.java Wed Apr 17 21:48:04 2013 -0700 @@ -55,6 +55,7 @@ import sun.misc.Resource; import sun.misc.URLClassPath; import sun.misc.VM; +import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.security.util.SecurityConstants; @@ -1159,11 +1160,6 @@ return java.util.Collections.emptyEnumeration(); } - // index 0: java.lang.ClassLoader.class - // index 1: the immediate caller of index 0. - // index 2: the immediate caller of index 1. - private static native Class getCaller(int index); - /** * Registers the caller as parallel capable.

* The registration succeeds if and only if all of the following @@ -1179,8 +1175,11 @@ * * @since 1.7 */ + @CallerSensitive protected static boolean registerAsParallelCapable() { - return ParallelLoaders.register(getCaller(1)); + Class callerClass = + Reflection.getCallerClass().asSubclass(ClassLoader.class); + return ParallelLoaders.register(callerClass); } /** @@ -1340,15 +1339,13 @@ * * @since 1.2 */ + @CallerSensitive public final ClassLoader getParent() { if (parent == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ClassLoader ccl = getCallerClassLoader(); - if (needsClassLoaderPermissionCheck(ccl, this)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } + checkClassLoaderPermission(this, Reflection.getCallerClass()); } return parent; } @@ -1408,6 +1405,7 @@ * * @revised 1.4 */ + @CallerSensitive public static ClassLoader getSystemClassLoader() { initSystemClassLoader(); if (scl == null) { @@ -1415,10 +1413,7 @@ } SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ClassLoader ccl = getCallerClassLoader(); - if (needsClassLoaderPermissionCheck(ccl, scl)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } + checkClassLoaderPermission(scl, Reflection.getCallerClass()); } return scl; } @@ -1471,8 +1466,8 @@ // class loader 'from' is same as class loader 'to' or an ancestor // of 'to'. The class loader in a system domain can access // any class loader. - static boolean needsClassLoaderPermissionCheck(ClassLoader from, - ClassLoader to) + private static boolean needsClassLoaderPermissionCheck(ClassLoader from, + ClassLoader to) { if (from == to) return false; @@ -1483,13 +1478,8 @@ return !to.isAncestor(from); } - // Returns the invoker's class loader, or null if none. - // NOTE: This must always be invoked when there is exactly one intervening - // frame from the core libraries on the stack between this method's - // invocation and the desired invoker. - static ClassLoader getCallerClassLoader() { - // NOTE use of more generic Reflection.getCallerClass() - Class caller = Reflection.getCallerClass(3); + // Returns the class's class loader, or null if none. + static ClassLoader getClassLoader(Class caller) { // This can be null if the VM is requesting it if (caller == null) { return null; @@ -1498,6 +1488,17 @@ return caller.getClassLoader0(); } + static void checkClassLoaderPermission(ClassLoader cl, Class caller) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // caller can be null if the VM is requesting it + ClassLoader ccl = getClassLoader(caller); + if (needsClassLoaderPermissionCheck(ccl, cl)) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + // The class loader for the system // @GuardedBy("ClassLoader.class") private static ClassLoader scl; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Iterable.java --- a/src/share/classes/java/lang/Iterable.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Iterable.java Wed Apr 17 21:48:04 2013 -0700 @@ -22,26 +22,55 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package java.lang; import java.util.Iterator; +import java.util.Objects; +import java.util.function.Consumer; /** * Implementing this interface allows an object to be the target of - * the "foreach" statement. + * the "for-each loop" statement. See + * + * For-each Loop + * * * @param the type of elements returned by the iterator * * @since 1.5 + * @jls 14.14.2 The enhanced for statement */ @FunctionalInterface public interface Iterable { - /** - * Returns an iterator over a set of elements of type T. + * Returns an iterator over elements of type {@code T}. * * @return an Iterator. */ Iterator iterator(); + + /** + * Performs the given action on the contents of the {@code Iterable}, in the + * order elements occur when iterating, until all elements have been + * processed or the action throws an exception. Errors or runtime + * exceptions thrown by the action are relayed to the caller. + * + * @implSpec + *

The default implementation behaves as if: + *

{@code
+     *     for (T t : this)
+     *         action.accept(t);
+     * }
+ * + * @param action The action to be performed for each element + * @throws NullPointerException if the specified action is null + * @since 1.8 + */ + default void forEach(Consumer action) { + Objects.requireNonNull(action); + for (T t : this) { + action.accept(t); + } + } } + diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Long.java --- a/src/share/classes/java/lang/Long.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Long.java Wed Apr 17 21:48:04 2013 -0700 @@ -479,7 +479,7 @@ * of the string as a type indicator, as would be permitted in * Java programming language source code - except that either * {@code L} or {@code l} may appear as a digit for a - * radix greater than 22. + * radix greater than or equal to 22. * *

An exception of type {@code NumberFormatException} is * thrown if any of the following situations occurs: diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Package.java --- a/src/share/classes/java/lang/Package.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Package.java Wed Apr 17 21:48:04 2013 -0700 @@ -49,6 +49,8 @@ import java.util.Iterator; import sun.net.www.ParseUtil; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; import java.lang.annotation.Annotation; @@ -273,8 +275,9 @@ * @return the package of the requested name. It may be null if no package * information is available from the archive or codebase. */ + @CallerSensitive public static Package getPackage(String name) { - ClassLoader l = ClassLoader.getCallerClassLoader(); + ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); if (l != null) { return l.getPackage(name); } else { @@ -294,8 +297,9 @@ * @return a new array of packages known to the callers {@code ClassLoader} * instance. An zero length array is returned if none are known. */ + @CallerSensitive public static Package[] getPackages() { - ClassLoader l = ClassLoader.getCallerClassLoader(); + ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); if (l != null) { return l.getPackages(); } else { diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/ProcessBuilder.java --- a/src/share/classes/java/lang/ProcessBuilder.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/ProcessBuilder.java Wed Apr 17 21:48:04 2013 -0700 @@ -30,6 +30,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; +import java.security.AccessControlException; import java.util.Arrays; import java.util.ArrayList; import java.util.List; @@ -1024,13 +1025,24 @@ redirects, redirectErrorStream); } catch (IOException e) { + String exceptionInfo = ": " + e.getMessage(); + Throwable cause = e; + if (security != null) { + // Can not disclose the fail reason for read-protected files. + try { + security.checkRead(prog); + } catch (AccessControlException ace) { + exceptionInfo = ""; + cause = ace; + } + } // It's much easier for us to create a high-quality error // message than the low-level C code which found the problem. throw new IOException( "Cannot run program \"" + prog + "\"" + (dir == null ? "" : " (in directory \"" + dir + "\")") - + ": " + e.getMessage(), - e); + + exceptionInfo, + cause); } } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Runtime.java --- a/src/share/classes/java/lang/Runtime.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Runtime.java Wed Apr 17 21:48:04 2013 -0700 @@ -27,6 +27,8 @@ import java.io.*; import java.util.StringTokenizer; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; /** * Every Java application has a single instance of class @@ -790,8 +792,9 @@ * @see java.lang.SecurityException * @see java.lang.SecurityManager#checkLink(java.lang.String) */ + @CallerSensitive public void load(String filename) { - load0(System.getCallerClass(), filename); + load0(Reflection.getCallerClass(), filename); } synchronized void load0(Class fromClass, String filename) { @@ -850,8 +853,9 @@ * @see java.lang.SecurityException * @see java.lang.SecurityManager#checkLink(java.lang.String) */ + @CallerSensitive public void loadLibrary(String libname) { - loadLibrary0(System.getCallerClass(), libname); + loadLibrary0(Reflection.getCallerClass(), libname); } synchronized void loadLibrary0(Class fromClass, String libname) { diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/SecurityManager.java --- a/src/share/classes/java/lang/SecurityManager.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/SecurityManager.java Wed Apr 17 21:48:04 2013 -0700 @@ -36,10 +36,10 @@ import java.net.NetPermission; import java.util.Hashtable; import java.net.InetAddress; -import java.lang.reflect.Member; import java.lang.reflect.*; import java.net.URL; +import sun.reflect.CallerSensitive; import sun.security.util.SecurityConstants; /** @@ -1679,6 +1679,7 @@ * @since JDK1.1 * @see #checkPermission(java.security.Permission) checkPermission */ + @CallerSensitive public void checkMemberAccess(Class clazz, int which) { if (clazz == null) { throw new NullPointerException("class can't be null"); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/System.java --- a/src/share/classes/java/lang/System.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/System.java Wed Apr 17 21:48:04 2013 -0700 @@ -35,6 +35,7 @@ import java.nio.channels.Channel; import java.nio.channels.spi.SelectorProvider; import sun.nio.ch.Interruptible; +import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.security.util.SecurityConstants; import sun.reflect.annotation.AnnotationType; @@ -1072,8 +1073,9 @@ * @see java.lang.Runtime#load(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String) */ + @CallerSensitive public static void load(String filename) { - Runtime.getRuntime().load0(getCallerClass(), filename); + Runtime.getRuntime().load0(Reflection.getCallerClass(), filename); } /** @@ -1107,8 +1109,9 @@ * @see java.lang.Runtime#loadLibrary(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String) */ + @CallerSensitive public static void loadLibrary(String libname) { - Runtime.getRuntime().loadLibrary0(getCallerClass(), libname); + Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname); } /** @@ -1245,10 +1248,4 @@ } }); } - - /* returns the class of the caller. */ - static Class getCallerClass() { - // NOTE use of more generic Reflection.getCallerClass() - return Reflection.getCallerClass(3); - } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/Thread.java --- a/src/share/classes/java/lang/Thread.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/Thread.java Wed Apr 17 21:48:04 2013 -0700 @@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.LockSupport; import sun.nio.ch.Interruptible; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; import sun.security.util.SecurityConstants; @@ -1443,15 +1445,14 @@ * * @since 1.2 */ + @CallerSensitive public ClassLoader getContextClassLoader() { if (contextClassLoader == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ClassLoader ccl = ClassLoader.getCallerClassLoader(); - if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) { - sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); - } + ClassLoader.checkClassLoaderPermission(contextClassLoader, + Reflection.getCallerClass()); } return contextClassLoader; } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/BoundMethodHandle.java --- a/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Apr 17 21:48:04 2013 -0700 @@ -709,7 +709,9 @@ InvokerBytecodeGenerator.maybeDump(className, classFile); Class bmhClass = //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); - UNSAFE.defineClass(className, classFile, 0, classFile.length).asSubclass(BoundMethodHandle.class); + UNSAFE.defineClass(className, classFile, 0, classFile.length, + BoundMethodHandle.class.getClassLoader(), null) + .asSubclass(BoundMethodHandle.class); UNSAFE.ensureClassInitialized(bmhClass); return bmhClass; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java --- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Wed Apr 17 21:48:04 2013 -0700 @@ -184,7 +184,7 @@ for (int i=0; i lookupClass) { diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/MethodHandleImpl.java --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Apr 17 21:48:04 2013 -0700 @@ -34,6 +34,8 @@ import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; +import sun.reflect.CallerSensitive; +import sun.reflect.Reflection; import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @@ -891,9 +893,11 @@ } } + @CallerSensitive private static boolean checkCallerClass(Class expected, Class expected2) { - final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected - Class actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG); + // This method is called via MH_checkCallerClass and so it's + // correct to ask for the immediate caller here. + Class actual = Reflection.getCallerClass(); if (actual != expected && actual != expected2) throw new InternalError("found "+actual.getName()+", expected "+expected.getName() +(expected == expected2 ? "" : ", or else "+expected2.getName())); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/MethodHandleNatives.java --- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Apr 17 21:48:04 2013 -0700 @@ -26,7 +26,6 @@ package java.lang.invoke; import java.lang.invoke.MethodHandles.Lookup; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; @@ -34,7 +33,7 @@ /** * The JVM interface for the method handles package is all here. - * This is an interface internal and private to an implemetantion of JSR 292. + * This is an interface internal and private to an implementation of JSR 292. * This class is not part of the JSR 292 standard. * @author jrose */ @@ -101,6 +100,7 @@ MN_IS_CONSTRUCTOR = 0x00020000, // constructor MN_IS_FIELD = 0x00040000, // field MN_IS_TYPE = 0x00080000, // nested type + MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected MN_REFERENCE_KIND_SHIFT = 24, // refKind MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers: @@ -391,129 +391,24 @@ * I.e., does it call Reflection.getCallerClass or a similer method * to ask about the identity of its caller? */ - // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive. static boolean isCallerSensitive(MemberName mem) { if (!mem.isInvocable()) return false; // fields are not caller sensitive + + return mem.isCallerSensitive() || canBeCalledVirtual(mem); + } + + static boolean canBeCalledVirtual(MemberName mem) { + assert(mem.isInvocable()); 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": - case "getBoolean": - case "getByte": - case "getChar": - case "getShort": - case "getInt": - case "getLong": - case "getFloat": - case "getDouble": - case "set": - case "setBoolean": - case "setByte": - case "setChar": - case "setShort": - case "setInt": - case "setLong": - case "setFloat": - case "setDouble": - return defc == java.lang.reflect.Field.class; - case "newInstance": - if (defc == java.lang.reflect.Constructor.class) return true; - if (defc == java.lang.Class.class) return true; - break; - case "forName": - case "getClassLoader": - case "getClasses": - case "getFields": - case "getMethods": - case "getConstructors": - case "getDeclaredClasses": - case "getDeclaredFields": - case "getDeclaredMethods": - case "getDeclaredConstructors": - case "getField": - case "getMethod": - case "getConstructor": - case "getDeclaredField": - case "getDeclaredMethod": - case "getDeclaredConstructor": - return defc == java.lang.Class.class; - case "getConnection": - case "getDriver": - case "getDrivers": - case "deregisterDriver": - return defc == getClass("java.sql.DriverManager"); - case "newUpdater": - if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true; - if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true; - if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true; - break; case "getContextClassLoader": return canBeCalledVirtual(mem, java.lang.Thread.class); - case "getPackage": - case "getPackages": - return defc == java.lang.Package.class; - case "getParent": - case "getSystemClassLoader": - return defc == java.lang.ClassLoader.class; - case "load": - case "loadLibrary": - if (defc == java.lang.Runtime.class) return true; - if (defc == java.lang.System.class) return true; - break; - case "getCallerClass": - if (defc == sun.reflect.Reflection.class) return true; - if (defc == java.lang.System.class) return true; - 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; } return false; } - // avoid static dependency to a class in other modules - private static Class getClass(String cn) { - try { - return Class.forName(cn, false, - MethodHandleNatives.class.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new InternalError(e); - } - } static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass) { Class symbolicRefClass = symbolicRef.getDeclaringClass(); if (symbolicRefClass == definingClass) return true; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/MethodHandleProxies.java --- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java Wed Apr 17 21:48:04 2013 -0700 @@ -30,6 +30,7 @@ import java.security.PrivilegedAction; import sun.invoke.WrapperInstance; import java.util.ArrayList; +import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.misc.ReflectUtil; @@ -137,14 +138,14 @@ // entry points, must be covered by hand-written or automatically // generated adapter classes. // + @CallerSensitive public static 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 Class caller = Reflection.getCallerClass(); final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; ReflectUtil.checkProxyPackageAccess(ccl, intfc); mh = ccl != null ? bindCaller(target, caller) : target; diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/invoke/MethodHandles.java --- a/src/share/classes/java/lang/invoke/MethodHandles.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Wed Apr 17 21:48:04 2013 -0700 @@ -26,13 +26,17 @@ package java.lang.invoke; import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; import sun.invoke.util.Wrapper; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; +import sun.reflect.CallerSensitive; import sun.reflect.Reflection; +import sun.security.util.SecurityConstants; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; @@ -65,8 +69,9 @@ * This lookup object is a capability which may be delegated to trusted agents. * Do not store it in place where untrusted code can access it. */ + @CallerSensitive public static Lookup lookup() { - return new Lookup(); + return new Lookup(Reflection.getCallerClass()); } /** @@ -416,20 +421,13 @@ * for method handle creation. * Must be called by from a method in this package, * which in turn is called by a method not in this package. - *

- * Also, don't make it private, lest javac interpose - * an access$N method. */ - Lookup() { - this(getCallerClassAtEntryPoint(false), ALL_MODES); + Lookup(Class lookupClass) { + this(lookupClass, ALL_MODES); // make sure we haven't accidentally picked up a privileged class: checkUnprivilegedlookupClass(lookupClass); } - Lookup(Class lookupClass) { - this(lookupClass, ALL_MODES); - } - private Lookup(Class lookupClass, int allowedModes) { this.lookupClass = lookupClass; this.allowedModes = allowedModes; @@ -554,20 +552,6 @@ } } - /* Obtain the external caller class, when called from Lookup. or a first-level subroutine. */ - private static Class getCallerClassAtEntryPoint(boolean inSubroutine) { - final int CALLER_DEPTH = 4; - // Stack for the constructor entry point (inSubroutine=false): - // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, - // 2: Lookup., 3: MethodHandles.*, 4: caller - // The stack is slightly different for a subroutine of a Lookup.find* method: - // 2: Lookup.*, 3: Lookup.find*.*, 4: caller - // Note: This should be the only use of getCallerClass in this file. - assert(Reflection.getCallerClass(CALLER_DEPTH-2) == Lookup.class); - assert(Reflection.getCallerClass(CALLER_DEPTH-1) == (inSubroutine ? Lookup.class : MethodHandles.class)); - return Reflection.getCallerClass(CALLER_DEPTH); - } - /** * Produces a method handle for a static method. * The type of the method handle will be that of the method. @@ -594,12 +578,14 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public 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 - Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - return getDirectMethod(REF_invokeStatic, refc, method, callerClass); + Class callerClass = Reflection.getCallerClass(); + checkSecurityManager(refc, method, callerClass); + return getDirectMethod(REF_invokeStatic, refc, method, + findBoundCallerClass(method, callerClass)); } /** @@ -645,6 +631,7 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findVirtual(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { if (refc == MethodHandle.class) { MethodHandle mh = findVirtualForMH(name, type); @@ -652,9 +639,10 @@ } byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class callerClass = findBoundCallerClass(method); - return getDirectMethod(refKind, refc, method, callerClass); + Class callerClass = Reflection.getCallerClass(); + checkSecurityManager(refc, method, callerClass); + return getDirectMethod(refKind, refc, method, + findBoundCallerClass(method, callerClass)); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -691,10 +679,11 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findConstructor(Class refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = ""; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); - checkSecurityManager(refc, ctor); // stack walk magic: do not refactor + checkSecurityManager(refc, ctor, Reflection.getCallerClass()); return getDirectConstructor(refc, ctor); } @@ -732,14 +721,16 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findSpecial(Class refc, String name, MethodType type, Class specialCaller) throws NoSuchMethodException, IllegalAccessException { checkSpecialCaller(specialCaller); Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class callerClass = findBoundCallerClass(method); - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); + Class callerClass = Reflection.getCallerClass(); + checkSecurityManager(refc, method, callerClass); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, + findBoundCallerClass(method, callerClass)); } /** @@ -759,9 +750,10 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findGetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getField, refc, name, type); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field, Reflection.getCallerClass()); return getDirectField(REF_getField, refc, field); } @@ -782,9 +774,10 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findSetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putField, refc, name, type); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field, Reflection.getCallerClass()); return getDirectField(REF_putField, refc, field); } @@ -804,9 +797,10 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findStaticGetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_getStatic, refc, name, type); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field, Reflection.getCallerClass()); return getDirectField(REF_getStatic, refc, field); } @@ -826,9 +820,10 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle findStaticSetter(Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { MemberName field = resolveOrFail(REF_putStatic, refc, name, type); - checkSecurityManager(refc, field); // stack walk magic: do not refactor + checkSecurityManager(refc, field, Reflection.getCallerClass()); return getDirectField(REF_putStatic, refc, field); } @@ -878,12 +873,14 @@ * refuses access * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); - checkSecurityManager(refc, method); // stack walk magic: do not refactor - Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); + Class callerClass = Reflection.getCallerClass(); + checkSecurityManager(refc, method, callerClass); + MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, + findBoundCallerClass(method, callerClass)); return mh.bindReceiver(receiver).setVarargs(method); } @@ -908,13 +905,14 @@ * is set and {@code asVarargsCollector} fails * @throws NullPointerException if the argument is null */ + @CallerSensitive public MethodHandle unreflect(Method m) throws IllegalAccessException { MemberName method = new MemberName(m); byte refKind = method.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); - Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + Class callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); } @@ -940,12 +938,13 @@ * is set and {@code asVarargsCollector} fails * @throws NullPointerException if any argument is null */ + @CallerSensitive public MethodHandle unreflectSpecial(Method m, Class specialCaller) throws IllegalAccessException { checkSpecialCaller(specialCaller); Lookup specialLookup = this.in(specialCaller); MemberName method = new MemberName(m, true); assert(method.isMethod()); - Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + Class callerClass = findBoundCallerClass(method, Reflection.getCallerClass()); // ignore m.isAccessible: this is a new kind of access return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); } @@ -1050,20 +1049,35 @@ * 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 findBoundCallerClass(MemberName m, Class callerAtEntryPoint) { 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)); + : callerAtEntryPoint); } return callerClass; } + + /** + * Determine whether a security manager has an overridden + * SecurityManager.checkMemberAccess method. + */ + private boolean isCheckMemberAccessOverridden(SecurityManager sm) { + final Class cls = sm.getClass(); + if (cls == SecurityManager.class) return false; + + try { + return cls.getMethod("checkMemberAccess", Class.class, int.class). + getDeclaringClass() != SecurityManager.class; + } catch (NoSuchMethodException e) { + throw new InternalError("should not reach here"); + } + } + /** * Perform necessary access checks. * Determines a trustable caller class to compare with refc, the symbolic reference class. @@ -1071,46 +1085,55 @@ * 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) { + void checkSecurityManager(Class refc, MemberName m, Class caller) { SecurityManager smgr = System.getSecurityManager(); if (smgr == null) return; if (allowedModes == TRUSTED) return; + + final boolean overridden = isCheckMemberAccessOverridden(smgr); // Step 1: - smgr.checkMemberAccess(refc, Member.PUBLIC); + { + // Default policy is to allow Member.PUBLIC; no need to check + // permission if SecurityManager is the default implementation + final int which = Member.PUBLIC; + final Class clazz = refc; + if (overridden) { + // Don't refactor; otherwise break the stack depth for + // checkMemberAccess of subclasses of SecurityManager as specified. + smgr.checkMemberAccess(clazz, which); + } + } + // Step 2: Class callerClass = ((allowedModes & PRIVATE) != 0 ? lookupClass // for strong access modes, no extra check - // next line does stack walk magic; do not refactor: - : getCallerClassAtEntryPoint(true)); + : caller); if (!VerifyAccess.classLoaderIsAncestor(lookupClass, refc) || (callerClass != lookupClass && !VerifyAccess.classLoaderIsAncestor(callerClass, refc))) smgr.checkPackageAccess(VerifyAccess.getPackageName(refc)); + // Step 3: if (m.isPublic()) return; Class defc = m.getDeclaringClass(); - smgr.checkMemberAccess(defc, Member.DECLARED); // STACK WALK HERE + { + // Inline SecurityManager.checkMemberAccess + final int which = Member.DECLARED; + final Class clazz = defc; + if (!overridden) { + if (caller.getClassLoader() != clazz.getClassLoader()) { + smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); + } + } else { + // Don't refactor; otherwise break the stack depth for + // checkMemberAccess of subclasses of SecurityManager as specified. + smgr.checkMemberAccess(clazz, which); + } + } + // Step 4: if (defc != refc) smgr.checkPackageAccess(VerifyAccess.getPackageName(defc)); - - // Comment from SM.checkMemberAccess, where which=DECLARED: - /* - * stack depth of 4 should be the caller of one of the - * methods in java.lang.Class that invoke checkMember - * access. The stack should look like: - * - * someCaller [3] - * java.lang.Class.someReflectionAPI [2] - * java.lang.Class.checkMemberAccess [1] - * SecurityManager.checkMemberAccess [0] - * - */ - // For us it is this stack: - // someCaller [3] - // Lookup.findSomeMember [2] - // Lookup.checkSecurityManager [1] - // SecurityManager.checkMemberAccess [0] } void checkMethod(byte refKind, Class refc, MemberName m) throws IllegalAccessException { @@ -1237,6 +1260,30 @@ checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); + + Class refcAsSuper; + if (refKind == REF_invokeSpecial && + refc != lookupClass() && + refc != (refcAsSuper = lookupClass().getSuperclass()) && + refc.isAssignableFrom(lookupClass())) { + assert(!method.getName().equals("")); // not this code path + // Per JVMS 6.5, desc. of invokespecial instruction: + // If the method is in a superclass of the LC, + // and if our original search was above LC.super, + // repeat the search (symbolic lookup) from LC.super. + // FIXME: MemberName.resolve should handle this instead. + MemberName m2 = new MemberName(refcAsSuper, + method.getName(), + method.getMethodType(), + REF_invokeSpecial); + m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull()); + if (m2 == null) throw new InternalError(method.toString()); + method = m2; + refc = refcAsSuper; + // redo basic checks + checkMethod(refKind, refc, method); + } + MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); mh = maybeBindCaller(method, mh, callerClass); mh = mh.setVarargs(method); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/ref/Finalizer.java --- a/src/share/classes/java/lang/ref/Finalizer.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/ref/Finalizer.java Wed Apr 17 21:48:04 2013 -0700 @@ -38,9 +38,9 @@ */ static native void invokeFinalizeMethod(Object o) throws Throwable; - static private ReferenceQueue queue = new ReferenceQueue(); - static private Finalizer unfinalized = null; - static private Object lock = new Object(); + private static ReferenceQueue queue = new ReferenceQueue(); + private static Finalizer unfinalized = null; + private static final Object lock = new Object(); private Finalizer next = null, @@ -142,7 +142,11 @@ /* Called by Runtime.runFinalization() */ static void runFinalization() { forkSecondaryFinalizer(new Runnable() { + private volatile boolean running; public void run() { + if (running) + return; + running = true; for (;;) { Finalizer f = (Finalizer)queue.poll(); if (f == null) break; @@ -155,7 +159,11 @@ /* Invoked by java.lang.Shutdown */ static void runAllFinalizers() { forkSecondaryFinalizer(new Runnable() { + private volatile boolean running; public void run() { + if (running) + return; + running = true; for (;;) { Finalizer f; synchronized (lock) { @@ -168,10 +176,14 @@ } private static class FinalizerThread extends Thread { + private volatile boolean running; FinalizerThread(ThreadGroup g) { super(g, "Finalizer"); } public void run() { + if (running) + return; + running = true; for (;;) { try { Finalizer f = (Finalizer)queue.remove(); diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/reflect/Constructor.java --- a/src/share/classes/java/lang/reflect/Constructor.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/reflect/Constructor.java Wed Apr 17 21:48:04 2013 -0700 @@ -25,6 +25,7 @@ package java.lang.reflect; +import sun.reflect.CallerSensitive; import sun.reflect.ConstructorAccessor; import sun.reflect.Reflection; import sun.reflect.generics.repository.ConstructorRepository; @@ -392,14 +393,14 @@ * @exception ExceptionInInitializerError if the initialization provoked * by this method fails. */ + @CallerSensitive public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - Class caller = Reflection.getCallerClass(2); - + Class caller = Reflection.getCallerClass(); checkAccess(caller, clazz, null, modifiers); } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/reflect/Field.java --- a/src/share/classes/java/lang/reflect/Field.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/reflect/Field.java Wed Apr 17 21:48:04 2013 -0700 @@ -25,6 +25,7 @@ package java.lang.reflect; +import sun.reflect.CallerSensitive; import sun.reflect.FieldAccessor; import sun.reflect.Reflection; import sun.reflect.generics.repository.FieldRepository; @@ -376,9 +377,16 @@ * @exception ExceptionInInitializerError if the initialization provoked * by this method fails. */ + @CallerSensitive public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).get(obj); } @@ -404,9 +412,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public boolean getBoolean(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getBoolean(obj); } @@ -432,9 +447,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public byte getByte(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getByte(obj); } @@ -462,9 +484,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public char getChar(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getChar(obj); } @@ -492,9 +521,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public short getShort(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getShort(obj); } @@ -522,9 +558,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public int getInt(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getInt(obj); } @@ -552,9 +595,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public long getLong(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getLong(obj); } @@ -582,9 +632,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public float getFloat(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getFloat(obj); } @@ -612,9 +669,16 @@ * by this method fails. * @see Field#get */ + @CallerSensitive public double getDouble(Object obj) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } return getFieldAccessor(obj).getDouble(obj); } @@ -684,9 +748,16 @@ * @exception ExceptionInInitializerError if the initialization provoked * by this method fails. */ + @CallerSensitive public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).set(obj, value); } @@ -714,9 +785,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setBoolean(Object obj, boolean z) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setBoolean(obj, z); } @@ -744,9 +822,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setByte(Object obj, byte b) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setByte(obj, b); } @@ -774,9 +859,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setChar(Object obj, char c) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setChar(obj, c); } @@ -804,9 +896,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setShort(Object obj, short s) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setShort(obj, s); } @@ -834,9 +933,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setInt(Object obj, int i) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setInt(obj, i); } @@ -864,9 +970,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setLong(Object obj, long l) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setLong(obj, l); } @@ -894,9 +1007,16 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setFloat(Object obj, float f) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setFloat(obj, f); } @@ -924,20 +1044,26 @@ * by this method fails. * @see Field#set */ + @CallerSensitive public void setDouble(Object obj, double d) throws IllegalArgumentException, IllegalAccessException { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(); + checkAccess(caller, clazz, obj, modifiers); + } + } getFieldAccessor(obj).setDouble(obj, d); } - // Convenience routine which performs security checks + // security check is done before calling this method private FieldAccessor getFieldAccessor(Object obj) throws IllegalAccessException { - doSecurityCheck(obj); boolean ov = override; - FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor; - return (a != null)? a : acquireFieldAccessor(ov); + FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor; + return (a != null) ? a : acquireFieldAccessor(ov); } // NOTE that there is no synchronization used here. It is correct @@ -982,19 +1108,6 @@ } } - // NOTE: be very careful if you change the stack depth of this - // routine. The depth of the "getCallerClass" call is hardwired so - // that the compiler can have an easier time if this gets inlined. - private void doSecurityCheck(Object obj) throws IllegalAccessException { - if (!override) { - if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - Class caller = Reflection.getCallerClass(4); - - checkAccess(caller, clazz, obj, modifiers); - } - } - } - /** * @throws NullPointerException {@inheritDoc} * @since 1.5 diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/reflect/Method.java --- a/src/share/classes/java/lang/reflect/Method.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/reflect/Method.java Wed Apr 17 21:48:04 2013 -0700 @@ -25,6 +25,7 @@ package java.lang.reflect; +import sun.reflect.CallerSensitive; import sun.reflect.MethodAccessor; import sun.reflect.Reflection; import sun.reflect.generics.repository.MethodRepository; @@ -472,14 +473,14 @@ * @exception ExceptionInInitializerError if the initialization * provoked by this method fails. */ + @CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { - Class caller = Reflection.getCallerClass(1); - + Class caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } diff -r bb098a221d85 -r 4b8e606f8afb src/share/classes/java/lang/reflect/Proxy.java --- a/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 21:32:11 2013 -0700 +++ b/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 21:48:04 2013 -0700 @@ -28,7 +28,6 @@ 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; @@ -39,6 +38,8 @@ import java.util.List; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; +import sun.misc.VM; +import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; @@ -51,16 +52,14 @@ *

To create a proxy for some interface {@code Foo}: *

  *     InvocationHandler handler = new MyInvocationHandler(...);
- *     Class proxyClass = Proxy.getProxyClass(
- *         Foo.class.getClassLoader(), new Class[] { Foo.class });
- *     Foo f = (Foo) proxyClass.
- *         getConstructor(new Class[] { InvocationHandler.class }).
- *         newInstance(new Object[] { handler });
+ *     Class<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ *                     newInstance(handler);
  * 
* or more simply: *
  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- *                                          new Class[] { Foo.class },
+ *                                          new Class<?>[] { Foo.class },
  *                                          handler);
  * 
* @@ -89,7 +88,11 @@ *

A proxy class has the following properties: * *