Mercurial > hg > jdk9-shenandoah > jdk
changeset 10692:8bdf7083b5bd jdk9-b32
Merge
author | lana |
---|---|
date | Thu, 18 Sep 2014 13:27:48 -0700 |
parents | edf3916a2fe9 (current diff) 10db6a9fe848 (diff) |
children | ffc1e07c7478 2c479a3aa7be |
files | make/gensrc/GensrcLocaleDataMetaInfo.gmk src/java.desktop/macosx/classes/sun/awt/datatransfer/flavormap.properties src/java.desktop/unix/classes/sun/awt/datatransfer/flavormap.properties src/java.desktop/windows/classes/sun/awt/datatransfer/flavormap.properties src/java.desktop/windows/classes/sun/awt/windows/WBufferStrategy.java src/java.desktop/windows/native/libawt/sun/java2d/d3d/D3DPipeline.cpp src/java.desktop/windows/native/libawt/sun/windows/WBufferStrategy.cpp src/java.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSContext.java src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java src/java.security.jgss/share/classes/com/sun/security/jgss/GSSUtil.java src/java.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java src/java.security.jgss/share/classes/com/sun/security/jgss/InquireType.java src/java.security.jgss/share/classes/com/sun/security/jgss/package-info.java src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java |
diffstat | 144 files changed, 9476 insertions(+), 3496 deletions(-) [+] |
line wrap: on
line diff
--- a/make/CreateJars.gmk Wed Sep 17 22:56:07 2014 -0700 +++ b/make/CreateJars.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -220,7 +220,6 @@ sun/tools/serialver \ sun/tools/tree \ sun/tools/util \ - sun/util/cldr/CLDRLocaleDataMetaInfo.class \ sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \ META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \ sun/util/resources/cldr \ @@ -452,11 +451,9 @@ $(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \ $(CLDR_METAINF_SERVICES), \ SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \ - $(JDK_OUTPUTDIR)/modules/java.base \ $(CLDR_SERVICES_DIR), \ SUFFIXES := .class, \ INCLUDES := sun/text/resources/cldr \ - sun/util/cldr/CLDRLocaleDataMetaInfo.class \ sun/util/resources/cldr, \ EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \ JAR := $(CLDRDATA_JAR_DST), \
--- a/make/gensrc/Gensrc-java.base.gmk Wed Sep 17 22:56:07 2014 -0700 +++ b/make/gensrc/Gensrc-java.base.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -29,14 +29,13 @@ include GensrcProperties.gmk GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES) -include GensrcLocaleDataMetaInfo.gmk +include GensrcLocaleData.gmk include GensrcCharacterData.gmk include GensrcMisc.gmk include GensrcCharsetMapping.gmk include GensrcCharsetCoder.gmk include GensrcBuffer.gmk include GensrcExceptions.gmk -include GensrcCLDR.gmk java.base: $(GENSRC_JAVA_BASE)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/gensrc/Gensrc-jdk.localedata.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,38 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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. +# + +include GensrcCommon.gmk + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-jdk.localedata.gmk)) + +include GensrcLocaleData.gmk +include GensrcCLDR.gmk + +jdk.localedata: $(GENSRC_JDK_LOCALEDATA) + +all: jdk.localedata + +.PHONY: all jdk.localedata
--- a/make/gensrc/GensrcCLDR.gmk Wed Sep 17 22:56:07 2014 -0700 +++ b/make/gensrc/GensrcCLDR.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -27,9 +27,8 @@ CLDRSRCDIR := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/cldr/resources/$(subst .,_,$(CLDRVERSION)) GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata -BASE_GENSRC_DIR := $(JDK_OUTPUTDIR)/gensrc/java.base -CLDR_METAINFO_FILE := $(BASE_GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java +CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java $(CLDR_METAINFO_FILE): $(wildcard $(CLDRSRCDIR)/common/dtd/*.dtd) \ $(wildcard $(CLDRSRCDIR)/common/main/*.xml) \ @@ -37,16 +36,6 @@ $(BUILD_TOOLS_JDK) $(MKDIR) -p $(GENSRC_DIR) $(TOOL_CLDRCONVERTER) -base $(CLDRSRCDIR) -o $(GENSRC_DIR) - $(MKDIR) -p $(BASE_GENSRC_DIR)/sun/text/resources/cldr - $(MKDIR) -p $(BASE_GENSRC_DIR)/sun/util/resources/cldr - $(RM) -r $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en \ - $(BASE_GENSRC_DIR)/sun/util/resources/cldr/en - $(MV) $(GENSRC_DIR)/sun/text/resources/cldr/en $(BASE_GENSRC_DIR)/sun/text/resources/cldr/en - $(MV) $(GENSRC_DIR)/sun/util/resources/cldr/en $(BASE_GENSRC_DIR)/sun/util/resources/cldr/en - $(MV) $(GENSRC_DIR)/sun/text/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/text/resources/cldr - $(MV) $(GENSRC_DIR)/sun/util/resources/cldr/*.java $(BASE_GENSRC_DIR)/sun/util/resources/cldr - $(MKDIR) -p $(@D) - $(MV) $(GENSRC_DIR)/sun/util/cldr/CLDRLocaleDataMetaInfo.java $@ GENSRC_CLDR := $(CLDR_METAINFO_FILE) -GENSRC_JAVA_BASE += $(GENSRC_CLDR) +GENSRC_JDK_LOCALEDATA += $(GENSRC_CLDR)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/gensrc/GensrcLocaleData.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,152 @@ +# +# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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. +# + +# Scan for all locale resources and extract for which locales there exists +# resources. Then put this meta information about existing (supported?) locales +# into LocaleDataMetaInfo.java + +# First go look for all locale files +LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \ + $(JDK_TOPDIR)/src/jdk.localedata/share/classes \ + -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \ + -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \ + -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \ + -name "LocaleNames_*.java" -o -name "LocaleNames_*.properties" -o \ + -name "CurrencyNames_*.java" -o -name "CurrencyNames_*.properties" -o \ + -name "CalendarData_*.java" -o -name "CalendarData_*.properties" -o \ + -name "BreakIteratorInfo_*.java" -o -name "BreakIteratorRules_*.java") + +# Then translate the locale files into for example: FormatData_sv +LOCALE_RESOURCES := $(sort $(subst .properties,,$(subst .java,,$(notdir $(LOCALE_FILES))))) + +# Include the list of resources found during the previous compile. +-include $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources + +MISSING_RESOURCES := $(filter-out $(LOCALE_RESOURCES), $(PREV_LOCALE_RESOURCES)) +NEW_RESOURCES := $(filter-out $(PREV_LOCALE_RESOURCES), $(LOCALE_RESOURCES)) + +ifneq (, $(MISSING_RESOURCES)$(NEW_RESOURCES)) + # There is a difference in the number of supported resources. Trigger a regeneration. + $(shell $(RM) $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java) +endif + +# The EN locales +EN_LOCALES := en% + +# Locales that don't have any resource files should be included here. +ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH + +SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g' +SED_NONENARGS := $(SED_ENARGS) + +# Fill in the languages and package names +SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \ + -e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/' +SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \ + -e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/' + +# This macro creates a sed expression that substitues for example: +# #FormatData_ENLocales# with: en% locales. +define CaptureLocale + $1_LOCALES := $$(subst _,-,$$(filter-out $1, $$(subst $1_,,$$(filter $1_%, $(LOCALE_RESOURCES))))) + $1_EN_LOCALES := $$(filter $(EN_LOCALES), $$($1_LOCALES)) + $1_NON_EN_LOCALES := $$(filter-out $(EN_LOCALES), $$($1_LOCALES)) + + # Special handling for Chinese locales to include implicit scripts + $1_NON_EN_LOCALES := $$(subst zh-CN,zh-CN$$(SPACE)zh-Hans-CN, $$($1_NON_EN_LOCALES)) + $1_NON_EN_LOCALES := $$(subst zh-SG,zh-SG$$(SPACE)zh-Hans-SG, $$($1_NON_EN_LOCALES)) + $1_NON_EN_LOCALES := $$(subst zh-HK,zh-HK$$(SPACE)zh-Hant-HK, $$($1_NON_EN_LOCALES)) + $1_NON_EN_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_EN_LOCALES)) + $1_NON_EN_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_EN_LOCALES)) + + ALL_EN_LOCALES += $$($1_EN_LOCALES) + ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES) + + # Don't sed in a space if there are no locales. + SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g' + SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g' +endef + +#sun.text.resources.FormatData +$(eval $(call CaptureLocale,FormatData)) + +#sun.text.resources.CollationData +$(eval $(call CaptureLocale,CollationData)) + +#sun.text.resources.BreakIteratorInfo +$(eval $(call CaptureLocale,BreakIteratorInfo)) + +#sun.text.resources.BreakIteratorRules +$(eval $(call CaptureLocale,BreakIteratorRules)) + +#sun.util.resources.TimeZoneNames +$(eval $(call CaptureLocale,TimeZoneNames)) + +#sun.util.resources.LocaleNames +$(eval $(call CaptureLocale,LocaleNames)) + +#sun.util.resources.CurrencyNames +$(eval $(call CaptureLocale,CurrencyNames)) + +#sun.util.resources.CalendarData +$(eval $(call CaptureLocale,CalendarData)) + +SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g' +SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g' + +$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \ + $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template + $(MKDIR) -p $(@D) + $(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources. + $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources + $(SED) $(SED_ENARGS) $< > $@ + +$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \ + $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template + $(MKDIR) -p $(@D) + $(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources. + $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources + $(SED) $(SED_NONENARGS) $< > $@ + +GENSRC_BASELOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java +GENSRC_LOCALEDATA := $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java + +################################################################################ + +GENSRC_CRBC_DST := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/CoreResourceBundleControl.java +GENSRC_CRBC_CMD := $(JDK_TOPDIR)/make/scripts/localelist.sh + +JRE_NONEXIST_LOCALES := en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh + +$(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template \ + $(GENSRC_CRBC_CMD) + $(MKDIR) -p $(@D) + NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@ + +GENSRC_BASELOCALEDATA += $(GENSRC_CRBC_DST) +GENSRC_JAVA_BASE += $(GENSRC_BASELOCALEDATA) +GENSRC_JDK_LOCALEDATA += $(GENSRC_LOCALEDATA) + +################################################################################
--- a/make/gensrc/GensrcLocaleDataMetaInfo.gmk Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -# -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute 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. -# - -# Scan for all locale resources and extract for which locales there exists -# resources. Then put this meta information about existing (supported?) locales -# into LocaleDataMetaInfo.java - -# First go look for all locale files -LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \ - $(JDK_TOPDIR)/src/jdk.localedata/share/classes \ - -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \ - -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \ - -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \ - -name "LocaleNames_*.java" -o -name "LocaleNames_*.properties" -o \ - -name "CurrencyNames_*.java" -o -name "CurrencyNames_*.properties" -o \ - -name "CalendarData_*.java" -o -name "CalendarData_*.properties" -o \ - -name "BreakIteratorInfo_*.java" -o -name "BreakIteratorRules_*.java") - -# Then translate the locale files into for example: FormatData_sv -LOCALE_RESOURCES := $(sort $(subst .properties,,$(subst .java,,$(notdir $(LOCALE_FILES))))) - -# Include the list of resources found during the previous compile. --include $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources - -MISSING_RESOURCES := $(filter-out $(LOCALE_RESOURCES), $(PREV_LOCALE_RESOURCES)) -NEW_RESOURCES := $(filter-out $(PREV_LOCALE_RESOURCES), $(LOCALE_RESOURCES)) - -ifneq (, $(MISSING_RESOURCES)$(NEW_RESOURCES)) - # There is a difference in the number of supported resources. Trigger a regeneration. - $(shell $(RM) $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java) -endif - -# The EN locales -EN_LOCALES := en% - -# Locales that don't have any resource files should be included here. -ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH - -SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g' -SED_NONENARGS := $(SED_ENARGS) - -# Fill in the languages and package names -SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \ - -e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/' -SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \ - -e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/' - -# This macro creates a sed expression that substitues for example: -# #FormatData_ENLocales# with: en% locales. -define CaptureLocale - $1_LOCALES := $$(subst _,-,$$(filter-out $1, $$(subst $1_,,$$(filter $1_%, $(LOCALE_RESOURCES))))) - $1_EN_LOCALES := $$(filter $(EN_LOCALES), $$($1_LOCALES)) - $1_NON_EN_LOCALES := $$(filter-out $(EN_LOCALES), $$($1_LOCALES)) - - # Special handling for Chinese locales to include implicit scripts - $1_NON_EN_LOCALES := $$(subst zh-CN,zh-CN$$(SPACE)zh-Hans-CN, $$($1_NON_EN_LOCALES)) - $1_NON_EN_LOCALES := $$(subst zh-SG,zh-SG$$(SPACE)zh-Hans-SG, $$($1_NON_EN_LOCALES)) - $1_NON_EN_LOCALES := $$(subst zh-HK,zh-HK$$(SPACE)zh-Hant-HK, $$($1_NON_EN_LOCALES)) - $1_NON_EN_LOCALES := $$(subst zh-MO,zh-MO$$(SPACE)zh-Hant-MO, $$($1_NON_EN_LOCALES)) - $1_NON_EN_LOCALES := $$(subst zh-TW,zh-TW$$(SPACE)zh-Hant-TW, $$($1_NON_EN_LOCALES)) - - ALL_EN_LOCALES += $$($1_EN_LOCALES) - ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES) - - # Don't sed in a space if there are no locales. - SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g' - SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g' -endef - -#sun.text.resources.FormatData -$(eval $(call CaptureLocale,FormatData)) - -#sun.text.resources.CollationData -$(eval $(call CaptureLocale,CollationData)) - -#sun.text.resources.BreakIteratorInfo -$(eval $(call CaptureLocale,BreakIteratorInfo)) - -#sun.text.resources.BreakIteratorRules -$(eval $(call CaptureLocale,BreakIteratorRules)) - -#sun.util.resources.TimeZoneNames -$(eval $(call CaptureLocale,TimeZoneNames)) - -#sun.util.resources.LocaleNames -$(eval $(call CaptureLocale,LocaleNames)) - -#sun.util.resources.CurrencyNames -$(eval $(call CaptureLocale,CurrencyNames)) - -#sun.util.resources.CalendarData -$(eval $(call CaptureLocale,CalendarData)) - -SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g' -SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g' - -$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \ - $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template - $(MKDIR) -p $(@D) - $(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources. - $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources - $(SED) $(SED_ENARGS) $< > $@ - -$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \ - $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template - $(MKDIR) -p $(@D) - $(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources. - $(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources - $(SED) $(SED_NONENARGS) $< > $@ - -GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \ - $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java - -################################################################################ - -GENSRC_CRBC_DST := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/CoreResourceBundleControl.java -GENSRC_CRBC_CMD := $(JDK_TOPDIR)/make/scripts/localelist.sh - -JRE_NONEXIST_LOCALES := en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh - -$(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/CoreResourceBundleControl-XLocales.java.template \ - $(GENSRC_CRBC_CMD) - $(MKDIR) -p $(@D) - NAWK="$(NAWK)" SED="$(SED)" $(SH) $(GENSRC_CRBC_CMD) "$(JRE_NONEXIST_LOCALES)" $< $@ - -GENSRC_LOCALEDATAMETAINFO += $(GENSRC_CRBC_DST) -GENSRC_JAVA_BASE += $(GENSRC_LOCALEDATAMETAINFO) - -################################################################################
--- a/make/lib/Awt2dLibraries.gmk Wed Sep 17 22:56:07 2014 -0700 +++ b/make/lib/Awt2dLibraries.gmk Thu Sep 18 13:27:48 2014 -0700 @@ -217,10 +217,8 @@ -I$(JDK_OUTPUTDIR)/gensrc_headers/java.base \ # LIBAWT_EXFILES += \ - sun/java2d/d3d/D3DPipeline.cpp \ sun/java2d/d3d/D3DShaderGen.c \ sun/awt/image/cvutils/img_colors.c \ - sun/windows/WBufferStrategy.cpp \ # LIBAWT_LANG := C++
--- a/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Wed Sep 17 22:56:07 2014 -0700 +++ b/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Thu Sep 18 13:27:48 2014 -0700 @@ -143,8 +143,9 @@ @Override public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException { - String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + File.separator - + "cldr" + File.separator; + String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator + "util" + + File.separator + "resources" + File.separator + "cldr" + File.separator + + "provider" + File.separator ; File dir = new File(dirName); if (!dir.exists()) { dir.mkdirs(); @@ -158,7 +159,7 @@ try (PrintWriter out = new PrintWriter(file, "us-ascii")) { out.println(CopyrightHeaders.getOpenJDKCopyright()); - out.println("package sun.util.cldr;\n\n" + out.println("package sun.util.resources.cldr.provider;\n\n" + "import java.util.ListResourceBundle;\n" + "import sun.util.locale.provider.LocaleProviderAdapter;\n" + "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
--- a/make/src/classes/build/tools/module/GenJdepsModulesXml.java Wed Sep 17 22:56:07 2014 -0700 +++ b/make/src/classes/build/tools/module/GenJdepsModulesXml.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,29 +25,17 @@ package build.tools.module; -import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; -import java.util.Objects; import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import javax.xml.namespace.QName; -import javax.xml.stream.*; -import javax.xml.stream.events.Attribute; -import javax.xml.stream.events.XMLEvent; +import java.util.stream.Collectors; /** * GenJdepsModulesXml augments the input modules.xml file(s) @@ -97,14 +85,14 @@ Set<Module> modules = new HashSet<>(); for (; i < args.length; i++) { Path p = Paths.get(args[i]); - try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) { - Set<Module> mods = gentool.load(in); - modules.addAll(mods); - } + modules.addAll(ModulesXmlReader.readModules(p) + .stream() + .map(gentool::buildIncludes) + .collect(Collectors.toSet())); } Files.createDirectories(outfile.getParent()); - gentool.writeXML(modules, outfile); + ModulesXmlWriter.writeModules(modules, outfile); } final Path modulepath; @@ -112,228 +100,21 @@ this.modulepath = modulepath; } - private static final String MODULES = "modules"; - private static final String MODULE = "module"; - private static final String NAME = "name"; - private static final String DEPEND = "depend"; - private static final String EXPORT = "export"; - private static final String TO = "to"; - private static final String INCLUDE = "include"; - private static final QName REEXPORTS = new QName("re-exports"); - private Set<Module> load(InputStream in) throws XMLStreamException, IOException { - Set<Module> modules = new HashSet<>(); - XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLEventReader stream = factory.createXMLEventReader(in); - Module.Builder mb = null; - String modulename = null; - String pkg = null; - Set<String> permits = new HashSet<>(); - while (stream.hasNext()) { - XMLEvent event = stream.nextEvent(); - if (event.isStartElement()) { - String startTag = event.asStartElement().getName().getLocalPart(); - switch (startTag) { - case MODULES: - break; - case MODULE: - if (mb != null) { - throw new RuntimeException("end tag for module is missing"); - } - modulename = getNextTag(stream, NAME); - mb = new Module.Builder(); - mb.name(modulename); - break; - case NAME: - throw new RuntimeException(event.toString()); - case DEPEND: - boolean reexports = false; - Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS); - if (attr != null) { - String value = attr.getValue(); - if (value.equals("true") || value.equals("false")) { - reexports = Boolean.parseBoolean(value); - } else { - throw new RuntimeException("unexpected attribute " + attr.toString()); - } - } - mb.require(getData(stream), reexports); - break; - case INCLUDE: - throw new RuntimeException("unexpected " + event); - case EXPORT: - pkg = getNextTag(stream, NAME); - break; - case TO: - permits.add(getData(stream)); - break; - default: - } - } else if (event.isEndElement()) { - String endTag = event.asEndElement().getName().getLocalPart(); - switch (endTag) { - case MODULE: - buildIncludes(mb, modulename); - modules.add(mb.build()); - mb = null; - break; - case EXPORT: - if (pkg == null) { - throw new RuntimeException("export-to is malformed"); - } - mb.exportTo(pkg, permits); - pkg = null; - permits.clear(); - break; - default: - } - } else if (event.isCharacters()) { - String s = event.asCharacters().getData(); - if (!s.trim().isEmpty()) { - throw new RuntimeException("export-to is malformed"); - } - } - } - return modules; - } - - private String getData(XMLEventReader reader) throws XMLStreamException { - XMLEvent e = reader.nextEvent(); - if (e.isCharacters()) { - return e.asCharacters().getData(); - } - throw new RuntimeException(e.toString()); - } - - private String getNextTag(XMLEventReader reader, String tag) throws XMLStreamException { - XMLEvent e = reader.nextTag(); - if (e.isStartElement()) { - String t = e.asStartElement().getName().getLocalPart(); - if (!tag.equals(t)) { - throw new RuntimeException(e + " expected: " + tag); - } - return getData(reader); - } - throw new RuntimeException("export-to name is missing:" + e); - } - private void writeXML(Set<Module> modules, Path path) - throws IOException, XMLStreamException - { - XMLOutputFactory xof = XMLOutputFactory.newInstance(); - try (OutputStream out = Files.newOutputStream(path)) { - int depth = 0; - XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8"); - xtw.writeStartDocument("utf-8","1.0"); - writeStartElement(xtw, MODULES, depth); - modules.stream() - .sorted(Comparator.comparing(Module::name)) - .forEach(m -> writeModuleElement(xtw, m, depth+1)); - writeEndElement(xtw, depth); - xtw.writeCharacters("\n"); - xtw.writeEndDocument(); - xtw.flush(); - xtw.close(); - } - } - - private void writeElement(XMLStreamWriter xtw, String element, String value, int depth) { - try { - writeStartElement(xtw, element, depth); - xtw.writeCharacters(value); - xtw.writeEndElement(); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - - private void writeDependElement(XMLStreamWriter xtw, Module.Dependence d, int depth) { - try { - writeStartElement(xtw, DEPEND, depth); - if (d.reexport) { - xtw.writeAttribute("re-exports", "true"); - } - xtw.writeCharacters(d.name); - xtw.writeEndElement(); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - - private void writeExportElement(XMLStreamWriter xtw, String pkg, int depth) { - writeExportElement(xtw, pkg, Collections.emptySet(), depth); - } - - private void writeExportElement(XMLStreamWriter xtw, String pkg, - Set<String> permits, int depth) { - try { - writeStartElement(xtw, EXPORT, depth); - writeElement(xtw, NAME, pkg, depth+1); - if (!permits.isEmpty()) { - permits.stream().sorted() - .forEach(m -> writeElement(xtw, TO, m, depth + 1)); - } - writeEndElement(xtw, depth); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } - private void writeModuleElement(XMLStreamWriter xtw, Module m, int depth) { - try { - writeStartElement(xtw, MODULE, depth); - writeElement(xtw, NAME, m.name(), depth+1); - m.requires().stream().sorted(Comparator.comparing(d -> d.name)) - .forEach(d -> writeDependElement(xtw, d, depth+1)); - m.exports().keySet().stream() - .filter(pn -> m.exports().get(pn).isEmpty()) - .sorted() - .forEach(pn -> writeExportElement(xtw, pn, depth+1)); - m.exports().entrySet().stream() - .filter(e -> !e.getValue().isEmpty()) - .sorted(Map.Entry.comparingByKey()) - .forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1)); - m.packages().stream().sorted() - .forEach(p -> writeElement(xtw, INCLUDE, p, depth+1)); - writeEndElement(xtw, depth); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - - } - } - - /** Two spaces; the default indentation. */ - public static final String DEFAULT_INDENT = " "; - - /** stack[depth] indicates what's been written into the current scope. */ - private static String[] stack = new String[] { "\n", - "\n" + DEFAULT_INDENT, - "\n" + DEFAULT_INDENT + DEFAULT_INDENT, - "\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT}; - - private void writeStartElement(XMLStreamWriter xtw, String name, int depth) - throws XMLStreamException - { - xtw.writeCharacters(stack[depth]); - xtw.writeStartElement(name); - } - - private void writeEndElement(XMLStreamWriter xtw, int depth) throws XMLStreamException { - xtw.writeCharacters(stack[depth]); - xtw.writeEndElement(); - } - - private String packageName(Path p) { + private static String packageName(Path p) { return packageName(p.toString().replace(File.separatorChar, '/')); } - private String packageName(String name) { + private static String packageName(String name) { int i = name.lastIndexOf('/'); return (i > 0) ? name.substring(0, i).replace('/', '.') : ""; } - private boolean includes(String name) { - return name.endsWith(".class") && !name.equals("module-info.class"); + private static boolean includes(String name) { + return name.endsWith(".class"); } - public void buildIncludes(Module.Builder mb, String modulename) throws IOException { - Path mclasses = modulepath.resolve(modulename); + public Module buildIncludes(Module module) { + Module.Builder mb = new Module.Builder(module); + Path mclasses = modulepath.resolve(module.name()); try { Files.find(mclasses, Integer.MAX_VALUE, (Path p, BasicFileAttributes attr) -> includes(p.getFileName().toString())) @@ -341,145 +122,9 @@ .forEach(mb::include); } catch (NoSuchFileException e) { // aggregate module may not have class - } - } - - static class Module { - static class Dependence { - final String name; - final boolean reexport; - Dependence(String name) { - this(name, false); - } - Dependence(String name, boolean reexport) { - this.name = name; - this.reexport = reexport; - } - - @Override - public int hashCode() { - int hash = 5; - hash = 11 * hash + Objects.hashCode(this.name); - hash = 11 * hash + (this.reexport ? 1 : 0); - return hash; - } - - public boolean equals(Object o) { - Dependence d = (Dependence)o; - return this.name.equals(d.name) && this.reexport == d.reexport; - } - } - private final String moduleName; - private final Set<Dependence> requires; - private final Map<String, Set<String>> exports; - private final Set<String> packages; - - private Module(String name, - Set<Dependence> requires, - Map<String, Set<String>> exports, - Set<String> packages) { - this.moduleName = name; - this.requires = Collections.unmodifiableSet(requires); - this.exports = Collections.unmodifiableMap(exports); - this.packages = Collections.unmodifiableSet(packages); - } - - public String name() { - return moduleName; - } - - public Set<Dependence> requires() { - return requires; - } - - public Map<String, Set<String>> exports() { - return exports; - } - - public Set<String> packages() { - return packages; - } - - @Override - public boolean equals(Object ob) { - if (!(ob instanceof Module)) { - return false; - } - Module that = (Module) ob; - return (moduleName.equals(that.moduleName) - && requires.equals(that.requires) - && exports.equals(that.exports) - && packages.equals(that.packages)); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); } - - @Override - public int hashCode() { - int hc = moduleName.hashCode(); - hc = hc * 43 + requires.hashCode(); - hc = hc * 43 + exports.hashCode(); - hc = hc * 43 + packages.hashCode(); - return hc; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("module ").append(moduleName).append(" {").append("\n"); - requires.stream().sorted().forEach(d -> - sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name))); - exports.entrySet().stream().filter(e -> e.getValue().isEmpty()) - .sorted(Map.Entry.comparingByKey()) - .forEach(e -> sb.append(String.format(" exports %s%n", e.getKey()))); - exports.entrySet().stream().filter(e -> !e.getValue().isEmpty()) - .sorted(Map.Entry.comparingByKey()) - .forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue()))); - packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn))); - sb.append("}"); - return sb.toString(); - } - - static class Builder { - private String name; - private final Set<Dependence> requires = new HashSet<>(); - private final Map<String, Set<String>> exports = new HashMap<>(); - private final Set<String> packages = new HashSet<>(); - - public Builder() { - } - - public Builder name(String n) { - name = n; - return this; - } - - public Builder require(String d, boolean reexport) { - requires.add(new Dependence(d, reexport)); - return this; - } - - public Builder include(String p) { - packages.add(p); - return this; - } - - public Builder export(String p) { - return exportTo(p, Collections.emptySet()); - } - - public Builder exportTo(String p, Set<String> ms) { - Objects.requireNonNull(p); - Objects.requireNonNull(ms); - if (exports.containsKey(p)) { - throw new RuntimeException(name + " already exports " + p); - } - exports.put(p, new HashSet<>(ms)); - return this; - } - - public Module build() { - Module m = new Module(name, requires, exports, packages); - return m; - } - } + return mb.build(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/src/classes/build/tools/module/GenModulesList.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.module; + +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + +/** + * $ java build.tools.module.GenModulesList \ + * -o modules.list \ + * top/modules.xml ... + */ +public final class GenModulesList { + private final static String USAGE = + "Usage: GenModulesList -o <output file> path-to-modules-xml"; + + private Set<Module> modules = new HashSet<>(); + private HashMap<String,Module> nameToModule = new HashMap<>(); + + public static void main(String[] args) throws Exception { + GenModulesList gen = new GenModulesList(); + gen.run(args); + } + + void run(String[] args) throws Exception { + Path outfile = null; + int i = 0; + while (i < args.length) { + String arg = args[i]; + if (arg.equals("-o")) { + outfile = Paths.get(args[i+1]); + i = i+2; + } else { + break; + } + } + if (outfile == null || i >= args.length) { + System.err.println(USAGE); + System.exit(-1); + } + + for (; i < args.length; i++) { + Path p = Paths.get(args[i]); + modules.addAll(ModulesXmlReader.readModules(p)); + } + + modules.stream() + .forEach(m -> nameToModule.put(m.name(), m)); + + Path parent = outfile.getParent(); + if (parent != null) + Files.createDirectories(parent); + + Iterable<Module> sortedModules = (new TopoSorter(modules)).result(); + try (PrintWriter writer = new PrintWriter(outfile.toFile())) { + for (Module m : sortedModules) { + if (isNotAggregator(m)) { + String deps = getModuleDependences(m).stream() + .filter(GenModulesList::isNotAggregator) + .map(Module::name) + .collect(Collectors.joining(" ")); + writer.format("%s: %s%n", m.name(), deps); + } + } + } + } + + private Module nameToModule(String name) { + return nameToModule.get(name); + } + + private Set<Module> getModuleDependences(Module m) { + return m.requires().stream() + .map(d -> d.name()) + .map(this::nameToModule) + .collect(Collectors.toSet()); + } + + static boolean isNotAggregator(Module m) { + return isNotAggregator(m.name()); + } + + static boolean isNotAggregator(String name) { + return AGGREGATORS.contains(name) ? false : true; + } + + static final List<String> AGGREGATORS = Arrays.asList(new String[] { + "java.se", "java.compact1", "java.compact2", + "java.compact3", "jdk.compact3"}); + + class TopoSorter { + final Deque<Module> result = new LinkedList<>(); + final Deque<Module> nodes = new LinkedList<>(); + + TopoSorter(Collection<Module> nodes) { + nodes.stream() + .forEach(m -> this.nodes.add(m)); + + sort(); + } + + public Iterable<Module> result() { + return result; + } + + private void sort() { + Deque<Module> visited = new LinkedList<>(); + Deque<Module> done = new LinkedList<>(); + Module node; + while ((node = nodes.poll()) != null) { + if (!visited.contains(node)) { + visit(node, visited, done); + } + } + } + + private void visit(Module m, Deque<Module> visited, Deque<Module> done) { + if (visited.contains(m)) { + if (!done.contains(m)) { + throw new IllegalArgumentException("Cyclic detected: " + + m + " " + getModuleDependences(m)); + } + return; + } + visited.add(m); + getModuleDependences(m).stream() + .forEach(x -> visit(x, visited, done)); + done.add(m); + result.addLast(m); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/src/classes/build/tools/module/Module.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.module; + +import java.util.*; + +public class Module { + static class Dependence { + final String name; + final boolean reexport; + Dependence(String name) { + this(name, false); + } + Dependence(String name, boolean reexport) { + this.name = name; + this.reexport = reexport; + } + + public String name() { + return name; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 11 * hash + Objects.hashCode(this.name); + hash = 11 * hash + (this.reexport ? 1 : 0); + return hash; + } + + public boolean equals(Object o) { + Dependence d = (Dependence)o; + return this.name.equals(d.name) && this.reexport == d.reexport; + } + } + private final String moduleName; + private final Set<Dependence> requires; + private final Map<String, Set<String>> exports; + private final Set<String> packages; + + private Module(String name, + Set<Dependence> requires, + Map<String, Set<String>> exports, + Set<String> packages) { + this.moduleName = name; + this.requires = Collections.unmodifiableSet(requires); + this.exports = Collections.unmodifiableMap(exports); + this.packages = Collections.unmodifiableSet(packages); + } + + public String name() { + return moduleName; + } + + public Set<Dependence> requires() { + return requires; + } + + public Map<String, Set<String>> exports() { + return exports; + } + + public Set<String> packages() { + return packages; + } + + @Override + public boolean equals(Object ob) { + if (!(ob instanceof Module)) { + return false; + } + Module that = (Module) ob; + return (moduleName.equals(that.moduleName) + && requires.equals(that.requires) + && exports.equals(that.exports) + && packages.equals(that.packages)); + } + + @Override + public int hashCode() { + int hc = moduleName.hashCode(); + hc = hc * 43 + requires.hashCode(); + hc = hc * 43 + exports.hashCode(); + hc = hc * 43 + packages.hashCode(); + return hc; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("module ").append(moduleName).append(" {").append("\n"); + requires.stream().sorted().forEach(d -> + sb.append(String.format(" requires %s%s%n", d.reexport ? "public " : "", d.name))); + exports.entrySet().stream().filter(e -> e.getValue().isEmpty()) + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> sb.append(String.format(" exports %s%n", e.getKey()))); + exports.entrySet().stream().filter(e -> !e.getValue().isEmpty()) + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> sb.append(String.format(" exports %s to %s%n", e.getKey(), e.getValue()))); + packages.stream().sorted().forEach(pn -> sb.append(String.format(" includes %s%n", pn))); + sb.append("}"); + return sb.toString(); + } + + static class Builder { + private String name; + private final Set<Dependence> requires = new HashSet<>(); + private final Map<String, Set<String>> exports = new HashMap<>(); + private final Set<String> packages = new HashSet<>(); + + public Builder() { + } + + public Builder(Module module) { + name = module.name(); + requires.addAll(module.requires()); + exports.putAll(module.exports()); + packages.addAll(module.packages()); + } + + public Builder name(String n) { + name = n; + return this; + } + + public Builder require(String d, boolean reexport) { + requires.add(new Dependence(d, reexport)); + return this; + } + + public Builder include(String p) { + packages.add(p); + return this; + } + + public Builder export(String p) { + return exportTo(p, Collections.emptySet()); + } + + public Builder exportTo(String p, Set<String> ms) { + Objects.requireNonNull(p); + Objects.requireNonNull(ms); + if (exports.containsKey(p)) { + throw new RuntimeException(name + " already exports " + p); + } + exports.put(p, new HashSet<>(ms)); + return this; + } + + public Module build() { + Module m = new Module(name, requires, exports, packages); + return m; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/src/classes/build/tools/module/ModulesXmlReader.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.module; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.XMLEvent; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; + +public class ModulesXmlReader { + + private ModulesXmlReader() {} + + public static Set<Module> readModules(Path modulesXml) + throws XMLStreamException, IOException + { + Set<Module> modules = new HashSet<>(); + try (InputStream in = new BufferedInputStream(Files.newInputStream(modulesXml))) { + Set<Module> mods = ModulesXmlReader.load(in); + modules.addAll(mods); + } + return modules; + } + + private static final String MODULES = "modules"; + private static final String MODULE = "module"; + private static final String NAME = "name"; + private static final String DEPEND = "depend"; + private static final String EXPORT = "export"; + private static final String TO = "to"; + private static final String INCLUDE = "include"; + private static final QName REEXPORTS = new QName("re-exports"); + private static Set<Module> load(InputStream in) + throws XMLStreamException, IOException + { + Set<Module> modules = new HashSet<>(); + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader stream = factory.createXMLEventReader(in); + Module.Builder mb = null; + String modulename = null; + String pkg = null; + Set<String> permits = new HashSet<>(); + while (stream.hasNext()) { + XMLEvent event = stream.nextEvent(); + if (event.isStartElement()) { + String startTag = event.asStartElement().getName().getLocalPart(); + switch (startTag) { + case MODULES: + break; + case MODULE: + if (mb != null) { + throw new RuntimeException("end tag for module is missing"); + } + modulename = getNextTag(stream, NAME); + mb = new Module.Builder(); + mb.name(modulename); + break; + case NAME: + throw new RuntimeException(event.toString()); + case DEPEND: + boolean reexports = false; + Attribute attr = event.asStartElement().getAttributeByName(REEXPORTS); + if (attr != null) { + String value = attr.getValue(); + if (value.equals("true") || value.equals("false")) { + reexports = Boolean.parseBoolean(value); + } else { + throw new RuntimeException("unexpected attribute " + attr.toString()); + } + } + mb.require(getData(stream), reexports); + break; + case INCLUDE: + throw new RuntimeException("unexpected " + event); + case EXPORT: + pkg = getNextTag(stream, NAME); + break; + case TO: + permits.add(getData(stream)); + break; + default: + } + } else if (event.isEndElement()) { + String endTag = event.asEndElement().getName().getLocalPart(); + switch (endTag) { + case MODULE: + modules.add(mb.build()); + mb = null; + break; + case EXPORT: + if (pkg == null) { + throw new RuntimeException("export-to is malformed"); + } + mb.exportTo(pkg, permits); + pkg = null; + permits.clear(); + break; + default: + } + } else if (event.isCharacters()) { + String s = event.asCharacters().getData(); + if (!s.trim().isEmpty()) { + throw new RuntimeException("export-to is malformed"); + } + } + } + return modules; + } + + private static String getData(XMLEventReader reader) + throws XMLStreamException + { + XMLEvent e = reader.nextEvent(); + if (e.isCharacters()) + return e.asCharacters().getData(); + + throw new RuntimeException(e.toString()); + } + + private static String getNextTag(XMLEventReader reader, String tag) + throws XMLStreamException + { + XMLEvent e = reader.nextTag(); + if (e.isStartElement()) { + String t = e.asStartElement().getName().getLocalPart(); + if (!tag.equals(t)) { + throw new RuntimeException(e + " expected: " + tag); + } + return getData(reader); + } + throw new RuntimeException("export-to name is missing:" + e); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/src/classes/build/tools/module/ModulesXmlWriter.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package build.tools.module; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.Set; + +public final class ModulesXmlWriter { + + private ModulesXmlWriter() {} + + public static void writeModules(Set<Module> modules, Path path) + throws IOException, XMLStreamException + { + writeXML(modules, path); + } + + private static final String MODULES = "modules"; + private static final String MODULE = "module"; + private static final String NAME = "name"; + private static final String DEPEND = "depend"; + private static final String EXPORT = "export"; + private static final String TO = "to"; + private static final String INCLUDE = "include"; + private static final QName REEXPORTS = new QName("re-exports"); + + private static void writeXML(Set<Module> modules, Path path) + throws IOException, XMLStreamException + { + XMLOutputFactory xof = XMLOutputFactory.newInstance(); + try (OutputStream out = Files.newOutputStream(path)) { + int depth = 0; + XMLStreamWriter xtw = xof.createXMLStreamWriter(out, "UTF-8"); + xtw.writeStartDocument("utf-8","1.0"); + writeStartElement(xtw, MODULES, depth); + modules.stream() + .sorted(Comparator.comparing(Module::name)) + .forEach(m -> writeModuleElement(xtw, m, depth+1)); + writeEndElement(xtw, depth); + xtw.writeCharacters("\n"); + xtw.writeEndDocument(); + xtw.flush(); + xtw.close(); + } + } + + private static void writeElement(XMLStreamWriter xtw, + String element, + String value, + int depth) { + try { + writeStartElement(xtw, element, depth); + xtw.writeCharacters(value); + xtw.writeEndElement(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + private static void writeDependElement(XMLStreamWriter xtw, + Module.Dependence d, + int depth) { + try { + writeStartElement(xtw, DEPEND, depth); + if (d.reexport) { + xtw.writeAttribute("re-exports", "true"); + } + xtw.writeCharacters(d.name); + xtw.writeEndElement(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + private static void writeExportElement(XMLStreamWriter xtw, + String pkg, + int depth) { + writeExportElement(xtw, pkg, Collections.emptySet(), depth); + } + + private static void writeExportElement(XMLStreamWriter xtw, + String pkg, + Set<String> permits, + int depth) { + try { + writeStartElement(xtw, EXPORT, depth); + writeElement(xtw, NAME, pkg, depth+1); + if (!permits.isEmpty()) { + permits.stream().sorted() + .forEach(m -> writeElement(xtw, TO, m, depth + 1)); + } + writeEndElement(xtw, depth); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + private static void writeModuleElement(XMLStreamWriter xtw, + Module m, + int depth) { + try { + writeStartElement(xtw, MODULE, depth); + writeElement(xtw, NAME, m.name(), depth+1); + m.requires().stream().sorted(Comparator.comparing(d -> d.name)) + .forEach(d -> writeDependElement(xtw, d, depth+1)); + m.exports().keySet().stream() + .filter(pn -> m.exports().get(pn).isEmpty()) + .sorted() + .forEach(pn -> writeExportElement(xtw, pn, depth+1)); + m.exports().entrySet().stream() + .filter(e -> !e.getValue().isEmpty()) + .sorted(Map.Entry.comparingByKey()) + .forEach(e -> writeExportElement(xtw, e.getKey(), e.getValue(), depth+1)); + m.packages().stream().sorted() + .forEach(p -> writeElement(xtw, INCLUDE, p, depth+1)); + writeEndElement(xtw, depth); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + + } + } + + /** Two spaces; the default indentation. */ + public static final String DEFAULT_INDENT = " "; + + /** stack[depth] indicates what's been written into the current scope. */ + private static String[] stack = new String[] { "\n", + "\n" + DEFAULT_INDENT, + "\n" + DEFAULT_INDENT + DEFAULT_INDENT, + "\n" + DEFAULT_INDENT + DEFAULT_INDENT + DEFAULT_INDENT}; + + private static void writeStartElement(XMLStreamWriter xtw, + String name, + int depth) + throws XMLStreamException + { + xtw.writeCharacters(stack[depth]); + xtw.writeStartElement(name); + } + + private static void writeEndElement(XMLStreamWriter xtw, int depth) + throws XMLStreamException + { + xtw.writeCharacters(stack[depth]); + xtw.writeEndElement(); + } +}
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Sep 18 13:27:48 2014 -0700 @@ -62,7 +62,7 @@ private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ - private static final String superName = LF; + private static final String superName = OBJ; /** Name of new class */ private final String className; @@ -97,7 +97,7 @@ if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = superName + "$" + className; + this.className = LF + "$" + className; this.sourceFile = "LambdaForm$" + className; this.lambdaForm = lambdaForm; this.invokerName = invokerName;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -188,7 +188,6 @@ static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, boolean strict, boolean monobox) { MethodType dstType = target.type(); - assert(dstType.parameterCount() == target.type().parameterCount()); if (srcType == dstType) return target; if (USE_LAMBDA_FORM_EDITOR) { @@ -265,6 +264,7 @@ static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, boolean strict, boolean monobox) { + assert(target.type().parameterCount() == srcType.parameterCount()); // Calculate extra arguments (temporaries) required in the names array. Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); final int INARG_COUNT = srcType.parameterCount();
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Sep 18 13:27:48 2014 -0700 @@ -2023,8 +2023,9 @@ */ public static MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { + explicitCastArgumentsChecks(target, newType); + // use the asTypeCache when possible: MethodType oldType = target.type(); - // use the asTypeCache when possible: if (oldType == newType) return target; if (oldType.explicitCastEquivalentToAsType(newType)) { return target.asType(newType); @@ -2032,6 +2033,12 @@ return MethodHandleImpl.makePairwiseConvert(target, newType, false); } + private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) { + if (target.type().parameterCount() != newType.parameterCount()) { + throw new WrongMethodTypeException("cannot explicitly cast " + target + " to " + newType); + } + } + /** * Produces a method handle which adapts the calling sequence of the * given method handle to a new type, by reordering the arguments. @@ -2164,7 +2171,7 @@ // dropIdx is missing from reorder; add it in at the end int oldArity = reorder.length; target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); - reorder = Arrays.copyOf(reorder, oldArity+1); + reorder = Arrays.copyOf(reorder, oldArity + 1); reorder[oldArity] = dropIdx; } assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); @@ -2182,9 +2189,9 @@ long mask = 0; for (int arg : reorder) { assert(arg < newArity); - mask |= (1 << arg); + mask |= (1L << arg); } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return -1; } @@ -2193,16 +2200,18 @@ int zeroPos = Long.numberOfTrailingZeros(zeroBit); assert(zeroPos < newArity); return zeroPos; + } else { + BitSet mask = new BitSet(newArity); + for (int arg : reorder) { + assert (arg < newArity); + mask.set(arg); + } + int zeroPos = mask.nextClearBit(0); + assert(zeroPos <= newArity); + if (zeroPos == newArity) + return -1; + return zeroPos; } - BitSet mask = new BitSet(newArity); - for (int arg : reorder) { - assert(arg < newArity); - mask.set(arg); - } - int zeroPos = mask.nextClearBit(0); - if (zeroPos == newArity) - return -1; - return zeroPos; } /** @@ -2218,32 +2227,42 @@ long mask = 0; for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - int bit = 1 << arg; - if ((mask & bit) != 0) + if (arg >= newArity) { + return reorder.length; + } + long bit = 1L << arg; + if ((mask & bit) != 0) { return i; // >0 indicates a dup + } mask |= bit; } - if (mask == (1 << newArity) - 1) { + if (mask == (1L << newArity) - 1) { assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); return 0; } // find first zero long zeroBit = Long.lowestOneBit(~mask); int zeroPos = Long.numberOfTrailingZeros(zeroBit); - assert(zeroPos < newArity); + assert(zeroPos <= newArity); + if (zeroPos == newArity) { + return 0; + } return ~zeroPos; } else { // same algorithm, different bit set BitSet mask = new BitSet(newArity); for (int i = 0; i < reorder.length; i++) { int arg = reorder[i]; - if (arg >= newArity) return reorder.length; - if (mask.get(arg)) + if (arg >= newArity) { + return reorder.length; + } + if (mask.get(arg)) { return i; // >0 indicates a dup + } mask.set(arg); } int zeroPos = mask.nextClearBit(0); + assert(zeroPos <= newArity); if (zeroPos == newArity) { return 0; } @@ -2479,6 +2498,7 @@ MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { MethodType oldType = target.type(); // get NPE int dropped = dropArgumentChecks(oldType, pos, valueTypes); + MethodType newType = oldType.insertParameterTypes(pos, valueTypes); if (dropped == 0) return target; BoundMethodHandle result = target.rebind(); LambdaForm lform = result.form; @@ -2490,7 +2510,6 @@ } else { lform = lform.addArguments(pos, valueTypes); } - MethodType newType = oldType.insertParameterTypes(pos, valueTypes); result = result.copyWith(newType, lform); return result; }
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Sep 18 13:27:48 2014 -0700 @@ -869,9 +869,7 @@ if (dstTypes == srcTypes) { return true; } - if (dstTypes.length != srcTypes.length) { - return false; - } + assert(dstTypes.length == srcTypes.length); for (int i = 0; i < dstTypes.length; i++) { if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) { return false;
--- a/src/java.base/share/classes/java/math/MutableBigInteger.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/math/MutableBigInteger.java Thu Sep 18 13:27:48 2014 -0700 @@ -1261,19 +1261,20 @@ int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} MutableBigInteger bShifted = new MutableBigInteger(b); bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n - safeLeftShift(sigma); // step 4b: shift this by the same amount + MutableBigInteger aShifted = new MutableBigInteger (this); + aShifted.safeLeftShift(sigma); // step 4b: shift a by the same amount - // step 5: t is the number of blocks needed to accommodate this plus one additional bit - int t = (int) ((bitLength()+n32) / n32); + // step 5: t is the number of blocks needed to accommodate a plus one additional bit + int t = (int) ((aShifted.bitLength()+n32) / n32); if (t < 2) { t = 2; } - // step 6: conceptually split this into blocks a[t-1], ..., a[0] - MutableBigInteger a1 = getBlock(t-1, t, n); // the most significant block of this + // step 6: conceptually split a into blocks a[t-1], ..., a[0] + MutableBigInteger a1 = aShifted.getBlock(t-1, t, n); // the most significant block of a // step 7: z[t-2] = [a[t-1], a[t-2]] - MutableBigInteger z = getBlock(t-2, t, n); // the second to most significant block + MutableBigInteger z = aShifted.getBlock(t-2, t, n); // the second to most significant block z.addDisjoint(a1, n); // z[t-2] // do schoolbook division on blocks, dividing 2-block numbers by 1-block numbers @@ -1284,7 +1285,7 @@ ri = z.divide2n1n(bShifted, qi); // step 8b: z = [ri, a[i-1]] - z = getBlock(i-1, t, n); // a[i-1] + z = aShifted.getBlock(i-1, t, n); // a[i-1] z.addDisjoint(ri, n); quotient.addShifted(qi, i*n); // update q (part of step 9) } @@ -1292,7 +1293,7 @@ ri = z.divide2n1n(bShifted, qi); quotient.add(qi); - ri.rightShift(sigma); // step 9: this and b were shifted, so shift back + ri.rightShift(sigma); // step 9: a and b were shifted, so shift back return ri; } }
--- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java Thu Sep 18 13:27:48 2014 -0700 @@ -336,8 +336,21 @@ return new ZipEntry(name); } - /* + /** * Reads end of deflated entry as well as EXT descriptor if present. + * + * Local headers for DEFLATED entries may optionally be followed by a + * data descriptor, and that data descriptor may optionally contain a + * leading signature (EXTSIG). + * + * From the zip spec http://www.pkware.com/documents/casestudies/APPNOTE.TXT + * + * """Although not originally assigned a signature, the value 0x08074b50 + * has commonly been adopted as a signature value for the data descriptor + * record. Implementers should be aware that ZIP files may be + * encountered with or without this signature marking data descriptors + * and should account for either case when reading ZIP files to ensure + * compatibility.""" */ private void readEnd(ZipEntry e) throws IOException { int n = inf.getRemaining(); @@ -356,7 +369,7 @@ e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); ((PushbackInputStream)in).unread( - tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC); + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC); } else { e.crc = get32(tmpbuf, ZIP64_EXTCRC); e.csize = get64(tmpbuf, ZIP64_EXTSIZ); @@ -370,7 +383,7 @@ e.csize = get32(tmpbuf, EXTSIZ - EXTCRC); e.size = get32(tmpbuf, EXTLEN - EXTCRC); ((PushbackInputStream)in).unread( - tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC); + tmpbuf, EXTHDR - EXTCRC, EXTCRC); } else { e.crc = get32(tmpbuf, EXTCRC); e.csize = get32(tmpbuf, EXTSIZ);
--- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Thu Sep 18 13:27:48 2014 -0700 @@ -34,6 +34,10 @@ #include <fcntl.h> #include <sys/uio.h> #include <unistd.h> +#if defined(__linux__) +#include <linux/fs.h> +#include <sys/ioctl.h> +#endif #include "nio.h" #include "nio_util.h" @@ -177,10 +181,21 @@ JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) { + jint fd = fdval(env, fdo); struct stat64 fbuf; - if (fstat64(fdval(env, fdo), &fbuf) < 0) + if (fstat64(fd, &fbuf) < 0) return handle(env, -1, "Size failed"); + +#ifdef BLKGETSIZE64 + if (S_ISBLK(fbuf.st_mode)) { + uint64_t size; + if (ioctl(fd, BLKGETSIZE64, &size) < 0) + return handle(env, -1, "Size failed"); + return (jlong)size; + } +#endif + return fbuf.st_size; }
--- a/src/java.base/windows/native/libnet/NetworkInterface.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.base/windows/native/libnet/NetworkInterface.c Thu Sep 18 13:27:48 2014 -0700 @@ -990,9 +990,11 @@ case MIB_IF_TYPE_FDDI: case IF_TYPE_IEEE80211: len = ifRowP->dwPhysAddrLen; - ret = (*env)->NewByteArray(env, len); - if (!IS_NULL(ret)) { - (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); + if (len > 0) { + ret = (*env)->NewByteArray(env, len); + if (!IS_NULL(ret)) { + (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) ifRowP->bPhysAddr); + } } break; }
--- a/src/java.desktop/macosx/classes/sun/awt/datatransfer/flavormap.properties Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -# -# This properties file is used to initialize the default -# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific, -# default mappings between common Mac OS X selection atoms and platform-independent -# MIME type strings, which will be converted into -# java.awt.datatransfer.DataFlavors. -# -# The standard format is: -# -# <native>=<MIME type>,<MIME type>, ... -# -# <native> should be a string identifier that the native platform will -# recognize as a valid data format. <MIME type> should specify both a MIME -# primary type and a MIME subtype separated by a '/'. The MIME type may include -# parameters, where each parameter is a key/value pair separated by '=', and -# where each parameter to the MIME type is separated by a ';'. -# -# Because SystemFlavorMap implements FlavorTable, developers are free to -# duplicate DataFlavor values and set multiple values for a single native by -# separating them with ",". If a mapping contains a duplicate key or value, -# earlier mappings which included this key or value will be preferred. -# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", and which support the charset parameter, should specify the exact -# format in which the native platform expects the data. The "charset" -# parameter specifies the char to byte encoding, the "eoln" parameter -# specifies the end-of-line marker, and the "terminators" parameter specifies -# the number of terminating NUL bytes. Note that "eoln" and "terminators" -# are not standardized MIME type parameters. They are specific to this file -# format ONLY. They will not appear in any of the DataFlavors returned by the -# SystemFlavorMap at the Java level. -# -# If the "charset" parameter is omitted, or has zero length, the platform -# default encoding is assumed. If the "eoln" parameter is omitted, or has -# zero length, "\n" is assumed. If the "terminators" parameter is omitted, -# or has a value less than zero, zero is assumed. -# -# Upon initialization, the data transfer subsystem will record the specified -# details of the native text format, but the default SystemFlavorMap will -# present a large set of synthesized DataFlavors which map, in both -# directions, to the native. After receiving data from the application in one -# of the synthetic DataFlavors, the data transfer subsystem will transform -# the data stream into the format specified in this file before passing the -# transformed stream to the native system. -# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", but which do not support the charset parameter, will be treated as -# opaque, 8-bit data. They will not undergo any transformation process, and -# any "charset", "eoln", or "terminators" parameters specified in this file -# will be ignored. -# -# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of -# text flavors which support the charset parameter. - -UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 - -# The COMPOUND_TEXT support for inter-client text transfer is disabled by -# default. The reason is that many native applications prefer this format over -# other native text formats, but are unable to decode the textual data in this -# format properly. This results in java-to-native text transfer failures. -# To enable the COMPOUND_TEXT support for this JRE installation uncomment -# the line below. - -# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0 - -TEXT=text/plain;eoln="\n";terminators=0 -STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 -FILE_NAME=application/x-java-file-list;class=java.util.List -text/uri-list=application/x-java-file-list;class=java.util.List -PNG=image/x-java-image;class=java.awt.Image -JFIF=image/x-java-image;class=java.awt.Image -TIFF=image/x-java-image;class=java.awt.Image -RICH_TEXT=text/rtf -HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1 -URL=application/x-java-url;class=java.net.URL,\ - text/uri-list;eoln="\r\n";terminators=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.desktop/macosx/classes/sun/datatransfer/resources/flavormap.properties Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,76 @@ +# +# This properties file is used to initialize the default +# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific, +# default mappings between common Mac OS X selection atoms and platform-independent +# MIME type strings, which will be converted into +# java.awt.datatransfer.DataFlavors. +# +# The standard format is: +# +# <native>=<MIME type>,<MIME type>, ... +# +# <native> should be a string identifier that the native platform will +# recognize as a valid data format. <MIME type> should specify both a MIME +# primary type and a MIME subtype separated by a '/'. The MIME type may include +# parameters, where each parameter is a key/value pair separated by '=', and +# where each parameter to the MIME type is separated by a ';'. +# +# Because SystemFlavorMap implements FlavorTable, developers are free to +# duplicate DataFlavor values and set multiple values for a single native by +# separating them with ",". If a mapping contains a duplicate key or value, +# earlier mappings which included this key or value will be preferred. +# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", and which support the charset parameter, should specify the exact +# format in which the native platform expects the data. The "charset" +# parameter specifies the char to byte encoding, the "eoln" parameter +# specifies the end-of-line marker, and the "terminators" parameter specifies +# the number of terminating NUL bytes. Note that "eoln" and "terminators" +# are not standardized MIME type parameters. They are specific to this file +# format ONLY. They will not appear in any of the DataFlavors returned by the +# SystemFlavorMap at the Java level. +# +# If the "charset" parameter is omitted, or has zero length, the platform +# default encoding is assumed. If the "eoln" parameter is omitted, or has +# zero length, "\n" is assumed. If the "terminators" parameter is omitted, +# or has a value less than zero, zero is assumed. +# +# Upon initialization, the data transfer subsystem will record the specified +# details of the native text format, but the default SystemFlavorMap will +# present a large set of synthesized DataFlavors which map, in both +# directions, to the native. After receiving data from the application in one +# of the synthetic DataFlavors, the data transfer subsystem will transform +# the data stream into the format specified in this file before passing the +# transformed stream to the native system. +# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", but which do not support the charset parameter, will be treated as +# opaque, 8-bit data. They will not undergo any transformation process, and +# any "charset", "eoln", or "terminators" parameters specified in this file +# will be ignored. +# +# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of +# text flavors which support the charset parameter. + +UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 + +# The COMPOUND_TEXT support for inter-client text transfer is disabled by +# default. The reason is that many native applications prefer this format over +# other native text formats, but are unable to decode the textual data in this +# format properly. This results in java-to-native text transfer failures. +# To enable the COMPOUND_TEXT support for this JRE installation uncomment +# the line below. + +# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0 + +TEXT=text/plain;eoln="\n";terminators=0 +STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 +FILE_NAME=application/x-java-file-list;class=java.util.List +text/uri-list=application/x-java-file-list;class=java.util.List +PNG=image/x-java-image;class=java.awt.Image +JFIF=image/x-java-image;class=java.awt.Image +TIFF=image/x-java-image;class=java.awt.Image +RICH_TEXT=text/rtf +HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1 +URL=application/x-java-url;class=java.net.URL,\ + text/uri-list;eoln="\r\n";terminators=1
--- a/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/classes/java/awt/event/InputMethodEvent.java Thu Sep 18 13:27:48 2014 -0700 @@ -418,7 +418,8 @@ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); if (when == 0) { - when = getMostRecentEventTimeForSource(this.source); + // Can't use getMostRecentEventTimeForSource because source is always null during deserialization + when = EventQueue.getMostRecentEventTime(); } }
--- a/src/java.desktop/share/classes/javax/swing/JDesktopPane.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/classes/javax/swing/JDesktopPane.java Thu Sep 18 13:27:48 2014 -0700 @@ -43,6 +43,7 @@ import java.beans.PropertyVetoException; import java.util.Set; import java.util.TreeSet; +import java.util.LinkedHashSet; /** * A container used to create a multiple-document interface or a virtual desktop. * You create <code>JInternalFrame</code> objects and add them to the @@ -271,7 +272,7 @@ private static Collection<JInternalFrame> getAllFrames(Container parent) { int i, count; - Collection<JInternalFrame> results = new ArrayList<JInternalFrame>(); + Collection<JInternalFrame> results = new LinkedHashSet<>(); count = parent.getComponentCount(); for (i = 0; i < count; i++) { Component next = parent.getComponent(i);
--- a/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceDataProxy.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceDataProxy.java Thu Sep 18 13:27:48 2014 -0700 @@ -65,7 +65,11 @@ int w, int h) { if (cachedData == null) { - cachedData = oglgc.createManagedSurface(w, h, transparency); + try { + cachedData = oglgc.createManagedSurface(w, h, transparency); + } catch (OutOfMemoryError er) { + return null; + } } return cachedData; }
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Thu Sep 18 13:27:48 2014 -0700 @@ -1082,86 +1082,60 @@ return 1; } -static void addToGP(GPData* gpdata, FT_Outline*outline) { - jbyte current_type=SEG_UNKNOWN; - int i, j; - jfloat x, y; +static void addSeg(GPData *gp, jbyte type) { + gp->pointTypes[gp->numTypes++] = type; +} + +static void addCoords(GPData *gp, FT_Vector *p) { + gp->pointCoords[gp->numCoords++] = F26Dot6ToFloat(p->x); + gp->pointCoords[gp->numCoords++] = -F26Dot6ToFloat(p->y); +} - j = 0; - for(i=0; i<outline->n_points; i++) { - x = F26Dot6ToFloat(outline->points[i].x); - y = -F26Dot6ToFloat(outline->points[i].y); +static int moveTo(FT_Vector *to, GPData *gp) { + if (gp->numCoords) + addSeg(gp, SEG_CLOSE); + addCoords(gp, to); + addSeg(gp, SEG_MOVETO); + return FT_Err_Ok; +} + +static int lineTo(FT_Vector *to, GPData *gp) { + addCoords(gp, to); + addSeg(gp, SEG_LINETO); + return FT_Err_Ok; +} - if (FT_CURVE_TAG(outline->tags[i]) == FT_CURVE_TAG_ON) { - /* If bit 0 is unset, the point is "off" the curve, - i.e., a Bezier control point, while it is "on" when set. */ - if (current_type == SEG_UNKNOWN) { /* special case: - very first point */ - /* add segment */ - gpdata->pointTypes[gpdata->numTypes++] = SEG_MOVETO; - current_type = SEG_LINETO; - } else { - gpdata->pointTypes[gpdata->numTypes++] = current_type; - current_type = SEG_LINETO; - } - } else { - if (current_type == SEG_UNKNOWN) { /* special case: - very first point */ - if (FT_CURVE_TAG(outline->tags[i+1]) == FT_CURVE_TAG_ON) { - /* just skip first point. Adhoc heuristic? */ - continue; - } else { - x = (x + F26Dot6ToFloat(outline->points[i+1].x))/2; - y = (y - F26Dot6ToFloat(outline->points[i+1].y))/2; - gpdata->pointTypes[gpdata->numTypes++] = SEG_MOVETO; - current_type = SEG_LINETO; - } - } else if (FT_CURVE_TAG(outline->tags[i]) == FT_CURVE_TAG_CUBIC) { - /* Bit 1 is meaningful for 'off' points only. - If set, it indicates a third-order Bezier arc control - point; and a second-order control point if unset. */ - current_type = SEG_CUBICTO; - } else { - /* two successive conic "off" points forces the rasterizer - to create (during the scan-line conversion process - exclusively) a virtual "on" point amidst them, at their - exact middle. This greatly facilitates the definition of - successive conic Bezier arcs. Moreover, it is the way - outlines are described in the TrueType specification. */ - if (current_type == SEG_QUADTO) { - gpdata->pointCoords[gpdata->numCoords++] = - F26Dot6ToFloat(outline->points[i].x + - outline->points[i-1].x)/2; - gpdata->pointCoords[gpdata->numCoords++] = - - F26Dot6ToFloat(outline->points[i].y + - outline->points[i-1].y)/2; - gpdata->pointTypes[gpdata->numTypes++] = SEG_QUADTO; - } - current_type = SEG_QUADTO; - } - } - gpdata->pointCoords[gpdata->numCoords++] = x; - gpdata->pointCoords[gpdata->numCoords++] = y; - if (outline->contours[j] == i) { //end of contour - int start = j > 0 ? outline->contours[j-1]+1 : 0; - gpdata->pointTypes[gpdata->numTypes++] = current_type; - if (current_type == SEG_QUADTO && - FT_CURVE_TAG(outline->tags[start]) != FT_CURVE_TAG_ON) { - gpdata->pointCoords[gpdata->numCoords++] = - (F26Dot6ToFloat(outline->points[start].x) + x)/2; - gpdata->pointCoords[gpdata->numCoords++] = - (-F26Dot6ToFloat(outline->points[start].y) + y)/2; - } else { - gpdata->pointCoords[gpdata->numCoords++] = - F26Dot6ToFloat(outline->points[start].x); - gpdata->pointCoords[gpdata->numCoords++] = - -F26Dot6ToFloat(outline->points[start].y); - } - gpdata->pointTypes[gpdata->numTypes++] = SEG_CLOSE; - current_type = SEG_UNKNOWN; - j++; - } - } +static int conicTo(FT_Vector *control, FT_Vector *to, GPData *gp) { + addCoords(gp, control); + addCoords(gp, to); + addSeg(gp, SEG_QUADTO); + return FT_Err_Ok; +} + +static int cubicTo(FT_Vector *control1, + FT_Vector *control2, + FT_Vector *to, + GPData *gp) { + addCoords(gp, control1); + addCoords(gp, control2); + addCoords(gp, to); + addSeg(gp, SEG_CUBICTO); + return FT_Err_Ok; +} + +static void addToGP(GPData* gpdata, FT_Outline*outline) { + static const FT_Outline_Funcs outline_funcs = { + (FT_Outline_MoveToFunc) moveTo, + (FT_Outline_LineToFunc) lineTo, + (FT_Outline_ConicToFunc) conicTo, + (FT_Outline_CubicToFunc) cubicTo, + 0, /* shift */ + 0, /* delta */ + }; + + FT_Outline_Decompose(outline, &outline_funcs, gpdata); + if (gpdata->numCoords) + addSeg(gpdata, SEG_CLOSE); /* If set to 1, the outline will be filled using the even-odd fill rule */ if (outline->flags & FT_OUTLINE_EVEN_ODD_FILL) {
--- a/src/java.desktop/share/native/liblcms/cmscam02.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmscam02.c Thu Sep 18 13:27:48 2014 -0700 @@ -467,11 +467,12 @@ CAM02COLOR clr; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; - memset(&clr, 0, sizeof(clr)); _cmsAssert(lpMod != NULL); _cmsAssert(pIn != NULL); _cmsAssert(pOut != NULL); + memset(&clr, 0, sizeof(clr)); + clr.XYZ[0] = pIn ->X; clr.XYZ[1] = pIn ->Y; clr.XYZ[2] = pIn ->Z; @@ -492,11 +493,12 @@ CAM02COLOR clr; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel; - memset(&clr, 0, sizeof(clr)); _cmsAssert(lpMod != NULL); _cmsAssert(pIn != NULL); _cmsAssert(pOut != NULL); + memset(&clr, 0, sizeof(clr)); + clr.J = pIn -> J; clr.C = pIn -> C; clr.h = pIn -> h; @@ -511,4 +513,3 @@ pOut ->Y = clr.XYZ[1]; pOut ->Z = clr.XYZ[2]; } -
--- a/src/java.desktop/share/native/liblcms/cmscgats.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmscgats.c Thu Sep 18 13:27:48 2014 -0700 @@ -2179,9 +2179,9 @@ if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) { - t -> SampleID = idField; - - for (i=0; i < t -> nPatches; i++) { + t -> SampleID = idField; + + for (i=0; i < t -> nPatches; i++) { char *Data = GetData(it8, i, idField); if (Data) { @@ -2196,7 +2196,7 @@ SetData(it8, i, idField, Buffer); } - } + } }
--- a/src/java.desktop/share/native/liblcms/cmscnvrt.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmscnvrt.c Thu Sep 18 13:27:48 2014 -0700 @@ -137,15 +137,68 @@ // A pointer to the begining of the list -static cmsIntentsList *Intents = DefaultIntents; +_cmsIntentsPluginChunkType _cmsIntentsPluginChunk = { NULL }; + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginIntentsList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsIntentsPluginChunkType newHead = { NULL }; + cmsIntentsList* entry; + cmsIntentsList* Anterior = NULL; + _cmsIntentsPluginChunkType* head = (_cmsIntentsPluginChunkType*) src->chunks[IntentPlugin]; + + // Walk the list copying all nodes + for (entry = head->Intents; + entry != NULL; + entry = entry ->Next) { + + cmsIntentsList *newEntry = ( cmsIntentsList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsIntentsList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.Intents == NULL) + newHead.Intents = newEntry; + } + + ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsIntentsPluginChunkType)); +} + +void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginIntentsList(ctx, src); + } + else { + static _cmsIntentsPluginChunkType IntentsPluginChunkType = { NULL }; + ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx ->MemPool, &IntentsPluginChunkType, sizeof(_cmsIntentsPluginChunkType)); + } +} + // Search the list for a suitable intent. Returns NULL if not found static -cmsIntentsList* SearchIntent(cmsUInt32Number Intent) +cmsIntentsList* SearchIntent(cmsContext ContextID, cmsUInt32Number Intent) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin); cmsIntentsList* pt; - for (pt = Intents; pt != NULL; pt = pt -> Next) + for (pt = ctx -> Intents; pt != NULL; pt = pt -> Next) + if (pt ->Intent == Intent) return pt; + + for (pt = DefaultIntents; pt != NULL; pt = pt -> Next) if (pt ->Intent == Intent) return pt; return NULL; @@ -1031,7 +1084,7 @@ // this case would present some issues if the custom intent tries to do things like // preserve primaries. This solution is not perfect, but works well on most cases. - Intent = SearchIntent(TheIntents[0]); + Intent = SearchIntent(ContextID, TheIntents[0]); if (Intent == NULL) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]); return NULL; @@ -1046,12 +1099,14 @@ // Get information about available intents. nMax is the maximum space for the supplied "Codes" // and "Descriptions" the function returns the total number of intents, which may be greater // than nMax, although the matrices are not populated beyond this level. -cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) +cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin); cmsIntentsList* pt; cmsUInt32Number nIntents; - for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next) + + for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next) { if (nIntents < nMax) { if (Codes != NULL) @@ -1064,37 +1119,52 @@ nIntents++; } + for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next) + { + if (nIntents < nMax) { + if (Codes != NULL) + Codes[nIntents] = pt ->Intent; + + if (Descriptions != NULL) + Descriptions[nIntents] = pt ->Description; + } + + nIntents++; + } return nIntents; } +cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions) +{ + return cmsGetSupportedIntentsTHR(NULL, nMax, Codes, Descriptions); +} + // The plug-in registration. User can add new intents or override default routines cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data) { + _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(id, IntentPlugin); cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data; cmsIntentsList* fl; - // Do we have to reset the intents? + // Do we have to reset the custom intents? if (Data == NULL) { - Intents = DefaultIntents; - return TRUE; + ctx->Intents = NULL; + return TRUE; } - fl = SearchIntent(Plugin ->Intent); + fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList)); + if (fl == NULL) return FALSE; - if (fl == NULL) { - fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList)); - if (fl == NULL) return FALSE; - } fl ->Intent = Plugin ->Intent; - strncpy(fl ->Description, Plugin ->Description, 255); - fl ->Description[255] = 0; + strncpy(fl ->Description, Plugin ->Description, sizeof(fl ->Description)-1); + fl ->Description[sizeof(fl ->Description)-1] = 0; fl ->Link = Plugin ->Link; - fl ->Next = Intents; - Intents = fl; + fl ->Next = ctx ->Intents; + ctx ->Intents = fl; return TRUE; }
--- a/src/java.desktop/share/native/liblcms/cmserr.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmserr.c Thu Sep 18 13:27:48 2014 -0700 @@ -60,13 +60,14 @@ // compare two strings ignoring case int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) { - register const unsigned char *us1 = (const unsigned char *)s1, - *us2 = (const unsigned char *)s2; + register const unsigned char *us1 = (const unsigned char *)s1, + *us2 = (const unsigned char *)s2; - while (toupper(*us1) == toupper(*us2++)) - if (*us1++ == '\0') - return (0); - return (toupper(*us1) - toupper(*--us2)); + while (toupper(*us1) == toupper(*us2++)) + if (*us1++ == '\0') + return 0; + + return (toupper(*us1) - toupper(*--us2)); } // long int because C99 specifies ftell in such way (7.19.9.2) @@ -91,9 +92,8 @@ // // This is the interface to low-level memory management routines. By default a simple // wrapping to malloc/free/realloc is provided, although there is a limit on the max -// amount of memoy that can be reclaimed. This is mostly as a safety feature to -// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms -// would never need. +// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent +// bogus or evil code to allocate huge blocks that otherwise lcms would never need. #define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) @@ -103,7 +103,7 @@ // required to be implemented: malloc, realloc and free, although the user may want to // replace the optional mallocZero, calloc and dup as well. -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // ********************************************************************************* @@ -143,7 +143,7 @@ cmsUNUSED_PARAMETER(ContextID); } -// The default realloc function. Again it check for exploits. If Ptr is NULL, +// The default realloc function. Again it checks for exploits. If Ptr is NULL, // realloc behaves the same way as malloc and allocates a new block of size bytes. static void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) @@ -196,28 +196,73 @@ return mem; } -// Pointers to malloc and _cmsFree functions in current environment -static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn; -static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn; -static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn; -static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn; -static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn; -static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn; + +// Pointers to memory manager functions in Context0 +_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, + _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn + }; + + +// Reset and duplicate memory manager +void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Duplicate + ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); + } + else { + + // To reset it, we use the default allocators, which cannot be overriden + ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; + } +} + +// Auxiliar to fill memory management functions from plugin (or context 0 defaults) +void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) +{ + if (Plugin == NULL) { + + memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); + } + else { + + ptr ->MallocPtr = Plugin -> MallocPtr; + ptr ->FreePtr = Plugin -> FreePtr; + ptr ->ReallocPtr = Plugin -> ReallocPtr; + + // Make sure we revert to defaults + ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; + ptr ->CallocPtr = _cmsCallocDefaultFn; + ptr ->DupPtr = _cmsDupDefaultFn; + + if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; + if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; + if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; + + } +} + // Plug-in replacement entry -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data) +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) { cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; + _cmsMemPluginChunkType* ptr; - // NULL forces to reset to defaults + // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. + // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the + // context internal data should be malloce'd by using those functions. if (Data == NULL) { - MallocPtr = _cmsMallocDefaultFn; - MallocZeroPtr= _cmsMallocZeroDefaultFn; - FreePtr = _cmsFreeDefaultFn; - ReallocPtr = _cmsReallocDefaultFn; - CallocPtr = _cmsCallocDefaultFn; - DupPtr = _cmsDupDefaultFn; + struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; + + // Return to the default allocators + if (ContextID != NULL) { + ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; + } return TRUE; } @@ -227,51 +272,56 @@ Plugin -> ReallocPtr == NULL) return FALSE; // Set replacement functions - MallocPtr = Plugin -> MallocPtr; - FreePtr = Plugin -> FreePtr; - ReallocPtr = Plugin -> ReallocPtr; + ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + if (ptr == NULL) + return FALSE; - if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr; - if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr; - if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr; - + _cmsInstallAllocFunctions(Plugin, ptr); return TRUE; } // Generic allocate void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) { - return MallocPtr(ContextID, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr ->MallocPtr(ContextID, size); } // Generic allocate & zero void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) { - return MallocZeroPtr(ContextID, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->MallocZeroPtr(ContextID, size); } // Generic calloc void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) { - return CallocPtr(ContextID, num, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->CallocPtr(ContextID, num, size); } // Generic reallocate void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) { - return ReallocPtr(ContextID, Ptr, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr->ReallocPtr(ContextID, Ptr, size); } // Generic free memory void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) { - if (Ptr != NULL) FreePtr(ContextID, Ptr); + if (Ptr != NULL) { + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + ptr ->FreePtr(ContextID, Ptr); + } } // Generic block duplication void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) { - return DupPtr(ContextID, Org, size); + _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); + return ptr ->DupPtr(ContextID, Org, size); } // ******************************************************************************************** @@ -380,6 +430,26 @@ return (void*) ptr; } +// Duplicate in pool +void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size) +{ + void *NewPtr; + + // Dup of null pointer is also NULL + if (ptr == NULL) + return NULL; + + NewPtr = _cmsSubAlloc(s, size); + + if (ptr != NULL && NewPtr != NULL) { + memcpy(NewPtr, ptr, size); + } + + return NewPtr; +} + + + // Error logging ****************************************************************** // There is no error handling at all. When a funtion fails, it returns proper value. @@ -401,8 +471,26 @@ // This is our default log error static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); -// The current handler in actual environment -static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction; +// Context0 storage, which is global +_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction }; + +// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value +// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients +void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction }; + void* from; + + if (src != NULL) { + from = src ->chunks[Logger]; + } + else { + from = &LogErrorChunk; + } + + ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType)); +} // The default error logger does nothing. static @@ -416,13 +504,24 @@ cmsUNUSED_PARAMETER(Text); } -// Change log error +// Change log error, context based +void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn) +{ + _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + + if (lhg != NULL) { + + if (Fn == NULL) + lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction; + else + lhg -> LogErrorHandler = Fn; + } +} + +// Change log error, legacy void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn) { - if (Fn == NULL) - LogErrorHandler = DefaultLogErrorHandlerFunction; - else - LogErrorHandler = Fn; + cmsSetLogErrorHandlerTHR(NULL, Fn); } // Log an error @@ -431,13 +530,18 @@ { va_list args; char Buffer[MAX_ERROR_MESSAGE_LEN]; + _cmsLogErrorChunkType* lhg; + va_start(args, ErrorText); vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); va_end(args); - // Call handler - LogErrorHandler(ContextID, ErrorCode, Buffer); + // Check for the context, if specified go there. If not, go for the global + lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); + if (lhg ->LogErrorHandler) { + lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer); + } } // Utility function to print signatures @@ -455,3 +559,125 @@ String[4] = 0; } +//-------------------------------------------------------------------------------------------------- + + +static +void* defMtxCreate(cmsContext id) +{ + _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); + _cmsInitMutexPrimitive(ptr_mutex); + return (void*) ptr_mutex; +} + +static +void defMtxDestroy(cmsContext id, void* mtx) +{ + _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); + _cmsFree(id, mtx); +} + +static +cmsBool defMtxLock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; +} + +static +void defMtxUnlock(cmsContext id, void* mtx) +{ + cmsUNUSED_PARAMETER(id); + _cmsUnlockPrimitive((_cmsMutex *) mtx); +} + + + +// Pointers to memory manager functions in Context0 +_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + +// Allocate and init mutex container. +void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; + void* from; + + if (src != NULL) { + from = src ->chunks[MutexPlugin]; + } + else { + from = &MutexChunk; + } + + ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType)); +} + +// Register new ways to transform +cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data) +{ + cmsPluginMutex* Plugin = (cmsPluginMutex*) Data; + _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (Data == NULL) { + + // No lock routines + ctx->CreateMutexPtr = NULL; + ctx->DestroyMutexPtr = NULL; + ctx->LockMutexPtr = NULL; + ctx ->UnlockMutexPtr = NULL; + return TRUE; + } + + // Factory callback is required + if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || + Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE; + + + ctx->CreateMutexPtr = Plugin->CreateMutexPtr; + ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr; + ctx ->LockMutexPtr = Plugin ->LockMutexPtr; + ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr; + + // All is ok + return TRUE; +} + +// Generic Mutex fns +void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->CreateMutexPtr == NULL) return NULL; + + return ptr ->CreateMutexPtr(ContextID); +} + +void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->DestroyMutexPtr != NULL) { + + ptr ->DestroyMutexPtr(ContextID, mtx); + } +} + +cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->LockMutexPtr == NULL) return TRUE; + + return ptr ->LockMutexPtr(ContextID, mtx); +} + +void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx) +{ + _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); + + if (ptr ->UnlockMutexPtr != NULL) { + + ptr ->UnlockMutexPtr(ContextID, mtx); + } +}
--- a/src/java.desktop/share/native/liblcms/cmsgamma.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsgamma.c Thu Sep 18 13:27:48 2014 -0700 @@ -82,7 +82,6 @@ } _cmsParametricCurvesCollection; - // This is the default (built-in) evaluator static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R); @@ -95,22 +94,77 @@ NULL // Next in chain }; +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginCurvesList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsCurvesPluginChunkType newHead = { NULL }; + _cmsParametricCurvesCollection* entry; + _cmsParametricCurvesCollection* Anterior = NULL; + _cmsCurvesPluginChunkType* head = (_cmsCurvesPluginChunkType*) src->chunks[CurvesPlugin]; + + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->ParametricCurves; + entry != NULL; + entry = entry ->Next) { + + _cmsParametricCurvesCollection *newEntry = ( _cmsParametricCurvesCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsParametricCurvesCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.ParametricCurves == NULL) + newHead.ParametricCurves = newEntry; + } + + ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsCurvesPluginChunkType)); +} + +// The allocator have to follow the chain +void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Copy all linked list + DupPluginCurvesList(ctx, src); + } + else { + static _cmsCurvesPluginChunkType CurvesPluginChunk = { NULL }; + ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx ->MemPool, &CurvesPluginChunk, sizeof(_cmsCurvesPluginChunkType)); + } +} + + // The linked list head -static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves; +_cmsCurvesPluginChunkType _cmsCurvesPluginChunk = { NULL }; // As a way to install new parametric curves -cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Data) { + _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin); cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data; _cmsParametricCurvesCollection* fl; if (Data == NULL) { - ParametricCurves = &DefaultCurves; + ctx -> ParametricCurves = NULL; return TRUE; } - fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection)); + fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsParametricCurvesCollection)); if (fl == NULL) return FALSE; // Copy the parameters @@ -126,8 +180,8 @@ memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number)); // Keep linked list - fl ->Next = ParametricCurves; - ParametricCurves = fl; + fl ->Next = ctx->ParametricCurves; + ctx->ParametricCurves = fl; // All is ok return TRUE; @@ -149,12 +203,24 @@ // Search for the collection which contains a specific type static -_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index) +_cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, int Type, int* index) { _cmsParametricCurvesCollection* c; int Position; + _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin); - for (c = ParametricCurves; c != NULL; c = c ->Next) { + for (c = ctx->ParametricCurves; c != NULL; c = c ->Next) { + + Position = IsInSet(Type, c); + + if (Position != -1) { + if (index != NULL) + *index = Position; + return c; + } + } + // If none found, revert for defaults + for (c = &DefaultCurves; c != NULL; c = c ->Next) { Position = IsInSet(Type, c); @@ -251,7 +317,7 @@ p ->Segments[i].SampledPoints = NULL; - c = GetParametricCurveByType(Segments[i].Type, NULL); + c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL); if (c != NULL) p ->Evals[i] = c ->Evaluator; } @@ -677,12 +743,12 @@ cmsCurveSegment Seg0; int Pos = 0; cmsUInt32Number size; - _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos); + _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos); _cmsAssert(Params != NULL); if (c == NULL) { - cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); + cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type); return NULL; } @@ -872,7 +938,10 @@ _cmsAssert(InCurve != NULL); // Try to reverse it analytically whatever possible - if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) { + + if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && + /* InCurve -> Segments[0].Type <= 5 */ + GetParametricCurveByType(InCurve ->InterpParams->ContextID, InCurve ->Segments[0].Type, NULL) != NULL) { return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID, -(InCurve -> Segments[0].Type),
--- a/src/java.desktop/share/native/liblcms/cmsgmt.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsgmt.c Thu Sep 18 13:27:48 2014 -0700 @@ -191,7 +191,7 @@ out = ComputeKToLstar(ContextID, nPoints, 1, Intents + (nProfiles - 1), - hProfiles + (nProfiles - 1), + &hProfiles [nProfiles - 1], BPC + (nProfiles - 1), AdaptationStates + (nProfiles - 1), dwFlags);
--- a/src/java.desktop/share/native/liblcms/cmsintrp.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsintrp.c Thu Sep 18 13:27:48 2014 -0700 @@ -62,31 +62,57 @@ static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags); // This is the default factory -static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory; +_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL }; + +// The interpolation plug-in memory chunk allocator/dup +void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) +{ + void* from; + + _cmsAssert(ctx != NULL); + + if (src != NULL) { + from = src ->chunks[InterpPlugin]; + } + else { + static _cmsInterpPluginChunkType InterpPluginChunk = { NULL }; + + from = &InterpPluginChunk; + } + + _cmsAssert(from != NULL); + ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType)); +} // Main plug-in entry -cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data) +cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data; + _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin); if (Data == NULL) { - Interpolators = DefaultInterpolatorsFactory; + ptr ->Interpolators = NULL; return TRUE; } // Set replacement functions - Interpolators = Plugin ->InterpolatorsFactory; + ptr ->Interpolators = Plugin ->InterpolatorsFactory; return TRUE; } // Set the interpolation method -cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p) +cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p) { - // Invoke factory, possibly in the Plug-in - p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags); + _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin); + + p ->Interpolation.Lerp16 = NULL; + + // Invoke factory, possibly in the Plug-in + if (ptr ->Interpolators != NULL) + p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags); // If unsupported by the plug-in, go for the LittleCMS default. // If happens only if an extern plug-in is being used @@ -97,6 +123,7 @@ if (p ->Interpolation.Lerp16 == NULL) { return FALSE; } + return TRUE; } @@ -141,7 +168,7 @@ p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i]; - if (!_cmsSetInterpolationRoutine(p)) { + if (!_cmsSetInterpolationRoutine(ContextID, p)) { cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan); _cmsFree(ContextID, p); return NULL;
--- a/src/java.desktop/share/native/liblcms/cmsio0.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsio0.c Thu Sep 18 13:27:48 2014 -0700 @@ -229,15 +229,14 @@ if (ResData == NULL) return FALSE; // Housekeeping // Check for available space. Clip. - if (iohandler ->UsedSpace + size > ResData->Size) { - size = ResData ->Size - iohandler ->UsedSpace; + if (ResData->Pointer + size > ResData->Size) { + size = ResData ->Size - ResData->Pointer; } if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing memmove(ResData ->Block + ResData ->Pointer, Ptr, size); ResData ->Pointer += size; - iohandler->UsedSpace += size; if (ResData ->Pointer > iohandler->UsedSpace) iohandler->UsedSpace = ResData ->Pointer; @@ -371,7 +370,7 @@ static cmsUInt32Number FileTell(cmsIOHANDLER* iohandler) { - return ftell((FILE*)iohandler ->stream); + return (cmsUInt32Number) ftell((FILE*)iohandler ->stream); } // Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error @@ -414,7 +413,7 @@ cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName); return NULL; } - iohandler -> ReportedSize = cmsfilelength(fm); + iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(fm); break; case 'w': @@ -461,7 +460,7 @@ iohandler -> ContextID = ContextID; iohandler -> stream = (void*) Stream; iohandler -> UsedSpace = 0; - iohandler -> ReportedSize = cmsfilelength(Stream); + iohandler -> ReportedSize = (cmsUInt32Number) cmsfilelength(Stream); iohandler -> PhysicalFile[0] = 0; iohandler ->Read = FileRead; @@ -501,6 +500,9 @@ // Set creation date/time memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created)); + // Create a mutex if the user provided proper plugin. NULL otherwise + Icc ->UsrMutex = _cmsCreateMutex(ContextID); + // Return the handle return (cmsHPROFILE) Icc; } @@ -579,9 +581,39 @@ return n; } +// Deletes a tag entry -// Create a new tag entry +static +void _cmsDeleteTagByPos(_cmsICCPROFILE* Icc, int i) +{ + _cmsAssert(Icc != NULL); + _cmsAssert(i >= 0); + + + if (Icc -> TagPtrs[i] != NULL) { + + // Free previous version + if (Icc ->TagSaveAsRaw[i]) { + _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); + } + else { + cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; + if (TypeHandler != NULL) { + + cmsTagTypeHandler LocalTypeHandler = *TypeHandler; + LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter + LocalTypeHandler.ICCVersion = Icc ->Version; + LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); + Icc ->TagPtrs[i] = NULL; + } + } + + } +} + + +// Creates a new tag entry static cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) { @@ -589,15 +621,15 @@ // Search for the tag i = _cmsSearchTag(Icc, sig, FALSE); + if (i >= 0) { - // Now let's do it easy. If the tag has been already written, that's an error - if (i >= 0) { - cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig); - return FALSE; + // Already exists? delete it + _cmsDeleteTagByPos(Icc, i); + *NewPos = i; } else { - // New one + // No, make a new one if (Icc -> TagCount >= MAX_TABLE_TAG) { cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); @@ -979,7 +1011,7 @@ // 4.2 -> 0x4200000 - Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16; + Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0 + 0.5), 10, 16) << 16; } cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile) @@ -1011,6 +1043,32 @@ return NULL; } +// Create profile from IOhandler +cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write) +{ + _cmsICCPROFILE* NewIcc; + cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); + + if (hEmpty == NULL) return NULL; + + NewIcc = (_cmsICCPROFILE*) hEmpty; + + NewIcc ->IOhandler = io; + if (write) { + + NewIcc -> IsWrite = TRUE; + return hEmpty; + } + + if (!_cmsReadHeader(NewIcc)) goto Error; + return hEmpty; + +Error: + cmsCloseProfile(hEmpty); + return NULL; +} + + // Create profile from disk file cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess) { @@ -1202,7 +1260,7 @@ else { // Search for support on this tag - TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, Icc -> TagNames[i]); if (TagDescriptor == NULL) continue; // Unsupported, ignore it if (TagDescriptor ->DecideType != NULL) { @@ -1214,7 +1272,7 @@ Type = TagDescriptor ->SupportedTypes[0]; } - TypeHandler = _cmsGetTagTypeHandler(Type); + TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); if (TypeHandler == NULL) { cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]); @@ -1282,10 +1340,12 @@ { _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; _cmsICCPROFILE Keep; - cmsIOHANDLER* PrevIO; + cmsIOHANDLER* PrevIO = NULL; cmsUInt32Number UsedSpace; cmsContext ContextID; + _cmsAssert(hProfile != NULL); + memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); ContextID = cmsGetProfileContextID(hProfile); @@ -1294,18 +1354,19 @@ // Pass #1 does compute offsets - if (!_cmsWriteHeader(Icc, 0)) return 0; - if (!SaveTags(Icc, &Keep)) return 0; + if (!_cmsWriteHeader(Icc, 0)) goto Error; + if (!SaveTags(Icc, &Keep)) goto Error; UsedSpace = PrevIO ->UsedSpace; // Pass #2 does save to iohandler if (io != NULL) { + Icc ->IOhandler = io; - if (!SetLinks(Icc)) goto CleanUp; - if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp; - if (!SaveTags(Icc, &Keep)) goto CleanUp; + if (!SetLinks(Icc)) goto Error; + if (!_cmsWriteHeader(Icc, UsedSpace)) goto Error; + if (!SaveTags(Icc, &Keep)) goto Error; } memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); @@ -1314,7 +1375,7 @@ return UsedSpace; -CleanUp: +Error: cmsCloseIOhandler(PrevIO); memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); return 0; @@ -1362,11 +1423,13 @@ cmsIOHANDLER* io; cmsContext ContextID = cmsGetProfileContextID(hProfile); + _cmsAssert(BytesNeeded != NULL); + // Should we just calculate the needed space? if (MemPtr == NULL) { *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); - return (*BytesNeeded == 0 ? FALSE : TRUE); + return (*BytesNeeded == 0) ? FALSE : TRUE; } // That is a real write operation @@ -1419,6 +1482,8 @@ rc &= cmsCloseIOhandler(Icc->IOhandler); } + _cmsDestroyMutex(Icc->ContextID, Icc->UsrMutex); + _cmsFree(Icc ->ContextID, Icc); // Free placeholder memory return rc; @@ -1459,14 +1524,18 @@ cmsUInt32Number ElemCount; int n; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL; + n = _cmsSearchTag(Icc, sig, TRUE); - if (n < 0) return NULL; // Not found, return NULL + if (n < 0) goto Error; // Not found, return NULL // If the element is already in memory, return the pointer if (Icc -> TagPtrs[n]) { - if (Icc ->TagSaveAsRaw[n]) return NULL; // We don't support read raw tags as cooked + if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked + + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc -> TagPtrs[n]; } @@ -1476,23 +1545,32 @@ // Seek to its location if (!io -> Seek(io, Offset)) - return NULL; + goto Error; // Search for support on this tag - TagDescriptor = _cmsGetTagDescriptor(sig); - if (TagDescriptor == NULL) return NULL; // Unsupported. + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); + if (TagDescriptor == NULL) { + + char String[5]; + + _cmsTagSignature2String(String, sig); + + // An unknown element was found. + cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown tag type '%s' found.", String); + goto Error; // Unsupported. + } // if supported, get type and check if in list BaseType = _cmsReadTypeBase(io); - if (BaseType == 0) return NULL; + if (BaseType == 0) goto Error; - if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL; + if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; TagSize -= 8; // Alredy read by the type base logic // Get type handler - TypeHandler = _cmsGetTagTypeHandler(BaseType); - if (TypeHandler == NULL) return NULL; + TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType); + if (TypeHandler == NULL) goto Error; LocalTypeHandler = *TypeHandler; @@ -1511,7 +1589,7 @@ _cmsTagSignature2String(String, sig); cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String); - return NULL; + goto Error; } // This is a weird error that may be a symptom of something more serious, the number of @@ -1527,7 +1605,14 @@ // Return the data + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc -> TagPtrs[n]; + + + // Return error and unlock tha data +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return NULL; } @@ -1561,49 +1646,26 @@ cmsFloat64Number Version; char TypeString[5], SigString[5]; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; + // To delete tags. if (data == NULL) { + // Delete the tag i = _cmsSearchTag(Icc, sig, FALSE); - if (i >= 0) + if (i >= 0) { + + // Use zero as a mark of deleted + _cmsDeleteTagByPos(Icc, i); Icc ->TagNames[i] = (cmsTagSignature) 0; - // Unsupported by now, reserved for future ampliations (delete) - return FALSE; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return TRUE; + } + // Didn't find the tag + goto Error; } - i = _cmsSearchTag(Icc, sig, FALSE); - if (i >=0) { - - if (Icc -> TagPtrs[i] != NULL) { - - // Already exists. Free previous version - if (Icc ->TagSaveAsRaw[i]) { - _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); - } - else { - TypeHandler = Icc ->TagTypeHandlers[i]; - - if (TypeHandler != NULL) { - - LocalTypeHandler = *TypeHandler; - LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter - LocalTypeHandler.ICCVersion = Icc ->Version; - LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); - } - } - } - } - else { - // New one - i = Icc -> TagCount; - - if (i >= MAX_TABLE_TAG) { - cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); - return FALSE; - } - - Icc -> TagCount++; - } + if (!_cmsNewTag(Icc, sig, &i)) goto Error; // This is not raw Icc ->TagSaveAsRaw[i] = FALSE; @@ -1612,10 +1674,10 @@ Icc ->TagLinked[i] = (cmsTagSignature) 0; // Get information about the TAG. - TagDescriptor = _cmsGetTagDescriptor(sig); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); if (TagDescriptor == NULL){ cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig); - return FALSE; + goto Error; } @@ -1633,7 +1695,6 @@ } else { - Type = TagDescriptor ->SupportedTypes[0]; } @@ -1644,18 +1705,18 @@ _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); - return FALSE; + goto Error; } // Does we have a handler for this type? - TypeHandler = _cmsGetTagTypeHandler(Type); + TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); if (TypeHandler == NULL) { _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); - return FALSE; // Should never happen + goto Error; // Should never happen } @@ -1668,7 +1729,7 @@ LocalTypeHandler = *TypeHandler; LocalTypeHandler.ContextID = Icc ->ContextID; LocalTypeHandler.ICCVersion = Icc ->Version; - Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); + Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); if (Icc ->TagPtrs[i] == NULL) { @@ -1676,10 +1737,16 @@ _cmsTagSignature2String(SigString, sig); cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString); - return FALSE; + goto Error; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; + +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Read and write raw data. The only way those function would work and keep consistence with normal read and write @@ -1700,9 +1767,11 @@ cmsUInt32Number rc; cmsUInt32Number Offset, TagSize; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + // Search for given tag in ICC profile directory i = _cmsSearchTag(Icc, sig, TRUE); - if (i < 0) return 0; // Not found, return 0 + if (i < 0) goto Error; // Not found, // It is already read? if (Icc -> TagPtrs[i] == NULL) { @@ -1717,12 +1786,14 @@ if (BufferSize < TagSize) TagSize = BufferSize; - if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0; - if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0; + if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error; + if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TagSize; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc ->TagSizes[i]; } @@ -1738,16 +1809,22 @@ memmove(data, Icc ->TagPtrs[i], TagSize); + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TagSize; } + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return Icc ->TagSizes[i]; } // Already readed, or previously set by cmsWriteTag(). We need to serialize that // data to raw in order to maintain consistency. + + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); Object = cmsReadTag(hProfile, sig); - if (Object == NULL) return 0; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + + if (Object == NULL) goto Error; // Now we need to serialize to a memory block: just use a memory iohandler @@ -1756,17 +1833,18 @@ } else{ MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w"); } - if (MemIO == NULL) return 0; + if (MemIO == NULL) goto Error; // Obtain type handling for the tag TypeHandler = Icc ->TagTypeHandlers[i]; - TagDescriptor = _cmsGetTagDescriptor(sig); + TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); if (TagDescriptor == NULL) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } - // FIXME: No handling for TypeHandler == NULL here? + if (TypeHandler == NULL) goto Error; + // Serialize LocalTypeHandler = *TypeHandler; LocalTypeHandler.ContextID = Icc ->ContextID; @@ -1774,19 +1852,24 @@ if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) { cmsCloseIOhandler(MemIO); - return 0; + goto Error; } // Get Size and close rc = MemIO ->Tell(MemIO); cmsCloseIOhandler(MemIO); // Ignore return code this time + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return rc; + +Error: + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return 0; } // Similar to the anterior. This function allows to write directly to the ICC profile any data, without @@ -1798,7 +1881,12 @@ _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; int i; - if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; + + if (!_cmsNewTag(Icc, sig, &i)) { + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Mark the tag as being written as RAW Icc ->TagSaveAsRaw[i] = TRUE; @@ -1809,6 +1897,7 @@ Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size); Icc ->TagSizes[i] = Size; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; } @@ -1818,7 +1907,12 @@ _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; int i; - if (!_cmsNewTag(Icc, sig, &i)) return FALSE; + if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; + + if (!_cmsNewTag(Icc, sig, &i)) { + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + return FALSE; + } // Keep necessary information Icc ->TagSaveAsRaw[i] = FALSE; @@ -1829,6 +1923,7 @@ Icc ->TagSizes[i] = 0; Icc ->TagOffsets[i] = 0; + _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); return TRUE; }
--- a/src/java.desktop/share/native/liblcms/cmsio1.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsio1.c Thu Sep 18 13:27:48 2014 -0700 @@ -334,7 +334,8 @@ // Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc -// is adjusted here in order to create a LUT that takes care of all those details +// is adjusted here in order to create a LUT that takes care of all those details. +// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; @@ -364,49 +365,54 @@ return Lut; } - if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + // This is an attempt to reuse this funtion to retrieve the matrix-shaper as pipeline no + // matter other LUT are present and have precedence. Intent = -1 means just this. + if (Intent != -1) { - // Floating point LUT are always V4, but the encoding range is no - // longer 0..1.0, so we need to add an stage depending on the color space - return _cmsReadFloatInputTag(hProfile, tagFloat); - } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + // Floating point LUT are always V4, but the encoding range is no + // longer 0..1.0, so we need to add an stage depending on the color space + return _cmsReadFloatInputTag(hProfile, tagFloat); + } - // Revert to perceptual if no tag is found - if (!cmsIsTag(hProfile, tag16)) { - tag16 = Device2PCS16[0]; - } + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = Device2PCS16[0]; + } - if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - // Check profile version and LUT type. Do the necessary adjustments if needed + // Check profile version and LUT type. Do the necessary adjustments if needed - // First read the tag - cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); - if (Lut == NULL) return NULL; + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; - // After reading it, we have now info about the original type - OriginalType = _cmsGetTagTrueType(hProfile, tag16); + // After reading it, we have now info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); - // The profile owns the Lut, so we need to copy it - Lut = cmsPipelineDup(Lut); + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); - // We need to adjust data only for Lab16 on output - if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) - return Lut; + // We need to adjust data only for Lab16 on output + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; - // If the input is Lab, add also a conversion at the begin - if (cmsGetColorSpace(hProfile) == cmsSigLabData && - !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) - goto Error; + // If the input is Lab, add also a conversion at the begin + if (cmsGetColorSpace(hProfile) == cmsSigLabData && + !cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) + goto Error; - // Add a matrix for conversion V2 to V4 Lab PCS - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) - goto Error; + // Add a matrix for conversion V2 to V4 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; - return Lut; + return Lut; Error: - cmsPipelineFree(Lut); - return NULL; + cmsPipelineFree(Lut); + return NULL; + } } // Lut was not found, try to create a matrix-shaper @@ -551,7 +557,7 @@ _cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data; CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR; - _cmsSetInterpolationRoutine(CLUT ->Params); + _cmsSetInterpolationRoutine(Lut->ContextID, CLUT ->Params); } } } @@ -609,54 +615,58 @@ cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; cmsContext ContextID = cmsGetProfileContextID(hProfile); - if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + if (Intent != -1) { - // Floating point LUT are always V4 - return _cmsReadFloatOutputTag(hProfile, tagFloat); - } + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence + + // Floating point LUT are always V4 + return _cmsReadFloatOutputTag(hProfile, tagFloat); + } - // Revert to perceptual if no tag is found - if (!cmsIsTag(hProfile, tag16)) { - tag16 = PCS2Device16[0]; - } + // Revert to perceptual if no tag is found + if (!cmsIsTag(hProfile, tag16)) { + tag16 = PCS2Device16[0]; + } - if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - - // Check profile version and LUT type. Do the necessary adjustments if needed + if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table? - // First read the tag - cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); - if (Lut == NULL) return NULL; + // Check profile version and LUT type. Do the necessary adjustments if needed - // After reading it, we have info about the original type - OriginalType = _cmsGetTagTrueType(hProfile, tag16); + // First read the tag + cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16); + if (Lut == NULL) return NULL; - // The profile owns the Lut, so we need to copy it - Lut = cmsPipelineDup(Lut); - if (Lut == NULL) return NULL; + // After reading it, we have info about the original type + OriginalType = _cmsGetTagTrueType(hProfile, tag16); - // Now it is time for a controversial stuff. I found that for 3D LUTS using - // Lab used as indexer space, trilinear interpolation should be used - if (cmsGetPCS(hProfile) == cmsSigLabData) - ChangeInterpolationToTrilinear(Lut); + // The profile owns the Lut, so we need to copy it + Lut = cmsPipelineDup(Lut); + if (Lut == NULL) return NULL; - // We need to adjust data only for Lab and Lut16 type - if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) - return Lut; + // Now it is time for a controversial stuff. I found that for 3D LUTS using + // Lab used as indexer space, trilinear interpolation should be used + if (cmsGetPCS(hProfile) == cmsSigLabData) + ChangeInterpolationToTrilinear(Lut); - // Add a matrix for conversion V4 to V2 Lab PCS - if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) - goto Error; + // We need to adjust data only for Lab and Lut16 type + if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData) + return Lut; - // If the output is Lab, add also a conversion at the end - if (cmsGetColorSpace(hProfile) == cmsSigLabData) - if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + // Add a matrix for conversion V4 to V2 Lab PCS + if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) goto Error; - return Lut; + // If the output is Lab, add also a conversion at the end + if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) + goto Error; + + return Lut; Error: - cmsPipelineFree(Lut); - return NULL; + cmsPipelineFree(Lut); + return NULL; + } } // Lut not found, try to create a matrix-shaper @@ -782,7 +792,7 @@ // Now it is time for a controversial stuff. I found that for 3D LUTS using // Lab used as indexer space, trilinear interpolation should be used - if (cmsGetColorSpace(hProfile) == cmsSigLabData) + if (cmsGetPCS(hProfile) == cmsSigLabData) ChangeInterpolationToTrilinear(Lut); // After reading it, we have info about the original type @@ -793,12 +803,12 @@ // Here it is possible to get Lab on both sides - if (cmsGetPCS(hProfile) == cmsSigLabData) { + if (cmsGetColorSpace(hProfile) == cmsSigLabData) { if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID))) goto Error2; } - if (cmsGetColorSpace(hProfile) == cmsSigLabData) { + if (cmsGetPCS(hProfile) == cmsSigLabData) { if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) goto Error2; }
--- a/src/java.desktop/share/native/liblcms/cmsopt.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsopt.c Thu Sep 18 13:27:48 2014 -0700 @@ -542,11 +542,13 @@ cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]); if (InversePostLin == NULL) { - WhiteOut[i] = 0; - continue; + WhiteOut[i] = WhitePointOut[i]; + + } else { + + WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]); + cmsFreeToneCurve(InversePostLin); } - WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]); - cmsFreeToneCurve(InversePostLin); } } else { @@ -1666,44 +1668,102 @@ }; // The linked list head -static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization; +_cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginOptimizationList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsOptimizationPluginChunkType newHead = { NULL }; + _cmsOptimizationCollection* entry; + _cmsOptimizationCollection* Anterior = NULL; + _cmsOptimizationPluginChunkType* head = (_cmsOptimizationPluginChunkType*) src->chunks[OptimizationPlugin]; + + _cmsAssert(ctx != NULL); + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->OptimizationCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsOptimizationCollection *newEntry = ( _cmsOptimizationCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsOptimizationCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.OptimizationCollection == NULL) + newHead.OptimizationCollection = newEntry; + } + + ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsOptimizationPluginChunkType)); +} + +void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginOptimizationList(ctx, src); + } + else { + static _cmsOptimizationPluginChunkType OptimizationPluginChunkType = { NULL }; + ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx ->MemPool, &OptimizationPluginChunkType, sizeof(_cmsOptimizationPluginChunkType)); + } +} + // Register new ways to optimize -cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data; + _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin); _cmsOptimizationCollection* fl; if (Data == NULL) { - OptimizationCollection = DefaultOptimization; + ctx->OptimizationCollection = NULL; return TRUE; } // Optimizer callback is required if (Plugin ->OptimizePtr == NULL) return FALSE; - fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection)); + fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsOptimizationCollection)); if (fl == NULL) return FALSE; // Copy the parameters fl ->OptimizePtr = Plugin ->OptimizePtr; // Keep linked list - fl ->Next = OptimizationCollection; - OptimizationCollection = fl; + fl ->Next = ctx->OptimizationCollection; + + // Set the head + ctx ->OptimizationCollection = fl; // All is ok return TRUE; } // The entry point for LUT optimization -cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut, +cmsBool _cmsOptimizePipeline(cmsContext ContextID, + cmsPipeline** PtrLut, int Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { + _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin); _cmsOptimizationCollection* Opts; cmsBool AnySuccess = FALSE; @@ -1733,8 +1793,8 @@ if (*dwFlags & cmsFLAGS_NOOPTIMIZE) return FALSE; - // Try built-in optimizations and plug-in - for (Opts = OptimizationCollection; + // Try plug-in optimizations + for (Opts = ctx->OptimizationCollection; Opts != NULL; Opts = Opts ->Next) { @@ -1745,6 +1805,17 @@ } } + // Try built-in optimizations + for (Opts = DefaultOptimization; + Opts != NULL; + Opts = Opts ->Next) { + + if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) { + + return TRUE; + } + } + // Only simple optimizations succeeded return AnySuccess; }
--- a/src/java.desktop/share/native/liblcms/cmspack.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmspack.c Thu Sep 18 13:27:48 2014 -0700 @@ -883,6 +883,42 @@ } } +// This is a conversion of XYZ float to 16 bits +static +cmsUInt8Number* UnrollXYZFloatTo16(register _cmsTRANSFORM* info, + register cmsUInt16Number wIn[], + register cmsUInt8Number* accum, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(info -> InputFormat)) { + + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + cmsCIEXYZ XYZ; + + XYZ.X = Pt[0]; + XYZ.Y = Pt[Stride]; + XYZ.Z = Pt[Stride*2]; + cmsFloat2XYZEncoded(wIn, &XYZ); + + return accum + sizeof(cmsFloat32Number); + + } + + else { + cmsFloat32Number* Pt = (cmsFloat32Number*) accum; + cmsCIEXYZ XYZ; + + XYZ.X = Pt[0]; + XYZ.Y = Pt[1]; + XYZ.Z = Pt[2]; + cmsFloat2XYZEncoded(wIn, &XYZ); + + accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number); + + return accum; + } +} + // Check if space is marked as ink cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type) { @@ -2334,6 +2370,39 @@ } static +cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info, + register cmsUInt16Number wOut[], + register cmsUInt8Number* output, + register cmsUInt32Number Stride) +{ + if (T_PLANAR(Info -> OutputFormat)) { + + cmsCIEXYZ XYZ; + cmsFloat32Number* Out = (cmsFloat32Number*) output; + cmsXYZEncoded2Float(&XYZ, wOut); + + Out[0] = (cmsFloat32Number) XYZ.X; + Out[Stride] = (cmsFloat32Number) XYZ.Y; + Out[Stride*2] = (cmsFloat32Number) XYZ.Z; + + return output + sizeof(cmsFloat32Number); + + } + else { + + cmsCIEXYZ XYZ; + cmsFloat32Number* Out = (cmsFloat32Number*) output; + cmsXYZEncoded2Float(&XYZ, wOut); + + Out[0] = (cmsFloat32Number) XYZ.X; + Out[1] = (cmsFloat32Number) XYZ.Y; + Out[2] = (cmsFloat32Number) XYZ.Z; + + return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number)); + } +} + +static cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, register cmsUInt16Number wOut[], register cmsUInt8Number* output, @@ -2893,6 +2962,7 @@ { TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16}, { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16}, { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16}, { TYPE_GRAY_DBL, 0, UnrollDouble1Chan}, { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR| ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16}, @@ -3027,6 +3097,7 @@ { TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16}, { TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16}, + { TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16}, { FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP| ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16}, @@ -3182,40 +3253,98 @@ } cmsFormattersFactoryList; -static cmsFormattersFactoryList* FactoryList = NULL; +_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupFormatterFactoryList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsFormattersPluginChunkType newHead = { NULL }; + cmsFormattersFactoryList* entry; + cmsFormattersFactoryList* Anterior = NULL; + _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin]; + + _cmsAssert(head != NULL); + + // Walk the list copying all nodes + for (entry = head->FactoryList; + entry != NULL; + entry = entry ->Next) { + + cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.FactoryList == NULL) + newHead.FactoryList = newEntry; + } + + ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType)); +} + +// The interpolation plug-in memory chunk allocator/dup +void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsAssert(ctx != NULL); + + if (src != NULL) { + + // Duplicate the LIST + DupFormatterFactoryList(ctx, src); + } + else { + static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL }; + ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType)); + } +} + // Formatters management -cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data) { + _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data; cmsFormattersFactoryList* fl ; - // Reset + // Reset to built-in defaults if (Data == NULL) { - FactoryList = NULL; + ctx ->FactoryList = NULL; return TRUE; } - fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList)); + fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList)); if (fl == NULL) return FALSE; fl ->Factory = Plugin ->FormattersFactory; - fl ->Next = FactoryList; - FactoryList = fl; + fl ->Next = ctx -> FactoryList; + ctx ->FactoryList = fl; return TRUE; } -cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 +cmsFormatter _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 cmsFormatterDirection Dir, cmsUInt32Number dwFlags) { + _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin); cmsFormattersFactoryList* f; - for (f = FactoryList; f != NULL; f = f ->Next) { + for (f =ctx->FactoryList; f != NULL; f = f ->Next) { cmsFormatter fn = f ->Factory(Type, Dir, dwFlags); if (fn.Fmt16 != NULL) return fn;
--- a/src/java.desktop/share/native/liblcms/cmsplugin.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsplugin.c Thu Sep 18 13:27:48 2014 -0700 @@ -544,22 +544,31 @@ // Plugin memory management ------------------------------------------------------------------------------------------------- -static _cmsSubAllocator* PluginPool = NULL; - // Specialized malloc for plug-ins, that is freed upon exit. -void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size) +void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size) { - if (PluginPool == NULL) - PluginPool = _cmsCreateSubAlloc(id, 4*1024); + struct _cmsContext_struct* ctx = _cmsGetContext(ContextID); + + if (ctx ->MemPool == NULL) { + + if (ContextID == NULL) { - return _cmsSubAlloc(PluginPool, size); + ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024); + } + else { + cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context"); + return NULL; + } + } + + return _cmsSubAlloc(ctx->MemPool, size); } // Main plug-in dispatcher cmsBool CMSEXPORT cmsPlugin(void* Plug_in) { - return cmsPluginTHR(NULL, Plug_in); + return cmsPluginTHR(NULL, Plug_in); } cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) @@ -571,12 +580,12 @@ Plugin = Plugin -> Next) { if (Plugin -> Magic != cmsPluginMagicNumber) { - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); return FALSE; } if (Plugin ->ExpectedVersion > LCMS_VERSION) { - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", Plugin ->ExpectedVersion, LCMS_VERSION); return FALSE; } @@ -584,11 +593,11 @@ switch (Plugin -> Type) { case cmsPluginMemHandlerSig: - if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE; + if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE; break; case cmsPluginInterpolationSig: - if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE; + if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE; break; case cmsPluginTagTypeSig: @@ -623,8 +632,12 @@ if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE; break; + case cmsPluginMutexSig: + if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE; + break; + default: - cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); return FALSE; } } @@ -637,19 +650,337 @@ // Revert all plug-ins to default void CMSEXPORT cmsUnregisterPlugins(void) { - _cmsRegisterMemHandlerPlugin(NULL); - _cmsRegisterInterpPlugin(NULL); - _cmsRegisterTagTypePlugin(NULL, NULL); - _cmsRegisterTagPlugin(NULL, NULL); - _cmsRegisterFormattersPlugin(NULL, NULL); - _cmsRegisterRenderingIntentPlugin(NULL, NULL); - _cmsRegisterParametricCurvesPlugin(NULL, NULL); - _cmsRegisterMultiProcessElementPlugin(NULL, NULL); - _cmsRegisterOptimizationPlugin(NULL, NULL); - _cmsRegisterTransformPlugin(NULL, NULL); + cmsUnregisterPluginsTHR(NULL); +} + + +// The Global storage for system context. This is the one and only global variable +// pointers structure. All global vars are referenced here. +static struct _cmsContext_struct globalContext = { + + NULL, // Not in the linked list + NULL, // No suballocator + { + NULL, // UserPtr, + &_cmsLogErrorChunk, // Logger, + &_cmsAlarmCodesChunk, // AlarmCodes, + &_cmsAdaptationStateChunk, // AdaptationState, + &_cmsMemPluginChunk, // MemPlugin, + &_cmsInterpPluginChunk, // InterpPlugin, + &_cmsCurvesPluginChunk, // CurvesPlugin, + &_cmsFormattersPluginChunk, // FormattersPlugin, + &_cmsTagTypePluginChunk, // TagTypePlugin, + &_cmsTagPluginChunk, // TagPlugin, + &_cmsIntentsPluginChunk, // IntentPlugin, + &_cmsMPETypePluginChunk, // MPEPlugin, + &_cmsOptimizationPluginChunk, // OptimizationPlugin, + &_cmsTransformPluginChunk, // TransformPlugin, + &_cmsMutexPluginChunk // MutexPlugin + }, + + { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0 +}; + + +// The context pool (linked list head) +static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER; +static struct _cmsContext_struct* _cmsContextPoolHead = NULL; + +// Internal, get associated pointer, with guessing. Never returns NULL. +struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) +{ + struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID; + struct _cmsContext_struct* ctx; + + + // On 0, use global settings + if (id == NULL) + return &globalContext; + + // Search + for (ctx = _cmsContextPoolHead; + ctx != NULL; + ctx = ctx ->Next) { + + // Found it? + if (id == ctx) + return ctx; // New-style context, + } + + return &globalContext; +} + + +// Internal: get the memory area associanted with each context client +// Returns the block assigned to the specific zone. +void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) +{ + struct _cmsContext_struct* ctx; + void *ptr; + + if (mc < 0 || mc >= MemoryClientMax) { + cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client"); + return NULL; + } + + ctx = _cmsGetContext(ContextID); + ptr = ctx ->chunks[mc]; + + if (ptr != NULL) + return ptr; + + // A null ptr means no special settings for that context, and this + // reverts to Context0 globals + return globalContext.chunks[mc]; +} + + +// This function returns the given context its default pristine state, +// as no plug-ins were declared. There is no way to unregister a single +// plug-in, as a single call to cmsPluginTHR() function may register +// many different plug-ins simultaneously, then there is no way to +// identify which plug-in to unregister. +void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID) +{ + _cmsRegisterMemHandlerPlugin(ContextID, NULL); + _cmsRegisterInterpPlugin(ContextID, NULL); + _cmsRegisterTagTypePlugin(ContextID, NULL); + _cmsRegisterTagPlugin(ContextID, NULL); + _cmsRegisterFormattersPlugin(ContextID, NULL); + _cmsRegisterRenderingIntentPlugin(ContextID, NULL); + _cmsRegisterParametricCurvesPlugin(ContextID, NULL); + _cmsRegisterMultiProcessElementPlugin(ContextID, NULL); + _cmsRegisterOptimizationPlugin(ContextID, NULL); + _cmsRegisterTransformPlugin(ContextID, NULL); + _cmsRegisterMutexPlugin(ContextID, NULL); +} + + +// Returns the memory manager plug-in, if any, from the Plug-in bundle +static +cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle) +{ + cmsPluginBase* Plugin; + + for (Plugin = (cmsPluginBase*) PluginBundle; + Plugin != NULL; + Plugin = Plugin -> Next) { + + if (Plugin -> Magic == cmsPluginMagicNumber && + Plugin -> ExpectedVersion <= LCMS_VERSION && + Plugin -> Type == cmsPluginMemHandlerSig) { + + // Found! + return (cmsPluginMemHandler*) Plugin; + } + } + + // Nope, revert to defaults + return NULL; +} + + +// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined +// data that will be forwarded to plug-ins and logger. +cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) +{ + struct _cmsContext_struct* ctx; + struct _cmsContext_struct fakeContext; + + _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager); + + fakeContext.chunks[UserPtr] = UserData; + fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; + + // Create the context structure. + ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct)); + if (ctx == NULL) + return NULL; // Something very wrong happened! + + // Init the structure and the memory manager + memset(ctx, 0, sizeof(struct _cmsContext_struct)); + + // Keep memory manager + memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk)); + + // Maintain the linked list (with proper locking) + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + ctx ->chunks[UserPtr] = UserData; + ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; + + // Now we can allocate the pool by using default memory manager + ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers + if (ctx ->MemPool == NULL) { - if (PluginPool != NULL) - _cmsSubAllocDestroy(PluginPool); + cmsDeleteContext(ctx); + return NULL; + } + + _cmsAllocLogErrorChunk(ctx, NULL); + _cmsAllocAlarmCodesChunk(ctx, NULL); + _cmsAllocAdaptationStateChunk(ctx, NULL); + _cmsAllocMemPluginChunk(ctx, NULL); + _cmsAllocInterpPluginChunk(ctx, NULL); + _cmsAllocCurvesPluginChunk(ctx, NULL); + _cmsAllocFormattersPluginChunk(ctx, NULL); + _cmsAllocTagTypePluginChunk(ctx, NULL); + _cmsAllocMPETypePluginChunk(ctx, NULL); + _cmsAllocTagPluginChunk(ctx, NULL); + _cmsAllocIntentsPluginChunk(ctx, NULL); + _cmsAllocOptimizationPluginChunk(ctx, NULL); + _cmsAllocTransformPluginChunk(ctx, NULL); + _cmsAllocMutexPluginChunk(ctx, NULL); + + // Setup the plug-ins + if (!cmsPluginTHR(ctx, Plugin)) { + + cmsDeleteContext(ctx); + return NULL; + } + + return (cmsContext) ctx; +} + +// Duplicates a context with all associated plug-ins. +// Caller may specify an optional pointer to user-defined +// data that will be forwarded to plug-ins and logger. +cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) +{ + int i; + struct _cmsContext_struct* ctx; + const struct _cmsContext_struct* src = _cmsGetContext(ContextID); + + void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr]; + + + ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct)); + if (ctx == NULL) + return NULL; // Something very wrong happened + + // Setup default memory allocators + memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); + + // Maintain the linked list + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + ctx ->Next = _cmsContextPoolHead; + _cmsContextPoolHead = ctx; + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + ctx ->chunks[UserPtr] = userData; + ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; + + ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); + if (ctx ->MemPool == NULL) { + + cmsDeleteContext(ctx); + return NULL; + } + + // Allocate all required chunks. + _cmsAllocLogErrorChunk(ctx, src); + _cmsAllocAlarmCodesChunk(ctx, src); + _cmsAllocAdaptationStateChunk(ctx, src); + _cmsAllocMemPluginChunk(ctx, src); + _cmsAllocInterpPluginChunk(ctx, src); + _cmsAllocCurvesPluginChunk(ctx, src); + _cmsAllocFormattersPluginChunk(ctx, src); + _cmsAllocTagTypePluginChunk(ctx, src); + _cmsAllocMPETypePluginChunk(ctx, src); + _cmsAllocTagPluginChunk(ctx, src); + _cmsAllocIntentsPluginChunk(ctx, src); + _cmsAllocOptimizationPluginChunk(ctx, src); + _cmsAllocTransformPluginChunk(ctx, src); + _cmsAllocMutexPluginChunk(ctx, src); + + // Make sure no one failed + for (i=Logger; i < MemoryClientMax; i++) { - PluginPool = NULL; + if (src ->chunks[i] == NULL) { + cmsDeleteContext((cmsContext) ctx); + return NULL; + } + } + + return (cmsContext) ctx; +} + + + +static +struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) +{ + struct _cmsContext_struct* prev; + + // Search for previous + for (prev = _cmsContextPoolHead; + prev != NULL; + prev = prev ->Next) + { + if (prev ->Next == id) + return prev; + } + + return NULL; // List is empty or only one element! } + +// Frees any resources associated with the given context, +// and destroys the context placeholder. +// The ContextID can no longer be used in any THR operation. +void CMSEXPORT cmsDeleteContext(cmsContext ContextID) +{ + if (ContextID != NULL) { + + struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID; + struct _cmsContext_struct fakeContext; + struct _cmsContext_struct* prev; + + memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); + + fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr]; + fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; + + // Get rid of plugins + cmsUnregisterPluginsTHR(ContextID); + + // Since all memory is allocated in the private pool, all what we need to do is destroy the pool + if (ctx -> MemPool != NULL) + _cmsSubAllocDestroy(ctx ->MemPool); + ctx -> MemPool = NULL; + + // Maintain list + _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + if (_cmsContextPoolHead == ctx) { + + _cmsContextPoolHead = ctx->Next; + } + else { + + // Search for previous + for (prev = _cmsContextPoolHead; + prev != NULL; + prev = prev ->Next) + { + if (prev -> Next == ctx) { + prev -> Next = ctx ->Next; + break; + } + } + } + _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); + + // free the memory block itself + _cmsFree(&fakeContext, ctx); + } +} + +// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation +void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID) +{ + return _cmsContextGetClientChunk(ContextID, UserPtr); +} + +
--- a/src/java.desktop/share/native/liblcms/cmsps2.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsps2.c Thu Sep 18 13:27:48 2014 -0700 @@ -942,7 +942,7 @@ if (DeviceLink == NULL) return 0; dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); + _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags); rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50); cmsPipelineFree(DeviceLink); @@ -1359,7 +1359,7 @@ // We need a CLUT dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); + _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags); _cmsIOPrintf(m, "<<\n"); _cmsIOPrintf(m, "/ColorRenderingType 1\n");
--- a/src/java.desktop/share/native/liblcms/cmstypes.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmstypes.c Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -61,7 +61,7 @@ // are no profiles holding them. The programmer can also extend this list by defining his own types // by using the appropiate plug-in. There are three types of plug ins regarding that. First type // allows to define new tags using any existing type. Next plug-in type allows to define new types -// and the third one is very specific: allows to extend the number of elements in the multiprofile +// and the third one is very specific: allows to extend the number of elements in the multiprocessing // elements special type. //-------------------------------------------------------------------------------------------------- @@ -89,54 +89,49 @@ // Helper macro to define a MPE handler. Callbacks do have a fixed naming convention #define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 } -// Register a new type handler. This routine is shared between normal types and MPE +// Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head static -cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount) +cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos) { cmsPluginTagType* Plugin = (cmsPluginTagType*) Data; - _cmsTagTypeLinkedList *pt, *Anterior = NULL; + _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos); + _cmsTagTypeLinkedList *pt; // Calling the function with NULL as plug-in would unregister the plug in. if (Data == NULL) { - LinkedList[DefaultListCount-1].Next = NULL; + // There is no need to set free the memory, as pool is destroyed as a whole. + ctx ->TagTypes = NULL; return TRUE; } - pt = Anterior = LinkedList; - while (pt != NULL) { - - if (Plugin->Handler.Signature == pt -> Handler.Signature) { - pt ->Handler = Plugin ->Handler; // Replace old behaviour. - // Note that since no memory is allocated, unregister does not - // reset this action. - return TRUE; - } - - Anterior = pt; - pt = pt ->Next; - } - - // Registering happens in plug-in memory pool + // Registering happens in plug-in memory pool. pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList)); if (pt == NULL) return FALSE; pt ->Handler = Plugin ->Handler; - pt ->Next = NULL; - - if (Anterior) - Anterior -> Next = pt; + pt ->Next = ctx ->TagTypes; + + ctx ->TagTypes = pt; return TRUE; } -// Return handler for a given type or NULL if not found. Shared between normal types and MPE +// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons +// made by plug-ins and then the built-in defaults. static -cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList) +cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList) { _cmsTagTypeLinkedList* pt; - for (pt = LinkedList; + for (pt = PluginLinkedList; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Handler.Signature) return &pt ->Handler; + } + + for (pt = DefaultLinkedList; pt != NULL; pt = pt ->Next) { @@ -163,6 +158,7 @@ return TRUE; } +// Auxiliar to read an array of wchar_t static cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array) { @@ -777,6 +773,8 @@ // Create memory Text = (char*) _cmsMalloc(self ->ContextID, size); + if (Text == NULL) return FALSE; + cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size); // Write it, including separator @@ -1783,7 +1781,6 @@ if (!_cmsReadUInt8Number(io, NULL)) goto Error; // Do some checking - if (InputChannels > cmsMAXCHANNELS) goto Error; if (OutputChannels > cmsMAXCHANNELS) goto Error; @@ -1824,9 +1821,16 @@ if (T == NULL) goto Error; Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize); - if (Temp == NULL) goto Error; - - if (io ->Read(io, Temp, nTabSize, 1) != 1) goto Error; + if (Temp == NULL) { + _cmsFree(self ->ContextID, T); + goto Error; + } + + if (io ->Read(io, Temp, nTabSize, 1) != 1) { + _cmsFree(self ->ContextID, T); + _cmsFree(self ->ContextID, Temp); + goto Error; + } for (i = 0; i < nTabSize; i++) { @@ -2371,27 +2375,30 @@ // Precision can be 1 or 2 bytes if (Precision == 1) { - cmsUInt8Number v; + cmsUInt8Number v; for (i=0; i < Data ->nEntries; i++) { - if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; - Data ->Tab.T[i] = FROM_8_TO_16(v); + if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL; + Data ->Tab.T[i] = FROM_8_TO_16(v); } } else if (Precision == 2) { - if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) return NULL; - } - else { - cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); - return NULL; - } - - - return CLUT; + if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) { + cmsStageFree(CLUT); + return NULL; + } + } + else { + cmsStageFree(CLUT); + cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision); + return NULL; + } + + return CLUT; } static @@ -4374,7 +4381,7 @@ {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut), NULL }, }; -#define DEFAULT_MPE_TYPE_COUNT (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList)) +_cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL }; static cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, @@ -4387,6 +4394,8 @@ cmsTagTypeHandler* TypeHandler; cmsUInt32Number nItems; cmsPipeline *NewLUT = (cmsPipeline *) Cargo; + _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); + // Take signature and channels for each element. if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE; @@ -4395,7 +4404,7 @@ if (!_cmsReadUInt32Number(io, NULL)) return FALSE; // Read diverse MPE types - TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes); if (TypeHandler == NULL) { char String[5]; @@ -4472,6 +4481,7 @@ cmsPipeline* Lut = (cmsPipeline*) Ptr; cmsStage* Elem = Lut ->Elements; cmsTagTypeHandler* TypeHandler; + _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); @@ -4505,7 +4515,7 @@ ElementSig = Elem ->Type; - TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes); + TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes); if (TypeHandler == NULL) { char String[5]; @@ -5125,7 +5135,7 @@ } else { - rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); + rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); } if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS); @@ -5282,24 +5292,95 @@ {TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL } }; -#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList)) + +_cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL }; + + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupTagTypeList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src, + int loc) +{ + _cmsTagTypePluginChunkType newHead = { NULL }; + _cmsTagTypeLinkedList* entry; + _cmsTagTypeLinkedList* Anterior = NULL; + _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc]; + + // Walk the list copying all nodes + for (entry = head->TagTypes; + entry != NULL; + entry = entry ->Next) { + + _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TagTypes == NULL) + newHead.TagTypes = newEntry; + } + + ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType)); +} + + +void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Duplicate the LIST + DupTagTypeList(ctx, src, TagTypePlugin); + } + else { + static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL }; + ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); + } +} + +void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Duplicate the LIST + DupTagTypeList(ctx, src, MPEPlugin); + } + else { + static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL }; + ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); + } + +} + // Both kind of plug-ins share same structure cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data) { - return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT); + return RegisterTypesPlugin(id, Data, TagTypePlugin); } cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data) { - return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT); + return RegisterTypesPlugin(id, Data,MPEPlugin); } // Wrapper for tag types -cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig) -{ - return GetHandler(sig, SupportedTagTypes); +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig) +{ + _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin); + + return GetHandler(sig, ctx->TagTypes, SupportedTagTypes); } // ******************************************************************************** @@ -5414,48 +5495,94 @@ cmsSigDeviceSettingsTag ==> Deprecated, useless */ -#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList)) + +_cmsTagPluginChunkType _cmsTagPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupTagList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsTagPluginChunkType newHead = { NULL }; + _cmsTagLinkedList* entry; + _cmsTagLinkedList* Anterior = NULL; + _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin]; + + // Walk the list copying all nodes + for (entry = head->Tag; + entry != NULL; + entry = entry ->Next) { + + _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.Tag == NULL) + newHead.Tag = newEntry; + } + + ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType)); +} + +void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + DupTagList(ctx, src); + } + else { + static _cmsTagPluginChunkType TagPluginChunk = { NULL }; + ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType)); + } + +} cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) { cmsPluginTag* Plugin = (cmsPluginTag*) Data; - _cmsTagLinkedList *pt, *Anterior; - + _cmsTagLinkedList *pt; + _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin); if (Data == NULL) { - SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL; + TagPluginChunk->Tag = NULL; return TRUE; } - pt = Anterior = SupportedTags; - while (pt != NULL) { - - if (Plugin->Signature == pt -> Signature) { - pt ->Descriptor = Plugin ->Descriptor; // Replace old behaviour - return TRUE; - } - - Anterior = pt; - pt = pt ->Next; - } - pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList)); if (pt == NULL) return FALSE; pt ->Signature = Plugin ->Signature; pt ->Descriptor = Plugin ->Descriptor; - pt ->Next = NULL; - - if (Anterior != NULL) Anterior -> Next = pt; + pt ->Next = TagPluginChunk ->Tag; + + TagPluginChunk ->Tag = pt; return TRUE; } // Return a descriptor for a given tag or NULL -cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig) +cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig) { _cmsTagLinkedList* pt; + _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin); + + for (pt = TagPluginChunk->Tag; + pt != NULL; + pt = pt ->Next) { + + if (sig == pt -> Signature) return &pt ->Descriptor; + } for (pt = SupportedTags; pt != NULL;
--- a/src/java.desktop/share/native/liblcms/cmsvirt.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsvirt.c Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -1019,7 +1019,7 @@ static const cmsAllowedLUT AllowedLUTTypes[] = { - { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, + { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, @@ -1150,7 +1150,7 @@ if (AllowedLUT == NULL) { // Try to optimize - _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag); } @@ -1159,7 +1159,7 @@ if (AllowedLUT == NULL) { dwFlags |= cmsFLAGS_FORCE_CLUT; - _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); + _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags); // Put identity curves if needed if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
--- a/src/java.desktop/share/native/liblcms/cmswtpnt.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmswtpnt.c Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"),
--- a/src/java.desktop/share/native/liblcms/cmsxform.c Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/cmsxform.c Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -58,44 +58,120 @@ // Transformations stuff // ----------------------------------------------------------------------- -// Alarm codes for 16-bit transformations, because the fixed range of containers there are -// no values left to mark out of gamut. volatile is C99 per 6.2.5 -static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static volatile cmsFloat64Number GlobalAdaptationState = 1; +#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0 + +// The Context0 observer adaptation state. +_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + +// Init and duplicate observer adaptation state +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE }; + void* from; + + if (src != NULL) { + from = src ->chunks[AdaptationStateContext]; + } + else { + from = &AdaptationStateChunk; + } + + ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType)); +} + + +// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all +// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states. +cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d) +{ + cmsFloat64Number prev; + _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext); + + // Get previous value for return + prev = ptr ->AdaptationState; + + // Set the value if d is positive or zero + if (d >= 0.0) { + + ptr ->AdaptationState = d; + } + + // Always return previous value + return prev; +} + // The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d) { - cmsFloat64Number OldVal = GlobalAdaptationState; - - if (d >= 0) - GlobalAdaptationState = d; - - return OldVal; + return cmsSetAdaptationStateTHR(NULL, d); } -// Alarm codes are always global -void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +// ----------------------------------------------------------------------- + +// Alarm codes for 16-bit transformations, because the fixed range of containers there are +// no values left to mark out of gamut. + +#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + +// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be +// encoded in 16 bits. +void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) { - int i; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes)); +} +// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context. +// Values are meant to be encoded in 16 bits. +void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS]) +{ + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext); + + _cmsAssert(ContextAlarmCodes != NULL); // Can't happen + + memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes)); +} + +void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]) +{ _cmsAssert(NewAlarm != NULL); - for (i=0; i < cmsMAXCHANNELS; i++) - Alarm[i] = NewAlarm[i]; + cmsSetAlarmCodesTHR(NULL, NewAlarm); } -// You can get the codes cas well void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS]) { - int i; + _cmsAssert(OldAlarm != NULL); + cmsGetAlarmCodesTHR(NULL, OldAlarm); +} + - _cmsAssert(OldAlarm != NULL); +// Init and duplicate alarm codes +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE }; + void* from; - for (i=0; i < cmsMAXCHANNELS; i++) - OldAlarm[i] = Alarm[i]; + if (src != NULL) { + from = src ->chunks[AlarmCodesContext]; + } + else { + from = &AlarmCodesChunk; + } + + ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType)); } +// ----------------------------------------------------------------------- + // Get rid of transform resources void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform) { @@ -202,6 +278,30 @@ } } + +static +void NullFloatXFORM(_cmsTRANSFORM* p, + const void* in, + void* out, + cmsUInt32Number Size, + cmsUInt32Number Stride) +{ + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsFloat32Number fIn[cmsMAXCHANNELS]; + cmsUInt32Number i, n; + + accum = (cmsUInt8Number*) in; + output = (cmsUInt8Number*) out; + n = Size; + + for (i=0; i < n; i++) { + + accum = p -> FromInputFloat(p, fIn, accum, Stride); + output = p -> ToOutputFloat(p, fIn, output, Stride); + } +} + // 16 bit precision ----------------------------------------------------------------------------------------------------------- // Null transformation, only applies formatters. No caché @@ -252,7 +352,7 @@ } -// Auxiliar: Handle precalculated gamut check +// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical. static void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, const cmsUInt16Number wIn[], @@ -264,9 +364,12 @@ if (wOutOfGamut >= 1) { cmsUInt16Number i; + _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext); - for (i=0; i < p ->Lut->OutputChannels; i++) - wOut[i] = Alarm[i]; + for (i=0; i < p ->Lut->OutputChannels; i++) { + + wOut[i] = ContextAlarmCodes ->AlarmCodes[i]; + } } else p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); @@ -393,34 +496,86 @@ } _cmsTransformCollection; // The linked list head -static _cmsTransformCollection* TransformCollection = NULL; +_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL }; + + +// Duplicates the zone of memory used by the plug-in in the new context +static +void DupPluginTransformList(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + _cmsTransformPluginChunkType newHead = { NULL }; + _cmsTransformCollection* entry; + _cmsTransformCollection* Anterior = NULL; + _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin]; + + // Walk the list copying all nodes + for (entry = head->TransformCollection; + entry != NULL; + entry = entry ->Next) { + + _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection)); + + if (newEntry == NULL) + return; + + // We want to keep the linked list order, so this is a little bit tricky + newEntry -> Next = NULL; + if (Anterior) + Anterior -> Next = newEntry; + + Anterior = newEntry; + + if (newHead.TransformCollection == NULL) + newHead.TransformCollection = newEntry; + } + + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); +} + +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src) +{ + if (src != NULL) { + + // Copy all linked list + DupPluginTransformList(ctx, src); + } + else { + static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL }; + ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType)); + } +} + + // Register new ways to transform -cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data) +cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) { cmsPluginTransform* Plugin = (cmsPluginTransform*) Data; _cmsTransformCollection* fl; + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin); - if (Data == NULL) { + if (Data == NULL) { // Free the chain. Memory is safely freed at exit - TransformCollection = NULL; + ctx->TransformCollection = NULL; return TRUE; } // Factory callback is required - if (Plugin ->Factory == NULL) return FALSE; + if (Plugin ->Factory == NULL) return FALSE; - fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection)); + fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); if (fl == NULL) return FALSE; - // Copy the parameters + // Copy the parameters fl ->Factory = Plugin ->Factory; // Keep linked list - fl ->Next = TransformCollection; - TransformCollection = fl; + fl ->Next = ctx->TransformCollection; + ctx->TransformCollection = fl; // All is ok return TRUE; @@ -463,6 +618,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { + _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); _cmsTransformCollection* Plugin; // Allocate needed memory @@ -473,7 +629,7 @@ p ->Lut = lut; // Let's see if any plug-in want to do the transform by itself - for (Plugin = TransformCollection; + for (Plugin = ctx ->TransformCollection; Plugin != NULL; Plugin = Plugin ->Next) { @@ -493,10 +649,10 @@ // Fill the formatters just in case the optimized routine is interested. // No error is thrown if the formatter doesn't exist. It is up to the optimization // factory to decide what to do in those cases. - p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; return p; } @@ -504,14 +660,14 @@ // Not suitable for the transform plug-in, let's check the pipeline plug-in if (p ->Lut != NULL) - _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); // Check whatever this is a true floating point transform if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { // Get formatter function always return a valid union, but the contents of this union may be NULL. - p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; *dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER; if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) { @@ -521,8 +677,15 @@ return NULL; } - // Float transforms don't use caché, always are non-NULL - p ->xform = FloatXFORM; + if (*dwFlags & cmsFLAGS_NULLTRANSFORM) { + + p ->xform = NullFloatXFORM; + } + else { + // Float transforms don't use caché, always are non-NULL + p ->xform = FloatXFORM; + } + } else { @@ -534,8 +697,8 @@ int BytesPerPixelInput; - p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (p ->FromInput == NULL || p ->ToOutput == NULL) { @@ -727,6 +890,7 @@ // Check channel count if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) || (cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) { + cmsPipelineFree(Lut); cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted"); return NULL; } @@ -829,7 +993,7 @@ for (i=0; i < nProfiles; i++) { BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE; Intents[i] = Intent; - AdaptationStates[i] = GlobalAdaptationState; + AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1); } @@ -909,7 +1073,7 @@ Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent; BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0; - Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState; + Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1); if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK))) return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags); @@ -984,8 +1148,8 @@ return FALSE; } - FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; if (FromInput == NULL || ToOutput == NULL) {
--- a/src/java.desktop/share/native/liblcms/lcms2.h Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/lcms2.h Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2013 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -52,7 +52,7 @@ // //--------------------------------------------------------------------------------- // -// Version 2.5 +// Version 2.6 // #ifndef _lcms2_H @@ -84,6 +84,9 @@ // Uncomment to get rid of the tables for "half" float support // #define CMS_NO_HALF_SUPPORT 1 +// Uncomment to get rid of pthreads/windows dependency +// #define CMS_NO_PTHREADS 1 + // ********** End of configuration toggles ****************************** // Needed for streams @@ -101,7 +104,7 @@ #endif // Version/release -#define LCMS_VERSION 2050 +#define LCMS_VERSION 2060 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED @@ -202,28 +205,42 @@ // Try to detect big endian platforms. This list can be endless, so only some checks are performed over here. // you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar -#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) -# define CMS_USE_BIG_ENDIAN 1 -#endif - -#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) +#if defined(__sgi__) || defined(__sgi) || defined(sparc) # define CMS_USE_BIG_ENDIAN 1 #endif -#if defined(__ppc__) || defined(__s390__) || defined(__s390x__) +#if defined(__s390__) || defined(__s390x__) # define CMS_USE_BIG_ENDIAN 1 #endif -#ifdef TARGET_CPU_PPC -# if TARGET_CPU_PPC +# ifdef TARGET_CPU_PPC +# if TARGET_CPU_PPC +# define CMS_USE_BIG_ENDIAN 1 +# endif +# endif + +#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC) # define CMS_USE_BIG_ENDIAN 1 -# endif +# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) +# if __BYTE_ORDER == __LITTLE_ENDIAN +// // Don't use big endian for PowerPC little endian mode +# undef CMS_USE_BIG_ENDIAN +# endif +# endif +#endif + +// WORDS_BIGENDIAN takes precedence +#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN) +# define CMS_USE_BIG_ENDIAN 1 #endif #ifdef macintosh # ifdef __BIG_ENDIAN__ # define CMS_USE_BIG_ENDIAN 1 # endif +# ifdef __LITTLE_ENDIAN__ +# undef CMS_USE_BIG_ENDIAN +# endif #endif // Calling convention -- this is hardly platform and compiler dependent @@ -249,6 +266,14 @@ # define CMSAPI #endif +#ifdef HasTHREADS +# if HasTHREADS == 1 +# undef CMS_NO_PTHREADS +# else +# define CMS_NO_PTHREADS 1 +# endif +#endif + // Some common definitions #define cmsMAX_PATH 256 @@ -642,7 +667,6 @@ // Little CMS specific typedefs -typedef void* cmsContext; // Context identifier for multithreaded environments typedef void* cmsHANDLE ; // Generic handle typedef void* cmsHPROFILE; // Opaque typedefs to hide internals typedef void* cmsHTRANSFORM; @@ -1012,11 +1036,25 @@ CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2); CMSAPI long int CMSEXPORT cmsfilelength(FILE* f); -// Plug-In registering --------------------------------------------------------------------------------------------------- + +// Context handling -------------------------------------------------------------------------------------------------------- + +// Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility +// though using the global context is not recomended. Proper context handling makes lcms more thread-safe. + +typedef struct _cmsContext_struct* cmsContext; + +CMSAPI cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData); +CMSAPI void CMSEXPORT cmsDeleteContext(cmsContext ContexID); +CMSAPI cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData); +CMSAPI void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID); + +// Plug-In registering -------------------------------------------------------------------------------------------------- CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin); CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin); CMSAPI void CMSEXPORT cmsUnregisterPlugins(void); +CMSAPI void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID); // Error logging ---------------------------------------------------------------------------------------------------------- @@ -1053,6 +1091,7 @@ // Allows user to set any specific logger CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn); +CMSAPI void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn); // Conversions -------------------------------------------------------------------------------------------------------------- @@ -1514,6 +1553,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize); CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize); CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io); +CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write); CMSAPI cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile); CMSAPI cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName); @@ -1604,6 +1644,7 @@ // Call with NULL as parameters to get the intent count CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions); +CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions); // Flags @@ -1715,11 +1756,22 @@ cmsUInt32Number Stride); -CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); +CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]); + +CMSAPI void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, + const cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]); +CMSAPI void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, + cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]); + + + // Adaptation state for absolute colorimetric intent CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d); +CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d); + + // Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform);
--- a/src/java.desktop/share/native/liblcms/lcms2_internal.h Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/lcms2_internal.h Thu Sep 18 13:27:48 2014 -0700 @@ -30,7 +30,7 @@ // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2014 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -193,16 +193,171 @@ return _cmsQuickFloorWord(d); } -// Plug-In registering --------------------------------------------------------------- + +// Pthread support -------------------------------------------------------------------- +#ifndef CMS_NO_PTHREADS + +// This is the threading support. Unfortunately, it has to be platform-dependent because +// windows does not support pthreads. + +#ifdef CMS_IS_WINDOWS_ + +#define WIN32_LEAN_AND_MEAN 1 +#include <windows.h> + + +// From: http://locklessinc.com/articles/pthreads_on_windows/ +// The pthreads API has an initialization macro that has no correspondence to anything in +// the windows API. By investigating the internal definition of the critical section type, +// one may work out how to initialize one without calling InitializeCriticalSection(). +// The trick here is that InitializeCriticalSection() is not allowed to fail. It tries +// to allocate a critical section debug object, but if no memory is available, it sets +// the pointer to a specific value. (One would expect that value to be NULL, but it is +// actually (void *)-1 for some reason.) Thus we can use this special value for that +// pointer, and the critical section code will work. + +// The other important part of the critical section type to initialize is the number +// of waiters. This controls whether or not the mutex is locked. Fortunately, this +// part of the critical section is unlikely to change. Apparently, many programs +// already test critical sections to see if they are locked using this value, so +// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical +// section, even when they changed the underlying algorithm to be more scalable. +// The final parts of the critical section object are unimportant, and can be set +// to zero for their defaults. This yields an initialization macro: + +typedef CRITICAL_SECTION _cmsMutex; + +#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0} + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + InitializeCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + DeleteCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + EnterCriticalSection(m); + return 0; +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + LeaveCriticalSection(m); + return 0; +} + +#else + +// Rest of the wide world +#include <pthread.h> + +#define CMS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_init(m, NULL); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return pthread_mutex_destroy(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_lock(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return pthread_mutex_unlock(m); +} + +#endif +#else + +#define CMS_MUTEX_INITIALIZER 0 +typedef int _cmsMutex; + + +cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} + +cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) +{ + return 0; + cmsUNUSED_PARAMETER(m); +} +#endif + +// Plug-In registration --------------------------------------------------------------- // Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once. void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size); // Memory management -cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // Interpolation -cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin); +cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Plugin); // Parametric curves cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin); @@ -228,9 +383,12 @@ // Transform cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin); +// Mutex +cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin); + // --------------------------------------------------------------------------------------------------------- -// Suballocators. Those are blocks of memory that is freed at the end on whole block. +// Suballocators. typedef struct _cmsSubAllocator_chunk_st { cmsUInt8Number* Block; @@ -253,9 +411,264 @@ _cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial); void _cmsSubAllocDestroy(_cmsSubAllocator* s); void* _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size); +void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size); // ---------------------------------------------------------------------------------- +// The context clients. +typedef enum { + + UserPtr, // User-defined pointer + Logger, + AlarmCodesContext, + AdaptationStateContext, + MemPlugin, + InterpPlugin, + CurvesPlugin, + FormattersPlugin, + TagTypePlugin, + TagPlugin, + IntentPlugin, + MPEPlugin, + OptimizationPlugin, + TransformPlugin, + MutexPlugin, + + // Last in list + MemoryClientMax + +} _cmsMemoryClient; + + +// Container for memory management plug-in. +typedef struct { + + _cmsMallocFnPtrType MallocPtr; + _cmsMalloZerocFnPtrType MallocZeroPtr; + _cmsFreeFnPtrType FreePtr; + _cmsReallocFnPtrType ReallocPtr; + _cmsCallocFnPtrType CallocPtr; + _cmsDupFnPtrType DupPtr; + +} _cmsMemPluginChunkType; + +// Copy memory management function pointers from plug-in to chunk, taking care of missing routines +void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr); + +// Internal structure for context +struct _cmsContext_struct { + + struct _cmsContext_struct* Next; // Points to next context in the new style + _cmsSubAllocator* MemPool; // The memory pool that stores context data + + void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator. + // If NULL, then it reverts to global Context0 + + _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overriden +}; + +// Returns a pointer to a valid context structure, including the global one if id is zero. +// Verifies the magic number. +struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID); + +// Returns the block assigned to the specific zone. +void* _cmsContextGetClientChunk(cmsContext id, _cmsMemoryClient mc); + + +// Chunks of context memory by plug-in client ------------------------------------------------------- + +// Those structures encapsulates all variables needed by the several context clients (mostly plug-ins) + +// Container for error logger -- not a plug-in +typedef struct { + + cmsLogErrorHandlerFunction LogErrorHandler; // Set to NULL for Context0 fallback + +} _cmsLogErrorChunkType; + +// The global Context0 storage for error logger +extern _cmsLogErrorChunkType _cmsLogErrorChunk; + +// Allocate and init error logger container. +void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for alarm codes -- not a plug-in +typedef struct { + + cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]; + +} _cmsAlarmCodesChunkType; + +// The global Context0 storage for alarm codes +extern _cmsAlarmCodesChunkType _cmsAlarmCodesChunk; + +// Allocate and init alarm codes container. +void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for adaptation state -- not a plug-in +typedef struct { + + cmsFloat64Number AdaptationState; + +} _cmsAdaptationStateChunkType; + +// The global Context0 storage for adaptation state +extern _cmsAdaptationStateChunkType _cmsAdaptationStateChunk; + +// Allocate and init adaptation state container. +void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + + +// The global Context0 storage for memory management +extern _cmsMemPluginChunkType _cmsMemPluginChunk; + +// Allocate and init memory management container. +void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for interpolation plug-in +typedef struct { + + cmsInterpFnFactory Interpolators; + +} _cmsInterpPluginChunkType; + +// The global Context0 storage for interpolation plug-in +extern _cmsInterpPluginChunkType _cmsInterpPluginChunk; + +// Allocate and init interpolation container. +void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for parametric curves plug-in +typedef struct { + + struct _cmsParametricCurvesCollection_st* ParametricCurves; + +} _cmsCurvesPluginChunkType; + +// The global Context0 storage for tone curves plug-in +extern _cmsCurvesPluginChunkType _cmsCurvesPluginChunk; + +// Allocate and init parametric curves container. +void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for formatters plug-in +typedef struct { + + struct _cms_formatters_factory_list* FactoryList; + +} _cmsFormattersPluginChunkType; + +// The global Context0 storage for formatters plug-in +extern _cmsFormattersPluginChunkType _cmsFormattersPluginChunk; + +// Allocate and init formatters container. +void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// This chunk type is shared by TagType plug-in and MPE Plug-in +typedef struct { + + struct _cmsTagTypeLinkedList_st* TagTypes; + +} _cmsTagTypePluginChunkType; + + +// The global Context0 storage for tag types plug-in +extern _cmsTagTypePluginChunkType _cmsTagTypePluginChunk; + + +// The global Context0 storage for mult process elements plug-in +extern _cmsTagTypePluginChunkType _cmsMPETypePluginChunk; + +// Allocate and init Tag types container. +void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); +// Allocate and init MPE container. +void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); +// Container for tag plug-in +typedef struct { + + struct _cmsTagLinkedList_st* Tag; + +} _cmsTagPluginChunkType; + + +// The global Context0 storage for tag plug-in +extern _cmsTagPluginChunkType _cmsTagPluginChunk; + +// Allocate and init Tag container. +void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for intents plug-in +typedef struct { + + struct _cms_intents_list* Intents; + +} _cmsIntentsPluginChunkType; + + +// The global Context0 storage for intents plug-in +extern _cmsIntentsPluginChunkType _cmsIntentsPluginChunk; + +// Allocate and init intents container. +void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for optimization plug-in +typedef struct { + + struct _cmsOptimizationCollection_st* OptimizationCollection; + +} _cmsOptimizationPluginChunkType; + + +// The global Context0 storage for optimizers plug-in +extern _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk; + +// Allocate and init optimizers container. +void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for transform plug-in +typedef struct { + + struct _cmsTransformCollection_st* TransformCollection; + +} _cmsTransformPluginChunkType; + +// The global Context0 storage for full-transform replacement plug-in +extern _cmsTransformPluginChunkType _cmsTransformPluginChunk; + +// Allocate and init transform container. +void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// Container for mutex plug-in +typedef struct { + + _cmsCreateMutexFnPtrType CreateMutexPtr; + _cmsDestroyMutexFnPtrType DestroyMutexPtr; + _cmsLockMutexFnPtrType LockMutexPtr; + _cmsUnlockMutexFnPtrType UnlockMutexPtr; + +} _cmsMutexPluginChunkType; + +// The global Context0 storage for mutex plug-in +extern _cmsMutexPluginChunkType _cmsMutexPluginChunk; + +// Allocate and init mutex container. +void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, + const struct _cmsContext_struct* src); + +// ---------------------------------------------------------------------------------- // MLU internal representation typedef struct { @@ -347,10 +760,14 @@ cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked void * TagPtrs[MAX_TABLE_TAG]; cmsTagTypeHandler* TagTypeHandlers[MAX_TABLE_TAG]; // Same structure may be serialized on different types - // depending on profile version, so we keep track of the // type handler for each tag in the list. + // depending on profile version, so we keep track of the + // type handler for each tag in the list. // Special cmsBool IsWrite; + // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin + void * UsrMutex; + } _cmsICCPROFILE; // IO helpers for profiles @@ -359,9 +776,9 @@ int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks); // Tag types -cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig); +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig); cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig); -cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig); +cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig); // Error logging --------------------------------------------------------------------------------------------------------- @@ -372,7 +789,7 @@ cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags); void _cmsFreeInterpParams(cmsInterpParams* p); -cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p); +cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p); // Curves ---------------------------------------------------------------------------------------------------------------- @@ -503,7 +920,8 @@ cmsUInt16Number **Black, cmsUInt32Number *nOutputs); -cmsBool _cmsOptimizePipeline(cmsPipeline** Lut, +cmsBool _cmsOptimizePipeline(cmsContext ContextID, + cmsPipeline** Lut, int Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, @@ -528,7 +946,8 @@ cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type); cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type); -cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 +cmsFormatter _cmsGetFormatter(cmsContext ContextID, + cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8 cmsFormatterDirection Dir, cmsUInt32Number dwFlags);
--- a/src/java.desktop/share/native/liblcms/lcms2_plugin.h Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/share/native/liblcms/lcms2_plugin.h Thu Sep 18 13:27:48 2014 -0700 @@ -231,6 +231,7 @@ #define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH' #define cmsPluginOptimizationSig 0x6F707448 // 'optH' #define cmsPluginTransformSig 0x7A666D48 // 'xfmH' +#define cmsPluginMutexSig 0x6D747A48 // 'mtxH' typedef struct _cmsPluginBaseStruct { @@ -247,19 +248,28 @@ //---------------------------------------------------------------------------------------------------------- // Memory handler. Each new plug-in type replaces current behaviour + +typedef void* (* _cmsMallocFnPtrType)(cmsContext ContextID, cmsUInt32Number size); +typedef void (* _cmsFreeFnPtrType)(cmsContext ContextID, void *Ptr); +typedef void* (* _cmsReallocFnPtrType)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); + +typedef void* (* _cmsMalloZerocFnPtrType)(cmsContext ContextID, cmsUInt32Number size); +typedef void* (* _cmsCallocFnPtrType)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); +typedef void* (* _cmsDupFnPtrType)(cmsContext ContextID, const void* Org, cmsUInt32Number size); + typedef struct { cmsPluginBase base; // Required - void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size); - void (* FreePtr)(cmsContext ContextID, void *Ptr); - void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize); + _cmsMallocFnPtrType MallocPtr; + _cmsFreeFnPtrType FreePtr; + _cmsReallocFnPtrType ReallocPtr; // Optional - void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size); - void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size); - void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size); + _cmsMalloZerocFnPtrType MallocZeroPtr; + _cmsCallocFnPtrType CallocPtr; + _cmsDupFnPtrType DupPtr; } cmsPluginMemHandler; @@ -622,6 +632,29 @@ } cmsPluginTransform; +//---------------------------------------------------------------------------------------------------------- +// Mutex + +typedef void* (* _cmsCreateMutexFnPtrType)(cmsContext ContextID); +typedef void (* _cmsDestroyMutexFnPtrType)(cmsContext ContextID, void* mtx); +typedef cmsBool (* _cmsLockMutexFnPtrType)(cmsContext ContextID, void* mtx); +typedef void (* _cmsUnlockMutexFnPtrType)(cmsContext ContextID, void* mtx); + +typedef struct { + cmsPluginBase base; + + _cmsCreateMutexFnPtrType CreateMutexPtr; + _cmsDestroyMutexFnPtrType DestroyMutexPtr; + _cmsLockMutexFnPtrType LockMutexPtr; + _cmsUnlockMutexFnPtrType UnlockMutexPtr; + +} cmsPluginMutex; + +CMSAPI void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID); +CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx); +CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx); +CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx); + #ifndef CMS_USE_CPP_API # ifdef __cplusplus
--- a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java Thu Sep 18 13:27:48 2014 -0700 @@ -55,7 +55,6 @@ */ private final static int AWT_MULTICLICK_SMUDGE = 4; // ButtonXXX events stuff - static int rbutton = 0; static int lastX = 0, lastY = 0; static long lastTime = 0; static long lastButton = 0; @@ -632,23 +631,6 @@ return res; } - /** - * Returns true if this event is disabled and shouldn't be passed to Java. - * Default implementation returns false for all events. - */ - static int getRightButtonNumber() { - if (rbutton == 0) { // not initialized yet - XToolkit.awtLock(); - try { - rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3); - } - finally { - XToolkit.awtUnlock(); - } - } - return rbutton; - } - static int getMouseMovementSmudge() { //TODO: It's possible to read corresponding settings return AWT_MULTICLICK_SMUDGE; @@ -716,11 +698,7 @@ /* Check for popup trigger !! */ - if (lbutton == getRightButtonNumber() || lbutton > 2) { - popupTrigger = true; - } else { - popupTrigger = false; - } + popupTrigger = (lbutton == 3); } button = XConstants.buttons[lbutton - 1];
--- a/src/java.desktop/unix/classes/sun/awt/datatransfer/flavormap.properties Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -# -# This properties file is used to initialize the default -# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific, -# default mappings between common X11 selection atoms and platform-independent -# MIME type strings, which will be converted into -# java.awt.datatransfer.DataFlavors. -# -# The standard format is: -# -# <native>=<MIME type>,<MIME type>, ... -# -# <native> should be a string identifier that the native platform will -# recognize as a valid data format. <MIME type> should specify both a MIME -# primary type and a MIME subtype separated by a '/'. The MIME type may include -# parameters, where each parameter is a key/value pair separated by '=', and -# where each parameter to the MIME type is separated by a ';'. -# -# Because SystemFlavorMap implements FlavorTable, developers are free to -# duplicate DataFlavor values and set multiple values for a single native by -# separating them with ",". If a mapping contains a duplicate key or value, -# earlier mappings which included this key or value will be preferred. -# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", and which support the charset parameter, should specify the exact -# format in which the native platform expects the data. The "charset" -# parameter specifies the char to byte encoding, the "eoln" parameter -# specifies the end-of-line marker, and the "terminators" parameter specifies -# the number of terminating NUL bytes. Note that "eoln" and "terminators" -# are not standardized MIME type parameters. They are specific to this file -# format ONLY. They will not appear in any of the DataFlavors returned by the -# SystemFlavorMap at the Java level. -# -# If the "charset" parameter is omitted, or has zero length, the platform -# default encoding is assumed. If the "eoln" parameter is omitted, or has -# zero length, "\n" is assumed. If the "terminators" parameter is omitted, -# or has a value less than zero, zero is assumed. -# -# Upon initialization, the data transfer subsystem will record the specified -# details of the native text format, but the default SystemFlavorMap will -# present a large set of synthesized DataFlavors which map, in both -# directions, to the native. After receiving data from the application in one -# of the synthetic DataFlavors, the data transfer subsystem will transform -# the data stream into the format specified in this file before passing the -# transformed stream to the native system. -# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", but which do not support the charset parameter, will be treated as -# opaque, 8-bit data. They will not undergo any transformation process, and -# any "charset", "eoln", or "terminators" parameters specified in this file -# will be ignored. -# -# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of -# text flavors which support the charset parameter. - -UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 - -# The COMPOUND_TEXT support for inter-client text transfer is disabled by -# default. The reason is that many native applications prefer this format over -# other native text formats, but are unable to decode the textual data in this -# format properly. This results in java-to-native text transfer failures. -# To enable the COMPOUND_TEXT support for this JRE installation uncomment -# the line below. - -# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0 - -TEXT=text/plain;eoln="\n";terminators=0 -STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0 -FILE_NAME=application/x-java-file-list;class=java.util.List -text/uri-list=application/x-java-file-list;class=java.util.List -PNG=image/x-java-image;class=java.awt.Image -JFIF=image/x-java-image;class=java.awt.Image
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.desktop/unix/classes/sun/datatransfer/resources/flavormap.properties Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,71 @@ +# +# This properties file is used to initialize the default +# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific, +# default mappings between common X11 selection atoms and platform-independent +# MIME type strings, which will be converted into +# java.awt.datatransfer.DataFlavors. +# +# The standard format is: +# +# <native>=<MIME type>,<MIME type>, ... +# +# <native> should be a string identifier that the native platform will +# recognize as a valid data format. <MIME type> should specify both a MIME +# primary type and a MIME subtype separated by a '/'. The MIME type may include +# parameters, where each parameter is a key/value pair separated by '=', and +# where each parameter to the MIME type is separated by a ';'. +# +# Because SystemFlavorMap implements FlavorTable, developers are free to +# duplicate DataFlavor values and set multiple values for a single native by +# separating them with ",". If a mapping contains a duplicate key or value, +# earlier mappings which included this key or value will be preferred. +# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", and which support the charset parameter, should specify the exact +# format in which the native platform expects the data. The "charset" +# parameter specifies the char to byte encoding, the "eoln" parameter +# specifies the end-of-line marker, and the "terminators" parameter specifies +# the number of terminating NUL bytes. Note that "eoln" and "terminators" +# are not standardized MIME type parameters. They are specific to this file +# format ONLY. They will not appear in any of the DataFlavors returned by the +# SystemFlavorMap at the Java level. +# +# If the "charset" parameter is omitted, or has zero length, the platform +# default encoding is assumed. If the "eoln" parameter is omitted, or has +# zero length, "\n" is assumed. If the "terminators" parameter is omitted, +# or has a value less than zero, zero is assumed. +# +# Upon initialization, the data transfer subsystem will record the specified +# details of the native text format, but the default SystemFlavorMap will +# present a large set of synthesized DataFlavors which map, in both +# directions, to the native. After receiving data from the application in one +# of the synthetic DataFlavors, the data transfer subsystem will transform +# the data stream into the format specified in this file before passing the +# transformed stream to the native system. +# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", but which do not support the charset parameter, will be treated as +# opaque, 8-bit data. They will not undergo any transformation process, and +# any "charset", "eoln", or "terminators" parameters specified in this file +# will be ignored. +# +# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of +# text flavors which support the charset parameter. + +UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0 + +# The COMPOUND_TEXT support for inter-client text transfer is disabled by +# default. The reason is that many native applications prefer this format over +# other native text formats, but are unable to decode the textual data in this +# format properly. This results in java-to-native text transfer failures. +# To enable the COMPOUND_TEXT support for this JRE installation uncomment +# the line below. + +# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0 + +TEXT=text/plain;eoln="\n";terminators=0 +STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0 +FILE_NAME=application/x-java-file-list;class=java.util.List +text/uri-list=application/x-java-file-list;class=java.util.List +PNG=image/x-java-image;class=java.awt.Image +JFIF=image/x-java-image;class=java.awt.Image
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRSolidSrcPict.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRSolidSrcPict.java Thu Sep 18 13:27:48 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,12 +31,14 @@ XRSurfaceData srcPict; XRColor xrCol; - int curPixVal = -1; + int curPixVal; public XRSolidSrcPict(XRBackend con, int parentXid) { this.con = con; xrCol = new XRColor(); + curPixVal = 0xFF000000; + int solidPixmap = con.createPixmap(parentXid, 32, 1, 1); int solidSrcPictXID = con.createPicture(solidPixmap, XRUtils.PictStandardARGB32); con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
--- a/src/java.desktop/windows/classes/sun/awt/datatransfer/flavormap.properties Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -# -# This properties file is used to initialize the default -# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform- -# specific, default mappings between common Win32 Clipboard atoms and platform- -# independent MIME type strings, which will be converted into -# java.awt.datatransfer.DataFlavors. -# -# The standard format is: -# -# <native>=<MIME type>,<MIME type>, ... -# -# <native> should be a string identifier that the native platform will -# recognize as a valid data format. <MIME type> should specify both a MIME -# primary type and a MIME subtype separated by a '/'. The MIME type may include -# parameters, where each parameter is a key/value pair separated by '=', and -# where each parameter to the MIME type is separated by a ';'. -# -# Because SystemFlavorMap implements FlavorTable, developers are free to -# duplicate DataFlavor values and set multiple values for a single native by -# separating them with ",". If a mapping contains a duplicate key or value, -# earlier mappings which included this key or value will be preferred.# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", and which support the charset parameter, should specify the exact -# format in which the native platform expects the data. The "charset" -# parameter specifies the char to byte encoding, the "eoln" parameter -# specifies the end-of-line marker, and the "terminators" parameter specifies -# the number of terminating NUL bytes. Note that "eoln" and "terminators" -# are not standardized MIME type parameters. They are specific to this file -# format ONLY. They will not appear in any of the DataFlavors returned by the -# SystemFlavorMap at the Java level. -# -# If the "charset" parameter is omitted, or has zero length, the platform -# default encoding is assumed. If the "eoln" parameter is omitted, or has -# zero length, "\n" is assumed. If the "terminators" parameter is omitted, -# or has a value less than zero, zero is assumed. -# -# Upon initialization, the data transfer subsystem will record the specified -# details of the native text format, but the default SystemFlavorMap will -# present a large set of synthesized DataFlavors which map, in both -# directions, to the native. After receiving data from the application in one -# of the synthetic DataFlavors, the data transfer subsystem will transform -# the data stream into the format specified in this file before passing the -# transformed stream to the native system. -# -# Mappings whose values specify DataFlavors with primary MIME types of -# "text", but which do not support the charset parameter, will be treated as -# opaque, 8-bit data. They will not undergo any transformation process, and -# any "charset", "eoln", or "terminators" parameters specified in this file -# will be ignored. -# -# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of -# text flavors which support the charset parameter. - -UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2 -TEXT=text/plain;eoln="\r\n";terminators=1 -HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1 -Rich\ Text\ Format=text/rtf -HDROP=application/x-java-file-list;class=java.util.List -PNG=image/x-java-image;class=java.awt.Image -JFIF=image/x-java-image;class=java.awt.Image -DIB=image/x-java-image;class=java.awt.Image -ENHMETAFILE=image/x-java-image;class=java.awt.Image -METAFILEPICT=image/x-java-image;class=java.awt.Image -LOCALE=application/x-java-text-encoding;class="[B" -UniformResourceLocator=application/x-java-url;class=java.net.URL,\ - text/uri-list;eoln="\r\n";terminators=1,\ - text/plain;eoln="\r\n";terminators=1 -FileGroupDescriptorW=application/x-java-file-list;class=java.util.List -FileGroupDescriptor=application/x-java-file-list;class=java.util.List
--- a/src/java.desktop/windows/classes/sun/awt/windows/WBufferStrategy.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package sun.awt.windows; - -import java.awt.Image; -import java.awt.Component; - -/** - * This sun-private class exists solely to get a handle to - * the back buffer associated with a Component. If that - * Component has a BufferStrategy with >1 buffer, then the - * Image subclass associated with that buffer will be returned. - * Note: the class is used by the JAWT3d. - */ -public final class WBufferStrategy { - - private static native void initIDs(Class <?> componentClass); - - static { - initIDs(Component.class); - } - - public static native Image getDrawBuffer(Component comp); - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.desktop/windows/classes/sun/datatransfer/resources/flavormap.properties Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,69 @@ +# +# This properties file is used to initialize the default +# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform- +# specific, default mappings between common Win32 Clipboard atoms and platform- +# independent MIME type strings, which will be converted into +# java.awt.datatransfer.DataFlavors. +# +# The standard format is: +# +# <native>=<MIME type>,<MIME type>, ... +# +# <native> should be a string identifier that the native platform will +# recognize as a valid data format. <MIME type> should specify both a MIME +# primary type and a MIME subtype separated by a '/'. The MIME type may include +# parameters, where each parameter is a key/value pair separated by '=', and +# where each parameter to the MIME type is separated by a ';'. +# +# Because SystemFlavorMap implements FlavorTable, developers are free to +# duplicate DataFlavor values and set multiple values for a single native by +# separating them with ",". If a mapping contains a duplicate key or value, +# earlier mappings which included this key or value will be preferred.# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", and which support the charset parameter, should specify the exact +# format in which the native platform expects the data. The "charset" +# parameter specifies the char to byte encoding, the "eoln" parameter +# specifies the end-of-line marker, and the "terminators" parameter specifies +# the number of terminating NUL bytes. Note that "eoln" and "terminators" +# are not standardized MIME type parameters. They are specific to this file +# format ONLY. They will not appear in any of the DataFlavors returned by the +# SystemFlavorMap at the Java level. +# +# If the "charset" parameter is omitted, or has zero length, the platform +# default encoding is assumed. If the "eoln" parameter is omitted, or has +# zero length, "\n" is assumed. If the "terminators" parameter is omitted, +# or has a value less than zero, zero is assumed. +# +# Upon initialization, the data transfer subsystem will record the specified +# details of the native text format, but the default SystemFlavorMap will +# present a large set of synthesized DataFlavors which map, in both +# directions, to the native. After receiving data from the application in one +# of the synthetic DataFlavors, the data transfer subsystem will transform +# the data stream into the format specified in this file before passing the +# transformed stream to the native system. +# +# Mappings whose values specify DataFlavors with primary MIME types of +# "text", but which do not support the charset parameter, will be treated as +# opaque, 8-bit data. They will not undergo any transformation process, and +# any "charset", "eoln", or "terminators" parameters specified in this file +# will be ignored. +# +# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of +# text flavors which support the charset parameter. + +UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2 +TEXT=text/plain;eoln="\r\n";terminators=1 +HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1 +Rich\ Text\ Format=text/rtf +HDROP=application/x-java-file-list;class=java.util.List +PNG=image/x-java-image;class=java.awt.Image +JFIF=image/x-java-image;class=java.awt.Image +DIB=image/x-java-image;class=java.awt.Image +ENHMETAFILE=image/x-java-image;class=java.awt.Image +METAFILEPICT=image/x-java-image;class=java.awt.Image +LOCALE=application/x-java-text-encoding;class="[B" +UniformResourceLocator=application/x-java-url;class=java.net.URL,\ + text/uri-list;eoln="\r\n";terminators=1,\ + text/plain;eoln="\r\n";terminators=1 +FileGroupDescriptorW=application/x-java-file-list;class=java.util.List +FileGroupDescriptor=application/x-java-file-list;class=java.util.List
--- a/src/java.desktop/windows/native/libawt/sun/java2d/d3d/D3DPipeline.cpp Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -#include "D3DPipeline.h" - -BOOL APIENTRY DllMain( HANDLE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved) -{ - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -}
--- a/src/java.desktop/windows/native/libawt/sun/windows/WBufferStrategy.cpp Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -#include "sun_awt_windows_WBufferStrategy.h" -#include "jni_util.h" - - -static jmethodID getBackBufferID; - -/* - * Class: sun_awt_windows_WBufferStrategy - * Method: initIDs - * Signature: (Ljava/lang/Class;)V - */ -JNIEXPORT void JNICALL -Java_sun_awt_windows_WBufferStrategy_initIDs(JNIEnv *env, jclass wbs, - jclass componentClass) -{ - getBackBufferID = env->GetMethodID(componentClass, "getBackBuffer", - "()Ljava/awt/Image;"); -} - -/** - * Native method of WBufferStrategy.java. Given a Component - * object, this method will find the back buffer associated - * with the Component's BufferStrategy and return a handle - * to it. - */ -extern "C" JNIEXPORT jobject JNICALL -Java_sun_awt_windows_WBufferStrategy_getDrawBuffer(JNIEnv *env, jclass wbs, - jobject component) -{ - if (!JNU_IsNull(env, getBackBufferID)) { - return env->CallObjectMethod(component, getBackBufferID); - } else { - return NULL; - } -}
--- a/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Sep 18 13:27:48 2014 -0700 @@ -1335,66 +1335,94 @@ int maxNotifications, long timeout) throws IOException, ClassNotFoundException { - IOException org; + boolean retried = false; while (true) { // used for a successful re-connection + // or a transient network problem try { return connection.fetchNotifications(clientSequenceNumber, maxNotifications, - timeout); + timeout); // return normally } catch (IOException ioe) { - org = ioe; + // Examine the chain of exceptions to determine whether this + // is a deserialization issue. If so - we propagate the + // appropriate exception to the caller, who will then + // proceed with fetching notifications one by one + rethrowDeserializationException(ioe); - // inform of IOException try { communicatorAdmin.gotIOException(ioe); - - // The connection should be re-established. - continue; + // reconnection OK, back to "while" to do again } catch (IOException ee) { - // No more fetch, the Exception will be re-thrown. - break; - } // never reached - } // never reached - } + boolean toClose = false; - // specially treating for an UnmarshalException - if (org instanceof UnmarshalException) { - UnmarshalException ume = (UnmarshalException)org; - - if (ume.detail instanceof ClassNotFoundException) - throw (ClassNotFoundException) ume.detail; + synchronized (this) { + if (terminated) { + // the connection is closed. + throw ioe; + } else if (retried) { + toClose = true; + } + } - /* In Sun's RMI implementation, if a method return - contains an unserializable object, then we get - UnmarshalException wrapping WriteAbortedException - wrapping NotSerializableException. In that case we - extract the NotSerializableException so that our - caller can realize it should try to skip past the - notification that presumably caused it. It's not - certain that every other RMI implementation will - generate this exact exception sequence. If not, we - will not detect that the problem is due to an - unserializable object, and we will stop trying to - receive notifications from the server. It's not - clear we can do much better. */ - if (ume.detail instanceof WriteAbortedException) { - WriteAbortedException wae = - (WriteAbortedException) ume.detail; - if (wae.detail instanceof IOException) - throw (IOException) wae.detail; + if (toClose) { + // JDK-8049303 + // We received an IOException - but the communicatorAdmin + // did not close the connection - possibly because + // the original exception was raised by a transient network + // problem? + // We already know that this exception is not due to a deserialization + // issue as we already took care of that before involving the + // communicatorAdmin. Moreover - we already made one retry attempt + // at fetching the same batch of notifications - and the + // problem persisted. + // Since trying again doesn't seem to solve the issue, we will now + // close the connection. Doing otherwise might cause the + // NotifFetcher thread to die silently. + final Notification failedNotif = + new JMXConnectionNotification( + JMXConnectionNotification.FAILED, + this, + connectionId, + clientNotifSeqNo++, + "Failed to communicate with the server: " + ioe.toString(), + ioe); + + sendNotification(failedNotif); + + try { + close(true); + } catch (Exception e) { + // OK. + // We are closing + } + throw ioe; // the connection is closed here. + } else { + // JDK-8049303 possible transient network problem, + // let's try one more time + retried = true; + } + } } - } else if (org instanceof MarshalException) { + } + } + + private void rethrowDeserializationException(IOException ioe) + throws ClassNotFoundException, IOException { + // specially treating for an UnmarshalException + if (ioe instanceof UnmarshalException) { + throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs + // fetch one by one with UnmarshalException + } else if (ioe instanceof MarshalException) { // IIOP will throw MarshalException wrapping a NotSerializableException // when a server fails to serialize a response. - MarshalException me = (MarshalException)org; + MarshalException me = (MarshalException)ioe; if (me.detail instanceof NotSerializableException) { throw (NotSerializableException)me.detail; } } - // Not serialization problem, simply re-throw the orginal exception - throw org; + // Not serialization problem, return. } protected Integer addListenerForMBeanRemovedNotif()
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2009, 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 com.sun.security.jgss; - -/** - * Kerberos 5 AuthorizationData entry. - */ -@jdk.Exported -public final class AuthorizationDataEntry { - - private final int type; - private final byte[] data; - - /** - * Create an AuthorizationDataEntry object. - * @param type the ad-type - * @param data the ad-data, a copy of the data will be saved - * inside the object. - */ - public AuthorizationDataEntry(int type, byte[] data) { - this.type = type; - this.data = data.clone(); - } - - /** - * Get the ad-type field. - * @return ad-type - */ - public int getType() { - return type; - } - - /** - * Get a copy of the ad-data field. - * @return ad-data - */ - public byte[] getData() { - return data.clone(); - } - - public String toString() { - return "AuthorizationDataEntry: type="+type+", data=" + - data.length + " bytes:\n" + - new sun.misc.HexDumpEncoder().encodeBuffer(data); - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSContext.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2009, 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 com.sun.security.jgss; - -import org.ietf.jgss.*; - -/** - * The extended GSSContext interface for supporting additional - * functionalities not defined by {@code org.ietf.jgss.GSSContext}, - * such as querying context-specific attributes. - */ -@jdk.Exported -public interface ExtendedGSSContext extends GSSContext { - /** - * Return the mechanism-specific attribute associated with {@code type}. - * <p> - * If there is a security manager, an {@link InquireSecContextPermission} - * with the name {@code type.mech} must be granted. Otherwise, this could - * result in a {@link SecurityException}.<p> - * - * Example: - * <pre> - * GSSContext ctxt = m.createContext(...) - * // Establishing the context - * if (ctxt instanceof ExtendedGSSContext) { - * ExtendedGSSContext ex = (ExtendedGSSContext)ctxt; - * try { - * Key key = (key)ex.inquireSecContext( - * InquireType.KRB5_GET_SESSION_KEY); - * // read key info - * } catch (GSSException gsse) { - * // deal with exception - * } - * } - * </pre> - * @param type the type of the attribute requested - * @return the attribute, see the method documentation for details. - * @throws GSSException containing the following - * major error codes: - * {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism - * does not support this method, - * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the - * type specified is not supported, - * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the - * security context is invalid, - * {@link GSSException#FAILURE GSSException.FAILURE} for other - * unspecified failures. - * @throws SecurityException if a security manager exists and a proper - * {@link InquireSecContextPermission} is not granted. - * @see InquireSecContextPermission - * @see InquireType - */ - public Object inquireSecContext(InquireType type) - throws GSSException; - - /** - * Requests that the delegation policy be respected. When a true value is - * requested, the underlying context would use the delegation policy - * defined by the environment as a hint to determine whether credentials - * delegation should be performed. This request can only be made on the - * context initiator's side and it has to be done prior to the first - * call to <code>initSecContext</code>. - * <p> - * When this flag is false, delegation will only be tried when the - * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} - * is true. - * <p> - * When this flag is true but the - * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} - * is false, delegation will be only tried if the delegation policy permits - * delegation. - * <p> - * When both this flag and the - * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} - * are true, delegation will be always tried. However, if the delegation - * policy does not permit delegation, the value of - * {@link #getDelegPolicyState} will be false, even - * if delegation is performed successfully. - * <p> - * In any case, if the delegation is not successful, the value returned - * by {@link GSSContext#getCredDelegState()} is false, and the value - * returned by {@link #getDelegPolicyState()} is also false. - * <p> - * Not all mechanisms support delegation policy. Therefore, the - * application should check to see if the request was honored with the - * {@link #getDelegPolicyState() getDelegPolicyState} method. When - * delegation policy is not supported, <code>requestDelegPolicy</code> - * should return silently without throwing an exception. - * <p> - * Note: for the Kerberos 5 mechanism, the delegation policy is expressed - * through the OK-AS-DELEGATE flag in the service ticket. When it's true, - * the KDC permits delegation to the target server. In a cross-realm - * environment, in order for delegation be permitted, all cross-realm TGTs - * on the authentication path must also have the OK-AS-DELAGATE flags set. - * @param state true if the policy should be respected - * @throws GSSException containing the following - * major error codes: - * {@link GSSException#FAILURE GSSException.FAILURE} - */ - public void requestDelegPolicy(boolean state) throws GSSException; - - /** - * Returns the delegation policy response. Called after a security context - * is established. This method can be only called on the initiator's side. - * See {@link ExtendedGSSContext#requestDelegPolicy}. - * @return the delegation policy response - */ - public boolean getDelegPolicyState(); -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.security.jgss; - -import org.ietf.jgss.*; - -/** - * The extended GSSCredential interface for supporting additional - * functionalities not defined by {@code org.ietf.jgss.GSSCredential}. - * @since 1.8 - */ -@jdk.Exported -public interface ExtendedGSSCredential extends GSSCredential { - /** - * Impersonates a principal. In Kerberos, this can be implemented - * using the Microsoft S4U2self extension. - * <p> - * A {@link GSSException#NO_CRED GSSException.NO_CRED} will be thrown if the - * impersonation fails. A {@link GSSException#FAILURE GSSException.FAILURE} - * will be thrown if the impersonation method is not available to this - * credential object. - * @param name the name of the principal to impersonate - * @return a credential for that principal - * @throws GSSException containing the following - * major error codes: - * {@link GSSException#NO_CRED GSSException.NO_CRED} - * {@link GSSException#FAILURE GSSException.FAILURE} - */ - public GSSCredential impersonate(GSSName name) throws GSSException; -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/GSSUtil.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * 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 - * 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 com.sun.security.jgss; - -import javax.security.auth.Subject; -import org.ietf.jgss.GSSName; -import org.ietf.jgss.GSSCredential; - -/** - * GSS-API Utilities for using in conjunction with Sun Microsystem's - * implementation of Java GSS-API. - */ -@jdk.Exported -public class GSSUtil { - - /** - * Use this method to convert a GSSName and GSSCredential into a - * Subject. Typically this would be done by a server that wants to - * impersonate a client thread at the Java level by setting a client - * Subject in the current access control context. If the server is merely - * interested in using a principal based policy in its local JVM, then - * it only needs to provide the GSSName of the client. - * - * The elements from the GSSName are placed in the principals set of this - * Subject and those from the GSSCredential are placed in the private - * credentials set of the Subject. Any Kerberos specific elements that - * are added to the subject will be instances of the standard Kerberos - * implementation classes defined in javax.security.auth.kerberos. - * - * @return a Subject with the entries that contain elements from the - * given GSSName and GSSCredential. - * - * @param principals a GSSName containing one or more mechanism specific - * representations of the same entity. These mechanism specific - * representations will be populated in the returned Subject's principal - * set. - * - * @param credentials a GSSCredential containing one or more mechanism - * specific credentials for the same entity. These mechanism specific - * credentials will be populated in the returned Subject's private - * credential set. Passing in a value of null will imply that the private - * credential set should be left empty. - */ - public static Subject createSubject(GSSName principals, - GSSCredential credentials) { - - return sun.security.jgss.GSSUtil.getSubject(principals, - credentials); - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2009, 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 com.sun.security.jgss; - -import java.security.BasicPermission; - -/** - * This class is used to protect various attributes of an established - * GSS security context that can be accessed using the - * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} - * method. - * - * <p>The target name is the {@link InquireType} allowed. - */ -@jdk.Exported -public final class InquireSecContextPermission extends BasicPermission { - private static final long serialVersionUID = -7131173349668647297L; - - /** - * Constructs a new {@code InquireSecContextPermission} object with - * the specified name. The name is the symbolic name of the - * {@link InquireType} allowed. - * - * @param name the {@link InquireType} allowed by this - * permission. "*" means all {@link InquireType}s are allowed. - * - * @throws NullPointerException if <code>name</code> is <code>null</code>. - * @throws IllegalArgumentException if <code>name</code> is empty. - */ - public InquireSecContextPermission(String name) { - super(name); - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/InquireType.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2009, 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 com.sun.security.jgss; - -/** - * Attribute types that can be specified as an argument of - * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} - */ -@jdk.Exported -public enum InquireType { - /** - * Attribute type for retrieving the session key of an established - * Kerberos 5 security context. The returned object is an instance of - * {@link java.security.Key}, which has the following properties: - * <ul> - * <li>Algorithm: enctype as a string, where - * enctype is defined in RFC 3961, section 8. - * <li>Format: "RAW" - * <li>Encoded form: the raw key bytes, not in any ASN.1 encoding - * </ul> - * @deprecated as of 1.9, replaced by {@link #KRB5_GET_SESSION_KEY_EX} - * which returns an instance of - * {@link javax.security.auth.kerberos.EncryptionKey} - * that implements the {@link javax.crypto.SecretKey} interface and - * has similar methods with {@link javax.security.auth.kerberos.KerberosKey}. - */ - @Deprecated - KRB5_GET_SESSION_KEY, - /** - * Attribute type for retrieving the session key of an - * established Kerberos 5 security context. The return value is an - * instance of {@link javax.security.auth.kerberos.EncryptionKey}. - * - * @since 1.9 - */ - KRB5_GET_SESSION_KEY_EX, - /** - * Attribute type for retrieving the service ticket flags of an - * established Kerberos 5 security context. The returned object is - * a boolean array for the service ticket flags, which is long enough - * to contain all true bits. This means if the user wants to get the - * <em>n</em>'th bit but the length of the returned array is less than - * <em>n</em>, it is regarded as false. - */ - KRB5_GET_TKT_FLAGS, - /** - * Attribute type for retrieving the authorization data in the - * service ticket of an established Kerberos 5 security context. - * Only supported on the acceptor side. - */ - KRB5_GET_AUTHZ_DATA, - /** - * Attribute type for retrieving the authtime in the service ticket - * of an established Kerberos 5 security context. The returned object - * is a String object in the standard KerberosTime format defined in - * RFC 4120 Section 5.2.3. - */ - KRB5_GET_AUTHTIME, - /** - * Attribute type for retrieving the KRB_CRED message that an initiator - * is about to send to an acceptor. The return type is an instance of - * {@link javax.security.auth.kerberos.KerberosCredMessage}. - * - * @since 1.9 - */ - KRB5_GET_KRB_CRED, -}
--- a/src/java.security.jgss/share/classes/com/sun/security/jgss/package-info.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/* - * 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. - */ - -@jdk.Exported -package com.sun.security.jgss;
--- a/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.security.sasl.gsskerb; - -import javax.security.sasl.*; -import com.sun.security.sasl.util.PolicyUtils; - -import java.util.Map; -import javax.security.auth.callback.CallbackHandler; - -/** - * Client/server factory for GSSAPI (Kerberos V5) SASL client/server mechs. - * See GssKrb5Client/GssKrb5Server for input requirements. - * - * @author Rosanna Lee - */ -public final class FactoryImpl implements SaslClientFactory, SaslServerFactory { - private static final String myMechs[] = { - "GSSAPI"}; - - private static final int mechPolicies[] = { - PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE - }; - - private static final int GSS_KERB_V5 = 0; - - public FactoryImpl() { - } - - public SaslClient createSaslClient(String[] mechs, - String authorizationId, - String protocol, - String serverName, - Map<String,?> props, - CallbackHandler cbh) throws SaslException { - - for (int i = 0; i < mechs.length; i++) { - if (mechs[i].equals(myMechs[GSS_KERB_V5]) - && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) { - return new GssKrb5Client( - authorizationId, - protocol, - serverName, - props, - cbh); - } - } - return null; - }; - - public SaslServer createSaslServer(String mech, - String protocol, - String serverName, - Map<String,?> props, - CallbackHandler cbh) throws SaslException { - if (mech.equals(myMechs[GSS_KERB_V5]) - && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) { - if (cbh == null) { - throw new SaslException( - "Callback handler with support for AuthorizeCallback required"); - } - return new GssKrb5Server( - protocol, - serverName, - props, - cbh); - } - return null; - }; - - public String[] getMechanismNames(Map<String,?> props) { - return PolicyUtils.filterMechs(myMechs, mechPolicies, props); - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * 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 - * 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 com.sun.security.sasl.gsskerb; - -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; -import javax.security.sasl.*; -import com.sun.security.sasl.util.AbstractSaslImpl; -import org.ietf.jgss.*; -import com.sun.security.jgss.ExtendedGSSContext; -import com.sun.security.jgss.InquireType; - -abstract class GssKrb5Base extends AbstractSaslImpl { - - private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2"; - protected static Oid KRB5_OID; - protected static final byte[] EMPTY = new byte[0]; - - static { - try { - KRB5_OID = new Oid(KRB5_OID_STR); - } catch (GSSException ignore) {} - } - - protected GSSContext secCtx = null; - protected static final int JGSS_QOP = 0; // unrelated to SASL QOP mask - - protected GssKrb5Base(Map<String, ?> props, String className) - throws SaslException { - super(props, className); - } - - /** - * Retrieves this mechanism's name. - * - * @return The string "GSSAPI". - */ - public String getMechanismName() { - return "GSSAPI"; - } - - @Override - public Object getNegotiatedProperty(String propName) { - if (!completed) { - throw new IllegalStateException("Authentication incomplete"); - } - String xprefix = "com.sun.security.jgss.inquiretype."; - if (propName.startsWith(xprefix)) { - String type = propName.substring(xprefix.length()); - if (logger.isLoggable(Level.FINEST)) { - logger.logp(Level.FINE, "GssKrb5Base", - "getNegotiatedProperty", propName); - } - for (InquireType t: InquireType.values()) { - if (t.name().toLowerCase(Locale.US).equals(type)) { - try { - return ((ExtendedGSSContext)secCtx).inquireSecContext(t); - } catch (GSSException e) { - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.WARNING, "inquireSecContext error", e); - } - return null; - } - } - } - // No such InquireType. Although not likely to be defined - // as a property in a parent class, still try it. - } - return super.getNegotiatedProperty(propName); - } - - public byte[] unwrap(byte[] incoming, int start, int len) - throws SaslException { - if (!completed) { - throw new IllegalStateException("GSSAPI authentication not completed"); - } - - // integrity will be true if either privacy or integrity negotiated - if (!integrity) { - throw new IllegalStateException("No security layer negotiated"); - } - - try { - MessageProp msgProp = new MessageProp(JGSS_QOP, privacy); - byte[] answer = secCtx.unwrap(incoming, start, len, msgProp); - if (logger.isLoggable(Level.FINEST)) { - traceOutput(myClassName, "KRB501:Unwrap", "incoming: ", - incoming, start, len); - traceOutput(myClassName, "KRB502:Unwrap", "unwrapped: ", - answer, 0, answer.length); - } - return answer; - } catch (GSSException e) { - throw new SaslException("Problems unwrapping SASL buffer", e); - } - } - - public byte[] wrap(byte[] outgoing, int start, int len) throws SaslException { - if (!completed) { - throw new IllegalStateException("GSSAPI authentication not completed"); - } - - // integrity will be true if either privacy or integrity negotiated - if (!integrity) { - throw new IllegalStateException("No security layer negotiated"); - } - - // Generate GSS token - try { - MessageProp msgProp = new MessageProp(JGSS_QOP, privacy); - byte[] answer = secCtx.wrap(outgoing, start, len, msgProp); - if (logger.isLoggable(Level.FINEST)) { - traceOutput(myClassName, "KRB503:Wrap", "outgoing: ", - outgoing, start, len); - traceOutput(myClassName, "KRB504:Wrap", "wrapped: ", - answer, 0, answer.length); - } - return answer; - - } catch (GSSException e) { - throw new SaslException("Problem performing GSS wrap", e); - } - } - - public void dispose() throws SaslException { - if (secCtx != null) { - try { - secCtx.dispose(); - } catch (GSSException e) { - throw new SaslException("Problem disposing GSS context", e); - } - secCtx = null; - } - } - - protected void finalize() throws Throwable { - dispose(); - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,329 +0,0 @@ -/* - * 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 - * 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 com.sun.security.sasl.gsskerb; - -import java.io.IOException; -import java.util.Map; -import java.util.logging.Level; -import javax.security.sasl.*; - -// JAAS -import javax.security.auth.callback.CallbackHandler; - -// JGSS -import org.ietf.jgss.*; - -/** - * Implements the GSSAPI SASL client mechanism for Kerberos V5. - * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>, - * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-04.txt">draft-ietf-cat-sasl-gssapi-04.txt</a>). - * It uses the Java Bindings for GSSAPI - * (<A HREF="http://www.ietf.org/rfc/rfc2853.txt">RFC 2853</A>) - * for getting GSSAPI/Kerberos V5 support. - * - * The client/server interactions are: - * C0: bind (GSSAPI, initial response) - * S0: sasl-bind-in-progress, challenge 1 (output of accept_sec_context or []) - * C1: bind (GSSAPI, response 1 (output of init_sec_context or [])) - * S1: sasl-bind-in-progress challenge 2 (security layer, server max recv size) - * C2: bind (GSSAPI, response 2 (security layer, client max recv size, authzid)) - * S2: bind success response - * - * Expects the client's credentials to be supplied from the - * javax.security.sasl.credentials property or from the thread's Subject. - * Otherwise the underlying KRB5 mech will attempt to acquire Kerberos creds - * by logging into Kerberos (via default TextCallbackHandler). - * These creds will be used for exchange with server. - * - * Required callbacks: none. - * - * Environment properties that affect behavior of implementation: - * - * javax.security.sasl.qop - * - quality of protection; list of auth, auth-int, auth-conf; default is "auth" - * javax.security.sasl.maxbuf - * - max receive buffer size; default is 65536 - * javax.security.sasl.sendmaxbuffer - * - max send buffer size; default is 65536; (min with server max recv size) - * - * javax.security.sasl.server.authentication - * - "true" means require mutual authentication; default is "false" - * - * javax.security.sasl.credentials - * - an {@link org.ietf.jgss.GSSCredential} used for delegated authentication. - * - * @author Rosanna Lee - */ - -final class GssKrb5Client extends GssKrb5Base implements SaslClient { - // ---------------- Constants ----------------- - private static final String MY_CLASS_NAME = GssKrb5Client.class.getName(); - - private boolean finalHandshake = false; - private boolean mutual = false; // default false - private byte[] authzID; - - /** - * Creates a SASL mechanism with client credentials that it needs - * to participate in GSS-API/Kerberos v5 authentication exchange - * with the server. - */ - GssKrb5Client(String authzID, String protocol, String serverName, - Map<String, ?> props, CallbackHandler cbh) throws SaslException { - - super(props, MY_CLASS_NAME); - - String service = protocol + "@" + serverName; - logger.log(Level.FINE, "KRB5CLNT01:Requesting service name: {0}", - service); - - try { - GSSManager mgr = GSSManager.getInstance(); - - // Create the name for the requested service entity for Krb5 mech - GSSName acceptorName = mgr.createName(service, - GSSName.NT_HOSTBASED_SERVICE, KRB5_OID); - - // Parse properties to check for supplied credentials - GSSCredential credentials = null; - if (props != null) { - Object prop = props.get(Sasl.CREDENTIALS); - if (prop != null && prop instanceof GSSCredential) { - credentials = (GSSCredential) prop; - logger.log(Level.FINE, - "KRB5CLNT01:Using the credentials supplied in " + - "javax.security.sasl.credentials"); - } - } - - // Create a context using credentials for Krb5 mech - secCtx = mgr.createContext(acceptorName, - KRB5_OID, /* mechanism */ - credentials, /* credentials */ - GSSContext.INDEFINITE_LIFETIME); - - // Request credential delegation when credentials have been supplied - if (credentials != null) { - secCtx.requestCredDeleg(true); - } - - // Parse properties to set desired context options - if (props != null) { - // Mutual authentication - String prop = (String)props.get(Sasl.SERVER_AUTH); - if (prop != null) { - mutual = "true".equalsIgnoreCase(prop); - } - } - secCtx.requestMutualAuth(mutual); - - // Always specify potential need for integrity and confidentiality - // Decision will be made during final handshake - secCtx.requestConf(true); - secCtx.requestInteg(true); - - } catch (GSSException e) { - throw new SaslException("Failure to initialize security context", e); - } - - if (authzID != null && authzID.length() > 0) { - try { - this.authzID = authzID.getBytes("UTF8"); - } catch (IOException e) { - throw new SaslException("Cannot encode authorization ID", e); - } - } - } - - public boolean hasInitialResponse() { - return true; - } - - /** - * Processes the challenge data. - * - * The server sends a challenge data using which the client must - * process using GSS_Init_sec_context. - * As per RFC 2222, when GSS_S_COMPLETE is returned, we do - * an extra handshake to determine the negotiated security protection - * and buffer sizes. - * - * @param challengeData A non-null byte array containing the - * challenge data from the server. - * @return A non-null byte array containing the response to be - * sent to the server. - */ - public byte[] evaluateChallenge(byte[] challengeData) throws SaslException { - if (completed) { - throw new IllegalStateException( - "GSSAPI authentication already complete"); - } - - if (finalHandshake) { - return doFinalHandshake(challengeData); - } else { - - // Security context not established yet; continue with init - - try { - byte[] gssOutToken = secCtx.initSecContext(challengeData, - 0, challengeData.length); - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "evaluteChallenge", - "KRB5CLNT02:Challenge: [raw]", challengeData); - traceOutput(MY_CLASS_NAME, "evaluateChallenge", - "KRB5CLNT03:Response: [after initSecCtx]", gssOutToken); - } - - if (secCtx.isEstablished()) { - finalHandshake = true; - if (gssOutToken == null) { - // RFC 2222 7.2.1: Client responds with no data - return EMPTY; - } - } - - return gssOutToken; - } catch (GSSException e) { - throw new SaslException("GSS initiate failed", e); - } - } - } - - private byte[] doFinalHandshake(byte[] challengeData) throws SaslException { - try { - // Security context already established. challengeData - // should contain security layers and server's maximum buffer size - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doFinalHandshake", - "KRB5CLNT04:Challenge [raw]:", challengeData); - } - - if (challengeData.length == 0) { - // Received S0, should return [] - return EMPTY; - } - - // Received S1 (security layer, server max recv size) - - byte[] gssOutToken = secCtx.unwrap(challengeData, 0, - challengeData.length, new MessageProp(0, false)); - - // First octet is a bit-mask specifying the protections - // supported by the server - if (logger.isLoggable(Level.FINE)) { - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doFinalHandshake", - "KRB5CLNT05:Challenge [unwrapped]:", gssOutToken); - } - logger.log(Level.FINE, "KRB5CLNT06:Server protections: {0}", - gssOutToken[0]); - } - - // Client selects preferred protection - // qop is ordered list of qop values - byte selectedQop = findPreferredMask(gssOutToken[0], qop); - if (selectedQop == 0) { - throw new SaslException( - "No common protection layer between client and server"); - } - - if ((selectedQop&PRIVACY_PROTECTION) != 0) { - privacy = true; - integrity = true; - } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) { - integrity = true; - } - - // 2nd-4th octets specifies maximum buffer size expected by - // server (in network byte order) - int srvMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3); - - // Determine the max send buffer size based on what the - // server is able to receive and our specified max - sendMaxBufSize = (sendMaxBufSize == 0) ? srvMaxBufSize : - Math.min(sendMaxBufSize, srvMaxBufSize); - - // Update context to limit size of returned buffer - rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy, - sendMaxBufSize); - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, -"KRB5CLNT07:Client max recv size: {0}; server max recv size: {1}; rawSendSize: {2}", - new Object[] {recvMaxBufSize, - srvMaxBufSize, - rawSendSize}); - } - - // Construct negotiated security layers and client's max - // receive buffer size and authzID - int len = 4; - if (authzID != null) { - len += authzID.length; - } - - byte[] gssInToken = new byte[len]; - gssInToken[0] = selectedQop; - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, - "KRB5CLNT08:Selected protection: {0}; privacy: {1}; integrity: {2}", - new Object[]{selectedQop, - Boolean.valueOf(privacy), - Boolean.valueOf(integrity)}); - } - - intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3); - if (authzID != null) { - // copy authorization id - System.arraycopy(authzID, 0, gssInToken, 4, authzID.length); - logger.log(Level.FINE, "KRB5CLNT09:Authzid: {0}", authzID); - } - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doFinalHandshake", - "KRB5CLNT10:Response [raw]", gssInToken); - } - - gssOutToken = secCtx.wrap(gssInToken, - 0, gssInToken.length, - new MessageProp(0 /* qop */, false /* privacy */)); - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doFinalHandshake", - "KRB5CLNT11:Response [after wrap]", gssOutToken); - } - - completed = true; // server authenticated - - return gssOutToken; - } catch (GSSException e) { - throw new SaslException("Final handshake failed", e); - } - } -}
--- a/src/java.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java Wed Sep 17 22:56:07 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,365 +0,0 @@ -/* - * 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 - * 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 com.sun.security.sasl.gsskerb; - -import javax.security.sasl.*; -import java.io.*; -import java.util.Map; -import java.util.logging.Level; - -// JAAS -import javax.security.auth.callback.*; - -// JGSS -import org.ietf.jgss.*; - -/** - * Implements the GSSAPI SASL server mechanism for Kerberos V5. - * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>, - * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-00.txt">draft-ietf-cat-sasl-gssapi-00.txt</a>). - * - * Expects thread's Subject to contain server's Kerberos credentials - * - If not, underlying KRB5 mech will attempt to acquire Kerberos creds - * by logging into Kerberos (via default TextCallbackHandler). - * - These creds will be used for exchange with client. - * - * Required callbacks: - * - AuthorizeCallback - * handler must verify that authid/authzids are allowed and set - * authorized ID to be the canonicalized authzid (if applicable). - * - * Environment properties that affect behavior of implementation: - * - * javax.security.sasl.qop - * - quality of protection; list of auth, auth-int, auth-conf; default is "auth" - * javax.security.sasl.maxbuf - * - max receive buffer size; default is 65536 - * javax.security.sasl.sendmaxbuffer - * - max send buffer size; default is 65536; (min with client max recv size) - * - * @author Rosanna Lee - */ -final class GssKrb5Server extends GssKrb5Base implements SaslServer { - private static final String MY_CLASS_NAME = GssKrb5Server.class.getName(); - - private int handshakeStage = 0; - private String peer; - private String me; - private String authzid; - private CallbackHandler cbh; - - // When serverName is null, the server will be unbound. We need to save and - // check the protocol name after the context is established. This value - // will be null if serverName is not null. - private final String protocolSaved; - /** - * Creates a SASL mechanism with server credentials that it needs - * to participate in GSS-API/Kerberos v5 authentication exchange - * with the client. - */ - GssKrb5Server(String protocol, String serverName, - Map<String, ?> props, CallbackHandler cbh) throws SaslException { - - super(props, MY_CLASS_NAME); - - this.cbh = cbh; - - String service; - if (serverName == null) { - protocolSaved = protocol; - service = null; - } else { - protocolSaved = null; - service = protocol + "@" + serverName; - } - - logger.log(Level.FINE, "KRB5SRV01:Using service name: {0}", service); - - try { - GSSManager mgr = GSSManager.getInstance(); - - // Create the name for the requested service entity for Krb5 mech - GSSName serviceName = service == null ? null: - mgr.createName(service, GSSName.NT_HOSTBASED_SERVICE, KRB5_OID); - - GSSCredential cred = mgr.createCredential(serviceName, - GSSCredential.INDEFINITE_LIFETIME, - KRB5_OID, GSSCredential.ACCEPT_ONLY); - - // Create a context using the server's credentials - secCtx = mgr.createContext(cred); - - if ((allQop&INTEGRITY_ONLY_PROTECTION) != 0) { - // Might need integrity - secCtx.requestInteg(true); - } - - if ((allQop&PRIVACY_PROTECTION) != 0) { - // Might need privacy - secCtx.requestConf(true); - } - } catch (GSSException e) { - throw new SaslException("Failure to initialize security context", e); - } - logger.log(Level.FINE, "KRB5SRV02:Initialization complete"); - } - - - /** - * Processes the response data. - * - * The client sends response data to which the server must - * process using GSS_accept_sec_context. - * As per RFC 2222, the GSS authenication completes (GSS_S_COMPLETE) - * we do an extra hand shake to determine the negotiated security protection - * and buffer sizes. - * - * @param responseData A non-null but possible empty byte array containing the - * response data from the client. - * @return A non-null byte array containing the challenge to be - * sent to the client, or null when no more data is to be sent. - */ - public byte[] evaluateResponse(byte[] responseData) throws SaslException { - if (completed) { - throw new SaslException( - "SASL authentication already complete"); - } - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "evaluateResponse", - "KRB5SRV03:Response [raw]:", responseData); - } - - switch (handshakeStage) { - case 1: - return doHandshake1(responseData); - - case 2: - return doHandshake2(responseData); - - default: - // Security context not established yet; continue with accept - - try { - byte[] gssOutToken = secCtx.acceptSecContext(responseData, - 0, responseData.length); - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "evaluateResponse", - "KRB5SRV04:Challenge: [after acceptSecCtx]", gssOutToken); - } - - if (secCtx.isEstablished()) { - handshakeStage = 1; - - peer = secCtx.getSrcName().toString(); - me = secCtx.getTargName().toString(); - - logger.log(Level.FINE, - "KRB5SRV05:Peer name is : {0}, my name is : {1}", - new Object[]{peer, me}); - - // me might take the form of proto@host or proto/host - if (protocolSaved != null && - !protocolSaved.equalsIgnoreCase(me.split("[/@]")[0])) { - throw new SaslException( - "GSS context targ name protocol error: " + me); - } - - if (gssOutToken == null) { - return doHandshake1(EMPTY); - } - } - - return gssOutToken; - } catch (GSSException e) { - throw new SaslException("GSS initiate failed", e); - } - } - } - - private byte[] doHandshake1(byte[] responseData) throws SaslException { - try { - // Security context already established. responseData - // should contain no data - if (responseData != null && responseData.length > 0) { - throw new SaslException( - "Handshake expecting no response data from server"); - } - - // Construct 4 octets of data: - // First octet contains bitmask specifying protections supported - // 2nd-4th octets contains max receive buffer of server - - byte[] gssInToken = new byte[4]; - gssInToken[0] = allQop; - intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3); - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, - "KRB5SRV06:Supported protections: {0}; recv max buf size: {1}", - new Object[]{allQop, - recvMaxBufSize}); - } - - handshakeStage = 2; // progress to next stage - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doHandshake1", - "KRB5SRV07:Challenge [raw]", gssInToken); - } - - byte[] gssOutToken = secCtx.wrap(gssInToken, 0, gssInToken.length, - new MessageProp(0 /* gop */, false /* privacy */)); - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doHandshake1", - "KRB5SRV08:Challenge [after wrap]", gssOutToken); - } - return gssOutToken; - - } catch (GSSException e) { - throw new SaslException("Problem wrapping handshake1", e); - } - } - - private byte[] doHandshake2(byte[] responseData) throws SaslException { - try { - // Expecting 4 octets from client selected protection - // and client's receive buffer size - byte[] gssOutToken = secCtx.unwrap(responseData, 0, - responseData.length, new MessageProp(0, false)); - - if (logger.isLoggable(Level.FINER)) { - traceOutput(MY_CLASS_NAME, "doHandshake2", - "KRB5SRV09:Response [after unwrap]", gssOutToken); - } - - // First octet is a bit-mask specifying the selected protection - byte selectedQop = gssOutToken[0]; - if ((selectedQop&allQop) == 0) { - throw new SaslException("Client selected unsupported protection: " - + selectedQop); - } - if ((selectedQop&PRIVACY_PROTECTION) != 0) { - privacy = true; - integrity = true; - } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) { - integrity = true; - } - - // 2nd-4th octets specifies maximum buffer size expected by - // client (in network byte order). This is the server's send - // buffer maximum. - int clntMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3); - - // Determine the max send buffer size based on what the - // client is able to receive and our specified max - sendMaxBufSize = (sendMaxBufSize == 0) ? clntMaxBufSize : - Math.min(sendMaxBufSize, clntMaxBufSize); - - // Update context to limit size of returned buffer - rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy, - sendMaxBufSize); - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, - "KRB5SRV10:Selected protection: {0}; privacy: {1}; integrity: {2}", - new Object[]{selectedQop, - Boolean.valueOf(privacy), - Boolean.valueOf(integrity)}); - logger.log(Level.FINE, -"KRB5SRV11:Client max recv size: {0}; server max send size: {1}; rawSendSize: {2}", - new Object[] {clntMaxBufSize, - sendMaxBufSize, - rawSendSize}); - } - - // Get authorization identity, if any - if (gssOutToken.length > 4) { - try { - authzid = new String(gssOutToken, 4, - gssOutToken.length - 4, "UTF-8"); - } catch (UnsupportedEncodingException uee) { - throw new SaslException ("Cannot decode authzid", uee); - } - } else { - authzid = peer; - } - logger.log(Level.FINE, "KRB5SRV12:Authzid: {0}", authzid); - - AuthorizeCallback acb = new AuthorizeCallback(peer, authzid); - - // In Kerberos, realm is embedded in peer name - cbh.handle(new Callback[] {acb}); - if (acb.isAuthorized()) { - authzid = acb.getAuthorizedID(); - completed = true; - } else { - // Authorization failed - throw new SaslException(peer + - " is not authorized to connect as " + authzid); - } - - return null; - } catch (GSSException e) { - throw new SaslException("Final handshake step failed", e); - } catch (IOException e) { - throw new SaslException("Problem with callback handler", e); - } catch (UnsupportedCallbackException e) { - throw new SaslException("Problem with callback handler", e); - } - } - - public String getAuthorizationID() { - if (completed) { - return authzid; - } else { - throw new IllegalStateException("Authentication incomplete"); - } - } - - public Object getNegotiatedProperty(String propName) { - if (!completed) { - throw new IllegalStateException("Authentication incomplete"); - } - - Object result; - switch (propName) { - case Sasl.BOUND_SERVER_NAME: - try { - // me might take the form of proto@host or proto/host - result = me.split("[/@]")[1]; - } catch (Exception e) { - result = null; - } - break; - default: - result = super.getNegotiatedProperty(propName); - } - return result; - } -}
--- a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSContext.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,7 +25,6 @@ package org.ietf.jgss; -import sun.security.jgss.spi.*; import java.io.InputStream; import java.io.OutputStream;
--- a/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/org/ietf/jgss/GSSName.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,10 +25,6 @@ package org.ietf.jgss; -import sun.security.jgss.spi.*; -import java.util.Vector; -import java.util.Enumeration; - /** * This interface encapsulates a single GSS-API principal entity. The * application obtains an implementation of this interface
--- a/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,7 +25,6 @@ package sun.net.www.protocol.http.spnego; -import com.sun.security.jgss.ExtendedGSSContext; import java.io.IOException; import org.ietf.jgss.GSSContext; @@ -36,6 +35,7 @@ import sun.net.www.protocol.http.HttpCallerInfo; import sun.net.www.protocol.http.Negotiator; import sun.security.jgss.GSSManagerImpl; +import sun.security.jgss.GSSContextImpl; import sun.security.jgss.GSSUtil; import sun.security.jgss.HttpCaller; @@ -102,8 +102,8 @@ GSSContext.DEFAULT_LIFETIME); // Always respect delegation policy in HTTP/SPNEGO. - if (context instanceof ExtendedGSSContext) { - ((ExtendedGSSContext)context).requestDelegPolicy(true); + if (context instanceof GSSContextImpl) { + ((GSSContextImpl)context).requestDelegPolicy(true); } oneToken = context.initSecContext(new byte[0], 0, 0); }
--- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSContextImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -33,7 +33,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import com.sun.security.jgss.*; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; /** * This class represents the JGSS security context and its associated @@ -87,10 +88,10 @@ * per-message operations are returned in an instance of the MessageProp * class, which is used as an argument in these calls.</dl> */ -class GSSContextImpl implements ExtendedGSSContext { +public class GSSContextImpl implements GSSContext { - private final GSSManagerImpl gssManager; - private final boolean initiator; + private GSSManagerImpl gssManager; + private boolean initiator; // private flags for the context state private static final int PRE_INIT = 1; @@ -122,6 +123,22 @@ private boolean reqAnonState = false; private boolean reqDelegPolicyState = false; + public GSSContextImpl() { + // Useless + } + + // Used by new ExtendedGSSContext.ExtendedGSSContextImpl(ctxt) + protected GSSContextImpl(GSSContextImpl src) { + for (Field f: GSSContextImpl.class.getDeclaredFields()) { + if (!Modifier.isStatic(f.getModifiers())) { + try { + f.set(this, f.get(src)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } /** * Creates a GSSContextImp on the context initiator's side. */ @@ -613,7 +630,7 @@ "No mechanism context yet!"); GSSCredentialSpi delCredElement = mechCtxt.getDelegCred(); return (delCredElement == null ? - null : new GSSCredentialImpl(gssManager, delCredElement)); + null : GSSManagerImpl.wrap(new GSSCredentialImpl(gssManager, delCredElement))); } public boolean isInitiator() throws GSSException { @@ -633,25 +650,18 @@ // ExtendedGSSContext methods: - @Override - public Object inquireSecContext(InquireType type) throws GSSException { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(new InquireSecContextPermission(type.toString())); - } + public Object inquireSecContext(String type) throws GSSException { if (mechCtxt == null) { throw new GSSException(GSSException.NO_CONTEXT); } return mechCtxt.inquireSecContext(type); } - @Override public void requestDelegPolicy(boolean state) throws GSSException { if (mechCtxt == null && initiator) reqDelegPolicyState = state; } - @Override public boolean getDelegPolicyState() { if (mechCtxt != null) return mechCtxt.getDelegPolicyState();
--- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,11 +27,11 @@ import org.ietf.jgss.*; import sun.security.jgss.spi.*; + import java.util.*; -import com.sun.security.jgss.*; import sun.security.jgss.spnego.SpNegoCredElement; -public class GSSCredentialImpl implements ExtendedGSSCredential { +public class GSSCredentialImpl implements GSSCredential { private GSSManagerImpl gssManager = null; private boolean destroyed = false; @@ -47,6 +47,18 @@ // XXX Optimization for single mech usage private GSSCredentialSpi tempCred = null; + public GSSCredentialImpl() { + // Useless + } + + // Used by new ExtendedGSSCredential.ExtendedGSSCredentialImpl(cred) + protected GSSCredentialImpl(GSSCredentialImpl src) { + this.gssManager = src.gssManager; + this.destroyed = src.destroyed; + this.hashtable = src.hashtable; + this.tempCred = src.tempCred; + } + GSSCredentialImpl(GSSManagerImpl gssManager, int usage) throws GSSException { this(gssManager, null, GSSCredential.DEFAULT_LIFETIME, @@ -140,7 +152,7 @@ ((GSSNameImpl)name).getElement(mech)); GSSCredentialSpi cred = tempCred.impersonate(nameElement); return (cred == null ? - null : new GSSCredentialImpl(gssManager, cred)); + null : GSSManagerImpl.wrap(new GSSCredentialImpl(gssManager, cred))); } public GSSName getName() throws GSSException {
--- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -145,35 +145,35 @@ public GSSCredential createCredential(int usage) throws GSSException { - return new GSSCredentialImpl(this, usage); + return wrap(new GSSCredentialImpl(this, usage)); } public GSSCredential createCredential(GSSName aName, int lifetime, Oid mech, int usage) throws GSSException { - return new GSSCredentialImpl(this, aName, lifetime, mech, usage); + return wrap(new GSSCredentialImpl(this, aName, lifetime, mech, usage)); } public GSSCredential createCredential(GSSName aName, int lifetime, Oid mechs[], int usage) throws GSSException { - return new GSSCredentialImpl(this, aName, lifetime, mechs, usage); + return wrap(new GSSCredentialImpl(this, aName, lifetime, mechs, usage)); } public GSSContext createContext(GSSName peer, Oid mech, GSSCredential myCred, int lifetime) throws GSSException { - return new GSSContextImpl(this, peer, mech, myCred, lifetime); + return wrap(new GSSContextImpl(this, peer, mech, myCred, lifetime)); } public GSSContext createContext(GSSCredential myCred) throws GSSException { - return new GSSContextImpl(this, myCred); + return wrap(new GSSContextImpl(this, myCred)); } public GSSContext createContext(byte[] interProcessToken) throws GSSException { - return new GSSContextImpl(this, interProcessToken); + return wrap(new GSSContextImpl(this, interProcessToken)); } public void addProviderAtFront(Provider p, Oid mech) @@ -257,4 +257,20 @@ } return result; } + + static { + // Load the extended JGSS interfaces if exist + try { + Class.forName("com.sun.security.jgss.Extender"); + } catch (Exception e) { + } + } + + static GSSCredential wrap(GSSCredentialImpl cred) { + return sun.security.jgss.JgssExtender.getExtender().wrap(cred); + } + + static GSSContext wrap(GSSContextImpl ctxt) { + return sun.security.jgss.JgssExtender.getExtender().wrap(ctxt); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/JgssExtender.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.jgss; + +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; + +/** + * The extending point of basic JGSS-API. + * <p> + * If a module wants to extend basic JGSS-API classes, it should extends this + * class and register itself as "the extender" using the setExtender method. + * When various GSSManager.createXXX methods are called, they will call + * "the extender"'s wrap methods to create objects of extended types + * instead of basic types. + * <p> + * We have only one extension now defined in com.sun.security.jgss, and the + * registering process is triggered in {@link GSSManagerImpl} by calling + * Class.forName("com.sun.security.jgss.Extender"). Only GSSContext + * and GSSCredential are extended now. + * <p> + * The setExtender method should be called before any JGSS call. + */ +public class JgssExtender { + + // "The extender" + private static volatile JgssExtender theOne = new JgssExtender(); + + /** + * Gets "the extender". GSSManager calls this method so that it can + * wrap basic objects into extended objects. + * @return the extender + */ + public static JgssExtender getExtender() { + return theOne; + } + + /** + * Set "the extender" so that GSSManager can create extended objects. + */ + protected static void setExtender(JgssExtender theOne) { + JgssExtender.theOne = theOne; + } + + /** + * Wraps a plain GSSCredential object into an extended type. + */ + public GSSCredential wrap(GSSCredential cred) { + return cred; + } + + /** + * Wraps a plain GSSContext object into an extended type. + */ + public GSSContext wrap(GSSContext ctxt) { + return ctxt; + } +}
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/InitSecContextToken.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,7 +25,6 @@ package sun.security.jgss.krb5; -import com.sun.security.jgss.AuthorizationDataEntry; import org.ietf.jgss.*; import java.io.InputStream; import java.io.IOException; @@ -152,17 +151,7 @@ new KerberosTime(apReq.getCreds().getAuthTime()).toString()); context.setTktFlags(apReq.getCreds().getFlags()); AuthorizationData ad = apReq.getCreds().getAuthzData(); - if (ad == null) { - context.setAuthzData(null); - } else { - AuthorizationDataEntry[] authzData = - new AuthorizationDataEntry[ad.count()]; - for (int i=0; i<ad.count(); i++) { - authzData[i] = new AuthorizationDataEntry( - ad.item(i).adType, ad.item(i).adData); - } - context.setAuthzData(authzData); - } + context.setAuthzData(ad); } public final KrbApReq getKrbApReq() {
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,7 +25,6 @@ package sun.security.jgss.krb5; -import com.sun.security.jgss.InquireType; import org.ietf.jgss.*; import sun.misc.HexDumpEncoder; import sun.security.jgss.GSSUtil; @@ -48,6 +47,7 @@ import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.kerberos.KerberosTicket; import sun.security.krb5.internal.Ticket; +import sun.security.krb5.internal.AuthorizationData; /** * Implements the mechanism specific context class for the Kerberos v5 @@ -1419,30 +1419,30 @@ /** * Return the mechanism-specific attribute associated with {@code type}. */ - public Object inquireSecContext(InquireType type) + public Object inquireSecContext(String type) throws GSSException { if (!isEstablished()) { throw new GSSException(GSSException.NO_CONTEXT, -1, "Security context not established."); } switch (type) { - case KRB5_GET_SESSION_KEY: + case "KRB5_GET_SESSION_KEY": return new KerberosSessionKey(key); - case KRB5_GET_SESSION_KEY_EX: + case "KRB5_GET_SESSION_KEY_EX": return new javax.security.auth.kerberos.EncryptionKey( key.getBytes(), key.getEType()); - case KRB5_GET_TKT_FLAGS: + case "KRB5_GET_TKT_FLAGS": return tktFlags.clone(); - case KRB5_GET_AUTHZ_DATA: + case "KRB5_GET_AUTHZ_DATA": if (isInitiator()) { throw new GSSException(GSSException.UNAVAILABLE, -1, "AuthzData not available on initiator side."); } else { - return (authzData==null)?null:authzData.clone(); + return authzData; } - case KRB5_GET_AUTHTIME: + case "KRB5_GET_AUTHTIME": return authTime; - case KRB5_GET_KRB_CRED: + case "KRB5_GET_KRB_CRED": if (!isInitiator()) { throw new GSSException(GSSException.UNAVAILABLE, -1, "KRB_CRED not available on acceptor side."); @@ -1470,7 +1470,7 @@ // Helpers for inquireSecContext private boolean[] tktFlags; private String authTime; - private com.sun.security.jgss.AuthorizationDataEntry[] authzData; + private AuthorizationData authzData; public void setTktFlags(boolean[] tktFlags) { this.tktFlags = tktFlags; @@ -1480,7 +1480,7 @@ this.authTime = authTime; } - public void setAuthzData(com.sun.security.jgss.AuthorizationDataEntry[] authzData) { + public void setAuthzData(AuthorizationData authzData) { this.authzData = authzData; }
--- a/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Thu Sep 18 13:27:48 2014 -0700 @@ -34,7 +34,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.Provider; -import com.sun.security.jgss.*; /** * This interface is implemented by a mechanism specific instance of a GSS @@ -403,6 +402,6 @@ * @throws GSSException see {@link ExtendedGSSContext#inquireSecContext} * for details */ - public Object inquireSecContext(InquireType type) + public Object inquireSecContext(String type) throws GSSException; }
--- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoContext.java Thu Sep 18 13:27:48 2014 -0700 @@ -25,8 +25,6 @@ package sun.security.jgss.spnego; -import com.sun.security.jgss.ExtendedGSSContext; -import com.sun.security.jgss.InquireType; import java.io.*; import java.security.Provider; import org.ietf.jgss.*; @@ -174,9 +172,9 @@ */ public final boolean getDelegPolicyState() { if (isInitiator() && mechContext != null && - mechContext instanceof ExtendedGSSContext && + mechContext instanceof GSSContextImpl && (state == STATE_IN_PROCESS || state == STATE_DONE)) { - return ((ExtendedGSSContext)mechContext).getDelegPolicyState(); + return ((GSSContextImpl)mechContext).getDelegPolicyState(); } else { return delegPolicyState; } @@ -850,7 +848,7 @@ myCred.getInternalCred()); } mechContext = - factory.manager.createContext(serverName, + factory.manager.createContext(serverName, internal_mech, cred, GSSContext.DEFAULT_LIFETIME); mechContext.requestConf(confState); mechContext.requestInteg(integState); @@ -858,8 +856,8 @@ mechContext.requestMutualAuth(mutualAuthState); mechContext.requestReplayDet(replayDetState); mechContext.requestSequenceDet(sequenceDetState); - if (mechContext instanceof ExtendedGSSContext) { - ((ExtendedGSSContext)mechContext).requestDelegPolicy( + if (mechContext instanceof GSSContextImpl) { + ((GSSContextImpl)mechContext).requestDelegPolicy( delegPolicyState); } } @@ -890,8 +888,7 @@ cred = new GSSCredentialImpl(factory.manager, myCred.getInternalCred()); } - mechContext = - factory.manager.createContext(cred); + mechContext = factory.manager.createContext(cred); } // pass token to mechanism acceptSecContext @@ -1217,14 +1214,14 @@ /** * Retrieve attribute of the context for {@code type}. */ - public Object inquireSecContext(InquireType type) + public Object inquireSecContext(String type) throws GSSException { if (mechContext == null) { throw new GSSException(GSSException.NO_CONTEXT, -1, "Underlying mech not established."); } - if (mechContext instanceof ExtendedGSSContext) { - return ((ExtendedGSSContext)mechContext).inquireSecContext(type); + if (mechContext instanceof GSSContextImpl) { + return ((GSSContextImpl)mechContext).inquireSecContext(type); } else { throw new GSSException(GSSException.BAD_MECH, -1, "inquireSecContext not supported by underlying mech.");
--- a/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/spnego/SpNegoCredElement.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,8 +27,6 @@ import org.ietf.jgss.*; import java.security.Provider; import sun.security.jgss.GSSUtil; -import sun.security.jgss.ProviderList; -import sun.security.jgss.GSSCredentialImpl; import sun.security.jgss.spi.GSSNameSpi; import sun.security.jgss.spi.GSSCredentialSpi;
--- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Thu Sep 18 13:27:48 2014 -0700 @@ -36,7 +36,6 @@ import sun.security.jgss.spnego.NegTokenInit; import sun.security.jgss.spnego.NegTokenTarg; import javax.security.auth.kerberos.DelegationPermission; -import com.sun.security.jgss.InquireType; import java.io.*; @@ -623,7 +622,7 @@ dispose(); } - public Object inquireSecContext(InquireType type) + public Object inquireSecContext(String type) throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "Inquire type not supported.");
--- a/src/java.sql/share/classes/java/sql/Date.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.sql/share/classes/java/sql/Date.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,6 +27,8 @@ import java.time.Instant; import java.time.LocalDate; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** * <P>A thin wrapper around a millisecond value that allows @@ -42,6 +44,8 @@ */ public class Date extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a <code>Date</code> object initialized with the given * year, month, and day. @@ -108,31 +112,27 @@ * JDBC date escape format (yyyy-[m]m-[d]d) */ public static Date valueOf(String s) { + if (s == null) { + throw new java.lang.IllegalArgumentException(); + } final int YEAR_LENGTH = 4; final int MONTH_LENGTH = 2; final int DAY_LENGTH = 2; final int MAX_MONTH = 12; final int MAX_DAY = 31; - int firstDash; - int secondDash; Date d = null; - if (s == null) { - throw new java.lang.IllegalArgumentException(); - } - firstDash = s.indexOf('-'); - secondDash = s.indexOf('-', firstDash + 1); + int firstDash = s.indexOf('-'); + int secondDash = s.indexOf('-', firstDash + 1); + int len = s.length(); - if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) { - String yyyy = s.substring(0, firstDash); - String mm = s.substring(firstDash + 1, secondDash); - String dd = s.substring(secondDash + 1); - if (yyyy.length() == YEAR_LENGTH && - (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) && - (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) { - int year = Integer.parseInt(yyyy); - int month = Integer.parseInt(mm); - int day = Integer.parseInt(dd); + if ((firstDash > 0) && (secondDash > 0) && (secondDash < len - 1)) { + if (firstDash == YEAR_LENGTH && + (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) && + (len - secondDash > 1 && len - secondDash <= DAY_LENGTH + 1)) { + int year = Integer.parseInt(s, 0, firstDash, 10); + int month = Integer.parseInt(s, firstDash + 1, secondDash, 10); + int day = Integer.parseInt(s, secondDash + 1, len, 10); if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) { d = new Date(year - 1900, month - 1, day); @@ -159,17 +159,34 @@ int month = super.getMonth() + 1; int day = super.getDate(); - char buf[] = "2000-00-00".toCharArray(); - buf[0] = Character.forDigit(year/1000,10); - buf[1] = Character.forDigit((year/100)%10,10); - buf[2] = Character.forDigit((year/10)%10,10); - buf[3] = Character.forDigit(year%10,10); - buf[5] = Character.forDigit(month/10,10); - buf[6] = Character.forDigit(month%10,10); - buf[8] = Character.forDigit(day/10,10); - buf[9] = Character.forDigit(day%10,10); + char buf[] = new char[10]; + formatDecimalInt(year, buf, 0, 4); + buf[4] = '-'; + Date.formatDecimalInt(month, buf, 5, 2); + buf[7] = '-'; + Date.formatDecimalInt(day, buf, 8, 2); + + return jla.newStringUnsafe(buf); + } - return new String(buf); + /** + * Formats an unsigned integer into a char array in decimal output format. + * Numbers will be zero-padded or truncated if the string representation + * of the integer is smaller than or exceeds len, respectively. + * + * Should consider moving this to Integer and expose it through + * JavaLangAccess similar to Integer::formatUnsignedInt + * @param val Value to convert + * @param buf Array containing converted value + * @param offset Starting pos in buf + * @param len length of output value + */ + static void formatDecimalInt(int val, char[] buf, int offset, int len) { + int charPos = offset + len; + do { + buf[--charPos] = (char)('0' + (val % 10)); + val /= 10; + } while (charPos > offset); } // Override all the time operations inherited from java.util.Date;
--- a/src/java.sql/share/classes/java/sql/Time.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.sql/share/classes/java/sql/Time.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,6 +27,8 @@ import java.time.Instant; import java.time.LocalTime; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** * <P>A thin wrapper around the <code>java.util.Date</code> class that allows the JDBC @@ -39,6 +41,8 @@ */ public class Time extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a <code>Time</code> object initialized with the * given values for the hour, minute, and second. @@ -90,22 +94,19 @@ * @return a corresponding <code>Time</code> object */ public static Time valueOf(String s) { + if (s == null) throw new java.lang.IllegalArgumentException(); + int hour; int minute; int second; - int firstColon; - int secondColon; - - if (s == null) throw new java.lang.IllegalArgumentException(); - - firstColon = s.indexOf(':'); - secondColon = s.indexOf(':', firstColon+1); - if ((firstColon > 0) & (secondColon > 0) & - (secondColon < s.length()-1)) { - hour = Integer.parseInt(s.substring(0, firstColon)); - minute = - Integer.parseInt(s.substring(firstColon+1, secondColon)); - second = Integer.parseInt(s.substring(secondColon+1)); + int firstColon = s.indexOf(':'); + int secondColon = s.indexOf(':', firstColon + 1); + int len = s.length(); + if (firstColon > 0 && secondColon > 0 && + secondColon < len - 1) { + hour = Integer.parseInt(s, 0, firstColon, 10); + minute = Integer.parseInt(s, firstColon + 1, secondColon, 10); + second = Integer.parseInt(s, secondColon + 1, len, 10); } else { throw new java.lang.IllegalArgumentException(); } @@ -123,26 +124,15 @@ int hour = super.getHours(); int minute = super.getMinutes(); int second = super.getSeconds(); - String hourString; - String minuteString; - String secondString; - if (hour < 10) { - hourString = "0" + hour; - } else { - hourString = Integer.toString(hour); - } - if (minute < 10) { - minuteString = "0" + minute; - } else { - minuteString = Integer.toString(minute); - } - if (second < 10) { - secondString = "0" + second; - } else { - secondString = Integer.toString(second); - } - return (hourString + ":" + minuteString + ":" + secondString); + char[] buf = new char[8]; + Date.formatDecimalInt(hour, buf, 0, 2); + buf[2] = ':'; + Date.formatDecimalInt(minute, buf, 3, 2); + buf[5] = ':'; + Date.formatDecimalInt(second, buf, 6, 2); + + return jla.newStringUnsafe(buf); } // Override all the date operations inherited from java.util.Date;
--- a/src/java.sql/share/classes/java/sql/Timestamp.java Wed Sep 17 22:56:07 2014 -0700 +++ b/src/java.sql/share/classes/java/sql/Timestamp.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,7 +27,8 @@ import java.time.Instant; import java.time.LocalDateTime; -import java.util.StringTokenizer; +import sun.misc.SharedSecrets; +import sun.misc.JavaLangAccess; /** * <P>A thin wrapper around <code>java.util.Date</code> that allows @@ -71,6 +72,8 @@ */ public class Timestamp extends java.util.Date { + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a <code>Timestamp</code> object initialized * with the given values. @@ -171,9 +174,6 @@ final int DAY_LENGTH = 2; final int MAX_MONTH = 12; final int MAX_DAY = 31; - String date_s; - String time_s; - String nanos_s; int year = 0; int month = 0; int day = 0; @@ -184,49 +184,38 @@ int firstDash; int secondDash; int dividingSpace; - int firstColon = 0; - int secondColon = 0; - int period = 0; + int firstColon; + int secondColon; + int period; String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]"; - String zeros = "000000000"; - String delimiterDate = "-"; - String delimiterTime = ":"; if (s == null) throw new java.lang.IllegalArgumentException("null string"); // Split the string into date and time components s = s.trim(); dividingSpace = s.indexOf(' '); - if (dividingSpace > 0) { - date_s = s.substring(0,dividingSpace); - time_s = s.substring(dividingSpace+1); - } else { + if (dividingSpace < 0) { throw new java.lang.IllegalArgumentException(formatError); } // Parse the date - firstDash = date_s.indexOf('-'); - secondDash = date_s.indexOf('-', firstDash+1); + firstDash = s.indexOf('-'); + secondDash = s.indexOf('-', firstDash+1); // Parse the time - if (time_s == null) - throw new java.lang.IllegalArgumentException(formatError); - firstColon = time_s.indexOf(':'); - secondColon = time_s.indexOf(':', firstColon+1); - period = time_s.indexOf('.', secondColon+1); + firstColon = s.indexOf(':', dividingSpace + 1); + secondColon = s.indexOf(':', firstColon + 1); + period = s.indexOf('.', secondColon + 1); // Convert the date boolean parsedDate = false; - if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) { - String yyyy = date_s.substring(0, firstDash); - String mm = date_s.substring(firstDash + 1, secondDash); - String dd = date_s.substring(secondDash + 1); - if (yyyy.length() == YEAR_LENGTH && - (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) && - (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) { - year = Integer.parseInt(yyyy); - month = Integer.parseInt(mm); - day = Integer.parseInt(dd); + if (firstDash > 0 && secondDash > 0 && secondDash < dividingSpace - 1) { + if (firstDash == YEAR_LENGTH && + (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) && + (dividingSpace - secondDash > 1 && dividingSpace - secondDash <= DAY_LENGTH + 1)) { + year = Integer.parseInt(s, 0, firstDash, 10); + month = Integer.parseInt(s, firstDash + 1, secondDash, 10); + day = Integer.parseInt(s, secondDash + 1, dividingSpace, 10); if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) { parsedDate = true; @@ -238,25 +227,27 @@ } // Convert the time; default missing nanos - if ((firstColon > 0) & (secondColon > 0) & - (secondColon < time_s.length()-1)) { - hour = Integer.parseInt(time_s.substring(0, firstColon)); - minute = - Integer.parseInt(time_s.substring(firstColon+1, secondColon)); - if ((period > 0) & (period < time_s.length()-1)) { - second = - Integer.parseInt(time_s.substring(secondColon+1, period)); - nanos_s = time_s.substring(period+1); - if (nanos_s.length() > 9) + int len = s.length(); + if (firstColon > 0 && secondColon > 0 && secondColon < len - 1) { + hour = Integer.parseInt(s, dividingSpace + 1, firstColon, 10); + minute = Integer.parseInt(s, firstColon + 1, secondColon, 10); + if (period > 0 && period < len - 1) { + second = Integer.parseInt(s, secondColon + 1, period, 10); + int nanoPrecision = len - (period + 1); + if (nanoPrecision > 9) throw new java.lang.IllegalArgumentException(formatError); - if (!Character.isDigit(nanos_s.charAt(0))) + if (!Character.isDigit(s.charAt(period + 1))) throw new java.lang.IllegalArgumentException(formatError); - nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length()); - a_nanos = Integer.parseInt(nanos_s); + int tmpNanos = Integer.parseInt(s, period + 1, len, 10); + while (nanoPrecision < 9) { + tmpNanos *= 10; + nanoPrecision++; + } + a_nanos = tmpNanos; } else if (period > 0) { throw new java.lang.IllegalArgumentException(formatError); } else { - second = Integer.parseInt(time_s.substring(secondColon+1)); + second = Integer.parseInt(s, secondColon + 1, len, 10); } } else { throw new java.lang.IllegalArgumentException(formatError); @@ -274,95 +265,53 @@ * <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format */ @SuppressWarnings("deprecation") - public String toString () { - + public String toString() { int year = super.getYear() + 1900; int month = super.getMonth() + 1; int day = super.getDate(); int hour = super.getHours(); int minute = super.getMinutes(); int second = super.getSeconds(); - String yearString; - String monthString; - String dayString; - String hourString; - String minuteString; - String secondString; - String nanosString; - String zeros = "000000000"; - String yearZeros = "0000"; - StringBuffer timestampBuf; - if (year < 1000) { - // Add leading zeros - yearString = "" + year; - yearString = yearZeros.substring(0, (4-yearString.length())) + - yearString; - } else { - yearString = "" + year; - } - if (month < 10) { - monthString = "0" + month; - } else { - monthString = Integer.toString(month); - } - if (day < 10) { - dayString = "0" + day; + int trailingZeros = 0; + int tmpNanos = nanos; + if (tmpNanos == 0) { + trailingZeros = 8; } else { - dayString = Integer.toString(day); - } - if (hour < 10) { - hourString = "0" + hour; - } else { - hourString = Integer.toString(hour); - } - if (minute < 10) { - minuteString = "0" + minute; - } else { - minuteString = Integer.toString(minute); - } - if (second < 10) { - secondString = "0" + second; - } else { - secondString = Integer.toString(second); - } - if (nanos == 0) { - nanosString = "0"; - } else { - nanosString = Integer.toString(nanos); - - // Add leading zeros - nanosString = zeros.substring(0, (9-nanosString.length())) + - nanosString; - - // Truncate trailing zeros - char[] nanosChar = new char[nanosString.length()]; - nanosString.getChars(0, nanosString.length(), nanosChar, 0); - int truncIndex = 8; - while (nanosChar[truncIndex] == '0') { - truncIndex--; + while (tmpNanos % 10 == 0) { + tmpNanos /= 10; + trailingZeros++; } - - nanosString = new String(nanosChar, 0, truncIndex + 1); } - // do a string buffer here instead. - timestampBuf = new StringBuffer(20+nanosString.length()); - timestampBuf.append(yearString); - timestampBuf.append("-"); - timestampBuf.append(monthString); - timestampBuf.append("-"); - timestampBuf.append(dayString); - timestampBuf.append(" "); - timestampBuf.append(hourString); - timestampBuf.append(":"); - timestampBuf.append(minuteString); - timestampBuf.append(":"); - timestampBuf.append(secondString); - timestampBuf.append("."); - timestampBuf.append(nanosString); + // 8058429: To comply with current JCK tests, we need to deal with year + // being any number between 0 and 292278995 + int count = 10000; + int yearSize = 4; + do { + if (year < count) { + break; + } + yearSize++; + count *= 10; + } while (count < 1000000000); - return (timestampBuf.toString()); + char[] buf = new char[25 + yearSize - trailingZeros]; + Date.formatDecimalInt(year, buf, 0, yearSize); + buf[yearSize] = '-'; + Date.formatDecimalInt(month, buf, yearSize + 1, 2); + buf[yearSize + 3] = '-'; + Date.formatDecimalInt(day, buf, yearSize + 4, 2); + buf[yearSize + 6] = ' '; + Date.formatDecimalInt(hour, buf, yearSize + 7, 2); + buf[yearSize + 9] = ':'; + Date.formatDecimalInt(minute, buf, yearSize + 10, 2); + buf[yearSize + 12] = ':'; + Date.formatDecimalInt(second, buf, yearSize + 13, 2); + buf[yearSize + 15] = '.'; + Date.formatDecimalInt(tmpNanos, buf, yearSize + 16, 9 - trailingZeros); + + return jla.newStringUnsafe(buf); } /**
--- a/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo Wed Sep 17 22:56:07 2014 -0700 +++ b/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo Thu Sep 18 13:27:48 2014 -0700 @@ -1,1 +1,1 @@ -sun.util.cldr.CLDRLocaleDataMetaInfo +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 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 com.sun.security.jgss; + +/** + * Kerberos 5 AuthorizationData entry. + */ +@jdk.Exported +public final class AuthorizationDataEntry { + + private final int type; + private final byte[] data; + + /** + * Create an AuthorizationDataEntry object. + * @param type the ad-type + * @param data the ad-data, a copy of the data will be saved + * inside the object. + */ + public AuthorizationDataEntry(int type, byte[] data) { + this.type = type; + this.data = data.clone(); + } + + /** + * Get the ad-type field. + * @return ad-type + */ + public int getType() { + return type; + } + + /** + * Get a copy of the ad-data field. + * @return ad-data + */ + public byte[] getData() { + return data.clone(); + } + + public String toString() { + return "AuthorizationDataEntry: type="+type+", data=" + + data.length + " bytes:\n" + + new sun.misc.HexDumpEncoder().encodeBuffer(data); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSContext.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2009, 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 com.sun.security.jgss; + +import org.ietf.jgss.*; +import sun.security.jgss.GSSContextImpl; +import sun.security.krb5.internal.AuthorizationData; + +/** + * The extended GSSContext interface for supporting additional + * functionalities not defined by {@code org.ietf.jgss.GSSContext}, + * such as querying context-specific attributes. + */ +@jdk.Exported +public interface ExtendedGSSContext extends GSSContext { + + // The impl is almost identical to GSSContextImpl with only 2 differences: + // 1. It implements the extended interface + // 2. It translates result to data types here in inquireSecContext + static class ExtendedGSSContextImpl extends GSSContextImpl + implements ExtendedGSSContext { + + public ExtendedGSSContextImpl(GSSContextImpl old) { + super(old); + } + + @Override + public Object inquireSecContext(InquireType type) throws GSSException { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPermission( + new InquireSecContextPermission(type.toString())); + } + Object output = super.inquireSecContext(type.name()); + if (output != null) { + if (type == InquireType.KRB5_GET_AUTHZ_DATA) { + AuthorizationData ad = (AuthorizationData) output; + AuthorizationDataEntry[] authzData = + new AuthorizationDataEntry[ad.count()]; + for (int i = 0; i < ad.count(); i++) { + authzData[i] = new AuthorizationDataEntry( + ad.item(i).adType, ad.item(i).adData); + } + output = authzData; + } + } + return output; + } + } + + /** + * Return the mechanism-specific attribute associated with {@code type}. + * <p> + * If there is a security manager, an {@link InquireSecContextPermission} + * with the name {@code type.mech} must be granted. Otherwise, this could + * result in a {@link SecurityException}. + * <p> + * Example: + * <pre> + * GSSContext ctxt = m.createContext(...) + * // Establishing the context + * if (ctxt instanceof ExtendedGSSContext) { + * ExtendedGSSContext ex = (ExtendedGSSContext)ctxt; + * try { + * Key key = (key)ex.inquireSecContext( + * InquireType.KRB5_GET_SESSION_KEY); + * // read key info + * } catch (GSSException gsse) { + * // deal with exception + * } + * } + * </pre> + * @param type the type of the attribute requested + * @return the attribute, see the method documentation for details. + * @throws GSSException containing the following + * major error codes: + * {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism + * does not support this method, + * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the + * type specified is not supported, + * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the + * security context is invalid, + * {@link GSSException#FAILURE GSSException.FAILURE} for other + * unspecified failures. + * @throws SecurityException if a security manager exists and a proper + * {@link InquireSecContextPermission} is not granted. + * @see InquireSecContextPermission + * @see InquireType + */ + public Object inquireSecContext(InquireType type) + throws GSSException; + + /** + * Requests that the delegation policy be respected. When a true value is + * requested, the underlying context would use the delegation policy + * defined by the environment as a hint to determine whether credentials + * delegation should be performed. This request can only be made on the + * context initiator's side and it has to be done prior to the first + * call to <code>initSecContext</code>. + * <p> + * When this flag is false, delegation will only be tried when the + * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} + * is true. + * <p> + * When this flag is true but the + * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} + * is false, delegation will be only tried if the delegation policy permits + * delegation. + * <p> + * When both this flag and the + * {@link GSSContext#requestCredDeleg(boolean) credentials delegation flag} + * are true, delegation will be always tried. However, if the delegation + * policy does not permit delegation, the value of + * {@link #getDelegPolicyState} will be false, even + * if delegation is performed successfully. + * <p> + * In any case, if the delegation is not successful, the value returned + * by {@link GSSContext#getCredDelegState()} is false, and the value + * returned by {@link #getDelegPolicyState()} is also false. + * <p> + * Not all mechanisms support delegation policy. Therefore, the + * application should check to see if the request was honored with the + * {@link #getDelegPolicyState() getDelegPolicyState} method. When + * delegation policy is not supported, <code>requestDelegPolicy</code> + * should return silently without throwing an exception. + * <p> + * Note: for the Kerberos 5 mechanism, the delegation policy is expressed + * through the OK-AS-DELEGATE flag in the service ticket. When it's true, + * the KDC permits delegation to the target server. In a cross-realm + * environment, in order for delegation be permitted, all cross-realm TGTs + * on the authentication path must also have the OK-AS-DELAGATE flags set. + * @param state true if the policy should be respected + * @throws GSSException containing the following + * major error codes: + * {@link GSSException#FAILURE GSSException.FAILURE} + */ + public void requestDelegPolicy(boolean state) throws GSSException; + + /** + * Returns the delegation policy response. Called after a security context + * is established. This method can be only called on the initiator's side. + * See {@link ExtendedGSSContext#requestDelegPolicy}. + * @return the delegation policy response + */ + public boolean getDelegPolicyState(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/ExtendedGSSCredential.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.security.jgss; + +import org.ietf.jgss.*; +import sun.security.jgss.GSSCredentialImpl; + +/** + * The extended GSSCredential interface for supporting additional + * functionalities not defined by {@code org.ietf.jgss.GSSCredential}. + * @since 1.8 + */ +@jdk.Exported +public interface ExtendedGSSCredential extends GSSCredential { + + static class ExtendedGSSCredentialImpl extends GSSCredentialImpl + implements ExtendedGSSCredential { + + public ExtendedGSSCredentialImpl(GSSCredentialImpl old) { + super(old); + } + } + + /** + * Impersonates a principal. In Kerberos, this can be implemented + * using the Microsoft S4U2self extension. + * <p> + * A {@link GSSException#NO_CRED GSSException.NO_CRED} will be thrown if the + * impersonation fails. A {@link GSSException#FAILURE GSSException.FAILURE} + * will be thrown if the impersonation method is not available to this + * credential object. + * @param name the name of the principal to impersonate + * @return a credential for that principal + * @throws GSSException containing the following + * major error codes: + * {@link GSSException#NO_CRED GSSException.NO_CRED} + * {@link GSSException#FAILURE GSSException.FAILURE} + */ + public GSSCredential impersonate(GSSName name) throws GSSException; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/Extender.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 com.sun.security.jgss; + +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import sun.security.jgss.GSSContextImpl; +import sun.security.jgss.GSSCredentialImpl; +import sun.security.jgss.JgssExtender; + +// The com.sun.security.jgss extension to JGSS-API +class Extender extends JgssExtender { + + static { + JgssExtender.setExtender(new Extender()); + } + + public GSSCredential wrap(GSSCredential cred) { + if (cred instanceof ExtendedGSSCredential.ExtendedGSSCredentialImpl) { + return cred; + } else { + return new ExtendedGSSCredential.ExtendedGSSCredentialImpl((GSSCredentialImpl)cred); + } + } + + public GSSContext wrap(GSSContext ctxt) { + if (ctxt instanceof ExtendedGSSContext.ExtendedGSSContextImpl) { + return ctxt; + } else { + return new ExtendedGSSContext.ExtendedGSSContextImpl((GSSContextImpl)ctxt); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/GSSUtil.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,73 @@ +/* + * 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 + * 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 com.sun.security.jgss; + +import javax.security.auth.Subject; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.GSSCredential; + +/** + * GSS-API Utilities for using in conjunction with Sun Microsystem's + * implementation of Java GSS-API. + */ +@jdk.Exported +public class GSSUtil { + + /** + * Use this method to convert a GSSName and GSSCredential into a + * Subject. Typically this would be done by a server that wants to + * impersonate a client thread at the Java level by setting a client + * Subject in the current access control context. If the server is merely + * interested in using a principal based policy in its local JVM, then + * it only needs to provide the GSSName of the client. + * + * The elements from the GSSName are placed in the principals set of this + * Subject and those from the GSSCredential are placed in the private + * credentials set of the Subject. Any Kerberos specific elements that + * are added to the subject will be instances of the standard Kerberos + * implementation classes defined in javax.security.auth.kerberos. + * + * @return a Subject with the entries that contain elements from the + * given GSSName and GSSCredential. + * + * @param principals a GSSName containing one or more mechanism specific + * representations of the same entity. These mechanism specific + * representations will be populated in the returned Subject's principal + * set. + * + * @param credentials a GSSCredential containing one or more mechanism + * specific credentials for the same entity. These mechanism specific + * credentials will be populated in the returned Subject's private + * credential set. Passing in a value of null will imply that the private + * credential set should be left empty. + */ + public static Subject createSubject(GSSName principals, + GSSCredential credentials) { + + return sun.security.jgss.GSSUtil.getSubject(principals, + credentials); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireSecContextPermission.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009, 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 com.sun.security.jgss; + +import java.security.BasicPermission; + +/** + * This class is used to protect various attributes of an established + * GSS security context that can be accessed using the + * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} + * method. + * + * <p>The target name is the {@link InquireType} allowed. + */ +@jdk.Exported +public final class InquireSecContextPermission extends BasicPermission { + private static final long serialVersionUID = -7131173349668647297L; + + /** + * Constructs a new {@code InquireSecContextPermission} object with + * the specified name. The name is the symbolic name of the + * {@link InquireType} allowed. + * + * @param name the {@link InquireType} allowed by this + * permission. "*" means all {@link InquireType}s are allowed. + * + * @throws NullPointerException if <code>name</code> is <code>null</code>. + * @throws IllegalArgumentException if <code>name</code> is empty. + */ + public InquireSecContextPermission(String name) { + super(name); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/InquireType.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2009, 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 com.sun.security.jgss; + +/** + * Attribute types that can be specified as an argument of + * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} + */ +@jdk.Exported +public enum InquireType { + /** + * Attribute type for retrieving the session key of an established + * Kerberos 5 security context. The returned object is an instance of + * {@link java.security.Key}, which has the following properties: + * <ul> + * <li>Algorithm: enctype as a string, where + * enctype is defined in RFC 3961, section 8. + * <li>Format: "RAW" + * <li>Encoded form: the raw key bytes, not in any ASN.1 encoding + * </ul> + * @deprecated as of 1.9, replaced by {@link #KRB5_GET_SESSION_KEY_EX} + * which returns an instance of + * {@link javax.security.auth.kerberos.EncryptionKey} + * that implements the {@link javax.crypto.SecretKey} interface and + * has similar methods with {@link javax.security.auth.kerberos.KerberosKey}. + */ + @Deprecated + KRB5_GET_SESSION_KEY, + /** + * Attribute type for retrieving the session key of an + * established Kerberos 5 security context. The return value is an + * instance of {@link javax.security.auth.kerberos.EncryptionKey}. + * + * @since 1.9 + */ + KRB5_GET_SESSION_KEY_EX, + /** + * Attribute type for retrieving the service ticket flags of an + * established Kerberos 5 security context. The returned object is + * a boolean array for the service ticket flags, which is long enough + * to contain all true bits. This means if the user wants to get the + * <em>n</em>'th bit but the length of the returned array is less than + * <em>n</em>, it is regarded as false. + */ + KRB5_GET_TKT_FLAGS, + /** + * Attribute type for retrieving the authorization data in the + * service ticket of an established Kerberos 5 security context. + * Only supported on the acceptor side. + */ + KRB5_GET_AUTHZ_DATA, + /** + * Attribute type for retrieving the authtime in the service ticket + * of an established Kerberos 5 security context. The returned object + * is a String object in the standard KerberosTime format defined in + * RFC 4120 Section 5.2.3. + */ + KRB5_GET_AUTHTIME, + /** + * Attribute type for retrieving the KRB_CRED message that an initiator + * is about to send to an acceptor. The return type is an instance of + * {@link javax.security.auth.kerberos.KerberosCredMessage}. + * + * @since 1.9 + */ + KRB5_GET_KRB_CRED, +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/jgss/package-info.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,27 @@ +/* + * 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. + */ + +@jdk.Exported +package com.sun.security.jgss;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.security.sasl.gsskerb; + +import javax.security.sasl.*; +import com.sun.security.sasl.util.PolicyUtils; + +import java.util.Map; +import javax.security.auth.callback.CallbackHandler; + +/** + * Client/server factory for GSSAPI (Kerberos V5) SASL client/server mechs. + * See GssKrb5Client/GssKrb5Server for input requirements. + * + * @author Rosanna Lee + */ +public final class FactoryImpl implements SaslClientFactory, SaslServerFactory { + private static final String myMechs[] = { + "GSSAPI"}; + + private static final int mechPolicies[] = { + PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE + }; + + private static final int GSS_KERB_V5 = 0; + + public FactoryImpl() { + } + + public SaslClient createSaslClient(String[] mechs, + String authorizationId, + String protocol, + String serverName, + Map<String,?> props, + CallbackHandler cbh) throws SaslException { + + for (int i = 0; i < mechs.length; i++) { + if (mechs[i].equals(myMechs[GSS_KERB_V5]) + && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) { + return new GssKrb5Client( + authorizationId, + protocol, + serverName, + props, + cbh); + } + } + return null; + }; + + public SaslServer createSaslServer(String mech, + String protocol, + String serverName, + Map<String,?> props, + CallbackHandler cbh) throws SaslException { + if (mech.equals(myMechs[GSS_KERB_V5]) + && PolicyUtils.checkPolicy(mechPolicies[GSS_KERB_V5], props)) { + if (cbh == null) { + throw new SaslException( + "Callback handler with support for AuthorizeCallback required"); + } + return new GssKrb5Server( + protocol, + serverName, + props, + cbh); + } + return null; + }; + + public String[] getMechanismNames(Map<String,?> props) { + return PolicyUtils.filterMechs(myMechs, mechPolicies, props); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,164 @@ +/* + * 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 + * 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 com.sun.security.sasl.gsskerb; + +import java.util.Locale; +import java.util.Map; +import java.util.logging.Level; +import javax.security.sasl.*; +import com.sun.security.sasl.util.AbstractSaslImpl; +import org.ietf.jgss.*; +import com.sun.security.jgss.ExtendedGSSContext; +import com.sun.security.jgss.InquireType; + +abstract class GssKrb5Base extends AbstractSaslImpl { + + private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2"; + protected static Oid KRB5_OID; + protected static final byte[] EMPTY = new byte[0]; + + static { + try { + KRB5_OID = new Oid(KRB5_OID_STR); + } catch (GSSException ignore) {} + } + + protected GSSContext secCtx = null; + protected static final int JGSS_QOP = 0; // unrelated to SASL QOP mask + + protected GssKrb5Base(Map<String, ?> props, String className) + throws SaslException { + super(props, className); + } + + /** + * Retrieves this mechanism's name. + * + * @return The string "GSSAPI". + */ + public String getMechanismName() { + return "GSSAPI"; + } + + @Override + public Object getNegotiatedProperty(String propName) { + if (!completed) { + throw new IllegalStateException("Authentication incomplete"); + } + String xprefix = "com.sun.security.jgss.inquiretype."; + if (propName.startsWith(xprefix)) { + String type = propName.substring(xprefix.length()); + if (logger.isLoggable(Level.FINEST)) { + logger.logp(Level.FINE, "GssKrb5Base", + "getNegotiatedProperty", propName); + } + for (InquireType t: InquireType.values()) { + if (t.name().toLowerCase(Locale.US).equals(type)) { + try { + return ((ExtendedGSSContext)secCtx).inquireSecContext(t); + } catch (GSSException e) { + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.WARNING, "inquireSecContext error", e); + } + return null; + } + } + } + // No such InquireType. Although not likely to be defined + // as a property in a parent class, still try it. + } + return super.getNegotiatedProperty(propName); + } + + public byte[] unwrap(byte[] incoming, int start, int len) + throws SaslException { + if (!completed) { + throw new IllegalStateException("GSSAPI authentication not completed"); + } + + // integrity will be true if either privacy or integrity negotiated + if (!integrity) { + throw new IllegalStateException("No security layer negotiated"); + } + + try { + MessageProp msgProp = new MessageProp(JGSS_QOP, privacy); + byte[] answer = secCtx.unwrap(incoming, start, len, msgProp); + if (logger.isLoggable(Level.FINEST)) { + traceOutput(myClassName, "KRB501:Unwrap", "incoming: ", + incoming, start, len); + traceOutput(myClassName, "KRB502:Unwrap", "unwrapped: ", + answer, 0, answer.length); + } + return answer; + } catch (GSSException e) { + throw new SaslException("Problems unwrapping SASL buffer", e); + } + } + + public byte[] wrap(byte[] outgoing, int start, int len) throws SaslException { + if (!completed) { + throw new IllegalStateException("GSSAPI authentication not completed"); + } + + // integrity will be true if either privacy or integrity negotiated + if (!integrity) { + throw new IllegalStateException("No security layer negotiated"); + } + + // Generate GSS token + try { + MessageProp msgProp = new MessageProp(JGSS_QOP, privacy); + byte[] answer = secCtx.wrap(outgoing, start, len, msgProp); + if (logger.isLoggable(Level.FINEST)) { + traceOutput(myClassName, "KRB503:Wrap", "outgoing: ", + outgoing, start, len); + traceOutput(myClassName, "KRB504:Wrap", "wrapped: ", + answer, 0, answer.length); + } + return answer; + + } catch (GSSException e) { + throw new SaslException("Problem performing GSS wrap", e); + } + } + + public void dispose() throws SaslException { + if (secCtx != null) { + try { + secCtx.dispose(); + } catch (GSSException e) { + throw new SaslException("Problem disposing GSS context", e); + } + secCtx = null; + } + } + + protected void finalize() throws Throwable { + dispose(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,329 @@ +/* + * 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 + * 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 com.sun.security.sasl.gsskerb; + +import java.io.IOException; +import java.util.Map; +import java.util.logging.Level; +import javax.security.sasl.*; + +// JAAS +import javax.security.auth.callback.CallbackHandler; + +// JGSS +import org.ietf.jgss.*; + +/** + * Implements the GSSAPI SASL client mechanism for Kerberos V5. + * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>, + * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-04.txt">draft-ietf-cat-sasl-gssapi-04.txt</a>). + * It uses the Java Bindings for GSSAPI + * (<A HREF="http://www.ietf.org/rfc/rfc2853.txt">RFC 2853</A>) + * for getting GSSAPI/Kerberos V5 support. + * + * The client/server interactions are: + * C0: bind (GSSAPI, initial response) + * S0: sasl-bind-in-progress, challenge 1 (output of accept_sec_context or []) + * C1: bind (GSSAPI, response 1 (output of init_sec_context or [])) + * S1: sasl-bind-in-progress challenge 2 (security layer, server max recv size) + * C2: bind (GSSAPI, response 2 (security layer, client max recv size, authzid)) + * S2: bind success response + * + * Expects the client's credentials to be supplied from the + * javax.security.sasl.credentials property or from the thread's Subject. + * Otherwise the underlying KRB5 mech will attempt to acquire Kerberos creds + * by logging into Kerberos (via default TextCallbackHandler). + * These creds will be used for exchange with server. + * + * Required callbacks: none. + * + * Environment properties that affect behavior of implementation: + * + * javax.security.sasl.qop + * - quality of protection; list of auth, auth-int, auth-conf; default is "auth" + * javax.security.sasl.maxbuf + * - max receive buffer size; default is 65536 + * javax.security.sasl.sendmaxbuffer + * - max send buffer size; default is 65536; (min with server max recv size) + * + * javax.security.sasl.server.authentication + * - "true" means require mutual authentication; default is "false" + * + * javax.security.sasl.credentials + * - an {@link org.ietf.jgss.GSSCredential} used for delegated authentication. + * + * @author Rosanna Lee + */ + +final class GssKrb5Client extends GssKrb5Base implements SaslClient { + // ---------------- Constants ----------------- + private static final String MY_CLASS_NAME = GssKrb5Client.class.getName(); + + private boolean finalHandshake = false; + private boolean mutual = false; // default false + private byte[] authzID; + + /** + * Creates a SASL mechanism with client credentials that it needs + * to participate in GSS-API/Kerberos v5 authentication exchange + * with the server. + */ + GssKrb5Client(String authzID, String protocol, String serverName, + Map<String, ?> props, CallbackHandler cbh) throws SaslException { + + super(props, MY_CLASS_NAME); + + String service = protocol + "@" + serverName; + logger.log(Level.FINE, "KRB5CLNT01:Requesting service name: {0}", + service); + + try { + GSSManager mgr = GSSManager.getInstance(); + + // Create the name for the requested service entity for Krb5 mech + GSSName acceptorName = mgr.createName(service, + GSSName.NT_HOSTBASED_SERVICE, KRB5_OID); + + // Parse properties to check for supplied credentials + GSSCredential credentials = null; + if (props != null) { + Object prop = props.get(Sasl.CREDENTIALS); + if (prop != null && prop instanceof GSSCredential) { + credentials = (GSSCredential) prop; + logger.log(Level.FINE, + "KRB5CLNT01:Using the credentials supplied in " + + "javax.security.sasl.credentials"); + } + } + + // Create a context using credentials for Krb5 mech + secCtx = mgr.createContext(acceptorName, + KRB5_OID, /* mechanism */ + credentials, /* credentials */ + GSSContext.INDEFINITE_LIFETIME); + + // Request credential delegation when credentials have been supplied + if (credentials != null) { + secCtx.requestCredDeleg(true); + } + + // Parse properties to set desired context options + if (props != null) { + // Mutual authentication + String prop = (String)props.get(Sasl.SERVER_AUTH); + if (prop != null) { + mutual = "true".equalsIgnoreCase(prop); + } + } + secCtx.requestMutualAuth(mutual); + + // Always specify potential need for integrity and confidentiality + // Decision will be made during final handshake + secCtx.requestConf(true); + secCtx.requestInteg(true); + + } catch (GSSException e) { + throw new SaslException("Failure to initialize security context", e); + } + + if (authzID != null && authzID.length() > 0) { + try { + this.authzID = authzID.getBytes("UTF8"); + } catch (IOException e) { + throw new SaslException("Cannot encode authorization ID", e); + } + } + } + + public boolean hasInitialResponse() { + return true; + } + + /** + * Processes the challenge data. + * + * The server sends a challenge data using which the client must + * process using GSS_Init_sec_context. + * As per RFC 2222, when GSS_S_COMPLETE is returned, we do + * an extra handshake to determine the negotiated security protection + * and buffer sizes. + * + * @param challengeData A non-null byte array containing the + * challenge data from the server. + * @return A non-null byte array containing the response to be + * sent to the server. + */ + public byte[] evaluateChallenge(byte[] challengeData) throws SaslException { + if (completed) { + throw new IllegalStateException( + "GSSAPI authentication already complete"); + } + + if (finalHandshake) { + return doFinalHandshake(challengeData); + } else { + + // Security context not established yet; continue with init + + try { + byte[] gssOutToken = secCtx.initSecContext(challengeData, + 0, challengeData.length); + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "evaluteChallenge", + "KRB5CLNT02:Challenge: [raw]", challengeData); + traceOutput(MY_CLASS_NAME, "evaluateChallenge", + "KRB5CLNT03:Response: [after initSecCtx]", gssOutToken); + } + + if (secCtx.isEstablished()) { + finalHandshake = true; + if (gssOutToken == null) { + // RFC 2222 7.2.1: Client responds with no data + return EMPTY; + } + } + + return gssOutToken; + } catch (GSSException e) { + throw new SaslException("GSS initiate failed", e); + } + } + } + + private byte[] doFinalHandshake(byte[] challengeData) throws SaslException { + try { + // Security context already established. challengeData + // should contain security layers and server's maximum buffer size + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doFinalHandshake", + "KRB5CLNT04:Challenge [raw]:", challengeData); + } + + if (challengeData.length == 0) { + // Received S0, should return [] + return EMPTY; + } + + // Received S1 (security layer, server max recv size) + + byte[] gssOutToken = secCtx.unwrap(challengeData, 0, + challengeData.length, new MessageProp(0, false)); + + // First octet is a bit-mask specifying the protections + // supported by the server + if (logger.isLoggable(Level.FINE)) { + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doFinalHandshake", + "KRB5CLNT05:Challenge [unwrapped]:", gssOutToken); + } + logger.log(Level.FINE, "KRB5CLNT06:Server protections: {0}", + gssOutToken[0]); + } + + // Client selects preferred protection + // qop is ordered list of qop values + byte selectedQop = findPreferredMask(gssOutToken[0], qop); + if (selectedQop == 0) { + throw new SaslException( + "No common protection layer between client and server"); + } + + if ((selectedQop&PRIVACY_PROTECTION) != 0) { + privacy = true; + integrity = true; + } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) { + integrity = true; + } + + // 2nd-4th octets specifies maximum buffer size expected by + // server (in network byte order) + int srvMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3); + + // Determine the max send buffer size based on what the + // server is able to receive and our specified max + sendMaxBufSize = (sendMaxBufSize == 0) ? srvMaxBufSize : + Math.min(sendMaxBufSize, srvMaxBufSize); + + // Update context to limit size of returned buffer + rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy, + sendMaxBufSize); + + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, +"KRB5CLNT07:Client max recv size: {0}; server max recv size: {1}; rawSendSize: {2}", + new Object[] {recvMaxBufSize, + srvMaxBufSize, + rawSendSize}); + } + + // Construct negotiated security layers and client's max + // receive buffer size and authzID + int len = 4; + if (authzID != null) { + len += authzID.length; + } + + byte[] gssInToken = new byte[len]; + gssInToken[0] = selectedQop; + + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, + "KRB5CLNT08:Selected protection: {0}; privacy: {1}; integrity: {2}", + new Object[]{selectedQop, + Boolean.valueOf(privacy), + Boolean.valueOf(integrity)}); + } + + intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3); + if (authzID != null) { + // copy authorization id + System.arraycopy(authzID, 0, gssInToken, 4, authzID.length); + logger.log(Level.FINE, "KRB5CLNT09:Authzid: {0}", authzID); + } + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doFinalHandshake", + "KRB5CLNT10:Response [raw]", gssInToken); + } + + gssOutToken = secCtx.wrap(gssInToken, + 0, gssInToken.length, + new MessageProp(0 /* qop */, false /* privacy */)); + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doFinalHandshake", + "KRB5CLNT11:Response [after wrap]", gssOutToken); + } + + completed = true; // server authenticated + + return gssOutToken; + } catch (GSSException e) { + throw new SaslException("Final handshake failed", e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,365 @@ +/* + * 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 + * 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 com.sun.security.sasl.gsskerb; + +import javax.security.sasl.*; +import java.io.*; +import java.util.Map; +import java.util.logging.Level; + +// JAAS +import javax.security.auth.callback.*; + +// JGSS +import org.ietf.jgss.*; + +/** + * Implements the GSSAPI SASL server mechanism for Kerberos V5. + * (<A HREF="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</A>, + * <a HREF="http://www.ietf.org/internet-drafts/draft-ietf-cat-sasl-gssapi-00.txt">draft-ietf-cat-sasl-gssapi-00.txt</a>). + * + * Expects thread's Subject to contain server's Kerberos credentials + * - If not, underlying KRB5 mech will attempt to acquire Kerberos creds + * by logging into Kerberos (via default TextCallbackHandler). + * - These creds will be used for exchange with client. + * + * Required callbacks: + * - AuthorizeCallback + * handler must verify that authid/authzids are allowed and set + * authorized ID to be the canonicalized authzid (if applicable). + * + * Environment properties that affect behavior of implementation: + * + * javax.security.sasl.qop + * - quality of protection; list of auth, auth-int, auth-conf; default is "auth" + * javax.security.sasl.maxbuf + * - max receive buffer size; default is 65536 + * javax.security.sasl.sendmaxbuffer + * - max send buffer size; default is 65536; (min with client max recv size) + * + * @author Rosanna Lee + */ +final class GssKrb5Server extends GssKrb5Base implements SaslServer { + private static final String MY_CLASS_NAME = GssKrb5Server.class.getName(); + + private int handshakeStage = 0; + private String peer; + private String me; + private String authzid; + private CallbackHandler cbh; + + // When serverName is null, the server will be unbound. We need to save and + // check the protocol name after the context is established. This value + // will be null if serverName is not null. + private final String protocolSaved; + /** + * Creates a SASL mechanism with server credentials that it needs + * to participate in GSS-API/Kerberos v5 authentication exchange + * with the client. + */ + GssKrb5Server(String protocol, String serverName, + Map<String, ?> props, CallbackHandler cbh) throws SaslException { + + super(props, MY_CLASS_NAME); + + this.cbh = cbh; + + String service; + if (serverName == null) { + protocolSaved = protocol; + service = null; + } else { + protocolSaved = null; + service = protocol + "@" + serverName; + } + + logger.log(Level.FINE, "KRB5SRV01:Using service name: {0}", service); + + try { + GSSManager mgr = GSSManager.getInstance(); + + // Create the name for the requested service entity for Krb5 mech + GSSName serviceName = service == null ? null: + mgr.createName(service, GSSName.NT_HOSTBASED_SERVICE, KRB5_OID); + + GSSCredential cred = mgr.createCredential(serviceName, + GSSCredential.INDEFINITE_LIFETIME, + KRB5_OID, GSSCredential.ACCEPT_ONLY); + + // Create a context using the server's credentials + secCtx = mgr.createContext(cred); + + if ((allQop&INTEGRITY_ONLY_PROTECTION) != 0) { + // Might need integrity + secCtx.requestInteg(true); + } + + if ((allQop&PRIVACY_PROTECTION) != 0) { + // Might need privacy + secCtx.requestConf(true); + } + } catch (GSSException e) { + throw new SaslException("Failure to initialize security context", e); + } + logger.log(Level.FINE, "KRB5SRV02:Initialization complete"); + } + + + /** + * Processes the response data. + * + * The client sends response data to which the server must + * process using GSS_accept_sec_context. + * As per RFC 2222, the GSS authenication completes (GSS_S_COMPLETE) + * we do an extra hand shake to determine the negotiated security protection + * and buffer sizes. + * + * @param responseData A non-null but possible empty byte array containing the + * response data from the client. + * @return A non-null byte array containing the challenge to be + * sent to the client, or null when no more data is to be sent. + */ + public byte[] evaluateResponse(byte[] responseData) throws SaslException { + if (completed) { + throw new SaslException( + "SASL authentication already complete"); + } + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "evaluateResponse", + "KRB5SRV03:Response [raw]:", responseData); + } + + switch (handshakeStage) { + case 1: + return doHandshake1(responseData); + + case 2: + return doHandshake2(responseData); + + default: + // Security context not established yet; continue with accept + + try { + byte[] gssOutToken = secCtx.acceptSecContext(responseData, + 0, responseData.length); + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "evaluateResponse", + "KRB5SRV04:Challenge: [after acceptSecCtx]", gssOutToken); + } + + if (secCtx.isEstablished()) { + handshakeStage = 1; + + peer = secCtx.getSrcName().toString(); + me = secCtx.getTargName().toString(); + + logger.log(Level.FINE, + "KRB5SRV05:Peer name is : {0}, my name is : {1}", + new Object[]{peer, me}); + + // me might take the form of proto@host or proto/host + if (protocolSaved != null && + !protocolSaved.equalsIgnoreCase(me.split("[/@]")[0])) { + throw new SaslException( + "GSS context targ name protocol error: " + me); + } + + if (gssOutToken == null) { + return doHandshake1(EMPTY); + } + } + + return gssOutToken; + } catch (GSSException e) { + throw new SaslException("GSS initiate failed", e); + } + } + } + + private byte[] doHandshake1(byte[] responseData) throws SaslException { + try { + // Security context already established. responseData + // should contain no data + if (responseData != null && responseData.length > 0) { + throw new SaslException( + "Handshake expecting no response data from server"); + } + + // Construct 4 octets of data: + // First octet contains bitmask specifying protections supported + // 2nd-4th octets contains max receive buffer of server + + byte[] gssInToken = new byte[4]; + gssInToken[0] = allQop; + intToNetworkByteOrder(recvMaxBufSize, gssInToken, 1, 3); + + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, + "KRB5SRV06:Supported protections: {0}; recv max buf size: {1}", + new Object[]{allQop, + recvMaxBufSize}); + } + + handshakeStage = 2; // progress to next stage + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doHandshake1", + "KRB5SRV07:Challenge [raw]", gssInToken); + } + + byte[] gssOutToken = secCtx.wrap(gssInToken, 0, gssInToken.length, + new MessageProp(0 /* gop */, false /* privacy */)); + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doHandshake1", + "KRB5SRV08:Challenge [after wrap]", gssOutToken); + } + return gssOutToken; + + } catch (GSSException e) { + throw new SaslException("Problem wrapping handshake1", e); + } + } + + private byte[] doHandshake2(byte[] responseData) throws SaslException { + try { + // Expecting 4 octets from client selected protection + // and client's receive buffer size + byte[] gssOutToken = secCtx.unwrap(responseData, 0, + responseData.length, new MessageProp(0, false)); + + if (logger.isLoggable(Level.FINER)) { + traceOutput(MY_CLASS_NAME, "doHandshake2", + "KRB5SRV09:Response [after unwrap]", gssOutToken); + } + + // First octet is a bit-mask specifying the selected protection + byte selectedQop = gssOutToken[0]; + if ((selectedQop&allQop) == 0) { + throw new SaslException("Client selected unsupported protection: " + + selectedQop); + } + if ((selectedQop&PRIVACY_PROTECTION) != 0) { + privacy = true; + integrity = true; + } else if ((selectedQop&INTEGRITY_ONLY_PROTECTION) != 0) { + integrity = true; + } + + // 2nd-4th octets specifies maximum buffer size expected by + // client (in network byte order). This is the server's send + // buffer maximum. + int clntMaxBufSize = networkByteOrderToInt(gssOutToken, 1, 3); + + // Determine the max send buffer size based on what the + // client is able to receive and our specified max + sendMaxBufSize = (sendMaxBufSize == 0) ? clntMaxBufSize : + Math.min(sendMaxBufSize, clntMaxBufSize); + + // Update context to limit size of returned buffer + rawSendSize = secCtx.getWrapSizeLimit(JGSS_QOP, privacy, + sendMaxBufSize); + + if (logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE, + "KRB5SRV10:Selected protection: {0}; privacy: {1}; integrity: {2}", + new Object[]{selectedQop, + Boolean.valueOf(privacy), + Boolean.valueOf(integrity)}); + logger.log(Level.FINE, +"KRB5SRV11:Client max recv size: {0}; server max send size: {1}; rawSendSize: {2}", + new Object[] {clntMaxBufSize, + sendMaxBufSize, + rawSendSize}); + } + + // Get authorization identity, if any + if (gssOutToken.length > 4) { + try { + authzid = new String(gssOutToken, 4, + gssOutToken.length - 4, "UTF-8"); + } catch (UnsupportedEncodingException uee) { + throw new SaslException ("Cannot decode authzid", uee); + } + } else { + authzid = peer; + } + logger.log(Level.FINE, "KRB5SRV12:Authzid: {0}", authzid); + + AuthorizeCallback acb = new AuthorizeCallback(peer, authzid); + + // In Kerberos, realm is embedded in peer name + cbh.handle(new Callback[] {acb}); + if (acb.isAuthorized()) { + authzid = acb.getAuthorizedID(); + completed = true; + } else { + // Authorization failed + throw new SaslException(peer + + " is not authorized to connect as " + authzid); + } + + return null; + } catch (GSSException e) { + throw new SaslException("Final handshake step failed", e); + } catch (IOException e) { + throw new SaslException("Problem with callback handler", e); + } catch (UnsupportedCallbackException e) { + throw new SaslException("Problem with callback handler", e); + } + } + + public String getAuthorizationID() { + if (completed) { + return authzid; + } else { + throw new IllegalStateException("Authentication incomplete"); + } + } + + public Object getNegotiatedProperty(String propName) { + if (!completed) { + throw new IllegalStateException("Authentication incomplete"); + } + + Object result; + switch (propName) { + case Sasl.BOUND_SERVER_NAME: + try { + // me might take the form of proto@host or proto/host + result = me.split("[/@]")[1]; + } catch (Exception e) { + result = null; + } + break; + default: + result = super.getNegotiatedProperty(propName); + } + return result; + } +}
--- a/test/ProblemList.txt Wed Sep 17 22:56:07 2014 -0700 +++ b/test/ProblemList.txt Thu Sep 18 13:27:48 2014 -0700 @@ -139,9 +139,6 @@ com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java aix-all javax/management/MBeanServer/OldMBeanServerTest.java aix-all -# 8050115 -javax/management/monitor/GaugeMonitorDeadlockTest.java generic-all - ############################################################################ # jdk_math
--- a/test/TEST.ROOT Wed Sep 17 22:56:07 2014 -0700 +++ b/test/TEST.ROOT Thu Sep 18 13:27:48 2014 -0700 @@ -8,7 +8,7 @@ othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces # Tests that cannot run concurrently -exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi +exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream # Group definitions groups=TEST.groups [closed/TEST.groups]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Graphics2D/WhiteTextColorTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.image.*; +import javax.swing.*; + +/** + * @test + * @bug 8056009 + * @summary tests whether Graphics.setColor-calls with Color.white are ignored directly + * after pipeline initialization for a certain set of operations. + * @author ceisserer + */ +public class WhiteTextColorTest extends Frame { + public static volatile boolean success = false; + + public WhiteTextColorTest() { + Image dstImg = getGraphicsConfiguration() + .createCompatibleVolatileImage(30, 20); + Graphics g = dstImg.getGraphics(); + + g.setColor(Color.BLACK); + g.fillRect(0, 0, dstImg.getWidth(null), dstImg.getHeight(null)); + g.setColor(Color.WHITE); + g.drawString("Test", 0, 15); + + BufferedImage readBackImg = new BufferedImage(dstImg.getWidth(null), + dstImg.getHeight(null), BufferedImage.TYPE_INT_RGB); + readBackImg.getGraphics().drawImage(dstImg, 0, 0, null); + + for (int x = 0; x < readBackImg.getWidth(); x++) { + for (int y = 0; y < readBackImg.getHeight(); y++) { + int pixel = readBackImg.getRGB(x, y); + + // In case a single white pixel is found, the + // setColor(Color.WHITE) + // call before was not ignored and the bug is not present + if (pixel == 0xFFFFFFFF) { + return; + } + } + } + + throw new RuntimeException("Test Failed"); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new WhiteTextColorTest(); + } + }); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Window/setLocRelativeTo/SetLocationRelativeToTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.util.ArrayList; +import javax.swing.*; + +/* +@test +@summary Toplevel should be correctly positioned as relative to a component: + so that their centers coincide + or, if the component is hidden, centered on the screen. +@bug 8036915 +@library ../../../../lib/testlibrary +@build ExtendedRobot +@run main/timeout=1200 SetLocationRelativeToTest +*/ + +public class SetLocationRelativeToTest { + private static int delay = 500; + private static boolean testEverything = false;// NB: change this to true to test everything + java.util.List<Window> awtToplevels = new ArrayList<Window>(); + java.util.List<Window> swingToplevels = new ArrayList<Window>(); + java.util.List<Window> allToplevels = new ArrayList<Window>(); + java.util.List<Component> awtComponents = new ArrayList<Component>(); + java.util.List<Component> swingComponents = new ArrayList<Component>(); + java.util.List<Component> allComponents = new ArrayList<Component>(); + Label placeholder = new Label(); + JLabel jplaceholder = new JLabel(); + JFrame jcontainer; + public SetLocationRelativeToTest() { + Frame frame = new Frame("Frame"); + frame.setSize(200,100); + Frame uframe = new Frame("U.Frame"); + uframe.setUndecorated(true); + uframe.setSize(200,100); + Window window = new Window(frame); + window.setSize(200,100); + Dialog dialog = new Dialog(frame, "Dialog"); + dialog.setSize(200,100); + awtToplevels.add(frame); + awtToplevels.add(uframe); + awtToplevels.add(window); + awtToplevels.add(dialog); + + awtComponents.add(new TextArea("Am a TextArea")); + awtComponents.add(new TextField("Am a TextField")); + awtComponents.add(new Button("Press")); + awtComponents.add(new Label("Label")); + Choice aChoice = new Choice(); + aChoice.add("One"); + aChoice.add("Two"); + awtComponents.add(aChoice); + awtComponents.add(new Canvas()); + awtComponents.add(new List(4)); + awtComponents.add(new Checkbox("Me CheckBox")); + awtComponents.add(new Scrollbar()); + + swingComponents.add(new JTextArea("Am a JTextArea")); + swingComponents.add(new JTextField("Am a JTextField")); + swingComponents.add(new JButton("Press")); + swingComponents.add(new JLabel("JLabel")); + JComboBox jcombo = new JComboBox(); + swingComponents.add(jcombo); + swingComponents.add(new JPanel()); + swingComponents.add(new JList()); + swingComponents.add(new JCheckBox("Me JCheckBox")); + swingComponents.add(new JScrollBar()); + } + + public static void main(String args[]) { + SetLocationRelativeToTest test = new SetLocationRelativeToTest(); + test.doAWTTest(true); + test.doAWTTest(false); + try { + test.doSwingTest(true); + test.doSwingTest(false); + }catch(InterruptedException ie) { + ie.printStackTrace(); + }catch(java.lang.reflect.InvocationTargetException ite) { + ite.printStackTrace(); + throw new RuntimeException("InvocationTarget?"); + } + return; + } + + // In regular testing, we select just few components to test + // randomly. If full testing required, select many ("all"). + void selectObjectsToTest(boolean doSwing) { + allToplevels.clear(); + allComponents.clear(); + if(testEverything) { + allToplevels.addAll(0, awtToplevels); + allComponents.addAll(0, awtComponents); + if(doSwing) { + allToplevels.addAll(allToplevels.size(), swingToplevels); + allComponents.addAll(allComponents.size(), swingComponents); + } + }else{ + //select a random of each + int i = (int)(java.lang.Math.random()*awtToplevels.size()); + allToplevels.add(awtToplevels.get(i)); + i = (int)(java.lang.Math.random()*awtComponents.size()); + allComponents.add(awtComponents.get(i)); + if(doSwing) { + i = (int)(java.lang.Math.random()*swingToplevels.size()); + allToplevels.add(swingToplevels.get(i)); + i = (int)(java.lang.Math.random()*swingComponents.size()); + allComponents.add(swingComponents.get(i)); + } + } + } + + // create Frame, add an AWT component to it, + // hide it (or not) and position a new toplevel + // relativeTo + void doAWTTest(boolean isHidden) { + boolean res; + ExtendedRobot robot; + try { + robot = new ExtendedRobot(); + }catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException("Failed: "+ex.getMessage()); + } + Frame container = new Frame("Frame"); + container.setBounds(100,100,300,300); + container.setLayout(new GridLayout(3,1)); + container.add(placeholder); + container.setVisible(true); + selectObjectsToTest(false); + for(Component c: allComponents) { + placeholder.setText((isHidden ? "Hidden: " : "Below is ")+ c.getClass().getName()); + c.setVisible(true); + container.add(c); + container.doLayout(); + if(isHidden) { + c.setVisible(false); + } + robot.waitForIdle(delay); + for(Window w: allToplevels) { + w.setLocationRelativeTo(c); + w.setVisible(true); + robot.waitForIdle(delay); + res = compareLocations(w, c, robot); + System.out.println(c.getClass().getName()+" \t: "+w.getClass().getName()+ + ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+ + (res ? "" : "Failed")); + if(!res) { + throw new RuntimeException("Test failed."); + } + w.dispose(); + } + container.remove(c); + robot.waitForIdle(delay); + } + container.dispose(); + } + + // Create JFrame, add an AWT or Swing component to it, + // hide it (or not) and position a new toplevel + // relativeTo + void doSwingTest(boolean isHidden) throws InterruptedException, + java.lang.reflect.InvocationTargetException { + boolean res; + ExtendedRobot robot; + try { + robot = new ExtendedRobot(); + }catch(Exception ex) { + ex.printStackTrace(); + throw new RuntimeException("Failed: "+ex.getMessage()); + } + + EventQueue.invokeAndWait( () -> { + JFrame jframe = new JFrame("jframe"); + jframe.setSize(200,100); + swingToplevels.add(jframe); + JFrame ujframe = new JFrame("ujframe"); + ujframe.setSize(200,100); + ujframe.setUndecorated(true); + swingToplevels.add(ujframe); + JWindow jwin = new JWindow(); + jwin.setSize(200,100); + swingToplevels.add(jwin); + JDialog jdia = new JDialog((Frame)null, "JDialog"); + jdia.setSize(200,100); + swingToplevels.add(jdia); + jcontainer = new JFrame("JFrame"); + jcontainer.setBounds(100,100,300,300); + jcontainer.setLayout(new GridLayout(3,1)); + jcontainer.add(jplaceholder); + jcontainer.setVisible(true); + selectObjectsToTest(true); + }); + robot.waitForIdle(delay); + + for(Component c: allComponents) { + EventQueue.invokeAndWait( () -> { + jplaceholder.setText((isHidden ? "Hidden: " : "Below is: ")+ c.getClass().getName()); + c.setVisible(true); + jcontainer.add(c); + jcontainer.doLayout(); + if(isHidden) { + c.setVisible(false); + } + }); + robot.waitForIdle(delay); + for(Window w: allToplevels) { + EventQueue.invokeAndWait( () -> { + w.setLocationRelativeTo(c); + w.setVisible(true); + }); + robot.waitForIdle(delay); + res = compareLocations(w, c, robot); + System.out.println(c.getClass().getName()+" \t: "+w.getClass().getName()+ + ((w instanceof Frame) && (((Frame)w).isUndecorated()) ? " undec\t\t:" : "\t\t:")+" "+ + (res ? "" : "Failed")); + EventQueue.invokeAndWait( () -> { + w.dispose(); + }); + robot.waitForIdle(); + if(!res) { + throw new RuntimeException("Test failed."); + } + } + EventQueue.invokeAndWait( () -> { + jcontainer.remove(c); + }); + robot.waitForIdle(delay); + } + EventQueue.invokeAndWait( () -> { + jcontainer.dispose(); + }); + } + + // Check, finally, if w either is concentric with c + // or sits in the center of the screen (if c is hidden) + boolean compareLocations(final Window w, final Component c, ExtendedRobot robot) { + final Point pc = new Point(); + final Point pw = new Point(); + try { + EventQueue.invokeAndWait( () -> { + pw.setLocation(w.getLocationOnScreen()); + pw.translate(w.getWidth()/2, w.getHeight()/2); + if(!c.isVisible()) { + Rectangle screenRect = w.getGraphicsConfiguration().getBounds(); + pc.setLocation(screenRect.x+screenRect.width/2, + screenRect.y+screenRect.height/2); + }else{ + pc.setLocation(c.getLocationOnScreen()); + pc.translate(c.getWidth()/2, c.getHeight()/2); + } + }); + } catch(InterruptedException ie) { + throw new RuntimeException("Interrupted"); + } catch(java.lang.reflect.InvocationTargetException ite) { + ite.printStackTrace(); + throw new RuntimeException("InvocationTarget?"); + } + robot.waitForIdle(delay); + // Compare with 1 tolerance to forgive possible rounding errors + if(pc.x - pw.x > 1 || + pc.x - pw.x < -1 || + pc.y - pw.y > 1 || + pc.y - pw.y < -1 ) { + System.out.println("Center of "+(c.isVisible() ? "Component:" : "screen:")+pc); + System.out.println("Center of Window:"+pw); + System.out.println("Centers of "+w+" and "+c+" do not coincide"); + return false; + } + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/font/GlyphVector/GlyphVectorOutline.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014 Google Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.image.BufferedImage; +import java.io.File; +import java.text.AttributedString; + +import javax.imageio.ImageIO; + +/** + * Manual test for: + * JDK-8057986: freetype code to get glyph outline does not handle initial control point properly + * + * Manual repro recipe: + * (cd test/java/awt/font/GlyphVector/ && javac GlyphVectorOutline.java && wget -q -O/tmp/msgothic.ttc https://browserlinux-jp.googlecode.com/files/msgothic.ttc && java GlyphVectorOutline /tmp/msgothic.ttc /tmp/katakana.png) + * + * Then examine the two rendered Japanese characters in the png file. + * + * Renders text to a PNG by + * 1. using the native Graphics2D#drawGlyphVector implementation + * 2. filling in the result of GlyphVector#getOutline + * + * Should be the same but is different for some CJK characters + * (e.g. Katakana character \u30AF). + * + * @author ikopylov@google.com (Igor Kopylov) + */ +public class GlyphVectorOutline { + public static void main(String[] args) throws Exception { + if (args.length != 2) { + throw new Error("Usage: java GlyphVectorOutline fontfile outputfile"); + } + writeImage(new File(args[0]), + new File(args[1]), + "\u30AF"); + } + + public static void writeImage(File fontFile, File outputFile, String value) throws Exception { + BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + g.setColor(Color.WHITE); + g.fillRect(0, 0, image.getWidth(), image.getHeight()); + g.setColor(Color.BLACK); + + Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile); + font = font.deriveFont(Font.PLAIN, 72f); + FontRenderContext frc = new FontRenderContext(null, false, false); + GlyphVector gv = font.createGlyphVector(frc, value); + g.drawGlyphVector(gv, 10, 80); + g.fill(gv.getOutline(10, 180)); + ImageIO.write(image, "png", outputFile); + } + + private static void drawString(Graphics2D g, Font font, String value, float x, float y) { + AttributedString str = new AttributedString(value); + str.addAttribute(TextAttribute.FOREGROUND, Color.BLACK); + str.addAttribute(TextAttribute.FONT, font); + FontRenderContext frc = new FontRenderContext(null, true, true); + TextLayout layout = new LineBreakMeasurer(str.getIterator(), frc).nextLayout(Integer.MAX_VALUE); + layout.draw(g, x, y); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.InvocationTargetException; + +/** + * Abstract class for lambda forms caching testing. + * + * @author kshefov + */ +public abstract class LFCachingTestCase extends LambdaFormTestCase { + + /** + * Constructor for lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + protected LFCachingTestCase(TestMethods testMethod) { + super(testMethod); + } + + /** + * Checks that the lambda forms of the two adapter method handles adapter1 + * and adapter2 are the same. + * + * @param adapter1 First method handle. + * @param adapter2 Second method handle. + */ + public void checkLFCaching(MethodHandle adapter1, MethodHandle adapter2) { + try { + + if (!adapter1.type().equals(adapter2.type())) { + throw new Error("TESTBUG: Types of the two method handles are not the same"); + } + + Object lambdaForm0 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter1); + Object lambdaForm1 = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter2); + + if (lambdaForm0 == null || lambdaForm1 == null) { + throw new Error("Unexpected error: One or both lambda forms of the method handles are null"); + } + + if (lambdaForm0 != lambdaForm1) { + System.err.println("Lambda form 0 toString is:"); + System.err.println(lambdaForm0); + System.err.println("Lambda form 1 toString is:"); + System.err.println(lambdaForm1); + throw new AssertionError("Error: Lambda forms of the two method handles" + + " are not the same. LF cahing does not work"); + } + } catch (IllegalAccessException | IllegalArgumentException | + SecurityException | InvocationTargetException ex) { + throw new Error("Unexpected exception: ", ex); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test LFGarbageCollectedTest + * @bug 8046703 + * @summary Test verifies that lambda forms are garbage collected + * @author kshefov + * @ignore 8057020 + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFGarbageCollectedTest + * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LFGarbageCollectedTest + */ + +import java.lang.invoke.MethodHandle; +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Map; + +/** + * Lambda forms garbage collection test class. + */ +public final class LFGarbageCollectedTest extends LambdaFormTestCase { + + /** + * Constructor for a lambda forms garbage collection test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFGarbageCollectedTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + try { + Map<String, Object> data = getTestMethod().getTestCaseData(); + MethodHandle adapter; + try { + adapter = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE); + } catch (NoSuchMethodException ex) { + throw new Error("Unexpected exception: ", ex); + } + Object lambdaForm = LambdaFormTestCase.INTERNAL_FORM.invoke(adapter); + if (lambdaForm == null) { + throw new Error("Unexpected error: Lambda form of the method handle is null"); + } + ReferenceQueue rq = new ReferenceQueue(); + PhantomReference ph = new PhantomReference(lambdaForm, rq); + lambdaForm = null; + data = null; + adapter = null; + for (int i = 0; i < 1000 && !ph.isEnqueued(); i++) { + System.gc(); + } + if (!ph.isEnqueued()) { + throw new AssertionError("Error: Lambda form is not garbage collected"); + } + } catch (IllegalAccessException | IllegalArgumentException | + InvocationTargetException ex) { + throw new Error("Unexpected exception: ", ex); + } + } + + /** + * Main routine for lambda forms garbage collection test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + // The "identity" and "constant" methods should be removed from this test, + // because their lambda forms are stored in a static filed and are not GC'ed. + // There can be only 5 such LFs for each method, so no memory leak happens. + EnumSet<TestMethods> testMethods = EnumSet.complementOf(EnumSet.of(TestMethods.IDENTITY, TestMethods.CONSTANT)); + LambdaFormTestCase.runTests(LFGarbageCollectedTest::new, testMethods); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test LFMultiThreadCachingTest + * @bug 8046703 + * @summary Test verifies that lambda forms are cached when run with multiple threads + * @author kshefov + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFCachingTestCase + * @build LFMultiThreadCachingTest + * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest + */ + +import java.lang.invoke.MethodHandle; +import java.util.EnumSet; +import java.util.Map; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +/** + * Multiple threaded lambda forms caching test class. + */ +public final class LFMultiThreadCachingTest extends LFCachingTestCase { + private static final TestMethods.Kind[] KINDS; + static { + EnumSet<TestMethods.Kind> set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT)); + KINDS = set.toArray(new TestMethods.Kind[set.size()]); + if (KINDS.length < 2) { + throw new Error("TESTBUG: KINDS.length[" + KINDS.length + "] should be at least 2"); + } + } + private static final int CORES = Math.max(KINDS.length, Runtime.getRuntime().availableProcessors()); + + /** + * Constructor a for multiple threaded lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFMultiThreadCachingTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + Map<String, Object> data = getTestMethod().getTestCaseData(); + ConcurrentLinkedQueue<MethodHandle> adapters = new ConcurrentLinkedQueue<>(); + CyclicBarrier begin = new CyclicBarrier(CORES); + CountDownLatch end = new CountDownLatch(CORES); + for (int i = 0; i < CORES; ++i) { + TestMethods.Kind kind = KINDS[i % KINDS.length]; + new Thread(() -> { + try { + begin.await(); + adapters.add(getTestMethod().getTestCaseMH(data, kind)); + } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) { + throw new Error("Unexpected exception: ", ex); + } finally { + end.countDown(); + } + }).start(); + } + try { + end.await(); + } catch (InterruptedException ex) { + throw new Error("Unexpected exception: ", ex); + } + if (adapters.size() < CORES) { + throw new Error("adapters size[" + adapters.size() + "] is less than " + CORES); + } + MethodHandle prev = adapters.poll(); + for (MethodHandle current : adapters) { + checkLFCaching(prev, current); + prev = current; + } + } + + /** + * Main routine for multiple threaded lambda forms caching test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + LambdaFormTestCase.runTests(LFMultiThreadCachingTest::new, EnumSet.allOf(TestMethods.class)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test LFSingleThreadCachingTest + * @bug 8046703 + * @summary Test verifies that lambda forms are cached when run with single thread + * @author kshefov + * @library /lib/testlibrary/jsr292 /lib/testlibrary + * @build TestMethods + * @build LambdaFormTestCase + * @build LFCachingTestCase + * @build LFSingleThreadCachingTest + * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest + */ + +import java.lang.invoke.MethodHandle; +import java.util.EnumSet; +import java.util.Map; + +/** + * Single threaded lambda forms caching test class. + */ +public final class LFSingleThreadCachingTest extends LFCachingTestCase { + + /** + * Constructor for a single threaded lambda forms caching test case. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class that + * returns a {@code j.l.i.MethodHandle} instance. + */ + public LFSingleThreadCachingTest(TestMethods testMethod) { + super(testMethod); + } + + @Override + public void doTest() { + MethodHandle adapter1; + MethodHandle adapter2; + Map<String, Object> data = getTestMethod().getTestCaseData(); + try { + adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE); + adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new Error("Unexpected exception: ", ex); + } + checkLFCaching(adapter1, adapter2); + } + + /** + * Main routine for single threaded lambda forms caching test. + * + * @param args Accepts no arguments. + */ + public static void main(String[] args) { + LambdaFormTestCase.runTests(LFSingleThreadCachingTest::new, EnumSet.allOf(TestMethods.class)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.testlibrary.jsr292.Helper; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.function.Function; + +/** + * Lambda forms caching test case class. Contains all necessary test routines to + * test lambda forms caching in method handles returned by methods of + * MethodHandles class. + * + * @author kshefov + */ +public abstract class LambdaFormTestCase { + + private final static String METHOD_HANDLE_CLASS_NAME = "java.lang.invoke.MethodHandle"; + private final static String INTERNAL_FORM_METHOD_NAME = "internalForm"; + + /** + * Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is + * used to get a lambda form from a method handle. + */ + protected final static Method INTERNAL_FORM; + + static { + try { + Class mhClass = Class.forName(METHOD_HANDLE_CLASS_NAME); + INTERNAL_FORM = mhClass.getDeclaredMethod(INTERNAL_FORM_METHOD_NAME); + INTERNAL_FORM.setAccessible(true); + } catch (Exception ex) { + throw new Error("Unexpected exception: ", ex); + } + } + + private final TestMethods testMethod; + + /** + * Test case constructor. Generates test cases with random method types for + * given methods form {@code j.l.i.MethodHandles} class. + * + * @param testMethod A method from {@code j.l.i.MethodHandles} class which + * returns a {@code j.l.i.MethodHandle}. + */ + protected LambdaFormTestCase(TestMethods testMethod) { + this.testMethod = testMethod; + } + + public TestMethods getTestMethod() { + return testMethod; + } + + /** + * Routine that executes a test case. + */ + public abstract void doTest(); + + /** + * Runs a number of test cases defined by the size of testCases list. + * + * @param ctor constructor of LambdaFormCachingTest or its child classes + * object. + * @param testMethods list of test methods + */ + public static void runTests(Function<TestMethods, LambdaFormTestCase> ctor, Collection<TestMethods> testMethods) { + boolean passed = true; + int testCounter = 0; + int failCounter = 0; + long iterations = Math.max(1, Helper.TEST_LIMIT / testMethods.size()); + for (long i = 0; i < iterations; i++) { + System.err.println(String.format("Iteration %d:", i)); + for (TestMethods testMethod : testMethods) { + LambdaFormTestCase testCase = ctor.apply(testMethod); + try { + System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n", + testCase.getTestMethod().name); + testCase.doTest(); + System.err.println("PASSED"); + } catch (Throwable t) { + t.printStackTrace(); + System.err.println("FAILED"); + passed = false; + failCounter++; + } + testCounter++; + } + } + if (!passed) { + throw new Error(String.format("%d of %d test cases FAILED! %n" + + "Rerun the test with the same \"-Dseed=\" option as in the log file!", + failCounter, testCounter)); + } else { + System.err.println(String.format("All %d test cases PASSED!", testCounter)); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/invoke/LFCaching/TestMethods.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,698 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.testlibrary.jsr292.Helper; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Enumeration containing information about methods from + * {@code j.l.i.MethodHandles} class that are used for testing lambda forms + * caching. + * + * @author kshefov + */ +public enum TestMethods { + + FOLD_ARGUMENTS("foldArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + Class<?> combinerReturnType; + if (realArity == 0) { + combinerReturnType = void.class; + } else { + combinerReturnType = Helper.RNG.nextBoolean() ? void.class : mtTarget.parameterType(0); + } + data.put("combinerReturnType", combinerReturnType); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> combinerReturnType = (Class) data.get("combinerReturnType"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + Class<?> rType = mtTarget.returnType(); + int combListStart = (combinerReturnType == void.class) ? 0 : 1; + if (modifierMHArgNum < combListStart) { + modifierMHArgNum = combListStart; + } + MethodHandle combiner = TestMethods.methodHandleGenerator(combinerReturnType, + mtTarget.parameterList().subList(combListStart, + modifierMHArgNum), kind); + return MethodHandles.foldArguments(target, combiner); + } + }, + DROP_ARGUMENTS("dropArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int dropArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("dropArgsPos", dropArgsPos); + MethodType mtDropArgs = TestMethods.randomMethodTypeGenerator( + Helper.RNG.nextInt(Helper.MAX_ARITY - realArity)); + data.put("mtDropArgs", mtDropArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtDropArgs = (MethodType) data.get("mtDropArgs"); + int dropArgsPos = (int) data.get("dropArgsPos"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + int mtTgtSlotsCount = TestMethods.argSlotsCount(mtTarget); + int mtDASlotsCount = TestMethods.argSlotsCount(mtDropArgs); + List<Class<?>> fakeParList; + if (mtTgtSlotsCount + mtDASlotsCount > Helper.MAX_ARITY - 1) { + fakeParList = TestMethods.reduceArgListToSlotsCount(mtDropArgs.parameterList(), + Helper.MAX_ARITY - mtTgtSlotsCount - 1); + } else { + fakeParList = mtDropArgs.parameterList(); + } + return MethodHandles.dropArguments(target, dropArgsPos, fakeParList); + } + }, + EXPLICIT_CAST_ARGUMENTS("explicitCastArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + MethodType mtExcplCastArgs = TestMethods.randomMethodTypeGenerator(realArity); + if (mtTarget.returnType() == void.class) { + mtExcplCastArgs = MethodType.methodType(void.class, + mtExcplCastArgs.parameterArray()); + } + if (mtExcplCastArgs.returnType() == void.class) { + mtExcplCastArgs = MethodType.methodType(mtTarget.returnType(), + mtExcplCastArgs.parameterArray()); + } + data.put("mtExcplCastArgs", mtExcplCastArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtExcplCastArgs = (MethodType) data.get("mtExcplCastArgs"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + return MethodHandles.explicitCastArguments(target, mtExcplCastArgs); + } + }, + FILTER_ARGUMENTS("filterArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int filterArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("filterArgsPos", filterArgsPos); + int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos); + data.put("filtersArgsArrayLength", filtersArgsArrayLength); + MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength); + data.put("mtFilter", mtFilter); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtFilter = (MethodType) data.get("mtFilter"); + int filterArgsPos = (int) data.get("filterArgsPos"); + int filtersArgsArrayLength = (int) data.get("filtersArgsArrayLength"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + MethodHandle[] filters = new MethodHandle[filtersArgsArrayLength]; + for (int i = 0; i < filtersArgsArrayLength; i++) { + filters[i] = TestMethods.filterGenerator(mtFilter.parameterType(i), + mtTarget.parameterType(filterArgsPos + i), kind); + } + return MethodHandles.filterArguments(target, filterArgsPos, filters); + } + }, + FILTER_RETURN_VALUE("filterReturnValue") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int filterArgsPos = Helper.RNG.nextInt(realArity + 1); + int filtersArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - filterArgsPos); + MethodType mtFilter = TestMethods.randomMethodTypeGenerator(filtersArgsArrayLength); + data.put("mtFilter", mtFilter); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtFilter = (MethodType) data.get("mtFilter"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + MethodHandle filter = TestMethods.filterGenerator(mtTarget.returnType(), + mtFilter.returnType(), kind); + return MethodHandles.filterReturnValue(target, filter); + } + }, + INSERT_ARGUMENTS("insertArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int insertArgsPos = Helper.RNG.nextInt(realArity + 1); + data.put("insertArgsPos", insertArgsPos); + int insertArgsArrayLength = Helper.RNG.nextInt(realArity + 1 - insertArgsPos); + MethodType mtInsertArgs = MethodType.methodType(void.class, mtTarget.parameterList() + .subList(insertArgsPos, insertArgsPos + insertArgsArrayLength)); + data.put("mtInsertArgs", mtInsertArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtInsertArgs = (MethodType) data.get("mtInsertArgs"); + int insertArgsPos = (int) data.get("insertArgsPos"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + Object[] insertList = Helper.randomArgs(mtInsertArgs.parameterList()); + return MethodHandles.insertArguments(target, insertArgsPos, insertList); + } + }, + PERMUTE_ARGUMENTS("permuteArguments") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY / 2); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int[] permuteArgsReorderArray = new int[realArity]; + int mtParmuteArgsNum = Helper.RNG.nextInt(Helper.MAX_ARITY); + mtParmuteArgsNum = mtParmuteArgsNum == 0 ? 1 : mtParmuteArgsNum; + MethodType mtPermuteArgs = TestMethods.randomMethodTypeGenerator(mtParmuteArgsNum); + mtTarget = mtTarget.changeReturnType(mtPermuteArgs.returnType()); + for (int i = 0; i < realArity; i++) { + int mtPermuteArgsParNum = Helper.RNG.nextInt(mtPermuteArgs.parameterCount()); + permuteArgsReorderArray[i] = mtPermuteArgsParNum; + mtTarget = mtTarget.changeParameterType( + i, mtPermuteArgs.parameterType(mtPermuteArgsParNum)); + } + data.put("mtTarget", mtTarget); + data.put("permuteArgsReorderArray", permuteArgsReorderArray); + data.put("mtPermuteArgs", mtPermuteArgs); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + MethodType mtPermuteArgs = (MethodType) data.get("mtPermuteArgs"); + int[] permuteArgsReorderArray = (int[]) data.get("permuteArgsReorderArray"); + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), kind); + return MethodHandles.permuteArguments(target, mtPermuteArgs, permuteArgsReorderArray); + } + }, + THROW_EXCEPTION("throwException") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + return MethodHandles.throwException(rType, Exception.class + ); + } + }, + GUARD_WITH_TEST("guardWithTest") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + TestMethods.Kind targetKind; + TestMethods.Kind fallbackKind; + if (kind.equals(TestMethods.Kind.ONE)) { + targetKind = TestMethods.Kind.ONE; + fallbackKind = TestMethods.Kind.TWO; + } else { + targetKind = TestMethods.Kind.TWO; + fallbackKind = TestMethods.Kind.ONE; + } + MethodHandle target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), targetKind); + MethodHandle fallback = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), fallbackKind); + MethodHandle test = TestMethods.methodHandleGenerator(boolean.class, + mtTarget.parameterList().subList(0, modifierMHArgNum), kind); + return MethodHandles.guardWithTest(test, target, fallback); + } + }, + CATCH_EXCEPTION("catchException") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + MethodHandle target; + if (kind.equals(TestMethods.Kind.ONE)) { + target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), TestMethods.Kind.ONE); + } else { + target = TestMethods.methodHandleGenerator(mtTarget.returnType(), + mtTarget.parameterList(), TestMethods.Kind.EXCEPT); + } + List<Class<?>> handlerParamList = new ArrayList<>(mtTarget.parameterCount() + 1); + handlerParamList.add(Exception.class); + handlerParamList.addAll(mtTarget.parameterList().subList(0, modifierMHArgNum)); + MethodHandle handler = TestMethods.methodHandleGenerator( + mtTarget.returnType(), handlerParamList, TestMethods.Kind.TWO); + return MethodHandles.catchException(target, Exception.class, handler); + } + }, + INVOKER("invoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + return MethodHandles.invoker(mtTarget); + } + }, + EXACT_INVOKER("exactInvoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + return MethodHandles.exactInvoker(mtTarget); + } + }, + SPREAD_INVOKER("spreadInvoker") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + // Arity after reducing because of long and double take 2 slots. + int realArity = mtTarget.parameterCount(); + int modifierMHArgNum = Helper.RNG.nextInt(realArity + 1); + data.put("modifierMHArgNum", modifierMHArgNum); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + int modifierMHArgNum = (int) data.get("modifierMHArgNum"); + return MethodHandles.spreadInvoker(mtTarget, modifierMHArgNum); + } + }, + ARRAY_ELEMENT_GETTER("arrayElementGetter") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.arrayElementGetter(Array.newInstance(rType, 2).getClass()); + } + }, + ARRAY_ELEMENT_SETTER("arrayElementSetter") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.arrayElementSetter(Array.newInstance(rType, 2).getClass()); + } + }, + CONSTANT("constant") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + if (rType.equals(boolean.class)) { + // There should be the same return values because for default values there are special "zero" forms + return MethodHandles.constant(rType, true); + } else { + return MethodHandles.constant(rType, kind.getValue(rType)); + } + } + }, + IDENTITY("identity") { + @Override + public Map<String, Object> getTestCaseData() { + Map<String, Object> data = new HashMap<>(); + int desiredArity = Helper.RNG.nextInt(Helper.MAX_ARITY); + MethodType mtTarget = TestMethods.randomMethodTypeGenerator(desiredArity); + data.put("mtTarget", mtTarget); + return data; + } + + @Override + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) { + MethodType mtTarget = (MethodType) data.get("mtTarget"); + Class<?> rType = mtTarget.returnType(); + if (rType == void.class) { + rType = Object.class; + } + return MethodHandles.identity(rType); + } + }; + + /** + * Test method's name. + */ + public final String name; + + private TestMethods(String name) { + this.name = name; + } + + protected MethodHandle getMH(Map<String, Object> data, TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + throw new UnsupportedOperationException("TESTBUG: getMH method is not implemented for test method " + this); + } + + /** + * Creates an adapter method handle depending on a test method from + * MethodHandles class. Adapter is what is returned by the test method. This + * method is able to create two kinds of adapters, their type will be the + * same, but return values are different. + * + * @param data a Map containing data to create a method handle, can be + * obtained by {@link #getTestCaseData} method + * @param kind defines whether adapter ONE or adapter TWO will be + * initialized. Should be equal to TestMethods.Kind.ONE or + * TestMethods.Kind.TWO + * @return Method handle adapter that behaves according to + * TestMethods.Kind.ONE or TestMethods.Kind.TWO + * @throws java.lang.NoSuchMethodException + * @throws java.lang.IllegalAccessException + */ + public MethodHandle getTestCaseMH(Map<String, Object> data, TestMethods.Kind kind) + throws NoSuchMethodException, IllegalAccessException { + if (data == null) { + throw new Error(String.format("TESTBUG: Data for test method %s is not prepared", + this.name)); + } + if (!kind.equals(TestMethods.Kind.ONE) && !kind.equals(TestMethods.Kind.TWO)) { + throw new IllegalArgumentException("TESTBUG: Wrong \"kind\" (" + kind + + ") arg to getTestCaseMH function." + + " Should be Kind.ONE or Kind.TWO"); + } + return getMH(data, kind); + } + + /** + * Returns a data Map needed for {@link #getTestCaseMH} method. + * + * @return data Map needed for {@link #getTestCaseMH} method + */ + public Map<String, Object> getTestCaseData() { + throw new UnsupportedOperationException( + "TESTBUG: getTestCaseData method is not implemented for test method " + this); + } + + /** + * Enumeration used in methodHandleGenerator to define whether a MH returned + * by this method returns "2" in different type representations, "4", or + * throw an Exception. + */ + public static enum Kind { + + ONE(2), + TWO(4), + EXCEPT(0); + + private final int value; + + private Object getValue(Class<?> cl) { + return Helper.castToWrapper(value, cl); + } + + private MethodHandle getBasicMH(Class<?> rType) throws NoSuchMethodException, IllegalAccessException { + MethodHandle result = null; + switch (this) { + case ONE: + case TWO: + if (rType.equals(void.class)) { + result = MethodHandles.lookup().findVirtual(Kind.class, "returnVoid", MethodType.methodType(void.class)); + result = MethodHandles.insertArguments(result, 0, this); + } else { + result = MethodHandles.constant(rType, getValue(rType)); + } + break; + case EXCEPT: + result = MethodHandles.throwException(rType, Exception.class); + result = MethodHandles.insertArguments(result, 0, new Exception()); + break; + } + return result; + } + + private void returnVoid() { + } + + private Kind(int value) { + this.value = value; + } + } + + /** + * Routine used to obtain a randomly generated method type. + * + * @param arity Arity of returned method type. + * @return MethodType generated randomly. + */ + private static MethodType randomMethodTypeGenerator(int arity) { + final Class<?>[] CLASSES = { + Object.class, + int.class, + boolean.class, + byte.class, + short.class, + char.class, + long.class, + float.class, + double.class + }; + if (arity > Helper.MAX_ARITY) { + throw new IllegalArgumentException( + String.format("Arity should not exceed %d!", Helper.MAX_ARITY)); + } + List<Class<?>> list = Helper.randomClasses(CLASSES, arity); + list = Helper.getParams(list, false, arity); + int i = Helper.RNG.nextInt(CLASSES.length + 1); + Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i]; + return MethodType.methodType(rtype, list); + } + + /** + * Routine used to obtain a method handles of a given type an kind (return + * value). + * + * @param returnType Type of MH return value. + * @param argTypes Types of MH args. + * @param kind Defines whether the obtained MH returns "1" or "2". + * @return Method handle of the given type. + * @throws NoSuchMethodException + * @throws IllegalAccessException + */ + private static MethodHandle methodHandleGenerator(Class<?> returnType, + List<Class<?>> argTypes, TestMethods.Kind kind) + throws NoSuchMethodException, IllegalAccessException { + MethodHandle result; + result = kind.getBasicMH(returnType); + return Helper.addTrailingArgs(result, argTypes.size(), argTypes); + } + + /** + * Routine that generates filter method handles to test + * MethodHandles.filterArguments method. + * + * @param inputType Filter's argument type. + * @param returnType Filter's return type. + * @param kind Filter's return value definer. + * @return A filter method handle, that takes one argument. + * @throws NoSuchMethodException + * @throws IllegalAccessException + */ + private static MethodHandle filterGenerator(Class<?> inputType, Class<?> returnType, + TestMethods.Kind kind) throws NoSuchMethodException, IllegalAccessException { + MethodHandle tmpMH = kind.getBasicMH(returnType); + if (inputType.equals(void.class)) { + return tmpMH; + } + ArrayList<Class<?>> inputTypeList = new ArrayList<>(1); + inputTypeList.add(inputType); + return Helper.addTrailingArgs(tmpMH, 1, inputTypeList); + } + + private static int argSlotsCount(MethodType mt) { + int result = 0; + for (Class cl : mt.parameterArray()) { + if (cl.equals(long.class) || cl.equals(double.class)) { + result += 2; + } else { + result++; + } + } + return result; + } + + private static List<Class<?>> reduceArgListToSlotsCount(List<Class<?>> list, + int desiredSlotCount) { + List<Class<?>> result = new ArrayList<>(desiredSlotCount); + int count = 0; + for (Class<?> cl : list) { + if (count >= desiredSlotCount) { + break; + } + if (cl.equals(long.class) || cl.equals(double.class)) { + count += 2; + } else { + count++; + } + result.add(cl); + } + return result; + } +}
--- a/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/lang/invoke/MethodHandles/CatchExceptionTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -42,6 +42,7 @@ public class CatchExceptionTest { private static final List<Class<?>> ARGS_CLASSES; protected static final int MAX_ARITY = Helper.MAX_ARITY - 1; + static { Class<?> classes[] = { Object.class, @@ -52,11 +53,8 @@ double[].class, String.class, }; - List<Class<?>> list = new ArrayList<>(MAX_ARITY); - for (int i = 0; i < MAX_ARITY; ++i) { - list.add(classes[Helper.RNG.nextInt(classes.length)]); - } - ARGS_CLASSES = Collections.unmodifiableList(list); + ARGS_CLASSES = Collections.unmodifiableList( + Helper.randomClasses(classes, MAX_ARITY)); } private final TestCase testCase; @@ -66,7 +64,6 @@ private int dropped; private MethodHandle thrower; - public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount, final int catchDrops) { this.testCase = testCase; @@ -107,37 +104,7 @@ } private List<Class<?>> getThrowerParams(boolean isVararg, int argsCount) { - boolean unmodifiable = true; - List<Class<?>> classes; - classes = ARGS_CLASSES.subList(0, - Math.min(argsCount, (MAX_ARITY / 2) - 1)); - int extra = 0; - if (argsCount >= MAX_ARITY / 2) { - classes = new ArrayList<>(classes); - unmodifiable = false; - extra = (int) classes.stream().filter(Helper::isDoubleCost).count(); - int i = classes.size(); - while (classes.size() + extra < argsCount) { - Class<?> aClass = ARGS_CLASSES.get(i); - if (Helper.isDoubleCost(aClass)) { - ++extra; - if (classes.size() + extra >= argsCount) { - break; - } - } - classes.add(aClass); - } - } - if (isVararg && classes.size() > 0) { - if (unmodifiable) { - classes = new ArrayList<>(classes); - } - int last = classes.size() - 1; - Class<?> aClass = classes.get(classes.size() - 1); - aClass = Array.newInstance(aClass, 2).getClass(); - classes.set(last, aClass); - } - return classes; + return Helper.getParams(ARGS_CLASSES, isVararg, argsCount); }
--- a/test/java/lang/invoke/lambda/LUtils.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/lang/invoke/lambda/LUtils.java Thu Sep 18 13:27:48 2014 -0700 @@ -37,8 +37,6 @@ * support infrastructure to invoke a java class from the command line */ class LUtils { - static final sun.tools.jar.Main jarTool = - new sun.tools.jar.Main(System.out, System.err, "jar-tool"); static final com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main(); static final File cwd = new File(".").getAbsoluteFile(); @@ -49,6 +47,10 @@ static final File JAVA_BIN_FILE = new File(JAVAHOME, "bin"); static final File JAVA_CMD = new File(JAVA_BIN_FILE, isWindows ? "java.exe" : "java"); + static final File JAR_BIN_FILE = + new File(new File(JAVAHOME).getParentFile(), "bin"); + static final File JAR_CMD = new File(JAR_BIN_FILE, + isWindows ? "jar.exe" : "jar"); protected LUtils() { }
--- a/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -67,12 +67,17 @@ compile(javacArgs); File jarFile = new File("foo.jar"); String[] jargs = {"cvf", jarFile.getName(), doprivClass.getName()}; - jarTool.run(jargs); + TestResult tr = doExec(JAR_CMD.getAbsolutePath(), + "cvf", jarFile.getName(), + doprivClass.getName()); + if (tr.exitValue != 0){ + throw new RuntimeException(tr.toString()); + } doprivJava.delete(); doprivClass.delete(); - TestResult tr = doExec(JAVA_CMD.getAbsolutePath(), - "-Xbootclasspath/p:foo.jar", - "-cp", ".", "Bar"); + tr = doExec(JAVA_CMD.getAbsolutePath(), + "-Xbootclasspath/p:foo.jar", + "-cp", ".", "Bar"); tr.assertZero("testDoPrivileged fails"); barJava.delete(); barClass.delete();
--- a/test/java/math/BigDecimal/ZeroScalingTests.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/math/BigDecimal/ZeroScalingTests.java Thu Sep 18 13:27:48 2014 -0700 @@ -23,8 +23,10 @@ /* * @test - * @bug 4902952 4905407 4916149 - * @summary Tests that the scale of zero is propagated properly and has the proper effect. + * @bug 4902952 4905407 4916149 8057793 + * @summary Tests that the scale of zero is propagated properly and has the + * proper effect and that setting the scale to zero does not mutate the + * BigDecimal. * @author Joseph D. Darcy */ @@ -445,6 +447,16 @@ return failures; } + static int setScaleDoesNotMutateTest() { + BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689" + + ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704"); + if (total.setScale(0, RoundingMode.DOWN).equals(total.setScale(0, RoundingMode.DOWN))) { + return 0; + } else { + return 1; + } + } + public static void main(String argv[]) { int failures = 0; @@ -455,6 +467,7 @@ failures += setScaleTests(); failures += toEngineeringStringTests(); failures += ulpTests(); + failures += setScaleDoesNotMutateTest(); if (failures > 0 ) { throw new RuntimeException("Incurred " + failures + " failures" +
--- a/test/java/math/BigInteger/BigIntegerTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/math/BigInteger/BigIntegerTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -71,6 +71,7 @@ static final int BITS_TOOM_COOK_SQUARE = 6912; static final int BITS_SCHOENHAGE_BASE = 640; static final int BITS_BURNIKEL_ZIEGLER = 2560; + static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280; static final int ORDER_SMALL = 60; static final int ORDER_MEDIUM = 100; @@ -288,19 +289,19 @@ * where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if * {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then * {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test - * ensures that {@code v} is just under the B-Z threshold and that {@code w} - * and {@code z} are both over the threshold. This implies that {@code u/v} - * uses the standard division algorithm and {@code w/z} uses the B-Z - * algorithm. The results of the two algorithms are then compared using the - * observation described in the foregoing and if they are not equal a - * failure is logged. + * ensures that {@code v} is just under the B-Z threshold, that {@code z} is + * over the threshold and {@code w} is much larger than {@code z}. This + * implies that {@code u/v} uses the standard division algorithm and + * {@code w/z} uses the B-Z algorithm. The results of the two algorithms + * are then compared using the observation described in the foregoing and + * if they are not equal a failure is logged. */ public static void divideLarge() { int failCount = 0; - BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER - 33); + BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33); for (int i=0; i<SIZE; i++) { - BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER - 34, rnd); + BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, rnd); BigInteger v = base.add(addend); BigInteger u = v.multiply(BigInteger.valueOf(2 + rnd.nextInt(Short.MAX_VALUE - 1))); @@ -312,14 +313,14 @@ v = v.negate(); } - int a = 17 + rnd.nextInt(16); + int a = BITS_BURNIKEL_ZIEGLER_OFFSET + rnd.nextInt(16); int b = 1 + rnd.nextInt(16); - BigInteger w = u.multiply(BigInteger.valueOf(1L << a)); - BigInteger z = v.multiply(BigInteger.valueOf(1L << b)); + BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a)); + BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b)); BigInteger[] divideResult = u.divideAndRemainder(v); - divideResult[0] = divideResult[0].multiply(BigInteger.valueOf(1L << (a - b))); - divideResult[1] = divideResult[1].multiply(BigInteger.valueOf(1L << b)); + divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b)); + divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b)); BigInteger[] bzResult = w.divideAndRemainder(z); if (divideResult[0].compareTo(bzResult[0]) != 0 ||
--- a/test/java/net/NetworkInterface/Test.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/net/NetworkInterface/Test.java Thu Sep 18 13:27:48 2014 -0700 @@ -22,7 +22,9 @@ */ /* @test - * @bug 4405354 6594296 + * @bug 4405354 6594296 8058216 + * @run main Test + * @run main/othervm -Djava.net.preferIPv4Stack=true Test * @summary Basic tests for NetworkInterface */ import java.net.NetworkInterface;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/nio/channels/FileChannel/BlockDeviceSize.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8054029 + * @summary Block devices should not report size=0 on Linux + */ + +import java.io.RandomAccessFile; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.channels.FileChannel; +import java.nio.file.AccessDeniedException; +import java.nio.file.NoSuchFileException; +import static java.nio.file.StandardOpenOption.*; + + +public class BlockDeviceSize { + private static final String BLK_FNAME = "/dev/sda1"; + private static final Path BLK_PATH = Paths.get(BLK_FNAME); + + public static void main(String[] args) throws Throwable { + try (FileChannel ch = FileChannel.open(BLK_PATH, READ); + RandomAccessFile file = new RandomAccessFile(BLK_FNAME, "r")) { + + long size1 = ch.size(); + long size2 = file.length(); + if (size1 != size2) { + throw new RuntimeException("size differs when retrieved" + + " in different ways: " + size1 + " != " + size2); + } + System.out.println("OK"); + + } catch (NoSuchFileException nsfe) { + System.err.println("File " + BLK_FNAME + " not found." + + " Skipping test"); + } catch (AccessDeniedException ade) { + System.err.println("Access to " + BLK_FNAME + " is denied." + + " Run test as root."); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/AccessController/LimitedDoPrivilegedWithNullPerms.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013,2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8050281 + * @summary Test that NullPointerException is thrown if any element of perms + * parameter is null + * @run testng LimitedDoPrivilegedWithNullPerms + */ +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.PropertyPermission; +import org.testng.annotations.Test; + +public class LimitedDoPrivilegedWithNullPerms { + + AccessControlContext acc = AccessController.getContext(); + Permission p1 = new PropertyPermission("user.name", "read"); + + @Test(expectedExceptions = NullPointerException.class) + public void test1() { + AccessController.doPrivileged( + (PrivilegedAction<Void>) () -> null, acc, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test2() { + AccessController.doPrivileged( + (PrivilegedAction<Void>) () -> null, acc, p1, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test3() { + AccessController.doPrivilegedWithCombiner( + (PrivilegedAction<Void>) () -> null, acc, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test4() { + AccessController.doPrivilegedWithCombiner( + (PrivilegedAction<Void>) () -> null, acc, p1, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test5() throws PrivilegedActionException { + AccessController.doPrivileged( + (PrivilegedExceptionAction<Void>) () -> null, + acc, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test6() throws PrivilegedActionException { + AccessController.doPrivileged( + (PrivilegedExceptionAction<Void>) () -> null, + acc, p1, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test7() throws PrivilegedActionException { + AccessController.doPrivilegedWithCombiner( + (PrivilegedExceptionAction<Void>) () -> null, + acc, null); + } + + @Test(expectedExceptions = NullPointerException.class) + public void test8() throws PrivilegedActionException { + AccessController.doPrivilegedWithCombiner( + (PrivilegedExceptionAction<Void>) () -> null, + acc, p1, null); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/AccessController/LimitedDoPrivilegedWithThread.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013,2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8050281 + * @summary Test limited doprivileged action with trhead calls. + * @run main/othervm/policy=policy LimitedDoPrivilegedWithThread + */ +import java.io.FilePermission; +import java.security.AccessControlContext; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.PropertyPermission; + +public class LimitedDoPrivilegedWithThread { + + private static final Permission PROPERTYPERM + = new PropertyPermission("user.name", "read"); + private static final Permission FILEPERM + = new FilePermission("*", "read"); + private static final AccessControlContext ACC + = new AccessControlContext( + new ProtectionDomain[]{new ProtectionDomain(null, null)}); + + public static void main(String args[]) { + //parent thread without any permission + AccessController.doPrivileged( + (PrivilegedAction) () -> { + Thread ct = new Thread( + new ChildThread(PROPERTYPERM, FILEPERM)); + ct.start(); + try { + ct.join(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + ie.printStackTrace(); + throw new RuntimeException("Unexpected InterruptedException"); + } + return null; + }, ACC); + } +} + +class ChildThread implements Runnable { + + private final Permission P1; + private final Permission P2; + private boolean catchACE = false; + + public ChildThread(Permission p1, Permission p2) { + this.P1 = p1; + this.P2 = p2; + } + + @Override + public void run() { + //Verified that child thread has permission p1, + runTest(null, P1, false, 1); + //Verified that child thread inherits parent thread's access control context + AccessControlContext childAcc = AccessController.getContext(); + runTest(childAcc, P1, true, 2); + //Verified that we can give permision p2 to limit the "privilege" of the + //class calling doprivileged action, stack walk will continue + runTest(null, P2, true, 3); + + } + + public void runTest(AccessControlContext acc, Permission perm, + boolean expectACE, int id) { + + AccessController.doPrivileged( + (PrivilegedAction) () -> { + try { + AccessController.getContext().checkPermission(P1); + } catch (AccessControlException ace) { + catchACE = true; + } + if (catchACE ^ expectACE) { + throw new RuntimeException("test" + id + " failed"); + } + return null; + }, acc, perm); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/AccessController/policy Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,4 @@ +grant{ + permission java.util.PropertyPermission "user.name", "read"; + permission java.io.FilePermission "*", "read"; +};
--- a/test/java/sql/test/sql/TimestampTests.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/java/sql/test/sql/TimestampTests.java Thu Sep 18 13:27:48 2014 -0700 @@ -27,14 +27,40 @@ import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Calendar; +import java.util.TimeZone; import static org.testng.Assert.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import util.BaseTest; public class TimestampTests extends BaseTest { + private static TimeZone defaultTimeZone = null; + + /* + * Need to set and use a custom TimeZone which does not + * observe daylight savings time for this test. + */ + @BeforeClass + public static void setUpClass() throws Exception { + defaultTimeZone = TimeZone.getDefault(); + TimeZone tzone = TimeZone.getTimeZone("GMT+01"); + assertFalse(tzone.observesDaylightTime()); + TimeZone.setDefault(tzone); + } + + /* + * Conservatively reset the default time zone after test. + */ + @AfterClass + public static void tearDownClass() throws Exception { + TimeZone.setDefault(defaultTimeZone); + } + /* * Validate an IllegalArgumentException is thrown for an invalid Timestamp */ @@ -610,6 +636,12 @@ "Error with Nanos"); } + @Test(dataProvider = "validTimestampLongValues") + public void test52(long value, String ts) { + Timestamp ts1 = new Timestamp(value); + assertEquals(ts1.toString(), ts, "ts1.toString() != ts"); + } + /* * DataProvider used to provide Timestamps which are not valid and are used * to validate that an IllegalArgumentException will be thrown from the @@ -678,6 +710,40 @@ }; } + @DataProvider(name = "validTimestampLongValues") + private Object[][] validTimestampLongValues() { + return new Object[][]{ + {1L, "1970-01-01 01:00:00.001"}, + {-3600*1000L - 1, "1969-12-31 23:59:59.999"}, + {-(20000L*365*24*60*60*1000), "18018-08-28 01:00:00.0"}, + {Timestamp.valueOf("1961-08-30 11:22:33").getTime(), "1961-08-30 11:22:33.0"}, + {Timestamp.valueOf("1961-08-30 11:22:33.54321000").getTime(), "1961-08-30 11:22:33.543"}, // nanoprecision lost + {new Timestamp(114, 10, 10, 10, 10, 10, 100000000).getTime(), "2014-11-10 10:10:10.1"}, + {new Timestamp(0, 10, 10, 10, 10, 10, 100000).getTime(), "1900-11-10 10:10:10.0"}, // nanoprecision lost + {new Date(114, 10, 10).getTime(), "2014-11-10 00:00:00.0"}, + {new Date(0, 10, 10).getTime(), "1900-11-10 00:00:00.0"}, + {LocalDateTime.of(1960, 10, 10, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles")) + .toInstant().toEpochMilli(), "1960-10-10 19:10:10.0"}, + + // millisecond timestamps wraps around at year 1, so Long.MIN_VALUE looks similar + // Long.MAX_VALUE, while actually representing 292278994 BCE + {Long.MIN_VALUE, "292278994-08-17 08:12:55.192"}, + {Long.MAX_VALUE + 1, "292278994-08-17 08:12:55.192"}, + {Long.MAX_VALUE, "292278994-08-17 08:12:55.807"}, + {Long.MIN_VALUE - 1, "292278994-08-17 08:12:55.807"}, + + // wrap around point near 0001-01-01, test that we never get a negative year: + {-(1970L*365*24*60*60*1000), "0001-04-25 01:00:00.0"}, + {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L), "0001-12-31 01:00:00.0"}, + {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L - 23*60*60*1000L), "0001-01-01 00:00:00.0"}, + + {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles")) + .toInstant().toEpochMilli() - 2*24*60*60*1000L, "0001-01-01 19:03:08.0"}, // 1 BCE + {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles")) + .toInstant().toEpochMilli() - 3*24*60*60*1000L, "0002-12-31 19:03:08.0"} // 2 BCE + }; + } + /* * DataProvider used to provide Timestamp and Nanos values in order to * validate that the correct Nanos value is generated from the specified
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/zip/DataDescriptorSignatureMissing.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,147 @@ +/* + * Copyright 2012 Google, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8056934 + * @summary Check ability to read zip files created by python zipfile + * implementation, which fails to write optional (but recommended) data + * descriptor signatures. Repro scenario is a Java -> Python -> Java round trip: + * - ZipOutputStream creates zip file with DEFLATED entries and data + * descriptors with optional signature "PK0x0708". + * - Python reads those entries, preserving the 0x08 flag byte + * - Python outputs those entries with data descriptors lacking the + * optional signature. + * - ZipInputStream cannot handle the missing signature + * + * No way to adapt the technique in this test to get a ZIP64 zip file + * without data descriptors was found. + * + * @ignore This test has brittle dependencies on an external working python. + */ + +import java.io.*; +import java.util.zip.*; + +public class DataDescriptorSignatureMissing { + void printStream(InputStream is) throws IOException { + Reader r = new InputStreamReader(is); + StringBuilder sb = new StringBuilder(); + char[] buf = new char[1024]; + int n; + while ((n = r.read(buf)) > 0) { + sb.append(buf, 0, n); + } + System.out.print(sb); + } + + int entryCount(File zipFile) throws IOException { + try (FileInputStream fis = new FileInputStream(zipFile); + ZipInputStream zis = new ZipInputStream(fis)) { + for (int count = 0;; count++) + if (zis.getNextEntry() == null) + return count; + } + } + + void test(String[] args) throws Throwable { + if (! new File("/usr/bin/python").canExecute()) + return; + + // Create a java zip file with DEFLATED entries and data + // descriptors with signatures. + final File in = new File("in.zip"); + final File out = new File("out.zip"); + final int count = 3; + try (FileOutputStream fos = new FileOutputStream(in); + ZipOutputStream zos = new ZipOutputStream(fos)) { + for (int i = 0; i < count; i++) { + ZipEntry ze = new ZipEntry("hello.python" + i); + ze.setMethod(ZipEntry.DEFLATED); + zos.putNextEntry(ze); + zos.write(new byte[10]); + zos.closeEntry(); + } + } + + // Copy the zip file using python's zipfile module + String[] python_program_lines = { + "import os", + "import zipfile", + "input_zip = zipfile.ZipFile('in.zip', mode='r')", + "output_zip = zipfile.ZipFile('out.zip', mode='w')", + "count08 = 0", + "for input_info in input_zip.infolist():", + " output_info = input_info", + " if output_info.flag_bits & 0x08 == 0x08:", + " count08 += 1", + " output_zip.writestr(output_info, input_zip.read(input_info))", + "output_zip.close()", + "if count08 == 0:", + " raise ValueError('Expected to see entries with 0x08 flag_bits set')", + }; + StringBuilder python_program_builder = new StringBuilder(); + for (String line : python_program_lines) + python_program_builder.append(line).append('\n'); + String python_program = python_program_builder.toString(); + String[] cmdline = { "/usr/bin/python", "-c", python_program }; + ProcessBuilder pb = new ProcessBuilder(cmdline); + pb.redirectErrorStream(true); + Process p = pb.start(); + printStream(p.getInputStream()); + p.waitFor(); + equal(p.exitValue(), 0); + + File pythonZipFile = new File("out.zip"); + check(pythonZipFile.exists()); + + equal(entryCount(in), + entryCount(out)); + + // We expect out to be identical to in, except for the removal of + // the optional data descriptor signatures. + final int SIG_LENGTH = 4; // length of a zip signature - PKxx + equal(in.length(), + out.length() + SIG_LENGTH * count); + + in.delete(); + out.delete(); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new DataDescriptorSignatureMissing().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +}
--- a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -58,9 +58,9 @@ public class AttributeArbitraryDataTypeTest implements NotificationListener { // Flag to notify that a message has been received - private boolean counterMessageReceived = false; - private boolean gaugeMessageReceived = false; - private boolean stringMessageReceived = false; + private volatile boolean counterMessageReceived = false; + private volatile boolean gaugeMessageReceived = false; + private volatile boolean stringMessageReceived = false; // Match enum public enum Match { do_not_match_0, @@ -195,21 +195,33 @@ " has reached or exceeded the threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - counterMessageReceived = true; + + synchronized (this) { + counterMessageReceived = true; + notifyAll(); + } } else if (type.equals(MonitorNotification. THRESHOLD_HIGH_VALUE_EXCEEDED)) { echo("\t\t" + n.getObservedAttribute() + " has reached or exceeded the high threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - gaugeMessageReceived = true; + + synchronized (this) { + gaugeMessageReceived = true; + notifyAll(); + } } else if (type.equals(MonitorNotification. STRING_TO_COMPARE_VALUE_MATCHED)) { echo("\t\t" + n.getObservedAttribute() + " matches the string-to-compare value"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - stringMessageReceived = true; + + synchronized (this) { + stringMessageReceived = true; + notifyAll(); + } } else { echo("\t\tSkipping notification of type: " + type); } @@ -358,6 +370,17 @@ // Check if notification was received // + synchronized (this) { + while (!counterMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (counterMessageReceived) { echo("\tOK: CounterMonitor notification received"); } else { @@ -525,6 +548,17 @@ // Check if notification was received // + synchronized (this) { + while (!gaugeMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (gaugeMessageReceived) { echo("\tOK: GaugeMonitor notification received"); } else { @@ -680,6 +714,17 @@ // Check if notification was received // + synchronized (this) { + while (!stringMessageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } if (stringMessageReceived) { echo("\tOK: StringMonitor notification received"); } else {
--- a/test/javax/management/monitor/CounterMonitorTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/CounterMonitorTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -43,9 +43,6 @@ // modulus number private Number modulus = new Integer(7); - // offset number - private int offset = 0; - // difference mode flag private boolean differenceModeFlag = true; @@ -58,9 +55,6 @@ // counter values private int[] values = new int[] {4, 6, 9, 11}; - // time to wait for notification (in seconds) - private int timeout = 5; - // flag to notify that a message has been received private volatile boolean messageReceived = false; @@ -92,8 +86,9 @@ echo("\t\t" + n.getObservedAttribute() + " has reached or exceeded the threshold"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); - messageReceived = true; + synchronized (this) { + messageReceived = true; notifyAll(); } } else { @@ -205,22 +200,17 @@ } /* - * Wait until timeout reached + * Wait messageReceived to be true */ - void doWait() { - for (int i = 0; i < timeout; i++) { - echo("\tdoWait: Waiting for " + timeout + " seconds. " + - "i = " + i + ", messageReceived = " + messageReceived); - if (messageReceived) { + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); break; } - try { - synchronized (this) { - wait(1000); - } - } catch (InterruptedException e) { - // OK: Ignore... - } } }
--- a/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/GaugeMonitorDeadlockTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -36,8 +36,9 @@ */ import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.util.concurrent.atomic.AtomicInteger; -import javax.management.Attribute; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.Notification; @@ -47,10 +48,16 @@ import javax.management.monitor.GaugeMonitorMBean; public class GaugeMonitorDeadlockTest { + private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY}; + private static long checkingTime; public static void main(String[] args) throws Exception { if (args.length != 1) throw new Exception("Arg should be test number"); + double factor = Double.parseDouble(System.getProperty("test.timeout.factor", "1.0")); + checkingTime = (long)factor*1000; + System.out.println("=== checkingTime = " + checkingTime + "ms"); + int testNo = Integer.parseInt(args[0]) - 1; TestCase test = testCases[testNo]; System.out.println("Test: " + test.getDescription()); @@ -58,8 +65,6 @@ System.out.println("Test passed"); } - private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY}; - private static abstract class TestCase { TestCase(String description, When when) { this.description = description; @@ -98,16 +103,29 @@ monitorProxy.setNotifyLow(true); monitorProxy.start(); + System.out.println("=== Waiting observedProxy.getGetCount() to be " + + "changed, presumable deadlock if timeout?"); final int initGetCount = observedProxy.getGetCount(); - int getCount = initGetCount; - for (int i = 0; i < 2000; i++) { // 2000 * 10 = 20 seconds - getCount = observedProxy.getGetCount(); - if (getCount != initGetCount) - break; - Thread.sleep(10); + long checkedTime = System.currentTimeMillis(); + long nowTime; + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + while (observedProxy.getGetCount() == initGetCount) { + Thread.sleep(100); + + nowTime = System.currentTimeMillis(); + if (nowTime - checkedTime >= checkingTime) { + System.out.println("=== Checking deadlocked ..."); + if (threadMXBean.findDeadlockedThreads() != null) { + for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) { + System.out.println(info); + } + throw new Error("Found deadlocked threads: " + + threadMXBean.findDeadlockedThreads().length); + } + checkedTime = System.currentTimeMillis(); + } } - if (getCount <= initGetCount) - throw new Exception("Test failed: presumable deadlock"); + // This won't show up as a deadlock in CTRL-\ or in // ThreadMXBean.findDeadlockedThreads(), because they don't // see that thread A is waiting for thread B (B.join()), and @@ -117,13 +135,13 @@ // so if we want to test notify behaviour we can trigger by // exceeding the threshold. if (when == When.IN_NOTIFY) { + final Thread testedThread = new Thread(sensitiveThing); final AtomicInteger notifCount = new AtomicInteger(); final NotificationListener listener = new NotificationListener() { public void handleNotification(Notification n, Object h) { - Thread t = new Thread(sensitiveThing); - t.start(); + testedThread.start(); try { - t.join(); + testedThread.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } @@ -132,12 +150,36 @@ }; mbs.addNotificationListener(monitorName, listener, null, null); observedProxy.setThing(1000); - for (int i = 0; i < 2000 && notifCount.get() == 0; i++) - Thread.sleep(10); - if (notifCount.get() == 0) - throw new Exception("Test failed: presumable deadlock"); + System.out.println("=== Waiting notifications, presumable " + + "deadlock if timeout?"); + long startTime = System.currentTimeMillis(); + checkedTime = startTime; + while (notifCount.get() == 0) { + Thread.sleep(100); + + nowTime = System.currentTimeMillis(); + if (nowTime - checkedTime >= checkingTime) { + System.out.println("=== Checking the thread state ..."); + if (testedThread.isAlive()) { + System.out.println("=== Waiting testedThread to die " + + "after " + (nowTime - startTime) + "ms"); + + ThreadInfo tinfo = threadMXBean.getThreadInfo(testedThread.getId()); + if (Thread.State.BLOCKED.equals(tinfo.getThreadState())) { + for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) { + System.out.println(info); + } + } else { + System.out.println(tinfo); + } + } else { + System.out.println("=== The testedThread is dead as wished, " + + "the test must be passed soon."); + } + checkedTime = System.currentTimeMillis(); + } + } } - } abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,
--- a/test/javax/management/monitor/NonComparableAttributeValueTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/NonComparableAttributeValueTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -39,7 +39,7 @@ public class NonComparableAttributeValueTest implements NotificationListener { // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; // MBean class public class ObservedObject implements ObservedObjectMBean { @@ -69,7 +69,11 @@ echo("\t\t" + n.getObservedAttribute() + " is null"); echo("\t\tDerived Gauge = " + n.getDerivedGauge()); echo("\t\tTrigger = " + n.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } else { echo("\t\tSkipping notification of type: " + type); } @@ -134,12 +138,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor notification received"); } else { @@ -212,12 +213,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor notification received"); } else { @@ -289,12 +287,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor notification received"); } else { @@ -334,6 +329,21 @@ } /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + + /* * Standalone entry point. * * Run the test and report to stdout.
--- a/test/javax/management/monitor/ReflectionExceptionTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/ReflectionExceptionTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -87,7 +87,11 @@ echo("\tObservedAttribute: " + mn.getObservedAttribute()); echo("\tDerivedGauge: " + mn.getDerivedGauge()); echo("\tTrigger: " + mn.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } } } @@ -135,12 +139,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!"); } else { @@ -203,12 +204,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!"); } else { @@ -270,12 +268,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor got RUNTIME_ERROR notification!"); } else { @@ -349,8 +344,23 @@ } } + /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; private MBeanServer server; private ObjectName obsObjName;
--- a/test/javax/management/monitor/RuntimeExceptionTest.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/javax/management/monitor/RuntimeExceptionTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -86,7 +86,11 @@ echo("\tObservedAttribute: " + mn.getObservedAttribute()); echo("\tDerivedGauge: " + mn.getDerivedGauge()); echo("\tTrigger: " + mn.getTrigger()); - messageReceived = true; + + synchronized (this) { + messageReceived = true; + notifyAll(); + } } } } @@ -134,12 +138,9 @@ echo(">>> START the CounterMonitor"); counterMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!"); } else { @@ -202,12 +203,9 @@ echo(">>> START the GaugeMonitor"); gaugeMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!"); } else { @@ -269,12 +267,9 @@ echo(">>> START the StringMonitor"); stringMonitor.start(); - // Wait for granularity period (multiplied by 2 for sure) - // - Thread.sleep(granularityperiod * 2); - // Check if notification was received // + doWait(); if (messageReceived) { echo("\tOK: StringMonitor got RUNTIME_ERROR notification!"); } else { @@ -347,8 +342,23 @@ } } + /* + * Wait messageReceived to be true + */ + synchronized void doWait() { + while (!messageReceived) { + try { + wait(); + } catch (InterruptedException e) { + System.err.println("Got unexpected exception: " + e); + e.printStackTrace(); + break; + } + } + } + // Flag to notify that a message has been received - private boolean messageReceived = false; + private volatile boolean messageReceived = false; private MBeanServer server; private ObjectName obsObjName;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/Common.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.Area; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.security.SecureRandom; + +public abstract class Common { + + ExtendedRobot robot; + Class<? extends JFrame> windowClass; + JFrame background; + BufferedImage foreground; + Window window; + volatile boolean gradientBackgroundEnabled = false; + volatile int gradientWidth = 255; + volatile int gradientHeight = 255; + + float opacity = 1.0f; + float perPixelTranslucency = 1.0f; + static Color BG_COLOR = Color.BLUE; + static Color FG_COLOR = Color.RED; + static final int delay = 1000; + static final SecureRandom random = new SecureRandom(); + static final int dl = 100; + static final Class[] WINDOWS_TO_TEST = { JWindow.class, JFrame.class, JDialog.class }; + + volatile int clicked; + + public Common(Class windowClass, float opacity, float perPixelTranslucency, boolean gradient) throws Exception { + this.gradientBackgroundEnabled = gradient; + this.perPixelTranslucency = perPixelTranslucency; + this.opacity = opacity; + robot = new ExtendedRobot(); + this.windowClass = windowClass; + EventQueue.invokeAndWait(this::initBackgroundFrame); + EventQueue.invokeAndWait(this::initGUI); + } + + public Common(Class windowClass) throws Exception { + this(windowClass, 1.0f, 1.0f, false); + } + + public Common(Class windowClass, boolean gradient) throws Exception { + this(windowClass, 1.0f, 1.0f, gradient); + } + + public abstract void doTest() throws Exception; + + public void dispose() { + window.dispose(); + background.dispose(); + } + + public void applyShape() {}; + + public void applyDynamicShape() { + final Area a = new Area(); + Dimension size = window.getSize(); + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + a.add(new Area(new Rectangle2D.Double( + x * size.getWidth() / 17*6, y * size.getHeight() / 17*6, + size.getWidth() / 17*5, size.getHeight() / 17*5))); + } + } + window.setShape(a); + } + + public BufferedImage getForegroundWindow() throws Exception { + final BufferedImage f[] = new BufferedImage[1]; + EventQueue.invokeAndWait( () -> { + f[0] = new BufferedImage(window.getWidth(), + window.getHeight(), BufferedImage.TYPE_INT_RGB); + window.printAll(f[0].createGraphics()); + }); + robot.waitForIdle(delay); + return f[0]; + } + + public static boolean checkTranslucencyMode(GraphicsDevice.WindowTranslucency mode) { + + if (!GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getDefaultScreenDevice() + .isWindowTranslucencySupported(mode)){ + System.out.println(mode+" translucency mode isn't supported"); + return false; + } else { + return true; + } + + } + + public void applyAppDragNResizeSupport() { + MouseAdapter m = new MouseAdapter() { + + private Point dragOrigin = null; + private Dimension origSize = null; + private Point origLoc = null; + private boolean left = false; + private boolean top = false; + private boolean bottom = false; + private boolean right = false; + + public void mousePressed(MouseEvent e) { + dragOrigin = e.getLocationOnScreen(); + origSize = window.getSize(); + origLoc = window.getLocationOnScreen(); + right = (origLoc.x + window.getWidth() - dragOrigin.x) < 5; + left = !right && dragOrigin.x - origLoc.x < 5; + bottom = (origLoc.y + window.getHeight() - dragOrigin.y) < 5; + top = !bottom && dragOrigin.y - origLoc.y < 5; + } + + public void mouseReleased(MouseEvent e) { resize(e); } + public void mouseDragged(MouseEvent e) { resize(e); } + + void resize(MouseEvent e) { + Point dragDelta = e.getLocationOnScreen(); + dragDelta.translate(-dragOrigin.x, -dragOrigin.y); + Point newLoc = new Point(origLoc); + newLoc.translate(dragDelta.x, dragDelta.y); + Dimension newSize = new Dimension(origSize); + if (left || right) { + newSize.width += right ? dragDelta.x : -dragDelta.x; + } + if (top || bottom) { + newSize.height += bottom ? dragDelta.y : -dragDelta.y; + } + if (right || (top || bottom) && !left) { + newLoc.x = origLoc.x; + } + if (bottom || (left || right) && !top) { + newLoc.y = origLoc.y; + } + window.setBounds(newLoc.x, newLoc.y, newSize.width, newSize.height); + } + }; + for (Component comp : window.getComponents()) { + comp.addMouseListener(m); + comp.addMouseMotionListener(m); + } + + window.addMouseListener(m); + window.addMouseMotionListener(m); + } + + public void checkTranslucentShape() throws Exception { + foreground = getForegroundWindow(); + Point[] points = new Point[4]; + + Dimension size = window.getSize(); + Point location = window.getLocationOnScreen(); + + points[0] = new Point(20, 20); + points[1] = new Point(20, size.height-20); + points[2] = new Point(size.width-20, 20); + points[3] = new Point(size.width-20, size.height-20); + + for (Point p : points){ + p.translate(location.x, location.y); + Color actual = robot.getPixelColor(p.x, p.y); + if (actual.equals(BG_COLOR)|| actual.equals(FG_COLOR)) + throw new RuntimeException("Error in point "+p+": "+actual+" equals to foreground or background color"); + else + System.out.println("OK with foreground point "+p); + } + } + + public void checkDynamicShape() throws Exception { + Point[] points = new Point[4]; + + Dimension size = window.getSize(); + + int blockSizeX = (int) (size.getWidth() / 17); + int blockSizeY = (int) (size.getHeight() / 17); + + // background + points[0] = new Point((int) (blockSizeX * 5.5), (int) (blockSizeY * 5.5)); + points[1] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5)); + points[2] = new Point((int) (blockSizeX * 5.5), (int) (size.getHeight() - blockSizeY * 5.5)); + points[3] = new Point((int) (size.getWidth() - blockSizeX * 5.5), (int) (blockSizeY * 5.5)); + checkShape(points, true); + + // foreground + if (opacity < 1.0f){ + checkTranslucentShape(); + } else { + points[0] = new Point(3 * blockSizeX, 3 * blockSizeY); + points[1] = new Point(14 * blockSizeX, 14 * blockSizeY); + points[2] = new Point(3 * blockSizeX, 14 * blockSizeY); + points[3] = new Point(14 * blockSizeX, 3 * blockSizeY); + checkShape(points, false); + } + } + + public void checkShape(Point[] points, boolean areBackgroundPoints) throws Exception { + + Point location = window.getLocationOnScreen(); + + for (Point p : points) { + p.translate(location.x, location.y); + Color pixel = robot.getPixelColor(p.x, p.y); + if (areBackgroundPoints) { + if (pixel.getRed() != 0 + || pixel.getGreen() != 0 ) + throw new RuntimeException("Background point " + p + + " color " + pixel + + " does not equal to background color " + BG_COLOR); + else + System.out.println("OK with background point " + p); + } else { + if (pixel.equals(BG_COLOR)) + throw new RuntimeException("Foreground point " + p + + " color " + pixel + + " equals to background color " + BG_COLOR); + else + System.out.println("OK with foreground point " + p); + } + } + } + + public void initBackgroundFrame() { + background = new JFrame(); + background.setUndecorated(true); + background.getContentPane().setBackground(BG_COLOR); + background.setSize(500, 500); + background.setLocation(dl, dl); + background.setVisible(true); + } + + public void initGUI() { + Container contentPane; + if (windowClass.equals(Frame.class)) { + window = new JFrame(); + ((JFrame) window).setUndecorated(true); + contentPane = ((JFrame) window).getContentPane(); + } else if (windowClass.equals(Dialog.class)) { + window = new JDialog(background); + ((JDialog) window).setUndecorated(true); + contentPane = ((JDialog) window).getContentPane(); + } else { + window = new JWindow(background); + contentPane = ((JWindow) window).getContentPane(); + } + + if (perPixelTranslucency < 1.0f) { + contentPane.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency)); + window.setBackground(colorWithOpacity(FG_COLOR, perPixelTranslucency)); + } else { + contentPane.setBackground(FG_COLOR); + window.setBackground(FG_COLOR); + } + + window.setLocation(2 * dl, 2 * dl); + window.setSize(255, 255); + window.setPreferredSize(new Dimension(255, 255)); + createSwingComponents(); + if (opacity < 1.0f) + window.setOpacity(opacity); + + window.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + applyShape(); + } + }); + applyShape(); + window.setVisible(true); + applyAppDragNResizeSupport(); + window.toFront(); + } + + public void createSwingComponents() { + Container contentPane; + if (gradientBackgroundEnabled) { + JPanel jPanel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + if (g instanceof Graphics2D) { + Color background = Color.RED; + Paint p = new GradientPaint(0.0f, 0.0f, colorWithOpacity(background, 0), + 0.0f, gradientHeight - 3, colorWithOpacity(background, 1), true); + Graphics2D g2d = (Graphics2D) g; + g2d.setPaint(p); + g2d.fillRect(0, 3, gradientWidth, gradientHeight - 3); + } else { + super.paintComponent(g); + } + } + }; + jPanel.setBorder(new EmptyBorder(15, 5, 5, 5)); + jPanel.setOpaque(false); + + contentPane = jPanel; + + RootPaneContainer.class.cast(window).setContentPane(contentPane); + } else { + contentPane = RootPaneContainer.class.cast(window).getContentPane(); + } + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); + + JButton button = new JButton("JButton"); + window.add(button); + + JTextArea textArea = new JTextArea("JTextArea"); + window.add(textArea); + + JCheckBox checkbox = new JCheckBox("JCheckBox"); + checkbox.setOpaque(false); + window.add(checkbox); + + JComboBox comboBox = new JComboBox(new String[]{"JComboBox", "Some item"}); + window.add(comboBox); + + JLabel label = new JLabel("JLabel"); + window.add(label); + + JTextField textField = new JTextField("JTextField"); + window.add(textField); + + JPanel panel = new JPanel(); + panel.setOpaque(false); + window.add(panel); + + JComboBox comboBox2 = new JComboBox(new String[]{"JComboBox2", "Another item"}); + window.add(comboBox2); + + JRadioButton radioButton = new JRadioButton("JRadioButton"); + radioButton.setOpaque(false); + window.add(radioButton); + } + + Color colorWithOpacity(Color color, float opacity) { + return new Color(color.getColorSpace(), color.getColorComponents(null), opacity); + } + + public void checkTranslucent() throws Exception { + checkTranslucentShape(); + + // Drag + Point location = window.getLocationOnScreen(); + robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl)); + robot.waitForIdle(delay); + checkTranslucentShape(); + + // Resize + location = window.getLocationOnScreen(); + robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl); + robot.waitForIdle(delay); + checkTranslucentShape(); + + EventQueue.invokeAndWait(this::dispose); + } + + public void checkDynamic() throws Exception { + checkDynamicShape(); + + // Drag + Point location = window.getLocationOnScreen(); + robot.dragAndDrop(location.x + 30, location.y + 5, location.x + dl + random.nextInt(dl), location.y + random.nextInt(dl)); + robot.waitForIdle(delay); + checkDynamicShape(); + + // Resize + location = window.getLocationOnScreen(); + robot.dragAndDrop(location.x + 4, location.y + 4, location.x + random.nextInt(2*dl)-dl, location.y + random.nextInt(2*dl)-dl); + robot.waitForIdle(delay); + checkDynamicShape(); + + EventQueue.invokeAndWait(this::dispose); + } + + void checkClick(int x, int y, int flag) throws Exception { + + System.out.println("Trying to click point " + x + ", " + y + ", looking for " + flag + " flag to trigger."); + + clicked = 0; + robot.mouseMove(x, y); + robot.click(); + + for (int i = 0; i < 100; i++) + if ((clicked & (1 << flag)) == 0) + robot.delay(50); + else + break; + + if ((clicked & (1 << flag)) == 0) + throw new RuntimeException("FAIL: Flag " + flag + " is not triggered for point " + x + ", " + y + "!"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; + +/* + * @test + * @summary Check if a per-pixel translucent window is dragged and resized + * by mouse correctly. + * Test Description: Check if PERPIXEL_TRANSLUCENT translucency type is supported + * on the current platform. Proceed if they are supported. Create a window + * with some components in it, make window undecorated, apply translucent + * background of 0.5. Drag and resize the window using AWT Robot and verify + * that translucency is correctly applied with pixels checking. Make the + * window appear on top of a known background. Repeat this for JWindow, + * JDialog, JFrame. + * Expected Result: If PERPIXEL_TRANSLUCENT translucency type is supported, the + * window should appear with the translucency. Only window background + * should be translucent, all the controls should be opaque. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main PerPixelTranslucent + */ + +public class PerPixelTranslucent extends Common { + + public static void main(String[] ignored) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new PerPixelTranslucent(windowClass).doTest(); + } + + public PerPixelTranslucent(Class windowClass) throws Exception { + super(windowClass, 1.0f, 0.5f, false); + } + + public void doTest() throws Exception { + robot.waitForIdle(delay); + checkTranslucent(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import javax.swing.*; +import java.awt.image.BufferedImage; + +/* + * @test + * @summary Check if a per-pixel translucent window shows up with correct translucency + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main PerPixelTranslucentCanvas + */ + +public class PerPixelTranslucentCanvas extends Common { + + JPanel center; + Color OVAL_COLOR = Color.BLUE; + + public static void main(String[] ignored) throws Exception { + FG_COLOR = new Color(200, 0, 0, 100); + BG_COLOR = Color.GREEN; + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new PerPixelTranslucentCanvas(windowClass).doTest(); + } + + public PerPixelTranslucentCanvas(Class windowClass) throws Exception { + super(windowClass); + } + + @Override + public void createSwingComponents() { + Container contentPane = RootPaneContainer.class.cast(window).getContentPane(); + BorderLayout bl = new BorderLayout(10, 10); + contentPane.setLayout(bl); + + JLabel label = new JLabel("North", new ImageIcon( + new BufferedImage(30, 30, BufferedImage.TYPE_INT_RGB)), SwingConstants.CENTER); + contentPane.add(label, BorderLayout.NORTH); + + JButton button = new JButton("West"); + contentPane.add(button, BorderLayout.WEST); + + center = new JPanel() { + @Override + public void paint(Graphics g) { + g.setColor(OVAL_COLOR); + g.fillOval(0, 0, getWidth(), getHeight()); + } + }; + contentPane.add(center, BorderLayout.CENTER); + + JTextField jTextField = new JTextField("South"); + contentPane.add(jTextField, BorderLayout.SOUTH); + } + + @Override + public void doTest() throws Exception { + robot.waitForIdle(delay); + + Rectangle bounds = center.getBounds(); + Point loc = center.getLocationOnScreen(); + + final int x = loc.x + bounds.width / 2; + final int y = loc.y + bounds.height / 2; + + Color color = robot.getPixelColor(x, y); + if (OVAL_COLOR.getRGB() != color.getRGB()) + throw new RuntimeException("bounds = " + bounds + "\n" + + "loc = " + loc + "\n" + + "background loc = " + background.getX() + ", " + background.getY() + "\n" + + "so middle point over background is " + (x - background.getX()) + ", " + (y - background.getY()) + "\n" + + "Oval is not opaque in the middle point (" + x + ", " + y + ", " + color + ")"); + + color = robot.getPixelColor(loc.x - 5, loc.y - 5); + if (FG_COLOR.getRGB() == color.getRGB()) + throw new RuntimeException("Background is not translucent (" + color + ")"); + + EventQueue.invokeAndWait(this::dispose); + robot.waitForIdle(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; + +/* + * @test + * @bug 8032644 + * @summary Check if a per-pixel translucent window is dragged and resized by + * mouse correctly + * Test Description: Check if PERPIXEL_TRANSLUCENT translucency type is supported + * on the current platform. Proceed if they are supported. Create a window + * with some components in it, make window undecorated, apply translucent + * background of 0 and have a gradient painted as background from + * fully-transparent to fully-opaque in componentResized listener. Drag and + * resize the window using AWT Robot and verify that translucency is + * correctly applied with pixels checking. Make the window appear on top of + * a known background. Repeat this for JWindow, JDialog, JFrame. + * Expected Result: If PERPIXEL_TRANSLUCENT translucency type is supported, + * the window should appear as specified with the translucency. Only window + * background should be translucent, all the controls should be opaque. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main PerPixelTranslucentGradient + */ + +public class PerPixelTranslucentGradient extends Common { + + public static void main(String[] ignored) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new PerPixelTranslucentGradient(windowClass).doTest(); + } + + public PerPixelTranslucentGradient(Class windowClass) throws Exception { + super(windowClass, 1.0f, 0f, true); + } + + public void doTest() throws Exception { + robot.waitForIdle(delay); + checkTranslucent(); + } + + @Override + public void applyShape() { + gradientWidth = window.getWidth(); + gradientHeight = window.getHeight(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import java.awt.*; + +/* + * @test + * @summary Check if a per-pixel translucent window shows only the area having + * opaque pixels + * Test Description: Check if PERPIXEL_TRANSLUCENT Translucency type is supported + * on the current platform. Proceed if it is supported. Create a swing window + * with some swing components in it and a transparent background (alpha 0.0). + * Bring this window on top of a known background. Do this test for JFrame, + * JWindow and JDialog + * Expected Result: Only the components present in the window must be shown. Other + * areas of the window must be transparent so that the background shows + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main PerPixelTranslucentSwing + */ + +public class PerPixelTranslucentSwing extends Common { + + JButton north; + + public static void main(String[] ignored) throws Exception { + FG_COLOR = new Color(200, 0, 0, 0); + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new PerPixelTranslucentSwing(windowClass).doTest(); + } + + public PerPixelTranslucentSwing(Class windowClass) throws Exception { + super(windowClass); + } + + @Override + public void createSwingComponents() { + Container contentPane = RootPaneContainer.class.cast(window).getContentPane(); + BorderLayout bl = new BorderLayout(10, 5); + contentPane.setLayout(bl); + + north = new JButton("North"); + contentPane.add(north, BorderLayout.NORTH); + + JList center = new JList(new String[] {"Center"}); + contentPane.add(center, BorderLayout.CENTER); + + JTextField south = new JTextField("South"); + contentPane.add(south, BorderLayout.SOUTH); + + window.pack(); + window.setVisible(true); + + north.requestFocus(); + } + + @Override + public void doTest() throws Exception { + robot.waitForIdle(delay); + + // Check for background translucency + Rectangle bounds = north.getBounds(); + Point loc = north.getLocationOnScreen(); + + Color color = robot.getPixelColor(loc.x + bounds.width / 2, loc.y + bounds.height + 3); + System.out.println(color); + if (FG_COLOR.getRGB() == color.getRGB()) + throw new RuntimeException("Background is not translucent (" + color + ")"); + + EventQueue.invokeAndWait(this::dispose); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Area; +import java.awt.geom.GeneralPath; +import java.awt.geom.Rectangle2D; + +/* + * @test + * @summary Check if a window set with shape clips the contents + * Test Description: Check if PERPIXEL_TRANSPARENT translucency type is supported + * by the current platform. Proceed if it is supported. Apply different types + * of shapes on a Window which contains some awt components. Shape should be + * applied in such a way that some components are partially clipped off. Check + * if the components appear only partially and events work correctly for those + * components - i.e. events occur only on the areas which appear and do not + * occur on the clipped off areas. Events should be checked by clicking on the + * visible and clipped regions. Repeat this for Window, Dialog and Frame. + * Expected Result: If PERPIXEL_TRANSPARENT translucency type is supported, clicking + * on clipped region should deliver the event to the background (it should be + * another Window behind the test window) + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main SetShapeAndClickSwing + */ + +public class SetShapeAndClickSwing extends Common { + + Component south, center, north; + + public static void main(String[] args) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new SetShapeAndClickSwing(windowClass).doTest(); + } + + public SetShapeAndClickSwing(Class windowClass) throws Exception { + super(windowClass); + } + + @Override + public void initBackgroundFrame() { + super.initBackgroundFrame(); + background.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + clicked |= 1 << 0; + } + }); + } + + @Override + public void createSwingComponents() { + window.setSize(200,200); + window.setLayout(new BorderLayout()); + + south = new JLabel("South"); + south.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + clicked |= 1 << 3; + } + }); + window.add(south, BorderLayout.SOUTH); + + center = new JList(); + center.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + clicked |= 1 << 2; + } + }); + window.add(center, BorderLayout.CENTER); + + north = new JTextField("North"); + north.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + clicked |= 1 << 1; + } + }); + window.add(north, BorderLayout.NORTH); + } + + @Override + public void doTest() throws Exception { + + robot.waitForIdle(); + + Point wls = window.getLocationOnScreen(); + Point ls; + int y; + ls = north.getLocationOnScreen(); + checkClick(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, 1); + + ls = center.getLocationOnScreen(); + checkClick(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, 2); + + ls = south.getLocationOnScreen(); + checkClick(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, 3); + + ls = center.getLocationOnScreen(); + checkClick(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, 2); + + ls = north.getLocationOnScreen(); + y = ls.y + north.getHeight() / 2; + checkClick(wls.x + 200 - (y - wls.y), y, 0); + + EventQueue.invokeAndWait(window::toFront); + robot.waitForIdle(); + + ls = center.getLocationOnScreen(); + y = ls.y + center.getHeight() / 2; + checkClick(wls.x + 200 - (y - wls.y), y, 0); + + EventQueue.invokeAndWait(window::toFront); + robot.waitForIdle(); + + ls = south.getLocationOnScreen(); + y = ls.y + south.getHeight() / 2; + checkClick(wls.x + 200 - (y - wls.y), y, 0); + + EventQueue.invokeAndWait(window::dispose); + EventQueue.invokeAndWait(background::dispose); + + robot.waitForIdle(); + } + + @Override + public void applyShape() { + Area shape = new Area(new Rectangle2D.Float(0, 0, 200, 200)); + GeneralPath gp; + gp = new GeneralPath(); + gp.moveTo(190, 0); + gp.lineTo(200, 0); + gp.lineTo(200, 10); + gp.lineTo(10, 200); + gp.lineTo(0, 200); + gp.lineTo(0, 190); + gp.closePath(); + shape.subtract(new Area(gp)); + + window.setShape(shape); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; + +/* + * @test + * @bug 7043845 + * @summary Check if shaped and per-pixel translucent window is dragged and + * resized by mouse correctly. + * Test Description: Check if PERPIXEL_TRANSLUCENT and PERPIXEL_TRANSPARENT + * translucency types are supported on the current platform. Proceed if + * they are supported. Create a window with some components in it, make + * window undecorated, apply shape in componentResized listener. The shape + * should match the window size; apply translucent background of 0 and have + * a gradient painted as background from fully-transparent to fully-opaque + * in componentResized listener. Drag and resize the window using AWT Robot + * and verify that shape and translucency are correctly applied with pixels + * checking. Make the window appear on top of a known background. Repeat + * this for JWindow, JDialog, JFrame. + * Expected Result: If PERPIXEL_TRANSLUCENT and PERPIXEL_TRANSPARENT translucency + * types are supported, the window should appear as specified with the + * expected shape and translucency. Window background should have + * translucent gradient in parts that are not clipped by shape, all the + * controls should be opaque. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main ShapedPerPixelTranslucentGradient + */ + +public class ShapedPerPixelTranslucentGradient extends Common { + + public static void main(String[] ignored) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT) + && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new ShapedPerPixelTranslucentGradient(windowClass).doTest(); + } + + public ShapedPerPixelTranslucentGradient(Class windowClass) throws Exception { + super(windowClass, 1.0f, 0f, true); + } + + public void doTest() throws Exception { + robot.waitForIdle(delay); + checkDynamic(); + } + + @Override + public void applyShape() { + applyDynamicShape(); + gradientWidth = window.getWidth(); + gradientHeight = window.getHeight(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; + +/* + * @test + * @summary Check if shaped, translucent and per-pixel translucent window is + * dragged and resized by mouse correctly. + * Test Description: Check if PERPIXEL_TRANSLUCENT, TRANSLUCENT and + * PERPIXEL_TRANSPARENT translucency types are supported on the current + * platform. Proceed if they are supported. Create a window with some + * components in it, make window undecorated, apply shape in componentResized + * listener. The shape should match the window size; apply opacity of 0.7, + * apply translucent background of 0 and have a gradient painted as + * background from fully-transparent to fully-opaque in componentResized + * listener. Drag and resize the window using AWT Robot and verify that + * shape and translucency are correctly applied with pixels checking. Make + * the window appear on top of a known background. Repeat this for JWindow, + * JDialog, JFrame. + * Expected Result: If PERPIXEL_TRANSLUCENT, TRANSLUCENT and PERPIXEL_TRANSPARENT + * translucency types are supported, the window should appear as specified + * with the expected shape and translucency. Window background should have + * translucent gradient in parts that are not clipped by shape, all the + * controls should be equally translucent. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main ShapedTranslucentPerPixelTranslucentGradient + */ + +public class ShapedTranslucentPerPixelTranslucentGradient extends Common { + + public static void main(String[] ignored) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT) + && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT) + && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new ShapedTranslucentPerPixelTranslucentGradient(windowClass).doTest(); + } + + public ShapedTranslucentPerPixelTranslucentGradient(Class windowClass) throws Exception { + super(windowClass, 0.7f, 0f, true); + } + + public void doTest() throws Exception { + robot.waitForIdle(delay); + checkDynamic(); + } + + @Override + public void applyShape() { + applyDynamicShape(); + gradientWidth = window.getWidth(); + gradientHeight = window.getHeight(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 8024627 + * @summary Check if a JComboBox present in a window set with opacity less than + * 1.0 shows a translucent drop down + * Test Description: Check if TRANSLUCENT translucency type is supported on the + * current platform. Proceed if supported. Show a window which contains an + * JComboBox and set with opacity less than 1.0. Another Window having a canvas + * component drawn with an image can be used as the background for the test + * window. Click on the ComboBox to show the drop down. Check if the drop down + * appears translucent. Repeat this for JWindow, JDialog and JFrame + * Expected Result: If TRANSLUCENT Translucency type is supported, the drop down + * should appear translucent. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main TranslucentJComboBox + */ + +public class TranslucentJComboBox extends Common { + + JComponent south; + JComponent center; + JPanel north; + volatile boolean southClicked = false; + + public static void main(String[] args) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new TranslucentJComboBox(windowClass).doTest(); + } + + public TranslucentJComboBox(Class windowClass) throws Exception { + super(windowClass, 0.3f, 1.0f, false); + } + + @Override + public void initBackgroundFrame() { + super.initBackgroundFrame(); + } + + @Override + public void createSwingComponents() { + Container contentPane = RootPaneContainer.class.cast(window).getContentPane(); + window.setLayout(new BorderLayout()); + + north = new JPanel(); + contentPane.add(north, BorderLayout.NORTH); + + center = new JList(new String [] { "Center" }); + contentPane.add(center, BorderLayout.CENTER); + + JComboBox jComboBox = new JComboBox(); + for(int i = 0; i < 20; i++) { + jComboBox.addItem("item " + i); + } + south = jComboBox; + + south.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + southClicked = true; + } + }); + contentPane.add(south, BorderLayout.SOUTH); + } + + + @Override + public void doTest() throws Exception { + robot.waitForIdle(delay); + // Make window an active + Point ls = north.getLocationOnScreen(); + robot.mouseMove(ls.x + north.getWidth()/2, ls.y + north.getHeight()/2); + robot.click(); + + // Invoke list + ls = south.getLocationOnScreen(); + + Point p1 = new Point( + (int) (ls.x + south.getWidth() * 0.75), + ls.y + south.getHeight() * 3); + + Point p2 = new Point( + (int) (ls.x + south.getWidth() * 0.75), + ls.y - south.getHeight() * 2); + + Color c1 = robot.getPixelColor(p1.x, p1.y); + Color c2 = robot.getPixelColor(p2.x, p2.y); + + int x = ls.x + south.getWidth()/2; + int y = ls.y + south.getHeight()/2; + + System.out.println("Trying to click point "+x+", "+y+ + ", looking for flag to trigger."); + + robot.mouseMove(x, y); + robot.waitForIdle(delay); + robot.click(); + robot.waitForIdle(delay); + + if (!southClicked) + throw new RuntimeException("Flag is not triggered for point "+x+", "+y+"!"); + + robot.waitForIdle(); + + Color c1b = robot.getPixelColor(p1.x, p1.y); + Color c2b = robot.getPixelColor(p2.x, p2.y); + + if (!c1.equals(c1b) && !south.getBackground().equals(c1b)) + throw new RuntimeException( + "Check for opaque drop down failed at point " + p1 + + ". Before click: " + c1 + ", after click: " + c1b + + ", expected is " + south.getBackground()); + + if (!c2.equals(c2b) && !south.getBackground().equals(c2b)) + throw new RuntimeException( + "Check for opaque drop down failed at point " + p2 + + ". Before click: " + c2 + ", after click: " + c2b + + ", expected is " + south.getBackground()); + + EventQueue.invokeAndWait(this::dispose); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; + +/* + * @test + * @summary Check if a per-pixel translucent and translucent window is dragged + * and resized by mouse correctly + * Test Description: Check if PERPIXEL_TRANSLUCENT and TRANSLUCENT translucency + * types are supported on the current platform. Proceed if they are supported. + * Create a window with some components in it, make window undecorated, apply + * opacity of 0.7, apply translucent background of 0 and have a gradient + * painted as background from fully-transparent to fully-opaque in + * componentResized listener. Drag and resize the window using AWT Robot and + * verify that translucency is correctly applied with pixels checking. Make + * the window appear on top of a known background. Repeat this for specified + * JWindow, JDialog, JFrame. + * Expected Result: If PERPIXEL_TRANSLUCENT and TRANSLUCENT translucency types + * are supported, the window should appear as specified with the translucency. + * Both window background and all the controls should be translucent but + * background should have a gradient in translucency while controls - not. + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main TranslucentPerPixelTranslucentGradient + */ + +public class TranslucentPerPixelTranslucentGradient extends Common { + + public static void main(String[] ignored) throws Exception { + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT) + && checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) + for (Class<Window> windowClass: WINDOWS_TO_TEST) + new TranslucentPerPixelTranslucentGradient(windowClass).doTest(); + } + + public TranslucentPerPixelTranslucentGradient(Class windowClass) throws Exception { + super(windowClass, 0.7f, 0f, true); + } + + public void doTest() throws Exception { + robot.waitForIdle(delay); + checkTranslucent(); + } + + @Override + public void applyShape() { + gradientWidth = window.getWidth(); + gradientHeight = window.getHeight(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentWindowClickSwing.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @summary Check if swing components present in a window set with opacity less + * than 1.0 appears translucent + * Test Description: Check if TRANSLUCENT Translucency type is supported for the + * current platform. Proceed if supported. Show a window containing some swing + * components and set it with opacity less than 1.0. Check if the swing components + * appear translucent and check if events trigger correctly for the components + * Expected Result: If TRANSLUCENT Translucency type is supported, the components + * should appear translucent showing the background. They should trigger events + * correctly + * @author mrkam + * @library ../../../../lib/testlibrary + * @build Common ExtendedRobot + * @run main TranslucentWindowClickSwing + */ + +public class TranslucentWindowClickSwing extends Common { + + private Component south; + private Component center; + private Component north; + + public static void main(String[] args) throws Exception{ + if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT)) + new TranslucentWindowClickSwing(JWindow.class).doTest(); + } + + public TranslucentWindowClickSwing(Class windowClass) throws Exception { + super(windowClass, 0.2f, 1.0f, false); + } + + @Override + public void createSwingComponents() { + south = new JButton("South"); + south.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { clicked |= 1 << 2; } + }); + window.add(south, BorderLayout.SOUTH); + + center = new JList(); + center.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { clicked |= 1 << 1; } + }); + window.add(center, BorderLayout.CENTER); + + north = new JTextField("North"); + north.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { clicked |= 1 << 0; } + }); + window.add(north, BorderLayout.NORTH); + } + + @Override + public void doTest() throws Exception { + Point ls; + robot.waitForIdle(); + + ls = north.getLocationOnScreen(); + checkClick(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, 0); + + ls = center.getLocationOnScreen(); + checkClick(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, 1); + + ls = center.getLocationOnScreen(); + checkClick(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, 1); + + ls = south.getLocationOnScreen(); + checkClick(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, 2); + + EventQueue.invokeAndWait(this::dispose); + robot.waitForIdle(); + } +}
--- a/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/lib/testlibrary/jsr292/com/oracle/testlibrary/jsr292/Helper.java Thu Sep 18 13:27:48 2014 -0700 @@ -52,7 +52,7 @@ public static final long TEST_LIMIT; static { String str = System.getProperty("testLimit"); - TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2_000L; + TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2000L; System.out.printf("-DtestLimit=%d%n", TEST_LIMIT); } @@ -116,6 +116,48 @@ return size <= lag ? null : calledLog.get(size - lag - 1); } + public static List<Class<?>> randomClasses(Class<?>[] classes, int size) { + List<Class<?>> result = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + result.add(classes[RNG.nextInt(classes.length)]); + } + return result; + } + + public static List<Class<?>> getParams(List<Class<?>> classes, + boolean isVararg, int argsCount) { + boolean unmodifiable = true; + List<Class<?>> result = classes.subList(0, + Math.min(argsCount, (MAX_ARITY / 2) - 1)); + int extra = 0; + if (argsCount >= MAX_ARITY / 2) { + result = new ArrayList<>(result); + unmodifiable = false; + extra = (int) result.stream().filter(Helper::isDoubleCost).count(); + int i = result.size(); + while (result.size() + extra < argsCount) { + Class<?> aClass = classes.get(i); + if (Helper.isDoubleCost(aClass)) { + ++extra; + if (result.size() + extra >= argsCount) { + break; + } + } + result.add(aClass); + } + } + if (isVararg && result.size() > 0) { + if (unmodifiable) { + result = new ArrayList<>(result); + } + int last = result.size() - 1; + Class<?> aClass = result.get(last); + aClass = Array.newInstance(aClass, 2).getClass(); + result.set(last, aClass); + } + return result; + } + public static MethodHandle addTrailingArgs(MethodHandle target, int nargs, List<Class<?>> classes) { int targetLen = target.type().parameterCount(); @@ -230,7 +272,7 @@ return randomArgs(params.toArray(new Class<?>[params.size()])); } - private static Object castToWrapper(Object value, Class<?> dst) { + public static Object castToWrapper(Object value, Class<?> dst) { Object wrap = null; if (value instanceof Number) { wrap = castToWrapperOrNull(((Number) value).longValue(), dst); @@ -268,7 +310,7 @@ if (dst == byte.class || dst == Byte.class) { return (byte) (value); } - if (dst == boolean.class || dst == boolean.class) { + if (dst == boolean.class || dst == Boolean.class) { return ((value % 29) & 1) == 0; } return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/java2d/OpenGL/DrawHugeImageTest.java Thu Sep 18 13:27:48 2014 -0700 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8040617 + * @summary Test verifies that an attempt to get an accelerated copy of + * a huge buffered image does not result in an OOME. + * + * @run main DrawHugeImageTest + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; + +public class DrawHugeImageTest { + // we have to render the BI source several times in order + // to get an accelerated copy to be used. + static { + System.setProperty("sun.java2d.accthreshold", "1"); + } + private static final int max_rendering_count = 5; + + private static final Color srcColor = Color.red; + private static final Color dstColor = Color.blue; + + public static void main(String[] args) { + BufferedImage src = createSrc(); + + VolatileImage dst = createDst(); + System.out.println("Dst: " + dst); + boolean status; + int count = max_rendering_count; + + do { + System.out.println("render image: " + (max_rendering_count - count)); + status = render(src, dst); + + } while (status && count-- > 0); + + if (!status || count > 0) { + throw new RuntimeException("Test failed: " + count); + } + } + + private static boolean render(BufferedImage src, VolatileImage dst) { + int cnt = 5; + do { + Graphics2D g = dst.createGraphics(); + g.setColor(dstColor); + g.fillRect(0, 0, dst.getWidth(), dst.getHeight()); + g.drawImage(src, 0, 0, null); + g.dispose(); + } while (dst.contentsLost() && (--cnt > 0)); + + if (cnt == 0) { + System.err.println("Test failed: unable to render to volatile destination"); + return false; + } + + BufferedImage s = dst.getSnapshot(); + + return s.getRGB(1,1) == srcColor.getRGB(); + } + + private static BufferedImage createSrc() { + final int w = 20000; + final int h = 5; + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR); + Graphics2D g = img.createGraphics(); + g.setColor(srcColor); + g.fillRect(0, 0, w, h); + g.dispose(); + + return img; + } + + private static VolatileImage createDst() { + GraphicsConfiguration gc = + GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); + + return gc.createCompatibleVolatileImage(200, 200); + } +}
--- a/test/sun/security/krb5/auto/Context.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/sun/security/krb5/auto/Context.java Thu Sep 18 13:27:48 2014 -0700 @@ -22,15 +22,14 @@ */ import com.sun.security.auth.module.Krb5LoginModule; -import java.security.Key; + +import java.lang.reflect.Method; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Arrays; -import java.util.Base64; import java.util.HashMap; import java.util.Map; import javax.security.auth.Subject; -import javax.security.auth.kerberos.KerberosCredMessage; import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosTicket; import javax.security.auth.login.LoginContext; @@ -41,10 +40,6 @@ import org.ietf.jgss.GSSName; import org.ietf.jgss.MessageProp; import org.ietf.jgss.Oid; -import com.sun.security.jgss.ExtendedGSSContext; -import com.sun.security.jgss.InquireType; -import com.sun.security.jgss.AuthorizationDataEntry; -import com.sun.security.jgss.ExtendedGSSCredential; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.security.Principal; @@ -78,7 +73,7 @@ public class Context { private Subject s; - private ExtendedGSSContext x; + private GSSContext x; private String name; private GSSCredential cred; // see static method delegated(). @@ -143,7 +138,6 @@ /** * Logins with username/password as an existing Subject. The * same subject can be used multiple times to simulate multiple logins. - * @param s existing subject */ public static Context fromUserPass(Subject s, String user, char[] pass, boolean storeKey) throws Exception { @@ -222,7 +216,7 @@ @Override public byte[] run(Context me, byte[] dummy) throws Exception { GSSManager m = GSSManager.getInstance(); - me.x = (ExtendedGSSContext)m.createContext( + me.x = m.createContext( target.indexOf('@') < 0 ? m.createName(target, null) : m.createName(target, GSSName.NT_HOSTBASED_SERVICE), @@ -267,7 +261,7 @@ asInitiator? GSSCredential.INITIATE_AND_ACCEPT: GSSCredential.ACCEPT_ONLY); - me.x = (ExtendedGSSContext)m.createContext(me.cred); + me.x = m.createContext(me.cred); return null; } }, null); @@ -285,7 +279,7 @@ * * @return the GSSContext object */ - public ExtendedGSSContext x() { + public GSSContext x() { return x; } @@ -339,7 +333,7 @@ */ public void status() throws Exception { System.out.println("STATUS OF " + name.toUpperCase()); - try { + if (x != null) { StringBuffer sb = new StringBuffer(); if (x.getAnonymityState()) { sb.append("anon, "); @@ -362,19 +356,15 @@ if (x.getSequenceDetState()) { sb.append("seq det, "); } - if (x instanceof ExtendedGSSContext) { - if (((ExtendedGSSContext)x).getDelegPolicyState()) { - sb.append("deleg policy, "); - } + System.out.println(" Context status of " + name + ": " + sb.toString()); + if (x.isProtReady() || x.isEstablished()) { + System.out.println(" " + x.getSrcName() + " -> " + x.getTargName()); } - System.out.println("Context status of " + name + ": " + sb.toString()); - System.out.println(x.getSrcName() + " -> " + x.getTargName()); - } catch (Exception e) { - ;// Don't care } + xstatus(); if (s != null) { System.out.println("====== START SUBJECT CONTENT ====="); - for (Principal p: s.getPrincipals()) { + for (Principal p : s.getPrincipals()) { System.out.println(" Principal: " + p); } for (Object o : s.getPublicCredentials()) { @@ -405,51 +395,42 @@ } System.out.println("====== END SUBJECT CONTENT ====="); } - if (x != null && x instanceof ExtendedGSSContext) { - if (x.isEstablished()) { - ExtendedGSSContext ex = (ExtendedGSSContext)x; - Key k = (Key)ex.inquireSecContext( - InquireType.KRB5_GET_SESSION_KEY); - if (k == null) { - throw new Exception("(Old) Session key cannot be null"); - } - System.out.println("(Old) Session key is: " + k); - Key k2 = (Key)ex.inquireSecContext( - InquireType.KRB5_GET_SESSION_KEY_EX); - if (k2 == null) { - throw new Exception("Session key cannot be null"); - } - System.out.println("Session key is: " + k); - boolean[] flags = (boolean[])ex.inquireSecContext( - InquireType.KRB5_GET_TKT_FLAGS); - if (flags == null) { - throw new Exception("Ticket flags cannot be null"); + } + + public void xstatus() throws Exception { + System.out.println(" Extended context status:"); + if (x != null) { + try { + Class<?> clazz = Class.forName("com.sun.security.jgss.ExtendedGSSContext"); + if (clazz.isAssignableFrom(x.getClass())) { + if (clazz.getMethod("getDelegPolicyState").invoke(x) == Boolean.TRUE) { + System.out.println(" deleg policy"); + } + if (x.isEstablished()) { + Class<?> inqType = Class.forName("com.sun.security.jgss.InquireType"); + Method inqMethod = clazz.getMethod("inquireSecContext", inqType); + for (Object o : inqType.getEnumConstants()) { + System.out.println(" " + o + ":"); + try { + System.out.println(" " + inqMethod.invoke(x, o)); + } catch (Exception e) { + System.out.println(e.getCause()); + } + } + } } - System.out.println("Ticket flags is: " + Arrays.toString(flags)); - String authTime = (String)ex.inquireSecContext( - InquireType.KRB5_GET_AUTHTIME); - if (authTime == null) { - throw new Exception("Auth time cannot be null"); - } - System.out.println("AuthTime is: " + authTime); - if (!x.isInitiator()) { - AuthorizationDataEntry[] ad = (AuthorizationDataEntry[])ex.inquireSecContext( - InquireType.KRB5_GET_AUTHZ_DATA); - System.out.println("AuthzData is: " + Arrays.toString(ad)); + } catch (ClassNotFoundException cnfe) { + System.out.println(" -- ExtendedGSSContext not available"); + } + } + if (cred != null) { + try { + Class<?> clazz2 = Class.forName("com.sun.security.jgss.ExtendedGSSCredential"); + if (!clazz2.isAssignableFrom(cred.getClass())) { + throw new Exception("cred is not extended"); } - try { - KerberosCredMessage tok = (KerberosCredMessage)ex.inquireSecContext( - InquireType.KRB5_GET_KRB_CRED); - System.out.println("KRB_CRED is " + - (tok == null?"not ":"") + "available"); - if (tok != null) { - System.out.println("From " + tok.getSender() + " to " - + tok.getRecipient()); - System.out.println(Base64.getEncoder().encodeToString(tok.getEncoded())); - } - } catch (Exception e) { - System.out.println("KRB_CRED is not available: " + e); - } + } catch (ClassNotFoundException cnfe) { + System.out.println(" -- ExtendedGSSCredential not available"); } } } @@ -591,7 +572,10 @@ if (Context.this.cred == null) { Context.this.cred = m.createCredential(GSSCredential.INITIATE_ONLY); } - return ((ExtendedGSSCredential)Context.this.cred).impersonate(other); + return (GSSCredential) + Class.forName("com.sun.security.jgss.ExtendedGSSCredential") + .getMethod("impersonate", GSSName.class) + .invoke(Context.this.cred, other); } }); Context out = new Context();
--- a/test/sun/security/krb5/auto/NewInquireTypes.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/sun/security/krb5/auto/NewInquireTypes.java Thu Sep 18 13:27:48 2014 -0700 @@ -29,6 +29,7 @@ * @run main/othervm NewInquireTypes */ +import com.sun.security.jgss.ExtendedGSSContext; import com.sun.security.jgss.InquireType; import sun.security.jgss.GSSUtil; import sun.security.krb5.internal.KRBCred; @@ -52,10 +53,12 @@ Context.handshake(c, s); + ExtendedGSSContext ctxt = (ExtendedGSSContext)c.x(); EncryptionKey key = (EncryptionKey) - c.x().inquireSecContext(InquireType.KRB5_GET_SESSION_KEY_EX); + ctxt.inquireSecContext(InquireType.KRB5_GET_SESSION_KEY_EX); KerberosCredMessage cred = (KerberosCredMessage) - c.x().inquireSecContext(InquireType.KRB5_GET_KRB_CRED); + ctxt.inquireSecContext(InquireType.KRB5_GET_KRB_CRED); + c.status(); // Confirm the KRB_CRED message is encrypted with the session key. new KRBCred(cred.getEncoded()).encPart.decrypt(
--- a/test/sun/security/krb5/auto/OkAsDelegate.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/sun/security/krb5/auto/OkAsDelegate.java Thu Sep 18 13:27:48 2014 -0700 @@ -48,6 +48,7 @@ * @summary Support OK-AS-DELEGATE flag */ import com.sun.security.jgss.ExtendedGSSContext; +import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSException; import org.ietf.jgss.Oid; @@ -102,7 +103,7 @@ cx.requestCredDeleg(requestDelegState); cx.requestDelegPolicy(requestDelegPolicyState); s.startAsServer(mech); - ExtendedGSSContext sx = (ExtendedGSSContext)s.x(); + GSSContext sx = s.x(); Context.handshake(c, s);
--- a/test/sun/security/krb5/auto/OkAsDelegateXRealm.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/sun/security/krb5/auto/OkAsDelegateXRealm.java Thu Sep 18 13:27:48 2014 -0700 @@ -42,6 +42,8 @@ import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; + +import com.sun.security.jgss.ExtendedGSSContext; import org.ietf.jgss.GSSException; import sun.security.jgss.GSSUtil; import sun.security.krb5.Config; @@ -129,7 +131,7 @@ for (int i=0; i<2; i++) { c.startAsClient("host@host.r3.local", GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); - c.x().requestDelegPolicy(true); + ((ExtendedGSSContext)c.x()).requestDelegPolicy(true); Context.handshake(c, s); boolean succeed = true;
--- a/test/sun/security/krb5/auto/SSL.java Wed Sep 17 22:56:07 2014 -0700 +++ b/test/sun/security/krb5/auto/SSL.java Thu Sep 18 13:27:48 2014 -0700 @@ -186,13 +186,13 @@ // Client checks "initiate", then server gets the name // and checks "accept". Second connection resume. if (!permChecks.equals("IA")) { - throw new Exception(); + throw new Exception(permChecks); } } else { // For bound, JAAS checks "accept" once. Server checks again, // client then checks "initiate". Second connection resume. if (!permChecks.equals("AAI")) { - throw new Exception(); + throw new Exception(permChecks); } } }