diff --git a/.hgtags b/.hgtags index 93a4114bab93d2be24bbb8c7e1453e13813a83d9..92fe10a1d9a4e4550859d0cc79b1677fc9d06982 100644 --- a/.hgtags +++ b/.hgtags @@ -201,3 +201,5 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70 b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77 00b7535d743f83eda763c10b3c9ea19ba4b67f55 jdk8-b78 c933505d75c2a0a671f06d6dac5d2237a9228d2d jdk8-b79 +dfb40f066c6ce129822f0f5dc2ac89173808781a jdk8-b80 +c0f8022eba536dcdc8aae659005b33f3982b9368 jdk8-b81 diff --git a/make/common/shared/Defs-utils.gmk b/make/common/shared/Defs-utils.gmk index a210de015b754a32e849a03e30ab32e92eb17dcb..a14a08d11980e9e5e8ce420a98b6df80cf769ea9 100644 --- a/make/common/shared/Defs-utils.gmk +++ b/make/common/shared/Defs-utils.gmk @@ -74,24 +74,24 @@ ifeq ($(PLATFORM),macosx) UTILS_DEVTOOL_PATH=$(DEVTOOLS_PATH) endif -# Utilities -ifdef CROSS_COMPILE_ARCH - AR = $(COMPILER_PATH)ar - AS = $(COMPILER_PATH)as - LD = $(COMPILER_PATH)ld - MCS = $(COMPILER_PATH)mcs - NM = $(COMPILER_PATH)nm - STRIP = $(COMPILER_PATH)strip -endif - -ifeq ($(PLATFORM),solaris) - AR = $(UTILS_CCS_BIN_PATH)ar - AS = $(UTILS_CCS_BIN_PATH)as - LD = $(UTILS_CCS_BIN_PATH)ld - MCS = $(UTILS_CCS_BIN_PATH)mcs - NM = $(UTILS_CCS_BIN_PATH)nm - STRIP = $(UTILS_CCS_BIN_PATH)strip -endif +ifndef CONFIGURE_BUILD + # Utilities + ifdef CROSS_COMPILE_ARCH + AR = $(COMPILER_PATH)ar + AS = $(COMPILER_PATH)as + LD = $(COMPILER_PATH)ld + MCS = $(COMPILER_PATH)mcs + NM = $(COMPILER_PATH)nm + STRIP = $(COMPILER_PATH)strip + else + AR = $(UTILS_CCS_BIN_PATH)ar + AS = $(UTILS_CCS_BIN_PATH)as + LD = $(UTILS_CCS_BIN_PATH)ld + MCS = $(UTILS_CCS_BIN_PATH)mcs + NM = $(UTILS_CCS_BIN_PATH)nm + STRIP = $(UTILS_CCS_BIN_PATH)strip + endif +endif # CONFIGURE_BUILD ADB = $(UTILS_COMMAND_PATH)adb BASENAME = $(UTILS_COMMAND_PATH)basename diff --git a/make/sun/cmm/lcms/Makefile b/make/sun/cmm/lcms/Makefile index 24fde37fba03bcc5894db836c2d3efdf7755a7c4..85b02e4960ec3c5ea84e560352da5fd557790b95 100644 --- a/make/sun/cmm/lcms/Makefile +++ b/make/sun/cmm/lcms/Makefile @@ -28,6 +28,9 @@ PACKAGE = sun.java2d.cmm.lcms LIBRARY = lcms PRODUCT = sun +# Use highest level of optimization on this library +OPTIMIZATION_LEVEL = HIGHEST + include $(BUILDDIR)/common/Defs.gmk # diff --git a/make/sun/cmm/lcms/mapfile-vers b/make/sun/cmm/lcms/mapfile-vers index ac4e7458b37123375dd604bcb5af17f189e64b5b..3d9074f746d99696605c52877c614c2c04d684dc 100644 --- a/make/sun/cmm/lcms/mapfile-vers +++ b/make/sun/cmm/lcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/makefiles/CompileNativeLibraries.gmk b/makefiles/CompileNativeLibraries.gmk index c6c50c61e7876a283ac495834b9718b725b7207b..790a456ab98b4fa692e95874ed1b238065935559 100644 --- a/makefiles/CompileNativeLibraries.gmk +++ b/makefiles/CompileNativeLibraries.gmk @@ -464,12 +464,13 @@ ifeq ($(OPENJDK_TARGET_OS),windows) $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/d3d + LIBAWT_CFLAGS+=-I$(DXSDK_INCLUDE_PATH) else LIBAWT_DIRS+=\ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/x11 endif -LIBAWT_CFLAGS:=-D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \ +LIBAWT_CFLAGS+=-D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \ $(X_CFLAGS) \ $(foreach dir,$(LIBAWT_DIRS),-I$(dir)) @@ -1218,7 +1219,7 @@ ifdef OPENJDK OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\ SRC:=$(JDK_TOPDIR)/src/share/native/sun/java2d/cmm/lcms,\ LANG:=C,\ - OPTIMIZATION:=LOW, \ + OPTIMIZATION:=HIGHEST, \ CFLAGS:=$(filter-out -xc99=%none,$(CFLAGS_JDKLIB)) \ $(SHARED_LIBRARY_FLAGS) \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ @@ -1461,7 +1462,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) -I$(JDK_TOPDIR)/src/share/native/sun/awt/debug \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ -I$(JDK_TOPDIR)/src/share/native/sun/awt/image/cvutils \ - -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows, \ + -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ + -I$(DXSDK_INCLUDE_PATH), \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(KERNEL32_LIB) $(LDFLAGS_CXX_JDK) \ advapi32.lib $(WIN_AWT_LIB),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX),\ @@ -2905,7 +2907,8 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJSOUNDDS,\ OPTIMIZATION:=LOW, \ CFLAGS:=$(CFLAGS_JDKLIB) \ $(LIBJSOUND_CFLAGS) \ - -DUSE_DAUDIO=TRUE, \ + -DUSE_DAUDIO=TRUE \ + -I$(DXSDK_INCLUDE_PATH), \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX) dsound.lib winmm.lib user32.lib ole32.lib,\ diff --git a/makefiles/Images.gmk b/makefiles/Images.gmk index 2d25473bce4d07616585418b696cb4a15f2ba292..4a3a23525d16bec461aefd02b14e7a4c2383c8e7 100644 --- a/makefiles/Images.gmk +++ b/makefiles/Images.gmk @@ -264,6 +264,13 @@ $(foreach f,$(filter $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_ISADIR)/%,$(JDK_JD $(foreach f,$(filter $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_ISADIR)/%,$(JDKJRE_JDKOUT_LIB_LIST)),\ $(eval $(call AddFileToCopy,$(JDK_OUTPUTDIR),$(JDK_OVERLAY_IMAGE_DIR)/jre,$f,JDKJRE_OVERLAY_LIB_TARGETS))) +ifneq ($(PROFILE),) +# Files in lib$(PROFILE) are excluded from the generic copying routines so +# we have to add them back in here +$(foreach f,$(CUSTOM_PROFILE_JARS),\ + $(eval $(call AddFileToCopy,$(IMAGES_OUTPUTDIR)/lib$(PROFILE),$(JRE_IMAGE_DIR)/lib,$f,JRE_LIB_TARGETS))) +endif + # CTE plugin security change require new empty directory lib/applet $(JRE_IMAGE_DIR)/lib/applet: $(ECHO) $(LOG_INFO) Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@) @@ -739,11 +746,6 @@ jdk-overlay-image: $(JDK_OVERLAY_BIN_TARGETS) $(JDKJRE_OVERLAY_BIN_TARGETS) \ $(JDKJRE_OVERLAY_STRIP_LIST) $(JDK_OVERLAY_BIN_STRIP_LIST) ifneq ($(PROFILE),) -# Files in lib$(PROFILE) are excluded from the generic copying routines so -# we have to add them back in here -$(foreach f,$(CUSTOM_PROFILE_JARS),\ - $(eval $(call AddFileToCopy,$(IMAGES_OUTPUTDIR)/lib$(PROFILE),$(JRE_IMAGE_DIR)/lib,$f,JRE_LIB_TARGETS))) - PROFILE_IMAGE_JARS := $(filter %.jar, $(JRE_LIB_TARGETS)) PROFILE_IMAGE_JARS_CHECKED := $(IMAGES_OUTPUTDIR)/lib$(PROFILE)/_jars_checked diff --git a/makefiles/mapfiles/liblcms/mapfile-vers b/makefiles/mapfiles/liblcms/mapfile-vers index 04703dffc5aa285af5dd91cb7e6702c788ffe3a2..024511423d3b4f6e4239dc6beb2fe142bf0571b3 100644 --- a/makefiles/mapfiles/liblcms/mapfile-vers +++ b/makefiles/mapfiles/liblcms/mapfile-vers @@ -27,13 +27,12 @@ SUNWprivate_1.1 { global: - Java_sun_java2d_cmm_lcms_LCMS_loadProfile; - Java_sun_java2d_cmm_lcms_LCMS_freeProfile; + Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; + Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileData; - Java_sun_java2d_cmm_lcms_LCMS_getTagSize; - Java_sun_java2d_cmm_lcms_LCMS_getTagData; - Java_sun_java2d_cmm_lcms_LCMS_setTagData; + Java_sun_java2d_cmm_lcms_LCMS_getTagNative; + Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_getProfileID; Java_sun_java2d_cmm_lcms_LCMS_initLCMS; diff --git a/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java index a4831d29ea90e751c20fd052b25d62a0f1eddd62..8e8527f65413098bf0933afea8e4d994b0675f0e 100644 --- a/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,6 @@ import javax.swing.border.Border; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; -import com.apple.laf.ClientPropertyApplicator; import com.apple.laf.ClientPropertyApplicator.Property; import apple.laf.JRSUIConstants.Size; @@ -142,35 +141,46 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { return new AquaComboBoxEditor(); } - class AquaComboBoxEditor extends BasicComboBoxEditor implements UIResource, DocumentListener { - protected AquaComboBoxEditor() { + final class AquaComboBoxEditor extends BasicComboBoxEditor + implements UIResource, DocumentListener { + + AquaComboBoxEditor() { super(); editor = new AquaCustomComboTextField(); editor.addFocusListener(this); editor.getDocument().addDocumentListener(this); } + @Override public void focusGained(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void focusLost(final FocusEvent e) { - arrowButton.repaint(); + if (arrowButton != null) { + arrowButton.repaint(); + } } + @Override public void changedUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void insertUpdate(final DocumentEvent e) { editorTextChanged(); } + @Override public void removeUpdate(final DocumentEvent e) { editorTextChanged(); } - protected void editorTextChanged() { + private void editorTextChanged() { if (!popup.isVisible()) return; final Object text = editor.getText(); diff --git a/src/macosx/classes/sun/awt/CGraphicsConfig.java b/src/macosx/classes/sun/awt/CGraphicsConfig.java index fb37d01209ccd803cdb855e803be220972be6a8a..055af2edb22b674673cdf69a13d8a42e959e48fc 100644 --- a/src/macosx/classes/sun/awt/CGraphicsConfig.java +++ b/src/macosx/classes/sun/awt/CGraphicsConfig.java @@ -53,7 +53,7 @@ public abstract class CGraphicsConfig extends GraphicsConfiguration @Override public Rectangle getBounds() { - final Rectangle2D nativeBounds = nativeGetBounds(device.getCoreGraphicsScreen()); + final Rectangle2D nativeBounds = nativeGetBounds(device.getCGDisplayID()); return nativeBounds.getBounds(); // does integer rounding } diff --git a/src/macosx/classes/sun/awt/CGraphicsDevice.java b/src/macosx/classes/sun/awt/CGraphicsDevice.java index bcb24ea46f7dd7dd1f4823db0f3cbc6b42acd8a1..1a5e22af582970c4a1524ec26d70b4eda2737957 100644 --- a/src/macosx/classes/sun/awt/CGraphicsDevice.java +++ b/src/macosx/classes/sun/awt/CGraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,12 @@ package sun.awt; +import java.awt.AWTPermission; +import java.awt.DisplayMode; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.Insets; import java.awt.Window; -import java.awt.AWTPermission; -import java.awt.DisplayMode; import java.util.Objects; import sun.java2d.opengl.CGLGraphicsConfig; @@ -58,9 +59,12 @@ public final class CGraphicsDevice extends GraphicsDevice { } /** + * Returns CGDirectDisplayID, which is the same id as @"NSScreenNumber" in + * NSScreen. + * * @return CoreGraphics display id. */ - public int getCoreGraphicsScreen() { + public int getCGDisplayID() { return displayID; } @@ -107,8 +111,9 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetYResolution(displayID); } - private static native double nativeGetXResolution(int displayID); - private static native double nativeGetYResolution(int displayID); + public Insets getScreenInsets() { + return nativeGetScreenInsets(displayID); + } /** * Enters full-screen mode, or returns to windowed mode. @@ -214,9 +219,15 @@ public final class CGraphicsDevice extends GraphicsDevice { return nativeGetDisplayModes(displayID); } - private native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); + private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); + + private static native DisplayMode nativeGetDisplayMode(int displayID); + + private static native DisplayMode[] nativeGetDisplayModes(int displayID); - private native DisplayMode nativeGetDisplayMode(int displayID); + private static native double nativeGetXResolution(int displayID); + + private static native double nativeGetYResolution(int displayID); - private native DisplayMode[] nativeGetDisplayModes(int displayID); + private static native Insets nativeGetScreenInsets(int displayID); } diff --git a/src/macosx/classes/sun/font/CStrike.java b/src/macosx/classes/sun/font/CStrike.java index 61fe234cb297f04afd941bfd735ef208e569df54..9635b85a1de72370d0c7d85704349ae25ea6621b 100644 --- a/src/macosx/classes/sun/font/CStrike.java +++ b/src/macosx/classes/sun/font/CStrike.java @@ -500,7 +500,10 @@ public class CStrike extends FontStrike { final Iterator i = generalCache.values().iterator(); while (i.hasNext()) { final long longValue = i.next().longValue(); - if (longValue != -1 && longValue != 0) StrikeCache.freeLongPointer(longValue); + if (longValue != -1 && longValue != 0) { + removeGlyphInfoFromCache(longValue); + StrikeCache.freeLongPointer(longValue); + } } } @@ -512,7 +515,10 @@ public class CStrike extends FontStrike { private static void disposeLongArray(final long[] longArray) { for (int i = 0; i < longArray.length; i++) { final long ptr = longArray[i]; - if (ptr != 0 && ptr != -1) StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + if (ptr != 0 && ptr != -1) { + removeGlyphInfoFromCache(ptr); + StrikeCache.freeLongPointer(ptr); // free's the native struct pointer + } } } diff --git a/src/macosx/classes/sun/font/CStrikeDisposer.java b/src/macosx/classes/sun/font/CStrikeDisposer.java index 7357ea6bd4240b4525e7777b54da8e79c7513ed8..661bd6a7b421d851e52ef526a7ffa2ccbdf49d81 100644 --- a/src/macosx/classes/sun/font/CStrikeDisposer.java +++ b/src/macosx/classes/sun/font/CStrikeDisposer.java @@ -85,4 +85,6 @@ class CStrikeDisposer extends FontStrikeDisposer { } private native void freeNativeScalerContext(long pContext); + + protected static native void removeGlyphInfoFromCache(long glyphInfo); } diff --git a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java index 230f7057927ec828836e563effeab6dc0dba7023..c8539a8e3f6d02cc4ffdd7106044cf94def36b46 100644 --- a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java +++ b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java @@ -80,10 +80,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig private ContextCapabilities oglCaps; private OGLContext context; private final Object disposerReferent = new Object(); - - public static native int getDefaultPixFmt(int screennum); private static native boolean initCGL(); - private static native long getCGLConfigInfo(int screennum, int visualnum, + private static native long getCGLConfigInfo(int displayID, int visualnum, int swapInterval); private static native int getOGLCapabilities(long configInfo); @@ -137,15 +135,16 @@ public final class CGLGraphicsConfig extends CGraphicsConfig // Java-level context and flush the queue... OGLContext.invalidateCurrentContext(); - cfginfo = getCGLConfigInfo(device.getCoreGraphicsScreen(), pixfmt, + cfginfo = getCGLConfigInfo(device.getCGDisplayID(), pixfmt, kOpenGLSwapInterval); - - OGLContext.setScratchSurface(cfginfo); - rq.flushAndInvokeNow(new Runnable() { - public void run() { - ids[0] = OGLContext.getOGLIdString(); - } - }); + if (cfginfo != 0L) { + OGLContext.setScratchSurface(cfginfo); + rq.flushAndInvokeNow(new Runnable() { + public void run() { + ids[0] = OGLContext.getOGLIdString(); + } + }); + } } finally { rq.unlock(); } @@ -253,8 +252,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public String toString() { - int screen = getDevice().getCoreGraphicsScreen(); - return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]"); + int displayID = getDevice().getCGDisplayID(); + return ("CGLGraphicsConfig[dev="+displayID+",pixfmt="+pixfmt+"]"); } @Override @@ -413,8 +412,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig @Override public void addDeviceEventListener(AccelDeviceEventListener l) { - int screen = getDevice().getCoreGraphicsScreen(); - AccelDeviceEventNotifier.addListener(l, screen); + int displayID = getDevice().getCGDisplayID(); + AccelDeviceEventNotifier.addListener(l, displayID); } @Override diff --git a/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/src/macosx/classes/sun/lwawt/LWComponentPeer.java index aa9b798c617df75d61f76b64120d89b89b84a9bc..052b91726b697bcfe8490ab0112e75c730566095 100644 --- a/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -439,7 +439,7 @@ public abstract class LWComponentPeer } @Override - public final Graphics getGraphics() { + public Graphics getGraphics() { final Graphics g = getOnscreenGraphics(); if (g != null) { synchronized (getPeerTreeLock()){ @@ -1227,10 +1227,10 @@ public abstract class LWComponentPeer } protected void sendEventToDelegate(final AWTEvent e) { + if (getDelegate() == null || !isShowing() || !isEnabled()) { + return; + } synchronized (getDelegateLock()) { - if (getDelegate() == null || !isShowing() || !isEnabled()) { - return; - } AWTEvent delegateEvent = createDelegateEvent(e); if (delegateEvent != null) { AWTAccessor.getComponentAccessor() @@ -1244,7 +1244,12 @@ public abstract class LWComponentPeer } } - protected AWTEvent createDelegateEvent(AWTEvent e) { + /** + * Changes the target of the AWTEvent from awt component to appropriate + * swing delegate. + */ + private AWTEvent createDelegateEvent(final AWTEvent e) { + // TODO modifiers should be changed to getModifiers()|getModifiersEx()? AWTEvent delegateEvent = null; if (e instanceof MouseWheelEvent) { MouseWheelEvent me = (MouseWheelEvent) e; diff --git a/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java new file mode 100644 index 0000000000000000000000000000000000000000..90e2e88c44191bc66d644bde239950e56b6d3964 --- /dev/null +++ b/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt; + +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.dnd.DropTarget; + +import sun.awt.CausedFocusEvent; +import sun.awt.LightweightFrame; + +public class LWLightweightFramePeer extends LWWindowPeer { + + public LWLightweightFramePeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + super(target, platformComponent, platformWindow, LWWindowPeer.PeerType.LW_FRAME); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)getTarget(); + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + protected void setVisibleImpl(final boolean visible) { + } + + @Override + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + if (!focusAllowedFor()) { + return false; + } + if (getPlatformWindow().rejectFocusRequest(cause)) { + return false; + } + + Window opposite = LWKeyboardFocusManagerPeer.getInstance(). + getCurrentFocusedWindow(); + + changeFocusedWindow(true, opposite); + + return true; + } + + @Override + public Point getLocationOnScreen() { + Rectangle bounds = getBounds(); + return new Point(bounds.x, bounds.y); // todo + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public void setBounds(int x, int y, int w, int h, int op) { + setBounds(x, y, w, h, op, true, false); + } + + @Override + public void updateCursorImmediately() { + // TODO: tries to switch to the awt/fx toolkit thread and causes a deadlock on macosx + } + + @Override + public void addDropTarget(DropTarget dt) { + } + + @Override + public void removeDropTarget(DropTarget dt) { + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/src/macosx/classes/sun/lwawt/LWToolkit.java b/src/macosx/classes/sun/lwawt/LWToolkit.java index 89f39fccbf8aadef63dc184902c93773891f2562..cad6e4353bafabe0b4fb6eaa084826b1c21b3cdf 100644 --- a/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -218,6 +218,23 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { return peer; } + private LWLightweightFramePeer createDelegatedLwPeer(LightweightFrame target, + PlatformComponent platformComponent, + PlatformWindow platformWindow) + { + LWLightweightFramePeer peer = new LWLightweightFramePeer(target, platformComponent, platformWindow); + targetCreatedPeer(target, peer); + peer.initialize(); + return peer; + } + + @Override + public FramePeer createLightweightFrame(LightweightFrame target) { + PlatformComponent platformComponent = createLwPlatformComponent(); + PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.LW_FRAME); + return createDelegatedLwPeer(target, platformComponent, platformWindow); + } + @Override public WindowPeer createWindow(Window target) { PlatformComponent platformComponent = createPlatformComponent(); @@ -502,6 +519,8 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { protected abstract PlatformComponent createPlatformComponent(); + protected abstract PlatformComponent createLwPlatformComponent(); + protected abstract FileDialogPeer createFileDialogPeer(FileDialog target); // ---- UTILITY METHODS ---- // diff --git a/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 5b19788f2447489fc8644b1fc2d016a326ed4071..d50335f7cd5d9860e43aa05a02fb1c101e01e900 100644 --- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -48,7 +48,8 @@ public class LWWindowPeer FRAME, DIALOG, EMBEDDED_FRAME, - VIEW_EMBEDDED_FRAME + VIEW_EMBEDDED_FRAME, + LW_FRAME } private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWWindowPeer"); @@ -1090,7 +1091,7 @@ public class LWWindowPeer return platformWindow.requestWindowFocus(); } - private boolean focusAllowedFor() { + protected boolean focusAllowedFor() { Window window = getTarget(); // TODO: check if modal blocked return window.isVisible() && window.isEnabled() && isFocusableWindow(); @@ -1113,10 +1114,15 @@ public class LWWindowPeer return !(window instanceof Dialog || window instanceof Frame); } + @Override + public void emulateActivation(boolean activate) { + changeFocusedWindow(activate, null); + } + /* * Changes focused window on java level. */ - private void changeFocusedWindow(boolean becomesFocused, Window opposite) { + protected void changeFocusedWindow(boolean becomesFocused, Window opposite) { if (focusLog.isLoggable(PlatformLogger.FINE)) { focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this); } diff --git a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java index 181d08472254f52587493dc1347706fff355e32c..0f32d3178fd326c4db6ac04f0ac4884bdc23bd60 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java +++ b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java @@ -128,6 +128,15 @@ final class CDropTargetContextPeer extends SunDropTargetContextPeer { } } + @Override + protected int postDropTargetEvent(Component component, int x, int y, int dropAction, + int actions, long[] formats, long nativeCtxt, int eventID, + boolean dispatchType) { + // On MacOS X all the DnD events should be synchronous + return super.postDropTargetEvent(component, x, y, dropAction, actions, formats, nativeCtxt, + eventID, SunDropTargetContextPeer.DISPATCH_SYNC); + } + // Signal drop complete: protected void doDropDone(boolean success, int dropAction, boolean isLocal) { long nativeDropTarget = this.getNativeDragContext(); diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java index 370b930ea985a81e15ba44b7f36750b004a0857b..978f65c3c91079d2b77c8d52b59867b8e4ea0512 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java @@ -35,7 +35,7 @@ import sun.lwawt.PlatformWindow; * On OSX {@code CPlatformComponent} stores pointer to the native CAlayer which * can be used from JAWT. */ -final class CPlatformComponent extends CFRetainedResource +class CPlatformComponent extends CFRetainedResource implements PlatformComponent { private volatile PlatformWindow platformWindow; diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..fd76cf5c8987aed8ff2a9406e963ee66b32e9b89 --- /dev/null +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package sun.lwawt.macosx; + +import sun.lwawt.PlatformWindow; + +class CPlatformLWComponent extends CPlatformComponent { + + CPlatformLWComponent() { + super(); + } + + @Override + public long getPointer() { + return 0; + } + + @Override + public void initialize(final PlatformWindow platformWindow) { + } + + @Override + public void setBounds(final int x, final int y, final int w, final int h) { + } + + @Override + public void dispose() { + } +} diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java new file mode 100644 index 0000000000000000000000000000000000000000..e5d99678b1838b6e06d9543967ed665b6d0039fa --- /dev/null +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt.macosx; + +import sun.lwawt.LWWindowPeer; +import sun.java2d.SurfaceData; + +public class CPlatformLWView extends CPlatformView { + + public CPlatformLWView() { + super(); + } + + @Override + public void initialize(LWWindowPeer peer, CPlatformResponder responder) { + initializeBase(peer, responder); + } + + @Override + public long getAWTView() { + return 0; + } + + @Override + public boolean isOpaque() { + return true; + } + + @Override + public void setBounds(int x, int y, int width, int height) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void dispose() { + } + + @Override + public long getWindowLayerPtr() { + return 0; + } +} diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..d7a912643289b8712fdbdd60e562984c6baa1d71 --- /dev/null +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.lwawt.macosx; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.Insets; +import java.awt.MenuBar; +import java.awt.Point; +import java.awt.Window; +import sun.awt.CausedFocusEvent; +import sun.java2d.SurfaceData; +import sun.lwawt.LWWindowPeer; +import sun.lwawt.PlatformWindow; + +public class CPlatformLWWindow extends CPlatformWindow { + + @Override + public void initialize(Window target, LWWindowPeer peer, PlatformWindow owner) { + initializeBase(target, peer, owner, new CPlatformLWView()); + } + + @Override + public void toggleFullScreen() { + } + + @Override + public void setMenuBar(MenuBar mb) { + } + + @Override + public void dispose() { + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return null; + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public Point getLocationOnScreen() { + return null; + } + + @Override + public GraphicsDevice getGraphicsDevice() { + return null; + } + + @Override + public SurfaceData getScreenSurface() { + return null; + } + + @Override + public SurfaceData replaceSurfaceData() { + return null; + } + + @Override + public void setBounds(int x, int y, int w, int h) { + if (getPeer() != null) { + getPeer().notifyReshape(x, y, w, h); + } + } + + @Override + public void setVisible(boolean visible) { + } + + @Override + public void setTitle(String title) { + } + + @Override + public void updateIconImages() { + } + + @Override + public long getNSWindowPtr() { + return 0; + } + + @Override + public SurfaceData getSurfaceData() { + return null; + } + + @Override + public void toBack() { + } + + @Override + public void toFront() { + } + + @Override + public void setResizable(final boolean resizable) { + } + + @Override + public void setSizeConstraints(int minW, int minH, int maxW, int maxH) { + } + + @Override + public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + return false; + } + + @Override + public boolean requestWindowFocus() { + return true; + } + + @Override + public boolean isActive() { + return true; + } + + @Override + public void updateFocusableWindowState() { + } + + @Override + public Graphics transformGraphics(Graphics g) { + return null; + } + + @Override + public void setAlwaysOnTop(boolean isAlwaysOnTop) { + } + + @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse(){ + return null; + } + + @Override + public void setOpacity(float opacity) { + } + + @Override + public void setOpaque(boolean isOpaque) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public void setWindowState(int windowState) { + } + + @Override + public LWWindowPeer getPeer() { + return super.getPeer(); + } + + @Override + public CPlatformView getContentView() { + return super.getContentView(); + } + + @Override + public long getLayerPtr() { + return 0; + } +} diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java index 495657963bd69d972153be70552cd522951c271d..3a0bec48629631c8c7efaf37f5328463dfdc4284 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java @@ -54,8 +54,7 @@ public class CPlatformView extends CFRetainedResource { } public void initialize(LWWindowPeer peer, CPlatformResponder responder) { - this.peer = peer; - this.responder = responder; + initializeBase(peer, responder); if (!LWCToolkit.getSunAwtDisableCALayers()) { this.windowLayer = new CGLLayer(peer); @@ -63,6 +62,11 @@ public class CPlatformView extends CFRetainedResource { setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr())); } + protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) { + this.peer = peer; + this.responder = responder; + } + public long getAWTView() { return ptr; } diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 8f83702a209ee3390f8ac6647f1c4540ffc1cf58..3fb585bdb534f86b913d274528ec05f43954c007 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -30,6 +30,7 @@ import java.awt.Dialog.ModalityType; import java.awt.event.*; import java.awt.peer.WindowPeer; import java.beans.*; +import java.lang.reflect.InvocationTargetException; import java.util.List; import javax.swing.*; @@ -44,7 +45,7 @@ import com.apple.laf.*; import com.apple.laf.ClientPropertyApplicator.Property; import com.sun.awt.AWTUtilities; -public final class CPlatformWindow extends CFRetainedResource implements PlatformWindow { +public class CPlatformWindow extends CFRetainedResource implements PlatformWindow { private native long nativeCreateNSWindow(long nsViewPtr, long styleBits, double x, double y, double w, double h); private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data); private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); @@ -218,11 +219,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor */ @Override // PlatformWindow public void initialize(Window _target, LWWindowPeer _peer, PlatformWindow _owner) { - this.peer = _peer; - this.target = _target; - if (_owner instanceof CPlatformWindow) { - this.owner = (CPlatformWindow)_owner; - } + initializeBase(_target, _peer, _owner, new CPlatformView()); final int styleBits = getInitialStyleBits(); @@ -231,7 +228,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor String warningString = target.getWarningString(); responder = new CPlatformResponder(peer, false); - contentView = new CPlatformView(); contentView.initialize(peer, responder); final long nativeWindowPtr = nativeCreateNSWindow(contentView.getAWTView(), styleBits, 0, 0, 0, 0); @@ -253,6 +249,15 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor validateSurface(); } + protected void initializeBase(Window target, LWWindowPeer peer, PlatformWindow owner, CPlatformView view) { + this.peer = peer; + this.target = target; + if (owner instanceof CPlatformWindow) { + this.owner = (CPlatformWindow)owner; + } + this.contentView = view; + } + private int getInitialStyleBits() { // defaults style bits int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE; @@ -857,7 +862,16 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor private void flushBuffers() { if (isVisible() && !nativeBounds.isEmpty()) { - LWCToolkit.getLWCToolkit().flushPendingEventsOnAppkit(target); + try { + LWCToolkit.invokeAndWait(new Runnable() { + @Override + public void run() { + //Posting an empty to flush the EventQueue without blocking the main thread + } + }, target); + } catch (InterruptedException | InvocationTargetException e) { + e.printStackTrace(); + } } } diff --git a/src/macosx/classes/sun/lwawt/macosx/CRobot.java b/src/macosx/classes/sun/lwawt/macosx/CRobot.java index e04a45fd5794ad78a082a00f50703f0c016e9be7..c74a589a328fa0b802b269152b9064b99ac9830f 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CRobot.java +++ b/src/macosx/classes/sun/lwawt/macosx/CRobot.java @@ -65,7 +65,7 @@ class CRobot implements RobotPeer { mouseLastX = x; mouseLastY = y; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, mouseButtonsState, true, true); } @@ -79,7 +79,7 @@ class CRobot implements RobotPeer { public void mousePress(int buttons) { mouseButtonsState |= buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, true, false); } @@ -93,7 +93,7 @@ class CRobot implements RobotPeer { public void mouseRelease(int buttons) { mouseButtonsState &= ~buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, false, false); } @@ -163,7 +163,7 @@ class CRobot implements RobotPeer { } private native void initRobot(); - private native void mouseEvent(int screen, int lastX, int lastY, + private native void mouseEvent(int displayID, int lastX, int lastY, int buttonsState, boolean isButtonsDownState, boolean isMouseMove); diff --git a/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java b/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java index 94a74e5174bf8f435d04ab6082e71a452e89fc68..6bc6cc7c41b0a71e3121b4e3668945b4e81902ce 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java +++ b/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java @@ -25,27 +25,33 @@ package sun.lwawt.macosx; +import sun.awt.Mutex; import sun.awt.datatransfer.ToolkitThreadBlockedHandler; -final class CToolkitThreadBlockedHandler implements ToolkitThreadBlockedHandler { - private final LWCToolkit toolkit = (LWCToolkit)java.awt.Toolkit.getDefaultToolkit(); +final class CToolkitThreadBlockedHandler extends Mutex implements ToolkitThreadBlockedHandler { + private long awtRunLoopMediator = 0; + private final boolean processEvents; - public void lock() { - } - - public void unlock() { - } - - protected boolean isOwned() { - return false; + CToolkitThreadBlockedHandler() { + super(); + this.processEvents = true; } public void enter() { - // Execute the next AppKit event while we are waiting for system to - // finish our request - this will save us from biting our own tail - toolkit.executeNextAppKitEvent(); + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + awtRunLoopMediator = LWCToolkit.createAWTRunLoopMediator(); + unlock(); + LWCToolkit.doAWTRunLoop(awtRunLoopMediator, processEvents); + lock(); } public void exit() { + if (!isOwned()) { + throw new IllegalMonitorStateException(); + } + LWCToolkit.stopAWTRunLoop(awtRunLoopMediator); + awtRunLoopMediator = 0; } } diff --git a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index ae6a4f77662193ca9df730423b5893e68a8df75d..a15eb46a1d122516660029023ce2e44b4a62bc17 100644 --- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,8 +63,6 @@ public final class LWCToolkit extends LWToolkit { private static native void initIDs(); - static native void executeNextAppKitEvent(); - private static CInputMethodDescriptor sInputMethodDescriptor; static { @@ -160,6 +158,8 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformEmbeddedFrame(); } else if (peerType == PeerType.VIEW_EMBEDDED_FRAME) { return new CViewPlatformEmbeddedFrame(); + } else if (peerType == PeerType.LW_FRAME) { + return new CPlatformLWWindow(); } else { assert (peerType == PeerType.SIMPLEWINDOW || peerType == PeerType.DIALOG || peerType == PeerType.FRAME); return new CPlatformWindow(); @@ -171,6 +171,11 @@ public final class LWCToolkit extends LWToolkit { return new CPlatformComponent(); } + @Override + protected PlatformComponent createLwPlatformComponent() { + return new CPlatformLWComponent(); + } + @Override protected FileDialogPeer createFileDialogPeer(FileDialog target) { return new CFileDialog(target); @@ -346,22 +351,7 @@ public final class LWCToolkit extends LWToolkit { @Override public Insets getScreenInsets(final GraphicsConfiguration gc) { - final CGraphicsConfig cgc = (CGraphicsConfig) gc; - final int displayId = cgc.getDevice().getCoreGraphicsScreen(); - Rectangle fullScreen, workArea; - final long screen = CWrapper.NSScreen.screenByDisplayId(displayId); - try { - fullScreen = CWrapper.NSScreen.frame(screen).getBounds(); - workArea = CWrapper.NSScreen.visibleFrame(screen).getBounds(); - } finally { - CWrapper.NSObject.release(screen); - } - // Convert between Cocoa's coordinate system and Java. - int bottom = workArea.y - fullScreen.y; - int top = fullScreen.height - workArea.height - bottom; - int left = workArea.x - fullScreen.x; - int right = fullScreen.width - workArea.width - left; - return new Insets(top, left, bottom, right); + return ((CGraphicsConfig) gc).getDevice().getScreenInsets(); } @Override @@ -495,30 +485,6 @@ public final class LWCToolkit extends LWToolkit { synchronized(ret) { return ret[0]; } } - /** - * Just a wrapper for LWCToolkit.invokeAndWait. Posts an empty event to the - * appropriate event queue and waits for it to finish. - */ - public static void flushPendingEventsOnAppkit(final Component component) { - try { - invokeAndWait(new Runnable() { - @Override - public void run() { - } - }, component); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // Kicks an event over to the appropriate eventqueue and waits for it to finish - // To avoid deadlocking, we manually run the NSRunLoop while waiting - // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop - // The CInvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop - public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { - invokeAndWait(event, component, true); - } - public static T invokeAndWait(final Callable callable, Component component) throws Exception { final CallableWrapper wrapper = new CallableWrapper(callable); invokeAndWait(wrapper, component); @@ -548,10 +514,27 @@ public final class LWCToolkit extends LWToolkit { } } - public static void invokeAndWait(Runnable event, Component component, boolean detectDeadlocks) throws InterruptedException, InvocationTargetException { - long mediator = createAWTRunLoopMediator(); + // Kicks an event over to the appropriate eventqueue and waits for it to finish + // To avoid deadlocking, we manually run the NSRunLoop while waiting + // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop + // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop + // Does not dispatch native events while in the loop + public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { + final long mediator = createAWTRunLoopMediator(); - InvocationEvent invocationEvent = new CPeerEvent(event, mediator); + InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) { + @Override + public void dispatch() { + try { + super.dispatch(); + } finally { + if (mediator != 0) { + stopAWTRunLoop(mediator); + } + } + } + }; if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component); @@ -564,7 +547,7 @@ public final class LWCToolkit extends LWToolkit { ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); } - doAWTRunLoop(mediator, true, detectDeadlocks); + doAWTRunLoop(mediator, false); Throwable eventException = invocationEvent.getException(); if (eventException != null) { @@ -576,7 +559,8 @@ public final class LWCToolkit extends LWToolkit { } public static void invokeLater(Runnable event, Component component) throws InvocationTargetException { - final InvocationEvent invocationEvent = new CPeerEvent(event, 0); + final InvocationEvent invocationEvent = + new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event); if (component != null) { final AppContext appContext = SunToolkit.targetToAppContext(component); @@ -681,31 +665,6 @@ public final class LWCToolkit extends LWToolkit { return false; } - // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early - // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop - public static class CPeerEvent extends PeerEvent { - private long _mediator = 0; - - public CPeerEvent(Runnable runnable, long mediator) { - super(Toolkit.getDefaultToolkit(), runnable, null, true, 0); - _mediator = mediator; - } - - public void dispatch() { - try { - super.dispatch(); - } finally { - if (_mediator != 0) { - LWCToolkit.stopAWTRunLoop(_mediator); - } - } - } - } - - // Call through to native methods - public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); } - public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); } - private static Boolean sunAwtDisableCALayers = null; /** @@ -730,12 +689,20 @@ public final class LWCToolkit extends LWToolkit { * Native methods section ************************/ - // These are public because they are accessed from WebKitPluginObject in JavaDeploy - // Basic usage: - // createAWTRunLoopMediator. Start client code on another thread. doAWTRunLoop. When client code is finished, stopAWTRunLoop. - public static native long createAWTRunLoopMediator(); - public static native void doAWTRunLoop(long mediator, boolean awtMode, boolean detectDeadlocks); - public static native void stopAWTRunLoop(long mediator); + static native long createAWTRunLoopMediator(); + /** + * Method to run a nested run-loop. The nested loop is spinned in the javaRunLoop mode, so selectors sent + * by [JNFRunLoop performOnMainThreadWaiting] are processed. + * @param mediator a native pointer to the mediator object created by createAWTRunLoopMediator + * @param processEvents if true - dispatches event while in the nested loop. Used in DnD. + * Additional attention is needed when using this feature as we short-circuit normal event + * processing which could break Appkit. + * (One known example is when the window is resized with the mouse) + * + * if false - all events come after exit form the nested loop + */ + static native void doAWTRunLoop(long mediator, boolean processEvents); + static native void stopAWTRunLoop(long mediator); private native boolean nativeSyncQueue(long timeout); diff --git a/src/macosx/native/sun/awt/AWTView.m b/src/macosx/native/sun/awt/AWTView.m index cc16a2026ee233b53cb55859c06f3e47254c4d2c..7e1f248c7ed7e2258d6ffa65584188e2b1094710 100644 --- a/src/macosx/native/sun/awt/AWTView.m +++ b/src/macosx/native/sun/awt/AWTView.m @@ -227,7 +227,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) mouseMoved: (NSEvent *)event { // TODO: better way to redirect move events to the "under" view - + NSPoint eventLocation = [event locationInWindow]; NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; @@ -668,7 +668,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) setDropTarget:(CDropTarget *)target { self._dropTarget = target; - [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) onObject:self._dropTarget withObject:nil waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES]; } /******************************** BEGIN NSDraggingSource Interface ********************************/ @@ -1215,7 +1215,7 @@ JNF_CLASS_CACHE(jc_CInputMethod, "sun/lwawt/macosx/CInputMethod"); fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n"); #endif // IM_DEBUG - [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) onObject:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES]; [self unmarkText]; } diff --git a/src/macosx/native/sun/awt/ApplicationDelegate.m b/src/macosx/native/sun/awt/ApplicationDelegate.m index 9a5aee94d44804e853fed1affa0c9a470e040170..6b584b21ca3c72754327f2a30a3648f42266ab44 100644 --- a/src/macosx/native/sun/awt/ApplicationDelegate.m +++ b/src/macosx/native/sun/awt/ApplicationDelegate.m @@ -567,10 +567,9 @@ JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNo { JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) - onObject:[ApplicationDelegate class] + on:[ApplicationDelegate class] withObject:[NSNumber numberWithInt:notificationType] - waitUntilDone:NO - awtMode:NO]; // AWT_THREADING Safe (non-blocking) + waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) JNF_COCOA_EXIT(env); } diff --git a/src/macosx/native/sun/awt/CClipboard.m b/src/macosx/native/sun/awt/CClipboard.m index fb300f729716754e6b6cbcf596e71c9680bd942d..bfba06b47d158bcac6fc2a46c54e6c6dc11c536f 100644 --- a/src/macosx/native/sun/awt/CClipboard.m +++ b/src/macosx/native/sun/awt/CClipboard.m @@ -120,7 +120,7 @@ static CClipboard *sClipboard = nil; fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard); } } - [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) onObject:self withObject:inTypes waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES]; } - (void) _nativeDeclareTypes:(NSArray *)inTypes { @@ -135,7 +135,7 @@ static CClipboard *sClipboard = nil; - (NSArray *) javaGetTypes { NSMutableArray *args = [NSMutableArray arrayWithCapacity:1]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard getTypes returns %@", [args lastObject]); return [args lastObject]; @@ -152,7 +152,7 @@ static CClipboard *sClipboard = nil; - (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat { CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) onObject:self withObject:newUpdate waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES]; [newUpdate release]; //NSLog(@"CClipboard javaSetData forType %@", inFormat); @@ -170,7 +170,7 @@ static CClipboard *sClipboard = nil; - (NSData *) javaGetDataForType:(NSString *) inFormat { NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat]; - [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES]; //NSLog(@"CClipboard javaGetDataForType %@ returns an NSData", inFormat); return [args lastObject]; diff --git a/src/macosx/native/sun/awt/CDropTarget.m b/src/macosx/native/sun/awt/CDropTarget.m index 60cd7818254d4e8c17fa4e9fb2f1f5920c7a827a..9dda8ae3551c1a5b3fab8210ca3cc10894aabb2f 100644 --- a/src/macosx/native/sun/awt/CDropTarget.m +++ b/src/macosx/native/sun/awt/CDropTarget.m @@ -390,8 +390,7 @@ extern JNFClassInfo jc_CDropTargetContextPeer; // Release dragging data if any when Java's AWT event thread is all finished. // Make sure dragging data is released on the native event thread. - [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) onObject:self - withObject:draggingSequenceNumberID waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO]; } - (jint)currentJavaActions { diff --git a/src/macosx/native/sun/awt/CGraphicsDevice.m b/src/macosx/native/sun/awt/CGraphicsDevice.m index 9bc5393d76528c05bdddf613d23934dd7c1e5ce1..1e2df28dd56cf473b87601a588e6f90a976ea0a7 100644 --- a/src/macosx/native/sun/awt/CGraphicsDevice.m +++ b/src/macosx/native/sun/awt/CGraphicsDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,8 @@ * questions. */ -#include "LWCToolkit.h" +#import "LWCToolkit.h" +#import "ThreadUtilities.h" /* * Convert the mode string to the more convinient bits per pixel value @@ -146,6 +147,47 @@ Java_sun_awt_CGraphicsDevice_nativeGetYResolution return dpi; } +/* + * Class: sun_awt_CGraphicsDevice + * Method: nativeGetScreenInsets + * Signature: (I)D + */ +JNIEXPORT jobject JNICALL +Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets + (JNIEnv *env, jclass class, jint displayID) +{ + jobject ret = NULL; + __block NSRect frame = NSZeroRect; + __block NSRect visibleFrame = NSZeroRect; +JNF_COCOA_ENTER(env); + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + NSArray *screens = [NSScreen screens]; + for (NSScreen *screen in screens) { + NSDictionary *screenInfo = [screen deviceDescription]; + NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"]; + if ([screenID pointerValue] == displayID){ + frame = [screen frame]; + visibleFrame = [screen visibleFrame]; + break; + } + } + }]; + // Convert between Cocoa's coordinate system and Java. + jint bottom = visibleFrame.origin.y - frame.origin.y; + jint top = frame.size.height - visibleFrame.size.height - bottom; + jint left = visibleFrame.origin.x - frame.origin.x; + jint right = frame.size.width - visibleFrame.size.width - left; + + static JNF_CLASS_CACHE(jc_Insets, "java/awt/Insets"); + static JNF_CTOR_CACHE(jc_Insets_ctor, jc_Insets, "(IIII)V"); + ret = JNFNewObject(env, jc_Insets_ctor, top, left, bottom, right); + +JNF_COCOA_EXIT(env); + + return ret; +} + /* * Class: sun_awt_CGraphicsDevice * Method: nativeSetDisplayMode diff --git a/src/macosx/native/sun/awt/CMenu.m b/src/macosx/native/sun/awt/CMenu.m index e6325c2c3db608607244c65ae6553cba83543968..8b643b3bca0dcc6c91299e2695ea7dc966a31a3a 100644 --- a/src/macosx/native/sun/awt/CMenu.m +++ b/src/macosx/native/sun/awt/CMenu.m @@ -55,11 +55,11 @@ AWT_ASSERT_APPKIT_THREAD; //- (void)finalize { [super finalize]; } - (void)addJavaSubmenu:(CMenu *)submenu { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:submenu waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES]; } - (void)addJavaMenuItem:(CMenuItem *)theMenuItem { - [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:theMenuItem waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES]; } - (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified { @@ -70,7 +70,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)setJavaMenuTitle:(NSString *)title { if (title) { - [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) onObject:self withObject:title waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES]; } } @@ -93,7 +93,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void)deleteJavaItem:(jint)index { - [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } - (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number { @@ -139,7 +139,7 @@ CMenu * createCMenu (jobject cPeerObjGlobal) { // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenu alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES]; aCMenu = (CMenu *)[args objectAtIndex: 0]; diff --git a/src/macosx/native/sun/awt/CMenuBar.m b/src/macosx/native/sun/awt/CMenuBar.m index 23c794961894763e8e5bf0dffad660f4816f3f6d..b0d67f71a2a40c3adcc378ac72d2b60f89856533 100644 --- a/src/macosx/native/sun/awt/CMenuBar.m +++ b/src/macosx/native/sun/awt/CMenuBar.m @@ -197,7 +197,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -216,7 +216,7 @@ static BOOL sSetupHelpMenu = NO; if (self == sActiveMenuBar) { NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil]; - [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES]; [args release]; } } @@ -286,7 +286,7 @@ static BOOL sSetupHelpMenu = NO; - (void) javaDeleteMenu: (jint)index { if (self == sActiveMenuBar) { - [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES]; } @synchronized(self) { @@ -388,7 +388,7 @@ Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar // We use an array here only to be able to get a return value NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenuBar alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES]; aCMenuBar = (CMenuBar *)[args objectAtIndex: 0]; diff --git a/src/macosx/native/sun/awt/CMenuItem.m b/src/macosx/native/sun/awt/CMenuItem.m index 2281d8bcd959db244dbd60e4b92410f68e47d66b..b67c70658dd5259435ed1c9e4c28e499796401a5 100644 --- a/src/macosx/native/sun/awt/CMenuItem.m +++ b/src/macosx/native/sun/awt/CMenuItem.m @@ -386,7 +386,7 @@ JNF_COCOA_ENTER(env); args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil]; } - [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) onObject:[CMenuItem alloc] withObject:args waitUntilDone:YES awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES]; aCMenuItem = (CMenuItem *)[args objectAtIndex: 0]; diff --git a/src/macosx/native/sun/awt/CRobot.m b/src/macosx/native/sun/awt/CRobot.m index c04d5685a56814c8ef495b9fd4d643cef09d2194..056fd19e29fefc3940ec88ea56ab6ce433716c30 100644 --- a/src/macosx/native/sun/awt/CRobot.m +++ b/src/macosx/native/sun/awt/CRobot.m @@ -135,7 +135,7 @@ Java_sun_lwawt_macosx_CRobot_initRobot JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CRobot_mouseEvent (JNIEnv *env, jobject peer, - jint screenIndex, jint mouseLastX, jint mouseLastY, jint buttonsState, + jint displayID, jint mouseLastX, jint mouseLastY, jint buttonsState, jboolean isButtonsDownState, jboolean isMouseMove) { JNF_COCOA_ENTER(env); @@ -149,8 +149,6 @@ Java_sun_lwawt_macosx_CRobot_mouseEvent CGError err = kCGErrorSuccess; - CGDirectDisplayID displayID = - FindCGDirectDisplayIDForScreenIndex(screenIndex); CGRect globalDeviceBounds = CGDisplayBounds(displayID); // Set unknown mouse location, if needed. diff --git a/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/src/macosx/native/sun/awt/JavaComponentAccessibility.m index f886c4afbe17610ee0afbb0b7c59cfdc2441c548..a01bd781faaebad0aed32edaf21c5abc3ab39882 100644 --- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m +++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m @@ -1113,18 +1113,10 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; - // This code frequently gets called indirectly by Java when VoiceOver is active. - // Basically, we just have to know when we going to be a bad state, and do something "special". - // Note that while NSApplication isn't technically correct, we post a focus changed notification - // (which will call this method, but with the correct codepath) shortly afterwards. See +postFocusChanged. - if (sInPerformFromJava) { - return [NSApplication sharedApplication]; - } else { - jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) - if (focused != NULL) { - if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { - value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; - } + jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + if (focused != NULL) { + if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { + value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; } } @@ -1149,7 +1141,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessibility_focusChanged { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) onObject:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) on:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1164,7 +1156,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_valueChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postValueChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postValueChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1177,7 +1169,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectionChanged (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } @@ -1191,7 +1183,7 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_unregisterFromCocoaAXSy (JNIEnv *env, jclass jklass, jlong element) { JNF_COCOA_ENTER(env); - [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO]; + [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO]; JNF_COCOA_EXIT(env); } diff --git a/src/macosx/native/sun/awt/LWCToolkit.h b/src/macosx/native/sun/awt/LWCToolkit.h index c318421c2e12b123b0e6a2f1f369c335e28e1b66..8df2c5539960c51155491aa80ff7b4aceaa1ef9e 100644 --- a/src/macosx/native/sun/awt/LWCToolkit.h +++ b/src/macosx/native/sun/awt/LWCToolkit.h @@ -44,8 +44,6 @@ extern jint* gButtonDownMasks; + (void) eventCountPlusPlus; @end -CGDirectDisplayID FindCGDirectDisplayIDForScreenIndex(jint screenIndex); - /* * Utility Macros */ diff --git a/src/macosx/native/sun/awt/LWCToolkit.m b/src/macosx/native/sun/awt/LWCToolkit.m index 45c546181f0374698f4d06aa775662134d1c1fdc..47c72abbfa54cebd16e5cf8c5fc6e80db285d582 100644 --- a/src/macosx/native/sun/awt/LWCToolkit.m +++ b/src/macosx/native/sun/awt/LWCToolkit.m @@ -177,39 +177,6 @@ Java_sun_lwawt_macosx_LWCToolkit_beep NSBeep(); // produces both sound and visual flash, if configured in System Preferences } -CGDirectDisplayID -FindCGDirectDisplayIDForScreenIndex(jint screenIndex) -{ - // most common case - just one monitor - CGDirectDisplayID screenID = CGMainDisplayID(); - - CGDisplayCount displayCount = 0; - CGGetOnlineDisplayList(0, NULL, &displayCount); - - if ((displayCount > 1) && - (screenIndex >= 0) && - (screenIndex < (jint)displayCount)) - { - if (displayCount < 10) { - // stack allocated optimization for less than 10 monitors - CGDirectDisplayID onlineDisplays[displayCount]; - CGGetOnlineDisplayList(displayCount, onlineDisplays, &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - } else { - CGDirectDisplayID *onlineDisplays = - malloc(displayCount*sizeof(CGDirectDisplayID)); - if (onlineDisplays != NULL) { - CGGetOnlineDisplayList(displayCount, onlineDisplays, - &displayCount); - screenID = (CGDirectDisplayID)onlineDisplays[screenIndex]; - free(onlineDisplays); - } - } - } - - return screenID; -} - /* * Class: sun_lwawt_macosx_LWCToolkit * Method: initIDs @@ -332,7 +299,7 @@ AWT_ASSERT_APPKIT_THREAD; * Signature: (JZZ)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoop -(JNIEnv *env, jclass clz, jlong mediator, jboolean awtMode, jboolean detectDeadlocks) +(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents) { AWT_ASSERT_APPKIT_THREAD; JNF_COCOA_ENTER(env); @@ -341,26 +308,25 @@ JNF_COCOA_ENTER(env); if (mediatorObject == nil) return; - if (!sInPerformFromJava || !detectDeadlocks) { - - NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; - NSDate *distantFuture = [NSDate distantFuture]; - NSString *mode = (awtMode) ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode; + // Don't use acceptInputForMode because that doesn't setup autorelease pools properly + BOOL isRunning = true; + while (![mediatorObject shouldEndRunLoop] && isRunning) { + isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode] + beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; + if (processEvents) { + //We do not spin a runloop here as date is nil, so does not matter which mode to use + NSEvent *event; + if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]) != nil) { + [NSApp sendEvent:event]; + } - BOOL isRunning = YES; - while (isRunning && ![mediatorObject shouldEndRunLoop]) { - // Don't use acceptInputForMode because that doesn't setup autorelease pools properly - isRunning = [currentRunLoop runMode:mode beforeDate:distantFuture]; } - - } -#ifndef PRODUCT_BUILD - if (sInPerformFromJava) { - NSLog(@"Apple AWT: Short-circuiting CToolkit.invokeAndWait trampoline deadlock!!!!!"); - NSLog(@"\tPlease file a bug report with this message and a reproducible test case."); } -#endif + CFRelease(mediatorObject); JNF_COCOA_EXIT(env); @@ -379,7 +345,7 @@ JNF_COCOA_ENTER(env); AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); - [ThreadUtilities performOnMainThread:@selector(endRunLoop) onObject:mediatorObject withObject:nil waitUntilDone:NO awtMode:YES]; + [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; CFRelease(mediatorObject); @@ -463,20 +429,3 @@ Java_sun_font_FontManager_populateFontFileNameMap } -/* - * Class: sun_lwawt_macosx_LWCToolkit - * Method: executeNextAppKitEvent - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_executeNextAppKitEvent -(JNIEnv *env, jclass cls) -{ - // Simply get the next event in native loop and pass it to execution - // We'll be called repeatedly so there's no need to block here - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - NSApplication * app = [NSApplication sharedApplication]; - NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; - if (event != nil) { - [app sendEvent: event]; - } -} diff --git a/src/macosx/native/sun/font/AWTStrike.m b/src/macosx/native/sun/font/AWTStrike.m index 261bd34ae579ff00f00a916c932b70a69a40d2c6..7f04b530ade01bc0d88d7a5f63ac1403e9a12d7d 100644 --- a/src/macosx/native/sun/font/AWTStrike.m +++ b/src/macosx/native/sun/font/AWTStrike.m @@ -27,11 +27,13 @@ #import "java_awt_geom_PathIterator.h" #import "sun_awt_SunHints.h" #import "sun_font_CStrike.h" +#import "sun_font_CStrikeDisposer.h" #import "CGGlyphImages.h" #import "CGGlyphOutlines.h" #import "AWTStrike.h" #import "CoreTextSupport.h" //#import "jni_util.h" +#include "fontscalerdefs.h" /* Use THIS_FILE when it is available. */ #ifndef THIS_FILE @@ -423,3 +425,19 @@ JNF_COCOA_EXIT(env); return metrics; } + +extern void AccelGlyphCache_RemoveAllInfos(GlyphInfo* glyph); +/* + * Class: sun_font_CStrikeDisposer + * Method: removeGlyphInfoFromCache + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_font_CStrikeDisposer_removeGlyphInfoFromCache +(JNIEnv *env, jclass cls, jlong glyphInfo) +{ + JNF_COCOA_ENTER(env); + + AccelGlyphCache_RemoveAllCellInfos((GlyphInfo*)jlong_to_ptr(glyphInfo)); + + JNF_COCOA_EXIT(env); +} diff --git a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m index 0bc58ec6ad3bae5acdeccd487de422c5dcfd8ec2..a9de285758d72de52e5ad067b064530080cc5e8a 100644 --- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m +++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m @@ -192,12 +192,12 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_initCGL JNIEXPORT jlong JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo (JNIEnv *env, jclass cglgc, - jint screennum, jint pixfmt, jint swapInterval) + jint displayID, jint pixfmt, jint swapInterval) { jlong ret = 0L; JNF_COCOA_ENTER(env); NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3]; - [retArray addObject: [NSNumber numberWithInt: (int)screennum]]; + [retArray addObject: [NSNumber numberWithInt: (int)displayID]]; [retArray addObject: [NSNumber numberWithInt: (int)pixfmt]]; [retArray addObject: [NSNumber numberWithInt: (int)swapInterval]]; if ([NSThread isMainThread]) { @@ -217,7 +217,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo + (void) _getCGLConfigInfo: (NSMutableArray *)argValue { AWT_ASSERT_APPKIT_THREAD; - jint screennum = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; + jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue]; jint pixfmt = (jint)[(NSNumber *)[argValue objectAtIndex: 1] intValue]; jint swapInterval = (jint)[(NSNumber *)[argValue objectAtIndex: 2] intValue]; JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; @@ -230,16 +230,11 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo CGOpenGLDisplayMask glMask = (CGOpenGLDisplayMask)pixfmt; if (sharedContext == NULL) { if (glMask == 0) { - CGDirectDisplayID id = - FindCGDirectDisplayIDForScreenIndex(screennum); - glMask = CGDisplayIDToOpenGLDisplayMask(id); + glMask = CGDisplayIDToOpenGLDisplayMask(displayID); } NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFAClosestPolicy, - NSOpenGLPFANoRecovery, - NSOpenGLPFAAccelerated, - NSOpenGLPFAFullScreen, NSOpenGLPFAWindow, NSOpenGLPFAPixelBuffer, NSOpenGLPFADoubleBuffer, @@ -412,7 +407,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo return; } memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo)); - cglinfo->screen = screennum; + cglinfo->screen = displayID; cglinfo->pixfmt = sharedPixelFormat; cglinfo->context = oglc; @@ -422,17 +417,6 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo } @end //GraphicsConfigUtil - -JNIEXPORT jint JNICALL -Java_sun_java2d_opengl_CGLGraphicsConfig_getDefaultPixFmt - (JNIEnv *env, jclass cglgc, jint screennum) -{ - J2dTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getDefaultPixFmt"); - - CGDirectDisplayID id = FindCGDirectDisplayIDForScreenIndex(screennum); - return (jint)CGDisplayIDToOpenGLDisplayMask(id); -} - JNIEXPORT jint JNICALL Java_sun_java2d_opengl_CGLGraphicsConfig_getOGLCapabilities (JNIEnv *env, jclass cglgc, jlong configInfo) diff --git a/src/macosx/native/sun/osxapp/ThreadUtilities.h b/src/macosx/native/sun/osxapp/ThreadUtilities.h index c0d2054f6e30c4d001376b7a83409ba76ddc4fcc..2ee65e94c65c349db7e49353886d88310ec797f7 100644 --- a/src/macosx/native/sun/osxapp/ThreadUtilities.h +++ b/src/macosx/native/sun/osxapp/ThreadUtilities.h @@ -122,19 +122,12 @@ do { \ #endif /* AWT_THREAD_ASSERTS */ // -------------------------------------------------------------------------- -// This tracks if we are current inside of a performOnMainThread that is both waiting and in the AWTRunLoopMode -extern BOOL sInPerformFromJava; - -// This is an empty Obj-C object just so that -performSelectorOnMainThread -// can be used, and to use the Obj-C +initialize feature. __attribute__((visibility("default"))) -@interface ThreadUtilities : NSObject { } +@interface ThreadUtilities { } + (JNIEnv*)getJNIEnv; + (JNIEnv*)getJNIEnvUncached; -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT; - //Wrappers for the corresponding JNFRunLoop methods with a check for main thread + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block; + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait; diff --git a/src/macosx/native/sun/osxapp/ThreadUtilities.m b/src/macosx/native/sun/osxapp/ThreadUtilities.m index 0b42f1b5896ee648b78bcb848ea9decdf22b4baf..d431386bbdbc4452597c2fbe610d20b245330367 100644 --- a/src/macosx/native/sun/osxapp/ThreadUtilities.m +++ b/src/macosx/native/sun/osxapp/ThreadUtilities.m @@ -34,85 +34,6 @@ JavaVM *jvm = NULL; static JNIEnv *appKitEnv = NULL; -static NSArray *sPerformModes = nil; -static NSArray *sAWTPerformModes = nil; - -static BOOL sLoggingEnabled = YES; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT -int sAWTThreadAsserts = 0; -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - -BOOL sInPerformFromJava = NO; - -// This class is used so that performSelectorOnMainThread can be -// controlled a little more easily by us. It has 2 roles. -// The first is to set/unset a flag (sInPerformFromJava) that code can -// check to see if we are in a synchronous perform initiated by a java thread. -// The second is to implement the CocoaComponent backward compatibility mode. -@interface CPerformer : NSObject { - id fTarget; - SEL fSelector; - id fArg; - BOOL fWait; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait; -- (void) perform; -@end - - -@implementation CPerformer - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg { - return [self initWithTarget:target selector:selector arg:arg wait:YES]; -} - -- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait { - self = [super init]; - if (self != nil) { - fTarget = [target retain]; - fSelector = selector; - fArg = [arg retain]; - // Only set sInPerformFromJava if this is a synchronous perform - fWait = wait; - } - return self; -} - -- (void) dealloc { - [fTarget release]; - [fArg release]; - [super dealloc]; -} -//- (void)finalize { [super finalize]; } - -- (void) perform { - AWT_ASSERT_APPKIT_THREAD; - - // If this is the first time we're going from java thread -> appkit thread, - // set sInPerformFromJava for the duration of the invocation - BOOL nestedPerform = sInPerformFromJava; - if (fWait) { - sInPerformFromJava = YES; - } - - // Actually do the work (cheat to avoid a method call) - @try { - objc_msgSend(fTarget, fSelector, fArg); - //[fTarget performSelector:fSelector withObject:fArg]; - } @catch (NSException *e) { - NSLog(@"*** CPerformer: ignoring exception '%@' raised during perform of selector '%@' on target '%@' with args '%@'", e, NSStringFromSelector(fSelector), fTarget, fArg); - } @finally { - // If we actually set sInPerformFromJava, unset it now - if (!nestedPerform && fWait) { - sInPerformFromJava = NO; - } - } -} -@end - - @implementation ThreadUtilities + (JNIEnv*)getJNIEnv { @@ -129,36 +50,6 @@ AWT_ASSERT_APPKIT_THREAD; return env; } -+ (void)initialize { - // Headless: BOTH - // Embedded: BOTH - // Multiple Calls: NO - // Caller: Obj-C class initialization - // Thread: ? - - if (sPerformModes == nil) { - // Create list of Run Loop modes to perform on - // The default performSelector, with no mode argument, runs in Default, - // ModalPanel, and EventTracking modes - sPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, nil]; - sAWTPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, [JNFRunLoop javaRunLoopMode], nil]; - -#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT - sAWTThreadAsserts = (getenv("COCOA_AWT_DISABLE_THREAD_ASSERTS") == NULL); -#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */ - } -} - -// These methods can behave slightly differently than the normal -// performSelector... In particular, we define a special runloop mode -// (AWTRunLoopMode) so that we can "block" the main thread against the -// java event thread without deadlocking. See CToolkit.invokeAndWait. -+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT { - CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait]; - [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method) - [performer release]; -} - + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); diff --git a/src/share/bin/jli_util.h b/src/share/bin/jli_util.h index 568318c95c67e463e1b6ad4b5a58d7ae4d615ecb..388910407ffb39c086bd3b93c839a4a44b59147e 100644 --- a/src/share/bin/jli_util.h +++ b/src/share/bin/jli_util.h @@ -66,7 +66,7 @@ int JLI_GetStdArgc(); #include #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) -#define JLI_Snprintf _snprintf +int JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 #else /* NIXES */ diff --git a/src/share/bin/parse_manifest.c b/src/share/bin/parse_manifest.c index 61b0bbf4884461b58ff88529114e30b36f427948..4926824e36b064266012f22c1210e577dea829c6 100644 --- a/src/share/bin/parse_manifest.c +++ b/src/share/bin/parse_manifest.c @@ -569,9 +569,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); - + } info->manifest_version = NULL; info->main_class = NULL; info->jre_version = NULL; @@ -618,15 +618,17 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { zentry entry; void *data = NULL; - fd = open(jarfile, O_RDONLY + if ((fd = open(jarfile, O_RDONLY #ifdef O_LARGEFILE | O_LARGEFILE /* large file mode */ #endif #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - ); - if (fd != -1 && find_file(fd, &entry, filename) == 0) { + )) == -1) { + return NULL; + } + if (find_file(fd, &entry, filename) == 0) { data = inflate_file(fd, &entry, size); } close(fd); @@ -671,8 +673,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) #ifdef O_BINARY | O_BINARY /* use binary mode on windows */ #endif - )) == -1) + )) == -1) { return (-1); + } if (rc = find_file(fd, &entry, manifest_name) != 0) { close(fd); diff --git a/src/share/classes/com/sun/beans/finder/MethodFinder.java b/src/share/classes/com/sun/beans/finder/MethodFinder.java index fa7cc5612abb762d75f5c61b18904e963e969710..98c52bc929a42c14b77450093db8ef014a927284 100644 --- a/src/share/classes/com/sun/beans/finder/MethodFinder.java +++ b/src/share/classes/com/sun/beans/finder/MethodFinder.java @@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder { Signature signature = new Signature(type, name, args); Method method = CACHE.get(signature); - if (method != null) { + boolean cached = method != null; + if (cached && isPackageAccessible(method.getDeclaringClass())) { return method; } method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); - CACHE.put(signature, method); + if (!cached) { + CACHE.put(signature, method); + } return method; } diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index b69875dd48182ccd0f74d49b393b65bf9d2908ee..33fa49297dd4022b6994936709cf5b92a3c510b7 100644 --- a/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException; import javax.crypto.SecretKey; import javax.crypto.spec.*; +import sun.security.util.KeyUtil; + /** * This class implements the Diffie-Hellman key agreement protocol between * any number of parties. @@ -200,6 +202,9 @@ extends KeyAgreementSpi { throw new InvalidKeyException("Incompatible parameters"); } + // validate the Diffie-Hellman public key + KeyUtil.validate(dhPubKey); + // store the y value this.y = dhPubKey.getY(); diff --git a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index 1a1ecef9055b244922626c1ba26de1d05febe5e3..322e2c333260148606a1cc82866e190fabc08fa5 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -1000,7 +1000,6 @@ class BandStructure { /** Write a constant pool reference. */ public void putRef(Entry e) { - assert(index != null); addValue(encodeRefOrNull(e, index)); } public void putRef(Entry e, Index index) { @@ -1052,6 +1051,8 @@ class BandStructure { int encodeRef(Entry e, Index ix) { + if (ix == null) + throw new RuntimeException("null index for " + e.stringValue()); int coding = ix.indexOf(e); if (verbose > 2) Utils.log.fine("putRef "+coding+" => "+e); diff --git a/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index c23dcb9d4a7db75f410ce5c0d05e5f8341226d9d..1ede29134b0c250dc6831d82a5afa9930e22b5e7 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -1409,6 +1409,8 @@ class ConstantPool { /** Index of all CP entries of a given tag and class. */ public Index getMemberIndex(byte tag, ClassEntry classRef) { + if (classRef == null) + throw new RuntimeException("missing class reference for " + tagName(tag)); if (indexByTagAndClass == null) indexByTagAndClass = new Index[CONSTANT_Limit][]; Index allClasses = getIndexByTag(CONSTANT_Class); diff --git a/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java b/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java index 532d4467664783a6f8f7d423f9d874bd9b39ab24..3f2f430fb84ce56c236c885a248fa7768cca1fe9 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java +++ b/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java @@ -109,6 +109,10 @@ class NativeUnpack { return (p200 == null)? null: p200._nunp; } + private synchronized long getUnpackerPtr() { + return unpackerPtr; + } + // Callback from the unpacker engine to get more data. private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { if (in == null) return 0; // nothing is readable diff --git a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java index 0dc88a108c76781719375878e0bac761bb2963cb..309c68a862367ef70da7450b7c8e538bba4656ef 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java +++ b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java @@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarFile in, OutputStream out) throws IOException { + public synchronized void pack(JarFile in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null @@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { * @param out an OutputStream * @exception IOException if an error is encountered. */ - public void pack(JarInputStream in, OutputStream out) throws IOException { + public synchronized void pack(JarInputStream in, OutputStream out) throws IOException { assert(Utils.currentInstance.get() == null); TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone.getDefault(); diff --git a/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java b/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java index 5727d32986ea73dd8372edd6baaf75ac7b18b2c6..fd8ccfd3c7105e9ce25d72bd4efa8f9f4226c5ad 100644 --- a/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java +++ b/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(InputStream in, JarOutputStream out) throws IOException { + public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } @@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { * @param out a JarOutputStream. * @exception IOException if an error is encountered. */ - public void unpack(File in, JarOutputStream out) throws IOException { + public synchronized void unpack(File in, JarOutputStream out) throws IOException { if (in == null) { throw new NullPointerException("null input"); } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java b/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java index 728fb12a7e869492ebea1a04504a2ac20a20c1fd..9fc0e7dbe9ef62de77c95f2d9fad2a83f2ac3795 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java @@ -36,6 +36,7 @@ import java.util.logging.Level; import javax.management.ObjectName; import javax.management.loading.PrivateClassLoader; +import sun.reflect.misc.ReflectUtil; /** * This class keeps the list of Class Loaders registered in the MBean Server. @@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport final ClassLoader without, final ClassLoader stop) throws ClassNotFoundException { + ReflectUtil.checkPackageAccess(className); final int size = list.length; for(int i=0; i theClass) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + Object moi; @@ -260,6 +266,9 @@ public class MBeanInstantiator { public Object instantiate(Class theClass, Object params[], String signature[], ClassLoader loader) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + // Instantiate the new object // ------------------------------ @@ -407,6 +416,8 @@ public class MBeanInstantiator { throw new RuntimeOperationsException(new IllegalArgumentException(), "Null className passed in parameter"); } + + ReflectUtil.checkPackageAccess(className); Class theClass; if (loaderName == null) { // Load the class using the agent class loader @@ -619,13 +630,13 @@ public class MBeanInstantiator { **/ static Class loadClass(String className, ClassLoader loader) throws ReflectionException { - Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), "Exception occurred during object instantiation"); } + ReflectUtil.checkPackageAccess(className); try { if (loader == null) loader = MBeanInstantiator.class.getClassLoader(); @@ -676,6 +687,7 @@ public class MBeanInstantiator { // We need to load the class through the class // loader of the target object. // + ReflectUtil.checkPackageAccess(signature[i]); tab[i] = Class.forName(signature[i], false, aLoader); } } catch (ClassNotFoundException e) { @@ -701,7 +713,7 @@ public class MBeanInstantiator { private Constructor findConstructor(Class c, Class[] params) { try { - return c.getConstructor(params); + return ConstructorUtil.getConstructor(c, params); } catch (Exception e) { return null; } @@ -715,4 +727,18 @@ public class MBeanInstantiator { char.class, boolean.class}) primitiveClasses.put(c.getName(), c); } + + private static void checkMBeanPermission(Class clazz, + String member, + ObjectName objectName, + String actions) { + SecurityManager sm = System.getSecurityManager(); + if (clazz != null && sm != null) { + Permission perm = new MBeanPermission(clazz.getName(), + member, + objectName, + actions); + sm.checkPermission(perm); + } + } } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java index 8109365e8d4dfdd8296d826eb4db0d52b393bfbd..3af4b8b86d763c2e87e91184e9a817381b53ecc9 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java @@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; import com.sun.jmx.mbeanserver.MXBeanMappingFactory; +import sun.reflect.misc.ReflectUtil; /** * Base class for MBeans. There is one instance of this class for @@ -131,6 +132,7 @@ public abstract class MBeanSupport " is not an instance of " + mbeanInterfaceType.getName(); throw new NotCompliantMBeanException(msg); } + ReflectUtil.checkPackageAccess(mbeanInterfaceType); this.resource = resource; MBeanIntrospector introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType); diff --git a/src/share/classes/java/awt/CheckboxMenuItem.java b/src/share/classes/java/awt/CheckboxMenuItem.java index 635e9b55b89607eaf47c96c60d3902d124eeb842..ad12d4c29a99cdc409af93243d6801f15f04e888 100644 --- a/src/share/classes/java/awt/CheckboxMenuItem.java +++ b/src/share/classes/java/awt/CheckboxMenuItem.java @@ -277,7 +277,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @since 1.4 */ public synchronized ItemListener[] getItemListeners() { - return (ItemListener[])(getListeners(ItemListener.class)); + return getListeners(ItemListener.class); } /** diff --git a/src/share/classes/java/awt/Cursor.java b/src/share/classes/java/awt/Cursor.java index c340532b20da1f49d052b921a99f90c796f86b82..d022a64786937baf8d43096775c53762526bb83b 100644 --- a/src/share/classes/java/awt/Cursor.java +++ b/src/share/classes/java/awt/Cursor.java @@ -163,11 +163,11 @@ public class Cursor implements java.io.Serializable { * hashtable, filesystem dir prefix, filename, and properties for custom cursors support */ - private static final Hashtable systemCustomCursors = new Hashtable(1); + private static final Hashtable systemCustomCursors = new Hashtable<>(1); private static final String systemCustomCursorDirPrefix = initCursorDir(); private static String initCursorDir() { - String jhome = (String) java.security.AccessController.doPrivileged( + String jhome = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.home")); return jhome + File.separator + "lib" + File.separator + "images" + @@ -298,7 +298,7 @@ public class Cursor implements java.io.Serializable { static public Cursor getSystemCustomCursor(final String name) throws AWTException, HeadlessException { GraphicsEnvironment.checkHeadless(); - Cursor cursor = (Cursor)systemCustomCursors.get(name); + Cursor cursor = systemCustomCursors.get(name); if (cursor == null) { synchronized(systemCustomCursors) { @@ -319,11 +319,11 @@ public class Cursor implements java.io.Serializable { final String fileName = systemCustomCursorProperties.getProperty(key); - String localized = (String)systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); + String localized = systemCustomCursorProperties.getProperty(prefix + DotNameSuffix); if (localized == null) localized = name; - String hotspot = (String)systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); + String hotspot = systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix); if (hotspot == null) throw new AWTException("no hotspot property defined for cursor: " + name); @@ -348,9 +348,9 @@ public class Cursor implements java.io.Serializable { final int fy = y; final String flocalized = localized; - cursor = (Cursor) java.security.AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { - public Object run() throws Exception { + cursor = java.security.AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { + public Cursor run() throws Exception { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = toolkit.getImage( systemCustomCursorDirPrefix + fileName); @@ -447,8 +447,8 @@ public class Cursor implements java.io.Serializable { systemCustomCursorProperties = new Properties(); try { - AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { + AccessController.doPrivileged( + new java.security.PrivilegedExceptionAction() { public Object run() throws Exception { FileInputStream fis = null; try { diff --git a/src/share/classes/java/awt/Dialog.java b/src/share/classes/java/awt/Dialog.java index 622a4531d3a73c39cdde8a7b6552651b535552cf..d27041fd322ec9fb9aa920edc0be070d16d4c189 100644 --- a/src/share/classes/java/awt/Dialog.java +++ b/src/share/classes/java/awt/Dialog.java @@ -39,6 +39,7 @@ import sun.awt.PeerEvent; import sun.awt.util.IdentityArrayList; import sun.awt.util.IdentityLinkedList; import sun.security.util.SecurityConstants; +import java.security.AccessControlException; /** * A Dialog is a top-level window with a title and a border @@ -128,6 +129,8 @@ public class Dialog extends Window { */ boolean undecorated = false; + private transient boolean initialized = false; + /** * Modal dialogs block all input to some top-level windows. * Whether a particular window is blocked depends on dialog's type @@ -671,6 +674,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -722,6 +726,7 @@ public class Dialog extends Window { this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -851,12 +856,9 @@ public class Dialog extends Window { if (modalityType == type) { return; } - if (type == ModalityType.TOOLKIT_MODAL) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION); - } - } + + checkModalityPermission(type); + modalityType = type; modal = (modalityType != ModalityType.MODELESS); } @@ -1025,6 +1027,11 @@ public class Dialog extends Window { */ @Deprecated public void show() { + if (!initialized) { + throw new IllegalStateException("The dialog component " + + "has not been initialized properly"); + } + beforeFirstShow = false; if (!isModal()) { conditionalShow(null, null); @@ -1600,18 +1607,51 @@ public class Dialog extends Window { } } + private void checkModalityPermission(ModalityType mt) { + if (mt == ModalityType.TOOLKIT_MODAL) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission( + SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION + ); + } + } + } + private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException, HeadlessException { GraphicsEnvironment.checkHeadless(); - s.defaultReadObject(); + + java.io.ObjectInputStream.GetField fields = + s.readFields(); + + ModalityType localModalityType = (ModalityType)fields.get("modalityType", null); + + try { + checkModalityPermission(localModalityType); + } catch (AccessControlException ace) { + localModalityType = DEFAULT_MODALITY_TYPE; + } // in 1.5 or earlier modalityType was absent, so use "modal" instead - if (modalityType == null) { + if (localModalityType == null) { + this.modal = fields.get("modal", false); setModal(modal); + } else { + this.modalityType = localModalityType; } + this.resizable = fields.get("resizable", true); + this.undecorated = fields.get("undecorated", false); + this.title = (String)fields.get("title", ""); + blockedWindows = new IdentityArrayList<>(); + + SunToolkit.checkAndSetPolicy(this); + + initialized = true; + } /* diff --git a/src/share/classes/java/awt/EventQueue.java b/src/share/classes/java/awt/EventQueue.java index 5ba9756a1af5ce61bc7a6948eac10b867e767eac..5795c37ae916faf7bdf6111437aa2a1bcc7f0803 100644 --- a/src/share/classes/java/awt/EventQueue.java +++ b/src/share/classes/java/awt/EventQueue.java @@ -171,7 +171,7 @@ public class EventQueue { * The modifiers field of the current event, if the current event is an * InputEvent or ActionEvent. */ - private WeakReference currentEvent; + private WeakReference currentEvent; /* * Non-zero if a thread is waiting in getNextEvent(int) for an event of @@ -194,7 +194,8 @@ public class EventQueue { } public void removeSourceEvents(EventQueue eventQueue, Object source, - boolean removeAllEvents) { + boolean removeAllEvents) + { eventQueue.removeSourceEvents(source, removeAllEvents); } public boolean noEvents(EventQueue eventQueue) { @@ -203,6 +204,11 @@ public class EventQueue { public void wakeup(EventQueue eventQueue, boolean isShutdown) { eventQueue.wakeup(isShutdown); } + public void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException + { + EventQueue.invokeAndWait(source, r); + } }); } @@ -809,7 +815,7 @@ public class EventQueue { pushPopLock.lock(); try { return (Thread.currentThread() == dispatchThread) - ? ((AWTEvent)currentEvent.get()) + ? currentEvent.get() : null; } finally { pushPopLock.unlock(); @@ -1167,7 +1173,7 @@ public class EventQueue { return; } - currentEvent = new WeakReference(e); + currentEvent = new WeakReference<>(e); // This series of 'instanceof' checks should be replaced with a // polymorphic type (for example, an interface which declares a @@ -1245,8 +1251,14 @@ public class EventQueue { * @since 1.2 */ public static void invokeAndWait(Runnable runnable) - throws InterruptedException, InvocationTargetException { + throws InterruptedException, InvocationTargetException + { + invokeAndWait(Toolkit.getDefaultToolkit(), runnable); + } + static void invokeAndWait(Object source, Runnable runnable) + throws InterruptedException, InvocationTargetException + { if (EventQueue.isDispatchThread()) { throw new Error("Cannot call invokeAndWait from the event dispatcher thread"); } @@ -1255,8 +1267,7 @@ public class EventQueue { Object lock = new AWTInvocationLock(); InvocationEvent event = - new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock, - true); + new InvocationEvent(source, runnable, lock, true); synchronized (lock) { Toolkit.getEventQueue().postEvent(event); diff --git a/src/share/classes/java/awt/Menu.java b/src/share/classes/java/awt/Menu.java index e702a9cb8fde0971efa4f37692f93f14de9104c1..ae5d2fa2f8287551f402c0f304667221c9a9b8e3 100644 --- a/src/share/classes/java/awt/Menu.java +++ b/src/share/classes/java/awt/Menu.java @@ -66,7 +66,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { AWTAccessor.setMenuAccessor( new AWTAccessor.MenuAccessor() { - public Vector getItems(Menu menu) { + public Vector getItems(Menu menu) { return menu.items; } }); @@ -78,7 +78,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * @serial * @see #countItems() */ - Vector items = new Vector(); + Vector items = new Vector<>(); /** * This field indicates whether the menu has the @@ -313,7 +313,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -330,7 +330,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -379,7 +379,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -396,7 +396,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { already in the correct order in the temp vector. */ for (int i = 0; i < tempItems.size() ; i++) { - add((MenuItem)tempItems.elementAt(i)); + add(tempItems.elementAt(i)); } } } @@ -475,13 +475,13 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { return null; } - synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + synchronized Enumeration shortcuts() { + Vector shortcuts = new Vector<>(); int nitems = getItemCount(); for (int i = 0 ; i < nitems ; i++) { MenuItem mi = getItem(i); if (mi instanceof Menu) { - Enumeration e = ((Menu)mi).shortcuts(); + Enumeration e = ((Menu)mi).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } diff --git a/src/share/classes/java/awt/MenuBar.java b/src/share/classes/java/awt/MenuBar.java index 1fd442e1583dbd6cd7437481e6c98c268f45e380..bd0a7d890c0f1c62ef88c3cf2c40b54f8d0821cc 100644 --- a/src/share/classes/java/awt/MenuBar.java +++ b/src/share/classes/java/awt/MenuBar.java @@ -81,7 +81,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible return menuBar.helpMenu; } - public Vector getMenus(MenuBar menuBar) { + public Vector getMenus(MenuBar menuBar) { return menuBar.menus; } }); @@ -94,7 +94,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @serial * @see #countMenus() */ - Vector menus = new Vector(); + Vector menus = new Vector<>(); /** * This menu is a special menu dedicated to @@ -309,7 +309,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * be called on the toolkit thread. */ final Menu getMenuImpl(int i) { - return (Menu)menus.elementAt(i); + return menus.elementAt(i); } /** @@ -321,10 +321,10 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible * @since JDK1.1 */ public synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + Vector shortcuts = new Vector<>(); int nmenus = getMenuCount(); for (int i = 0 ; i < nmenus ; i++) { - Enumeration e = getMenu(i).shortcuts(); + Enumeration e = getMenu(i).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } @@ -438,7 +438,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible // HeadlessException will be thrown from MenuComponent's readObject s.defaultReadObject(); for (int i = 0; i < menus.size(); i++) { - Menu m = (Menu)menus.elementAt(i); + Menu m = menus.elementAt(i); m.parent = this; } } diff --git a/src/share/classes/java/awt/MenuComponent.java b/src/share/classes/java/awt/MenuComponent.java index ebd9c0576baf5b20937b8994bc6f194563cd7be1..4895fdc9548bddf4f1b53436912dcacdaf22e5fd 100644 --- a/src/share/classes/java/awt/MenuComponent.java +++ b/src/share/classes/java/awt/MenuComponent.java @@ -290,7 +290,7 @@ public abstract class MenuComponent implements java.io.Serializable { public void setFont(Font f) { font = f; //Fixed 6312943: NullPointerException in method MenuComponent.setFont(Font) - MenuComponentPeer peer = (MenuComponentPeer)this.peer; + MenuComponentPeer peer = this.peer; if (peer != null) { peer.setFont(f); } @@ -303,7 +303,7 @@ public abstract class MenuComponent implements java.io.Serializable { */ public void removeNotify() { synchronized (getTreeLock()) { - MenuComponentPeer p = (MenuComponentPeer)this.peer; + MenuComponentPeer p = this.peer; if (p != null) { Toolkit.getEventQueue().removeSourceEvents(this, true); this.peer = null; diff --git a/src/share/classes/java/awt/MenuItem.java b/src/share/classes/java/awt/MenuItem.java index 3b8b2cffa0ee64fea7cefef638c1f6e19b87d8fb..4838d187a89a1cfd30763a881ac49ff27b5b75bc 100644 --- a/src/share/classes/java/awt/MenuItem.java +++ b/src/share/classes/java/awt/MenuItem.java @@ -564,7 +564,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @since 1.4 */ public synchronized ActionListener[] getActionListeners() { - return (ActionListener[])(getListeners(ActionListener.class)); + return getListeners(ActionListener.class); } /** diff --git a/src/share/classes/java/awt/RenderingHints.java b/src/share/classes/java/awt/RenderingHints.java index 5b8daa9e519c987eaaf6310cbb43947b3f440004..48cf9e11d329e09f03dc238d1d7b86233aee0861 100644 --- a/src/share/classes/java/awt/RenderingHints.java +++ b/src/share/classes/java/awt/RenderingHints.java @@ -92,7 +92,7 @@ public class RenderingHints * {@code equals()} method. */ public abstract static class Key { - private static HashMap identitymap = new HashMap(17); + private static HashMap identitymap = new HashMap<>(17); private String getIdentity() { // Note that the identity string is dependent on 3 variables: @@ -138,7 +138,7 @@ public class RenderingHints } // Note: Use a weak reference to avoid holding on to extra // objects and classes after they should be unloaded. - identitymap.put(identity, new WeakReference(k)); + identitymap.put(identity, new WeakReference(k)); } private int privatekey; @@ -195,7 +195,7 @@ public class RenderingHints } } - HashMap hintmap = new HashMap(7); + HashMap hintmap = new HashMap<>(7); /** * Antialiasing hint key. @@ -1267,12 +1267,13 @@ public class RenderingHints * object. * @return a clone of this instance. */ + @SuppressWarnings("unchecked") public Object clone() { RenderingHints rh; try { rh = (RenderingHints) super.clone(); if (hintmap != null) { - rh.hintmap = (HashMap) hintmap.clone(); + rh.hintmap = (HashMap) hintmap.clone(); } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable diff --git a/src/share/classes/java/awt/TextComponent.java b/src/share/classes/java/awt/TextComponent.java index ecc9b3fd47c507ef9d00a3f127ea748681054d01..0a2fe254fc3701b6a9f08a27db05e6f1a16eddc8 100644 --- a/src/share/classes/java/awt/TextComponent.java +++ b/src/share/classes/java/awt/TextComponent.java @@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible { // the background color of non-editable TextComponents. boolean backgroundSetByClientCode = false; - /** - * True if this TextComponent has access - * to the System clipboard. - */ - transient private boolean canAccessClipboard; - transient protected TextListener textListener; /* @@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible { GraphicsEnvironment.checkHeadless(); this.text = (text != null) ? text : ""; setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); - checkSystemClipboardAccess(); } private void enableInputMethodsIfNecessary() { @@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible { /** * Assigns a valid value to the canAccessClipboard instance variable. */ - private void checkSystemClipboardAccess() { - canAccessClipboard = true; + private boolean canAccessClipboard() { SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkSystemClipboardAccess(); - } - catch (SecurityException e) { - canAccessClipboard = false; - } - } + if (sm == null) return true; + try { + sm.checkSystemClipboardAccess(); + return true; + } catch (SecurityException e) {} + return false; } /* @@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible { } } enableInputMethodsIfNecessary(); - checkSystemClipboardAccess(); } diff --git a/src/share/classes/java/awt/Window.java b/src/share/classes/java/awt/Window.java index 4b9765443ebd1191b973845c859e3c4fd54ed6d2..68b9af95a96cda281c7bdca34719da31969f5457 100644 --- a/src/share/classes/java/awt/Window.java +++ b/src/share/classes/java/awt/Window.java @@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible { } else { try { - EventQueue.invokeAndWait(action); + EventQueue.invokeAndWait(this, action); } catch (InterruptedException e) { System.err.println("Disposal was interrupted:"); diff --git a/src/share/classes/java/awt/datatransfer/Clipboard.java b/src/share/classes/java/awt/datatransfer/Clipboard.java index d58bd92f3e0cb50e9910ad96351b18b6e16c3377..cce9c74c19272fd9d9778466a7e76f838488c4f2 100644 --- a/src/share/classes/java/awt/datatransfer/Clipboard.java +++ b/src/share/classes/java/awt/datatransfer/Clipboard.java @@ -71,7 +71,7 @@ public class Clipboard { * * @since 1.5 */ - private Set currentDataFlavors; + private Set currentDataFlavors; /** * Creates a clipboard object. @@ -313,7 +313,7 @@ public class Clipboard { if (flavorListeners == null) { return; } - Set prevDataFlavors = currentDataFlavors; + Set prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); if (prevDataFlavors.equals(currentDataFlavors)) { return; @@ -339,8 +339,8 @@ public class Clipboard { * * @since 1.5 */ - private Set getAvailableDataFlavorSet() { - Set set = new HashSet(); + private Set getAvailableDataFlavorSet() { + Set set = new HashSet<>(); Transferable contents = getContents(null); if (contents != null) { DataFlavor[] flavors = contents.getTransferDataFlavors(); diff --git a/src/share/classes/java/awt/dnd/DragGestureEvent.java b/src/share/classes/java/awt/dnd/DragGestureEvent.java index 298436fc50fdee02b3128fc8e6f33a71bddffb5c..3b72ed9afda09f82d1e63c696009c8bdbc3ed3be 100644 --- a/src/share/classes/java/awt/dnd/DragGestureEvent.java +++ b/src/share/classes/java/awt/dnd/DragGestureEvent.java @@ -165,7 +165,7 @@ public class DragGestureEvent extends EventObject { *

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

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

Default policy: allow all clients access with normal Java access * control. */ - private void checkMemberAccess(int which, ClassLoader ccl) { + private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { SecurityManager s = System.getSecurityManager(); if (s != null) { s.checkMemberAccess(this, which); ClassLoader cl = getClassLoader0(); - if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) { + if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { String name = this.getName(); int i = name.lastIndexOf('.'); if (i != -1) { - s.checkPackageAccess(name.substring(0, i)); + // skip the package access check on a proxy class in default proxy package + String pkg = name.substring(0, i); + if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { + s.checkPackageAccess(pkg); + } } } + // check package access on the proxy interfaces + if (checkProxyInterfaces && Proxy.isProxyClass(this)) { + ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces()); + } } } diff --git a/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/share/classes/java/lang/invoke/DirectMethodHandle.java index 68fe71c72c0f3c00f733c363fdcf532550d8307b..7793bc2dd98ef011e3572e6bb5cb0a919807d428 100644 --- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -51,6 +51,16 @@ class DirectMethodHandle extends MethodHandle { private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form); if (!member.isResolved()) throw new InternalError(); + + if (member.getDeclaringClass().isInterface() && !member.isAbstract()) { + // Check for corner case: invokeinterface of Object method + MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); + m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); + if (m != null && m.isPublic()) { + member = m; + } + } + this.member = member; } diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 376a0a0f5528131730087d919430af12b75450d3..a18a7a484a8231c37d1eaad7056cc1143c1b7289 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -807,12 +807,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static MethodHandle bindCaller(MethodHandle mh, Class hostClass) { // Do not use this function to inject calls into system classes. - if (hostClass == null) { - hostClass = C_Trampoline; - } else if (hostClass.isArray() || + if (hostClass == null + || (hostClass.isArray() || hostClass.isPrimitive() || hostClass.getName().startsWith("java.") || - hostClass.getName().startsWith("sun.")) { + hostClass.getName().startsWith("sun."))) { throw new InternalError(); // does not happen, and should not anyway } // For simplicity, convert mh to a varargs-like method. @@ -822,23 +821,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return restoreToType(bccInvoker.bindTo(vamh), mh.type()); } - // This class ("Trampoline") is known to be inside a dead-end class loader. - // Inject all doubtful calls into this class. - private static Class C_Trampoline; - static { - Class tramp = null; - try { - final int FRAME_COUNT_ARG = 1; // [0] Reflection [1] Trampoline - java.lang.reflect.Method gcc = sun.reflect.Reflection.class.getMethod("getCallerClass", int.class); - tramp = (Class) sun.reflect.misc.MethodUtil.invoke(gcc, null, new Object[]{ FRAME_COUNT_ARG }); - if (tramp.getClassLoader() == BindCaller.class.getClassLoader()) - throw new RuntimeException(tramp.getName()+" class loader"); - } catch (Throwable ex) { - throw new InternalError(ex); - } - C_Trampoline = tramp; - } - private static MethodHandle makeInjectedInvoker(Class hostClass) { Class bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null); if (hostClass.getClassLoader() != bcc.getClassLoader()) diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java index fcc928a327d874e86ce575da71745df1eebaf47b..db072126e1f074c317dd0c4e8569c9d97794e957 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -393,15 +393,33 @@ class MethodHandleNatives { */ // FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive. static boolean isCallerSensitive(MemberName mem) { - assert(mem.isInvocable()); + if (!mem.isInvocable()) return false; // fields are not caller sensitive Class defc = mem.getDeclaringClass(); switch (mem.getName()) { case "doPrivileged": + case "doPrivilegedWithCombiner": return defc == java.security.AccessController.class; + case "checkMemberAccess": + return canBeCalledVirtual(mem, java.lang.SecurityManager.class); case "getUnsafe": return defc == sun.misc.Unsafe.class; case "lookup": return defc == java.lang.invoke.MethodHandles.class; + case "findStatic": + case "findVirtual": + case "findConstructor": + case "findSpecial": + case "findGetter": + case "findSetter": + case "findStaticGetter": + case "findStaticSetter": + case "bind": + case "unreflect": + case "unreflectSpecial": + case "unreflectConstructor": + case "unreflectGetter": + case "unreflectSetter": + return defc == java.lang.invoke.MethodHandles.Lookup.class; case "invoke": return defc == java.lang.reflect.Method.class; case "get": @@ -455,7 +473,7 @@ class MethodHandleNatives { if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true; break; case "getContextClassLoader": - return defc == java.lang.Thread.class; + return canBeCalledVirtual(mem, java.lang.Thread.class); case "getPackage": case "getPackages": return defc == java.lang.Package.class; @@ -473,9 +491,13 @@ class MethodHandleNatives { break; case "getCallerClassLoader": return defc == java.lang.ClassLoader.class; + case "registerAsParallelCapable": + return canBeCalledVirtual(mem, java.lang.ClassLoader.class); case "getProxyClass": case "newProxyInstance": return defc == java.lang.reflect.Proxy.class; + case "asInterfaceInstance": + return defc == java.lang.invoke.MethodHandleProxies.class; case "getBundle": case "clearCache": return defc == java.util.ResourceBundle.class; @@ -492,4 +514,11 @@ class MethodHandleNatives { throw new InternalError(e); } } + static boolean canBeCalledVirtual(MemberName symbolicRef, Class definingClass) { + Class symbolicRefClass = symbolicRef.getDeclaringClass(); + if (symbolicRefClass == definingClass) return true; + if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false; + return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef + symbolicRefClass.isInterface()); // Mdef implements Msym + } } diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java index 20bc06de8794424dc283bf828f4350e2a70e1b34..ade1630dcfb4f47f0f7449d6c3aaed835514adbf 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -26,8 +26,12 @@ package java.lang.invoke; import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.invoke.WrapperInstance; import java.util.ArrayList; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; /** * This class consists exclusively of static methods that help adapt @@ -137,6 +141,21 @@ public class MethodHandleProxies { T asInterfaceInstance(final Class intfc, final MethodHandle target) { if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) throw new IllegalArgumentException("not a public interface: "+intfc.getName()); + final MethodHandle mh; + if (System.getSecurityManager() != null) { + final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; + ReflectUtil.checkProxyPackageAccess(ccl, intfc); + mh = ccl != null ? bindCaller(target, caller) : target; + } else { + mh = target; + } + ClassLoader proxyLoader = intfc.getClassLoader(); + if (proxyLoader == null) { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP + proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader(); + } final Method[] methods = getSingleNameMethods(intfc); if (methods == null) throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); @@ -144,31 +163,58 @@ public class MethodHandleProxies { for (int i = 0; i < methods.length; i++) { Method sm = methods[i]; MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes()); - MethodHandle checkTarget = target.asType(smMT); // make throw WMT + MethodHandle checkTarget = mh.asType(smMT); // make throw WMT checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); } - return intfc.cast(Proxy.newProxyInstance( - intfc.getClassLoader(), - new Class[]{ intfc, WrapperInstance.class }, - new InvocationHandler() { - private Object getArg(String name) { - if ((Object)name == "getWrapperInstanceTarget") return target; - if ((Object)name == "getWrapperInstanceType") return intfc; - throw new AssertionError(); + final InvocationHandler ih = new InvocationHandler() { + private Object getArg(String name) { + if ((Object)name == "getWrapperInstanceTarget") return target; + if ((Object)name == "getWrapperInstanceType") return intfc; + throw new AssertionError(); + } + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + for (int i = 0; i < methods.length; i++) { + if (method.equals(methods[i])) + return vaTargets[i].invokeExact(args); } - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - for (int i = 0; i < methods.length; i++) { - if (method.equals(methods[i])) - return vaTargets[i].invokeExact(args); - } - if (method.getDeclaringClass() == WrapperInstance.class) - return getArg(method.getName()); - if (isObjectMethod(method)) - return callObjectMethod(proxy, method, args); - throw new InternalError("bad proxy method: "+method); - } - })); + if (method.getDeclaringClass() == WrapperInstance.class) + return getArg(method.getName()); + if (isObjectMethod(method)) + return callObjectMethod(proxy, method, args); + throw new InternalError("bad proxy method: "+method); + } + }; + + final Object proxy; + if (System.getSecurityManager() != null) { + // sun.invoke.WrapperInstance is a restricted interface not accessible + // by any non-null class loader. + final ClassLoader loader = proxyLoader; + proxy = AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return Proxy.newProxyInstance( + loader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + }); + } else { + proxy = Proxy.newProxyInstance(proxyLoader, + new Class[]{ intfc, WrapperInstance.class }, + ih); + } + return intfc.cast(proxy); + } + + private static MethodHandle bindCaller(MethodHandle target, Class hostClass) { + MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass); + if (target.isVarargsCollector()) { + MethodType type = cbmh.type(); + int arity = type.parameterCount(); + return cbmh.asVarargsCollector(type.parameterType(arity-1)); + } + return cbmh; } /** diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index 80a44ff2f355eac38b4230aa1204b1afbbeafca5..f4cad4deaa8ba2efb34942dce7204936eda75ed1 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -598,7 +598,8 @@ public class MethodHandles { MethodHandle findStatic(Class refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(REF_invokeStatic, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + return getDirectMethod(REF_invokeStatic, refc, method, callerClass); } /** @@ -652,7 +653,8 @@ public class MethodHandles { byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual); MemberName method = resolveOrFail(refKind, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return getDirectMethod(refKind, refc, method); + Class callerClass = findBoundCallerClass(method); + return getDirectMethod(refKind, refc, method, callerClass); } private MethodHandle findVirtualForMH(String name, MethodType type) { // these names require special lookups because of the implicit MethodType argument @@ -736,7 +738,8 @@ public class MethodHandles { Lookup specialLookup = this.in(specialCaller); MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); + return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, callerClass); } /** @@ -879,7 +882,8 @@ return mh1; Class refc = receiver.getClass(); // may get NPE MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); checkSecurityManager(refc, method); // stack walk magic: do not refactor - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor + MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, callerClass); return mh.bindReceiver(receiver).setVarargs(method); } @@ -910,8 +914,9 @@ return mh1; if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; - return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method); + return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, callerClass); } /** @@ -940,8 +945,9 @@ return mh1; Lookup specialLookup = this.in(specialCaller); MemberName method = new MemberName(m, true); assert(method.isMethod()); + Class callerClass = findBoundCallerClass(method); // stack walk magic: do not refactor // ignore m.isAccessible: this is a new kind of access - return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method); + return specialLookup.getDirectMethod(REF_invokeSpecial, method.getDeclaringClass(), method, callerClass); } /** @@ -1039,8 +1045,30 @@ return mh1; throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this); } + /** + * Find my trustable caller class if m is a caller sensitive method. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). + * This is the same caller class as is used by checkSecurityManager. + * This function performs stack walk magic: do not refactor it. + */ + Class findBoundCallerClass(MemberName m) { + Class callerClass = null; + if (MethodHandleNatives.isCallerSensitive(m)) { + // Do not refactor this to a more "logical" place, since it is stack walk magic. + // Note that this is the same expression as in Step 2 below in checkSecurityManager. + callerClass = ((allowedModes & PRIVATE) != 0 + ? lookupClass // for strong access modes, no extra check + // next line does stack walk magic; do not refactor: + : getCallerClassAtEntryPoint(true)); + } + return callerClass; + } /** * Perform necessary access checks. + * Determines a trustable caller class to compare with refc, the symbolic reference class. + * If this lookup object has private access, then the caller class is the lookupClass. + * Otherwise, it is the caller of the currently executing public API method (e.g., findVirtual). * This function performs stack walk magic: do not refactor it. */ void checkSecurityManager(Class refc, MemberName m) { @@ -1195,22 +1223,22 @@ return mh1; return mh.viewAsType(narrowType); } - private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method) throws IllegalAccessException { + private MethodHandle getDirectMethod(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { return getDirectMethodCommon(refKind, refc, method, (refKind == REF_invokeSpecial || (MethodHandleNatives.refKindHasReceiver(refKind) && - restrictProtectedReceiver(method)))); + restrictProtectedReceiver(method))), callerClass); } - private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method) throws IllegalAccessException { - return getDirectMethodCommon(refKind, refc, method, false); + private MethodHandle getDirectMethodNoRestrict(byte refKind, Class refc, MemberName method, Class callerClass) throws IllegalAccessException { + return getDirectMethodCommon(refKind, refc, method, false, callerClass); } private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, - boolean doRestrict) throws IllegalAccessException { + boolean doRestrict, Class callerClass) throws IllegalAccessException { checkMethod(refKind, refc, method); if (method.isMethodHandleInvoke()) return fakeMethodHandleInvoke(method); MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); - mh = maybeBindCaller(method, mh); + mh = maybeBindCaller(method, mh, callerClass); mh = mh.setVarargs(method); if (doRestrict) mh = restrictReceiver(method, mh, lookupClass()); @@ -1219,12 +1247,14 @@ return mh1; private MethodHandle fakeMethodHandleInvoke(MemberName method) { return throwException(method.getReturnType(), UnsupportedOperationException.class); } - private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh) throws IllegalAccessException { + private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, + Class callerClass) + throws IllegalAccessException { if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method)) return mh; Class hostClass = lookupClass; if ((allowedModes & PRIVATE) == 0) // caller must use full-power lookup - hostClass = null; + hostClass = callerClass; // callerClass came from a security manager style stack walk MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass); // Note: caller will apply varargs after this step happens. return cbmh; @@ -1262,7 +1292,7 @@ return mh1; } else if (MethodHandleNatives.refKindIsMethod(refKind)) { MemberName method = (resolved != null) ? resolved : resolveOrFail(refKind, defc, name, (MethodType) type); - return getDirectMethod(refKind, defc, method); + return getDirectMethod(refKind, defc, method, lookupClass); } else if (refKind == REF_newInvokeSpecial) { assert(name == null || name.equals("")); MemberName ctor = (resolved != null) ? resolved diff --git a/src/share/classes/java/lang/management/ManagementFactory.java b/src/share/classes/java/lang/management/ManagementFactory.java index d99333c9e11096bdf2262d3a8eb8e4bf6c88114e..278ace1d7d11cb03f0f97a44ef0bd9590488f4e3 100644 --- a/src/share/classes/java/lang/management/ManagementFactory.java +++ b/src/share/classes/java/lang/management/ManagementFactory.java @@ -802,20 +802,20 @@ public class ManagementFactory { */ private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) { // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean - final DynamicMBean dmbean; - if (pmo instanceof DynamicMBean) { - dmbean = DynamicMBean.class.cast(pmo); - } else if (pmo instanceof NotificationEmitter) { - dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); - } else { - dmbean = new StandardMBean(pmo, null, true); - } - try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Void run() throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { + final DynamicMBean dmbean; + if (pmo instanceof DynamicMBean) { + dmbean = DynamicMBean.class.cast(pmo); + } else if (pmo instanceof NotificationEmitter) { + dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo); + } else { + dmbean = new StandardMBean(pmo, null, true); + } + mbs.registerMBean(dmbean, pmo.getObjectName()); return null; } diff --git a/src/share/classes/java/lang/reflect/Proxy.java b/src/share/classes/java/lang/reflect/Proxy.java index 9f5bb289dd3de3294dcbfc55f61251ddf43e2a53..e946ba3226d72ce94a2460637d8e33d58306fbd0 100644 --- a/src/share/classes/java/lang/reflect/Proxy.java +++ b/src/share/classes/java/lang/reflect/Proxy.java @@ -27,6 +27,9 @@ package java.lang.reflect; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.Permission; +import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -36,6 +39,9 @@ import java.util.Set; import java.util.List; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; +import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; +import sun.security.util.SecurityConstants; /** * {@code Proxy} provides static methods for creating dynamic proxy @@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable { * @param h the invocation handler for this proxy instance */ protected Proxy(InvocationHandler h) { + doNewInstanceCheck(); this.h = h; } + private static class ProxyAccessHelper { + // The permission is implementation specific. + static final Permission PROXY_PERMISSION = + new ReflectPermission("proxyConstructorNewInstance"); + // These system properties are defined to provide a short-term + // workaround if customers need to disable the new security checks. + static final boolean allowNewInstance; + static final boolean allowNullLoader; + static { + allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance"); + allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader"); + } + + private static boolean getBooleanProperty(final String key) { + String s = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(key); + } + }); + return Boolean.valueOf(s); + } + + static boolean needsNewInstanceCheck(Class proxyClass) { + if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) { + return false; + } + + if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { + // all proxy interfaces are public + return false; + } + for (Class intf : proxyClass.getInterfaces()) { + if (!Modifier.isPublic(intf.getModifiers())) { + return true; + } + } + return false; + } + } + + /* + * Access check on a proxy class that implements any non-public interface. + * + * @throws SecurityException if a security manager exists, and + * the caller does not have the permission. + */ + private void doNewInstanceCheck() { + SecurityManager sm = System.getSecurityManager(); + Class proxyClass = this.getClass(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) { + try { + sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION); + } catch (SecurityException e) { + throw new SecurityException("Not allowed to construct a Proxy " + + "instance that implements a non-public interface", e); + } + } + } + /** * Returns the {@code java.lang.Class} object for a proxy class * given a class loader and an array of interfaces. The proxy class @@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable { Class... interfaces) throws IllegalArgumentException { + return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor + } + + private static void checkProxyLoader(ClassLoader ccl, + ClassLoader loader) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (loader == null && ccl != null) { + if (!ProxyAccessHelper.allowNullLoader) { + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + } + } + } + } + + /* + * Generate a proxy class (caller-sensitive). + * + * To define a proxy class, it performs the access checks as in + * Class.forName (VM will invoke ClassLoader.checkPackageAccess): + * 1. "getClassLoader" permission check if loader == null + * 2. checkPackageAccess on the interfaces it implements + * + * To get a constructor and new instance of a proxy class, it performs + * the package access check on the interfaces it implements + * as in Class.getConstructor. + * + * If an interface is non-public, the proxy class must be defined by + * the defining loader of the interface. If the caller's class loader + * is not the same as the defining loader of the interface, the VM + * will throw IllegalAccessError when the generated proxy class is + * being defined via the defineClass0 method. + */ + private static Class getProxyClass0(ClassLoader loader, + Class... interfaces) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller + final Class caller = Reflection.getCallerClass(CALLER_FRAME); + final ClassLoader ccl = caller.getClassLoader(); + checkProxyLoader(ccl, loader); + ReflectUtil.checkProxyPackageAccess(ccl, interfaces); + } + if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } @@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable { } } - if (proxyPkg == null) { // if no non-public proxy interfaces, - proxyPkg = ""; // use the unnamed package + if (proxyPkg == null) { + // if no non-public proxy interfaces, use com.sun.proxy package + proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } { @@ -598,19 +710,43 @@ public class Proxy implements java.io.Serializable { /* * Look up or generate the designated proxy class. */ - Class cl = getProxyClass(loader, interfaces); + Class cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor /* * Invoke its constructor with the designated invocation handler. */ try { - Constructor cons = cl.getConstructor(constructorParams); - return cons.newInstance(new Object[] { h }); - } catch (NoSuchMethodException | - IllegalAccessException | - InstantiationException | - InvocationTargetException e) { + final Constructor cons = cl.getConstructor(constructorParams); + final InvocationHandler ih = h; + SecurityManager sm = System.getSecurityManager(); + if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { + // create proxy instance with doPrivilege as the proxy class may + // implement non-public interfaces that requires a special permission + return AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return newInstance(cons, ih); + } + }); + } else { + return newInstance(cons, ih); + } + } catch (NoSuchMethodException e) { + throw new InternalError(e.toString(), e); + } + } + + private static Object newInstance(Constructor cons, InvocationHandler h) { + try { + return cons.newInstance(new Object[] {h} ); + } catch (IllegalAccessException | InstantiationException e) { throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + throw new InternalError(t.toString(), t); + } } } diff --git a/src/share/classes/java/net/InetSocketAddress.java b/src/share/classes/java/net/InetSocketAddress.java index b250b18ce5ab30a57764bccc59f47d9995ba9d12..d4322e9b427ba11955b1324942aa931e46a62496 100644 --- a/src/share/classes/java/net/InetSocketAddress.java +++ b/src/share/classes/java/net/InetSocketAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,12 @@ */ package java.net; -import java.io.ObjectInputStream; import java.io.IOException; import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.ObjectStreamField; /** * @@ -46,23 +49,105 @@ import java.io.InvalidObjectException; * @see java.net.ServerSocket * @since 1.4 */ -public class InetSocketAddress extends SocketAddress { - /* The hostname of the Socket Address - * @serial - */ - private String hostname = null; - /* The IP address of the Socket Address - * @serial - */ - private InetAddress addr = null; - /* The port number of the Socket Address - * @serial - */ - private int port; +public class InetSocketAddress + extends SocketAddress +{ + // Private implementation class pointed to by all public methods. + private static class InetSocketAddressHolder { + // The hostname of the Socket Address + private String hostname; + // The IP address of the Socket Address + private InetAddress addr; + // The port number of the Socket Address + private int port; + + private InetSocketAddressHolder(String hostname, InetAddress addr, int port) { + this.hostname = hostname; + this.addr = addr; + this.port = port; + } + + private int getPort() { + return port; + } + + private InetAddress getAddress() { + return addr; + } + + private String getHostName() { + if (hostname != null) + return hostname; + if (addr != null) + return addr.getHostName(); + return null; + } + + private String getHostString() { + if (hostname != null) + return hostname; + if (addr != null) { + if (addr.hostName != null) + return addr.hostName; + else + return addr.getHostAddress(); + } + return null; + } + + private boolean isUnresolved() { + return addr == null; + } + + @Override + public String toString() { + if (isUnresolved()) { + return hostname + ":" + port; + } else { + return addr.toString() + ":" + port; + } + } + + @Override + public final boolean equals(Object obj) { + if (obj == null || !(obj instanceof InetSocketAddressHolder)) + return false; + InetSocketAddressHolder that = (InetSocketAddressHolder)obj; + boolean sameIP; + if (addr != null) + sameIP = addr.equals(that.addr); + else if (hostname != null) + sameIP = (that.addr == null) && + hostname.equalsIgnoreCase(that.hostname); + else + sameIP = (that.addr == null) && (that.hostname == null); + return sameIP && (port == that.port); + } + + @Override + public final int hashCode() { + if (addr != null) + return addr.hashCode() + port; + if (hostname != null) + return hostname.toLowerCase().hashCode() + port; + return port; + } + } + + private final transient InetSocketAddressHolder holder; private static final long serialVersionUID = 5076001401234631237L; - private InetSocketAddress() { + private static int checkPort(int port) { + if (port < 0 || port > 0xFFFF) + throw new IllegalArgumentException("port out of range:" + port); + return port; + } + + private static String checkHost(String hostname) { + if (hostname == null) + throw new IllegalArgumentException("hostname can't be null"); + return hostname; } /** @@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress { * range of valid port values. */ public InetSocketAddress(InetAddress addr, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - this.port = port; - if (addr == null) - this.addr = InetAddress.anyLocalAddress(); - else - this.addr = addr; + holder = new InetSocketAddressHolder( + null, + addr == null ? InetAddress.anyLocalAddress() : addr, + checkPort(port)); } /** @@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress { * @see #isUnresolved() */ public InetSocketAddress(String hostname, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (hostname == null) { - throw new IllegalArgumentException("hostname can't be null"); - } + checkHost(hostname); + InetAddress addr = null; + String host = null; try { addr = InetAddress.getByName(hostname); } catch(UnknownHostException e) { - this.hostname = hostname; - addr = null; + host = hostname; } - this.port = port; + holder = new InetSocketAddressHolder(host, addr, checkPort(port)); + } + + // private constructor for creating unresolved instances + private InetSocketAddress(int port, String hostname) { + holder = new InetSocketAddressHolder(hostname, null, port); } /** @@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress { * @since 1.5 */ public static InetSocketAddress createUnresolved(String host, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (host == null) { - throw new IllegalArgumentException("hostname can't be null"); - } - InetSocketAddress s = new InetSocketAddress(); - s.port = port; - s.hostname = host; - s.addr = null; - return s; + return new InetSocketAddress(checkPort(port), checkHost(host)); } - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); + /** + * @serialField hostname String + * @serialField addr InetAddress + * @serialField port int + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("hostname", String.class), + new ObjectStreamField("addr", InetAddress.class), + new ObjectStreamField("port", int.class)}; + + private void writeObject(ObjectOutputStream out) + throws IOException + { + // Don't call defaultWriteObject() + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("hostname", holder.hostname); + pfields.put("addr", holder.addr); + pfields.put("port", holder.port); + out.writeFields(); + } - // Check that our invariants are satisfied - if (port < 0 || port > 0xFFFF) { - throw new InvalidObjectException("port out of range:" + port); - } + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = in.readFields(); + final String oisHostname = (String)oisFields.get("hostname", null); + final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null); + final int oisPort = oisFields.get("port", -1); - if (hostname == null && addr == null) { + // Check that our invariants are satisfied + checkPort(oisPort); + if (oisHostname == null && oisAddr == null) throw new InvalidObjectException("hostname and addr " + "can't both be null"); + + InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname, + oisAddr, + oisPort); + UNSAFE.putObject(this, FIELDS_OFFSET, h); + } + + private void readObjectNoData() + throws ObjectStreamException + { + throw new InvalidObjectException("Stream data required"); + } + + private static final long FIELDS_OFFSET; + private static final sun.misc.Unsafe UNSAFE; + static { + try { + sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + FIELDS_OFFSET = unsafe.objectFieldOffset( + InetSocketAddress.class.getDeclaredField("holder")); + UNSAFE = unsafe; + } catch (ReflectiveOperationException e) { + throw new Error(e); } } @@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress { * @return the port number. */ public final int getPort() { - return port; + return holder.getPort(); } /** @@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress { * @return the InetAdress or null if it is unresolved. */ public final InetAddress getAddress() { - return addr; + return holder.getAddress(); } /** @@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress { * @return the hostname part of the address. */ public final String getHostName() { - if (hostname != null) - return hostname; - if (addr != null) - return addr.getHostName(); - return null; + return holder.getHostName(); } /** * Returns the hostname, or the String form of the address if it * doesn't have a hostname (it was created using a literal). - * This has the benefit of not attemptimg a reverse lookup. + * This has the benefit of not attempting a reverse lookup. * * @return the hostname, or String representation of the address. * @since 1.7 */ public final String getHostString() { - if (hostname != null) - return hostname; - if (addr != null) { - if (addr.hostName != null) - return addr.hostName; - else - return addr.getHostAddress(); - } - return null; + return holder.getHostString(); } /** @@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress { * an InetAddress. */ public final boolean isUnresolved() { - return addr == null; + return holder.isUnresolved(); } /** @@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress { * * @return a string representation of this object. */ + @Override public String toString() { - if (isUnresolved()) { - return hostname + ":" + port; - } else { - return addr.toString() + ":" + port; - } + return holder.toString(); } /** @@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress { * false otherwise. * @see java.net.InetAddress#equals(java.lang.Object) */ + @Override public final boolean equals(Object obj) { if (obj == null || !(obj instanceof InetSocketAddress)) return false; - InetSocketAddress sockAddr = (InetSocketAddress) obj; - boolean sameIP = false; - if (this.addr != null) - sameIP = this.addr.equals(sockAddr.addr); - else if (this.hostname != null) - sameIP = (sockAddr.addr == null) && - this.hostname.equalsIgnoreCase(sockAddr.hostname); - else - sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null); - return sameIP && (this.port == sockAddr.port); + return holder.equals(((InetSocketAddress) obj).holder); } /** @@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress { * * @return a hash code value for this socket address. */ + @Override public final int hashCode() { - if (addr != null) - return addr.hashCode() + port; - if (hostname != null) - return hostname.toLowerCase().hashCode() + port; - return port; + return holder.hashCode(); } } diff --git a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java index db7adf0e417aaf127015d4c68ceb1b1ed776be50..b7be7274d3f75dae9f68e3b48f276f537452b7bc 100644 --- a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -34,8 +34,10 @@ */ package java.util.concurrent; -import java.util.concurrent.locks.*; -import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.atomic.AtomicInteger; import java.util.*; /** @@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * policy limiting the number of threads. Even though it is not * treated as an error, failure to create threads may result in * new tasks being rejected or existing ones remaining stuck in - * the queue. On the other hand, no special precautions exist to - * handle OutOfMemoryErrors that might be thrown while trying to - * create threads, since there is generally no recourse from - * within this class. + * the queue. + * + * We go further and preserve pool invariants even in the face of + * errors such as OutOfMemoryError, that might be thrown while + * trying to create threads. Such errors are rather common due to + * the need to allocate a native stack in Thread#start, and users + * will want to perform clean pool shutdown to clean up. There + * will likely be enough memory available for the cleanup code to + * complete without encountering yet another OutOfMemoryError. */ private volatile ThreadFactory threadFactory; @@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * task execution. This protects against interrupts that are * intended to wake up a worker thread waiting for a task from * instead interrupting a task being run. We implement a simple - * non-reentrant mutual exclusion lock rather than use ReentrantLock - * because we do not want worker tasks to be able to reacquire the - * lock when they invoke pool control methods like setCorePoolSize. + * non-reentrant mutual exclusion lock rather than use + * ReentrantLock because we do not want worker tasks to be able to + * reacquire the lock when they invoke pool control methods like + * setCorePoolSize. Additionally, to suppress interrupts until + * the thread actually starts running tasks, we initialize lock + * state to a negative value, and clear it upon start (in + * runWorker). */ private final class Worker extends AbstractQueuedSynchronizer @@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { + setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } @@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { // The value 1 represents the locked state. protected boolean isHeldExclusively() { - return getState() == 1; + return getState() != 0; } protected boolean tryAcquire(int unused) { @@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService { public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } + + void interruptIfStarted() { + Thread t; + if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { + try { + t.interrupt(); + } catch (SecurityException ignore) { + } + } + } } /* @@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - for (Worker w : workers) { - try { - w.thread.interrupt(); - } catch (SecurityException ignore) { - } - } + for (Worker w : workers) + w.interruptIfStarted(); } finally { mainLock.unlock(); } @@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService { private static final boolean ONLY_ONE = true; - /** - * Ensures that unless the pool is stopping, the current thread - * does not have its interrupt set. This requires a double-check - * of state in case the interrupt was cleared concurrently with a - * shutdownNow -- if so, the interrupt is re-enabled. - */ - private void clearInterruptsForTaskRun() { - if (runStateLessThan(ctl.get(), STOP) && - Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP)) - Thread.currentThread().interrupt(); - } - /* * Misc utilities, most of which are also exported to * ScheduledThreadPoolExecutor @@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * Checks if a new worker can be added with respect to current * pool state and the given bound (either core or maximum). If so, * the worker count is adjusted accordingly, and, if possible, a - * new worker is created and started running firstTask as its + * new worker is created and started, running firstTask as its * first task. This method returns false if the pool is stopped or * eligible to shut down. It also returns false if the thread - * factory fails to create a thread when asked, which requires a - * backout of workerCount, and a recheck for termination, in case - * the existence of this worker was holding up termination. + * factory fails to create a thread when asked. If the thread + * creation fails, either due to the thread factory returning + * null, or due to an exception (typically OutOfMemoryError in + * Thread#start), we roll back cleanly. * * @param firstTask the task the new thread should run first (or * null if none). Workers are created with an initial first task @@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } - Worker w = new Worker(firstTask); - Thread t = w.thread; + boolean workerStarted = false; + boolean workerAdded = false; + Worker w = null; + try { + final ReentrantLock mainLock = this.mainLock; + w = new Worker(firstTask); + final Thread t = w.thread; + if (t != null) { + mainLock.lock(); + try { + // Recheck while holding lock. + // Back out on ThreadFactory failure or if + // shut down before lock acquired. + int c = ctl.get(); + int rs = runStateOf(c); + + if (rs < SHUTDOWN || + (rs == SHUTDOWN && firstTask == null)) { + if (t.isAlive()) // precheck that t is startable + throw new IllegalThreadStateException(); + workers.add(w); + int s = workers.size(); + if (s > largestPoolSize) + largestPoolSize = s; + workerAdded = true; + } + } finally { + mainLock.unlock(); + } + if (workerAdded) { + t.start(); + workerStarted = true; + } + } + } finally { + if (! workerStarted) + addWorkerFailed(w); + } + return workerStarted; + } + /** + * Rolls back the worker thread creation. + * - removes worker from workers, if present + * - decrements worker count + * - rechecks for termination, in case the existence of this + * worker was holding up termination + */ + private void addWorkerFailed(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int c = ctl.get(); - int rs = runStateOf(c); - - if (t == null || - (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null))) { - decrementWorkerCount(); - tryTerminate(); - return false; - } - - workers.add(w); - - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; + if (w != null) + workers.remove(w); + decrementWorkerCount(); + tryTerminate(); } finally { mainLock.unlock(); } - - t.start(); - // It is possible (but unlikely) for a thread to have been - // added to workers, but not yet started, during transition to - // STOP, which could result in a rare missed interrupt, - // because Thread.interrupt is not guaranteed to have any effect - // on a non-yet-started Thread (see Thread#interrupt). - if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) - t.interrupt(); - - return true; } /** @@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @param w the worker */ final void runWorker(Worker w) { + Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; + w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { w.lock(); - clearInterruptsForTaskRun(); + // If pool is stopping, ensure thread is interrupted; + // if not, ensure thread is not interrupted. This + // requires a recheck in second case to deal with + // shutdownNow race while clearing interrupt + if ((runStateAtLeast(ctl.get(), STOP) || + (Thread.interrupted() && + runStateAtLeast(ctl.get(), STOP))) && + !wt.isInterrupted()) + wt.interrupt(); try { - beforeExecute(w.thread, task); + beforeExecute(wt, task); Throwable thrown = null; try { task.run(); @@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } } + diff --git a/src/share/classes/java/util/jar/JarFile.java b/src/share/classes/java/util/jar/JarFile.java index a225d95fce78b5bc9b9bb33373d80cf3a7c93109..84c03753cfef85c5c47a6edfeb0274eb465ab4cb 100644 --- a/src/share/classes/java/util/jar/JarFile.java +++ b/src/share/classes/java/util/jar/JarFile.java @@ -34,6 +34,7 @@ import java.security.CodeSigner; import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; +import sun.misc.IOUtils; import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.misc.SharedSecrets; @@ -334,6 +335,9 @@ class JarFile extends ZipFile { if (names != null) { for (int i = 0; i < names.length; i++) { JarEntry e = getJarEntry(names[i]); + if (e == null) { + throw new JarException("corrupted jar file"); + } if (!e.isDirectory()) { if (mev == null) { mev = new ManifestEntryVerifier @@ -353,6 +357,10 @@ class JarFile extends ZipFile { // treat the jar file as being unsigned jv = null; verify = false; + if (JarVerifier.debug != null) { + JarVerifier.debug.println("jarfile parsing error!"); + ex.printStackTrace(); + } } // if after initializing the verifier we have nothing @@ -380,11 +388,9 @@ class JarFile extends ZipFile { * META-INF files. */ private byte[] getBytes(ZipEntry ze) throws IOException { - byte[] b = new byte[(int)ze.getSize()]; - try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) { - is.readFully(b, 0, b.length); + try (InputStream is = super.getInputStream(ze)) { + return IOUtils.readFully(is, (int)ze.getSize(), true); } - return b; } /** @@ -540,11 +546,7 @@ class JarFile extends ZipFile { if (!isKnownNotToHaveSpecialAttributes()) { JarEntry manEntry = getManEntry(); if (manEntry != null) { - byte[] b = new byte[(int)manEntry.getSize()]; - try (DataInputStream dis = new DataInputStream( - super.getInputStream(manEntry))) { - dis.readFully(b, 0, b.length); - } + byte[] b = getBytes(manEntry); if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT)) hasClassPathAttribute = true; if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT)) diff --git a/src/share/classes/java/util/logging/Level.java b/src/share/classes/java/util/logging/Level.java index 286ed5e600891c127ae5063a923b81c180c12daa..6847518ce02351c98aec9b70d1ad105689fdebd9 100644 --- a/src/share/classes/java/util/logging/Level.java +++ b/src/share/classes/java/util/logging/Level.java @@ -24,6 +24,10 @@ */ package java.util.logging; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.ResourceBundle; /** @@ -59,7 +63,6 @@ import java.util.ResourceBundle; */ public class Level implements java.io.Serializable { - private static java.util.ArrayList known = new java.util.ArrayList<>(); private static String defaultBundle = "sun.util.logging.resources.logging"; /** @@ -77,6 +80,9 @@ public class Level implements java.io.Serializable { */ private final String resourceBundleName; + // localized level name + private String localizedLevelName; + /** * OFF is a special level that can be used to turn off logging. * This level is initialized to Integer.MAX_VALUE. @@ -202,9 +208,8 @@ public class Level implements java.io.Serializable { this.name = name; this.value = value; this.resourceBundleName = resourceBundleName; - synchronized (Level.class) { - known.add(this); - } + this.localizedLevelName = resourceBundleName == null ? name : null; + KnownLevel.add(this); } /** @@ -236,12 +241,76 @@ public class Level implements java.io.Serializable { * @return localized name */ public String getLocalizedName() { + return getLocalizedLevelName(); + } + + // package-private getLevelName() is used by the implementation + // instead of getName() to avoid calling the subclass's version + final String getLevelName() { + return this.name; + } + + final synchronized String getLocalizedLevelName() { + if (localizedLevelName != null) { + return localizedLevelName; + } + try { ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); - return rb.getString(name); + localizedLevelName = rb.getString(name); } catch (Exception ex) { - return name; + localizedLevelName = name; + } + return localizedLevelName; + } + + // Returns a mirrored Level object that matches the given name as + // specified in the Level.parse method. Returns null if not found. + // + // It returns the same Level object as the one returned by Level.parse + // method if the given name is a non-localized name or integer. + // + // If the name is a localized name, findLevel and parse method may + // return a different level value if there is a custom Level subclass + // that overrides Level.getLocalizedName() to return a different string + // than what's returned by the default implementation. + // + static Level findLevel(String name) { + if (name == null) { + throw new NullPointerException(); + } + + KnownLevel level; + + // Look for a known Level with the given non-localized name. + level = KnownLevel.findByName(name); + if (level != null) { + return level.mirroredLevel; } + + // Now, check if the given name is an integer. If so, + // first look for a Level with the given value and then + // if necessary create one. + try { + int x = Integer.parseInt(name); + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); + } + return level.mirroredLevel; + } catch (NumberFormatException ex) { + // Not an integer. + // Drop through. + } + + level = KnownLevel.findByLocalizedLevelName(name); + if (level != null) { + return level.mirroredLevel; + } + + return null; } /** @@ -268,21 +337,15 @@ public class Level implements java.io.Serializable { // Serialization magic to prevent "doppelgangers". // This is a performance optimization. private Object readResolve() { - synchronized (Level.class) { - for (int i = 0; i < known.size(); i++) { - Level other = known.get(i); - if (this.name.equals(other.name) && this.value == other.value - && (this.resourceBundleName == other.resourceBundleName || - (this.resourceBundleName != null && - this.resourceBundleName.equals(other.resourceBundleName)))) { - return other; - } - } - // Woops. Whoever sent us this object knows - // about a new log level. Add it to our list. - known.add(this); - return this; + KnownLevel o = KnownLevel.matches(this); + if (o != null) { + return o.levelObject; } + + // Woops. Whoever sent us this object knows + // about a new log level. Add it to our list. + Level level = new Level(this.name, this.value, this.resourceBundleName); + return level; } /** @@ -296,6 +359,7 @@ public class Level implements java.io.Serializable { *
  • "SEVERE" *
  • "1000" * + * * @param name string to be parsed * @throws NullPointerException if the name is null * @throws IllegalArgumentException if the value is not valid. @@ -315,12 +379,12 @@ public class Level implements java.io.Serializable { // Check that name is not null. name.length(); + KnownLevel level; + // Look for a known Level with the given non-localized name. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.name)) { - return l; - } + level = KnownLevel.findByName(name); + if (level != null) { + return level.levelObject; } // Now, check if the given name is an integer. If so, @@ -328,14 +392,13 @@ public class Level implements java.io.Serializable { // if necessary create one. try { int x = Integer.parseInt(name); - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (l.value == x) { - return l; - } + level = KnownLevel.findByValue(x); + if (level == null) { + // add new Level + Level levelObject = new Level(name, x); + level = KnownLevel.findByValue(x); } - // Create a new Level. - return new Level(name, x); + return level.levelObject; } catch (NumberFormatException ex) { // Not an integer. // Drop through. @@ -344,11 +407,9 @@ public class Level implements java.io.Serializable { // Finally, look for a known level with the given localized name, // in the current default locale. // This is relatively expensive, but not excessively so. - for (int i = 0; i < known.size(); i++) { - Level l = known.get(i); - if (name.equals(l.getLocalizedName())) { - return l; - } + level = KnownLevel.findByLocalizedName(name); + if (level != null) { + return level.levelObject; } // OK, we've tried everything and failed @@ -375,4 +436,124 @@ public class Level implements java.io.Serializable { public int hashCode() { return this.value; } + + // KnownLevel class maintains the global list of all known levels. + // The API allows multiple custom Level instances of the same name/value + // be created. This class provides convenient methods to find a level + // by a given name, by a given value, or by a given localized name. + // + // KnownLevel wraps the following Level objects: + // 1. levelObject: standard Level object or custom Level object + // 2. mirroredLevel: Level object representing the level specified in the + // logging configuration. + // + // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // are non-final but the name and resource bundle name are parameters to + // the Level constructor. Use the mirroredLevel object instead of the + // levelObject to prevent the logging framework to execute foreign code + // implemented by untrusted Level subclass. + // + // Implementation Notes: + // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods + // were final, the following KnownLevel implementation can be removed. + // Future API change should take this into consideration. + static final class KnownLevel { + private static Map> nameToLevels = new HashMap<>(); + private static Map> intToLevels = new HashMap<>(); + final Level levelObject; // instance of Level class or Level subclass + final Level mirroredLevel; // instance of Level class + KnownLevel(Level l) { + this.levelObject = l; + if (l.getClass() == Level.class) { + this.mirroredLevel = l; + } else { + this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName); + } + } + + static synchronized void add(Level l) { + // the mirroredLevel object is always added to the list + // before the custom Level instance + KnownLevel o = new KnownLevel(l); + List list = nameToLevels.get(l.name); + if (list == null) { + list = new ArrayList<>(); + nameToLevels.put(l.name, list); + } + list.add(o); + + list = intToLevels.get(l.value); + if (list == null) { + list = new ArrayList<>(); + intToLevels.put(l.value, list); + } + list.add(o); + } + + // Returns a KnownLevel with the given non-localized name. + static synchronized KnownLevel findByName(String name) { + List list = nameToLevels.get(name); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given value. + static synchronized KnownLevel findByValue(int value) { + List list = intToLevels.get(value); + if (list != null) { + return list.get(0); + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedLevelName() method (i.e. found + // from the resourceBundle associated with the Level object). + // This method does not call Level.getLocalizedName() that may + // be overridden in a subclass implementation + static synchronized KnownLevel findByLocalizedLevelName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedLevelName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + // Returns a KnownLevel with the given localized name matching + // by calling the Level.getLocalizedName() method + static synchronized KnownLevel findByLocalizedName(String name) { + for (List levels : nameToLevels.values()) { + for (KnownLevel l : levels) { + String lname = l.levelObject.getLocalizedName(); + if (name.equals(lname)) { + return l; + } + } + } + return null; + } + + static synchronized KnownLevel matches(Level l) { + List list = nameToLevels.get(l.name); + if (list != null) { + for (KnownLevel level : list) { + Level other = level.mirroredLevel; + if (l.value == other.value && + (l.resourceBundleName == other.resourceBundleName || + (l.resourceBundleName != null && + l.resourceBundleName.equals(other.resourceBundleName)))) { + return level; + } + } + } + return null; + } + } + } diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java index 2041acba80d6d9a827643ec7f750bff909f643ad..3cb35f584f4abae6f8bedf85d2a9719b98d11f4c 100644 --- a/src/share/classes/java/util/logging/LogManager.java +++ b/src/share/classes/java/util/logging/LogManager.java @@ -35,6 +35,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.beans.PropertyChangeListener; +import java.net.URL; +import sun.misc.JavaAWTAccess; +import sun.misc.SharedSecrets; +import sun.security.action.GetPropertyAction; /** * There is a single global LogManager object that is used to @@ -152,10 +156,9 @@ public class LogManager { // count to allow for cases where the same listener is registered many times. private final Map listenerMap = new HashMap<>(); - // Table of named Loggers that maps names to Loggers. - private Hashtable namedLoggers = new Hashtable<>(); - // Tree of named Loggers - private LogNode root = new LogNode(null); + // LoggerContext for system loggers and user loggers + private final LoggerContext systemContext = new SystemLoggerContext(); + private final LoggerContext userContext = new LoggerContext(); private Logger rootLogger; // Have we done the primordial reading of the configuration file? @@ -194,11 +197,12 @@ public class LogManager { // Create and retain Logger for the root of the namespace. manager.rootLogger = manager.new RootLogger(); manager.addLogger(manager.rootLogger); + manager.systemContext.addLocalLogger(manager.rootLogger); // Adding the global Logger. Doing so in the Logger. // would deadlock with the LogManager.. - Logger.getGlobal().setLogManager(manager); - manager.addLogger(Logger.getGlobal()); + Logger.global.setLogManager(manager); + manager.addLogger(Logger.global); // We don't call readConfiguration() here, as we may be running // very early in the JVM startup sequence. Instead readConfiguration @@ -276,14 +280,14 @@ public class LogManager { return; } readPrimordialConfiguration = true; + try { - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Void run() throws Exception { readConfiguration(); // Platform loggers begin to delegate to java.util.logging.Logger sun.util.logging.PlatformLogger.redirectPlatformLoggers(); - return null; } }); @@ -375,20 +379,68 @@ public class LogManager { } } - // Package-level method. + // Returns the LoggerContext for the user code (i.e. application or AppContext). + // Loggers are isolated from each AppContext. + private LoggerContext getUserContext() { + LoggerContext context = null; + + SecurityManager sm = System.getSecurityManager(); + JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess(); + if (sm != null && javaAwtAccess != null) { + synchronized (javaAwtAccess) { + // AppContext.getAppContext() returns the system AppContext if called + // from a system thread but Logger.getLogger might be called from + // an applet code. Instead, find the AppContext of the applet code + // from the execution stack. + Object ecx = javaAwtAccess.getExecutionContext(); + if (ecx == null) { + // fall back to AppContext.getAppContext() + ecx = javaAwtAccess.getContext(); + } + context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class); + if (context == null) { + if (javaAwtAccess.isMainAppContext()) { + context = userContext; + } else { + context = new LoggerContext(); + // during initialization, rootLogger is null when + // instantiating itself RootLogger + if (manager.rootLogger != null) + context.addLocalLogger(manager.rootLogger); + } + javaAwtAccess.put(ecx, LoggerContext.class, context); + } + } + } else { + context = userContext; + } + return context; + } + + private List contexts() { + List cxs = new ArrayList<>(); + cxs.add(systemContext); + cxs.add(getUserContext()); + return cxs; + } + // Find or create a specified logger instance. If a logger has // already been created with the given name it is returned. // Otherwise a new logger instance is created and registered // in the LogManager global namespace. - // This method will always return a non-null Logger object. // Synchronization is not required here. All synchronization for // adding a new Logger object is handled by addLogger(). - Logger demandLogger(String name) { + // + // This method must delegate to the LogManager implementation to + // add a new Logger or return the one that has been added previously + // as a LogManager subclass may override the addLogger, getLogger, + // readConfiguration, and other methods. + Logger demandLogger(String name, String resourceBundleName) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, null); + Logger newLogger = new Logger(name, resourceBundleName); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -413,24 +465,249 @@ public class LogManager { return result; } - // If logger.getUseParentHandlers() returns 'true' and any of the logger's - // parents have levels or handlers defined, make sure they are instantiated. - private void processParentHandlers(Logger logger, String name) { - int ix = 1; - for (;;) { - int ix2 = name.indexOf(".", ix); - if (ix2 < 0) { - break; + Logger demandSystemLogger(String name, String resourceBundleName) { + // Add a system logger in the system context's namespace + final Logger sysLogger = systemContext.demandLogger(name, resourceBundleName); + + // Add the system logger to the LogManager's namespace if not exist + // so that there is only one single logger of the given name. + // System loggers are visible to applications unless a logger of + // the same name has been added. + Logger logger; + do { + // First attempt to call addLogger instead of getLogger + // This would avoid potential bug in custom LogManager.getLogger + // implementation that adds a logger if does not exist + if (addLogger(sysLogger)) { + // successfully added the new system logger + logger = sysLogger; + } else { + logger = getLogger(name); + } + } while (logger == null); + + // LogManager will set the sysLogger's handlers via LogManager.addLogger method. + if (logger != sysLogger && sysLogger.getHandlers().length == 0) { + // if logger already exists but handlers not set + final Logger l = logger; + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + for (Handler hdl : l.getHandlers()) { + sysLogger.addHandler(hdl); + } + return null; + } + }); + } + return sysLogger; + } + + // LoggerContext maintains the logger namespace per context. + // The default LogManager implementation has one system context and user + // context. The system context is used to maintain the namespace for + // all system loggers and is queried by the system code. If a system logger + // doesn't exist in the user context, it'll also be added to the user context. + // The user context is queried by the user code and all other loggers are + // added in the user context. + static class LoggerContext { + // Table of named Loggers that maps names to Loggers. + private final Hashtable namedLoggers = new Hashtable<>(); + // Tree of named Loggers + private final LogNode root; + + private LoggerContext() { + this.root = new LogNode(null, this); + } + + Logger demandLogger(String name, String resourceBundleName) { + // a LogManager subclass may have its own implementation to add and + // get a Logger. So delegate to the LogManager to do the work. + return manager.demandLogger(name, resourceBundleName); + } + + synchronized Logger findLogger(String name) { + LoggerWeakRef ref = namedLoggers.get(name); + if (ref == null) { + return null; + } + Logger logger = ref.get(); + if (logger == null) { + // Hashtable holds stale weak reference + // to a logger which has been GC-ed. + removeLogger(name); + } + return logger; + } + + // Add a logger to this context. This method will only set its level + // and process parent loggers. It doesn't set its handlers. + synchronized boolean addLocalLogger(Logger logger) { + final String name = logger.getName(); + if (name == null) { + throw new NullPointerException(); + } + + // cleanup some Loggers that have been GC'ed + manager.drainLoggerRefQueueBounded(); + + LoggerWeakRef ref = namedLoggers.get(name); + if (ref != null) { + if (ref.get() == null) { + // It's possible that the Logger was GC'ed after the + // drainLoggerRefQueueBounded() call above so allow + // a new one to be registered. + removeLogger(name); + } else { + // We already have a registered logger with the given name. + return false; + } + } + + // We're adding a new logger. + // Note that we are creating a weak reference here. + ref = manager.new LoggerWeakRef(logger); + namedLoggers.put(name, ref); + + // Apply any initial level defined for the new logger. + Level level = manager.getLevelProperty(name + ".level", null); + if (level != null) { + doSetLevel(logger, level); + } + + // instantiation of the handler is done in the LogManager.addLogger + // implementation as a handler class may be only visible to LogManager + // subclass for the custom log manager case + processParentHandlers(logger, name); + + // Find the new node and its parent. + LogNode node = getNode(name); + node.loggerRef = ref; + Logger parent = null; + LogNode nodep = node.parent; + while (nodep != null) { + LoggerWeakRef nodeRef = nodep.loggerRef; + if (nodeRef != null) { + parent = nodeRef.get(); + if (parent != null) { + break; + } + } + nodep = nodep.parent; + } + + if (parent != null) { + doSetParent(logger, parent); + } + // Walk over the children and tell them we are their new parent. + node.walkAndSetParent(logger); + // new LogNode is ready so tell the LoggerWeakRef about it + ref.setNode(node); + return true; + } + + void removeLogger(String name) { + namedLoggers.remove(name); + } + + synchronized Enumeration getLoggerNames() { + return namedLoggers.keys(); + } + + // If logger.getUseParentHandlers() returns 'true' and any of the logger's + // parents have levels or handlers defined, make sure they are instantiated. + private void processParentHandlers(final Logger logger, final String name) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + if (logger != manager.rootLogger) { + boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true); + if (!useParent) { + logger.setUseParentHandlers(false); + } + } + return null; + } + }); + + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (manager.getProperty(pname + ".level") != null || + manager.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + demandLogger(pname, null); + } + ix = ix2+1; } - String pname = name.substring(0,ix2); + } - if (getProperty(pname+".level") != null || - getProperty(pname+".handlers") != null) { - // This pname has a level/handlers definition. - // Make sure it exists. - demandLogger(pname); + // Gets a node in our tree of logger nodes. + // If necessary, create it. + LogNode getNode(String name) { + if (name == null || name.equals("")) { + return root; } - ix = ix2+1; + LogNode node = root; + while (name.length() > 0) { + int ix = name.indexOf("."); + String head; + if (ix > 0) { + head = name.substring(0, ix); + name = name.substring(ix + 1); + } else { + head = name; + name = ""; + } + if (node.children == null) { + node.children = new HashMap<>(); + } + LogNode child = node.children.get(head); + if (child == null) { + child = new LogNode(node, this); + node.children.put(head, child); + } + node = child; + } + return node; + } + } + + static class SystemLoggerContext extends LoggerContext { + // Add a system logger in the system context's namespace as well as + // in the LogManager's namespace if not exist so that there is only + // one single logger of the given name. System loggers are visible + // to applications unless a logger of the same name has been added. + Logger demandLogger(String name, String resourceBundleName) { + Logger result = findLogger(name); + if (result == null) { + // only allocate the new system logger once + Logger newLogger = new Logger(name, resourceBundleName); + do { + if (addLocalLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + result = newLogger; + } else { + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); + } + } while (result == null); + } + return result; } } @@ -439,32 +716,27 @@ public class LogManager { // be made based on the logging configuration, which can // only be modified by trusted code. private void loadLoggerHandlers(final Logger logger, final String name, - final String handlersPropertyName) { + final String handlersPropertyName) + { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - if (logger != rootLogger) { - boolean useParent = getBooleanProperty(name + ".useParentHandlers", true); - if (!useParent) { - logger.setUseParentHandlers(false); - } - } - String names[] = parseClassNames(handlersPropertyName); for (int i = 0; i < names.length; i++) { String word = names[i]; try { Class clz = ClassLoader.getSystemClassLoader().loadClass(word); - Handler hdl = (Handler) clz.newInstance(); - try { - // Check if there is a property defining the - // this handler's level. - String levs = getProperty(word + ".level"); - if (levs != null) { - hdl.setLevel(Level.parse(levs)); + Handler hdl = (Handler) clz.newInstance(); + // Check if there is a property defining the + // this handler's level. + String levs = getProperty(word + ".level"); + if (levs != null) { + Level l = Level.findLevel(levs); + if (l != null) { + hdl.setLevel(l); + } else { + // Probably a bad level. Drop through. + System.err.println("Can't set level for " + word); } - } catch (Exception ex) { - System.err.println("Can't set level for " + word); - // Probably a bad level. Drop through. } // Add this Handler to the logger logger.addHandler(hdl); @@ -475,7 +747,8 @@ public class LogManager { } } return null; - }}); + } + }); } @@ -520,7 +793,7 @@ public class LogManager { if (node != null) { // if we have a LogNode, then we were a named Logger // so clear namedLoggers weak ref to us - manager.namedLoggers.remove(name); + node.context.removeLogger(name); name = null; // clear our ref to the Logger's name node.loggerRef = null; // clear LogNode's weak ref to us @@ -609,73 +882,22 @@ public class LogManager { * false if a logger of that name already exists. * @exception NullPointerException if the logger name is null. */ - public synchronized boolean addLogger(Logger logger) { + public boolean addLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); } - - // cleanup some Loggers that have been GC'ed - drainLoggerRefQueueBounded(); - - LoggerWeakRef ref = namedLoggers.get(name); - if (ref != null) { - if (ref.get() == null) { - // It's possible that the Logger was GC'ed after the - // drainLoggerRefQueueBounded() call above so allow - // a new one to be registered. - namedLoggers.remove(name); - } else { - // We already have a registered logger with the given name. - return false; - } - } - - // We're adding a new logger. - // Note that we are creating a weak reference here. - ref = new LoggerWeakRef(logger); - namedLoggers.put(name, ref); - - // Apply any initial level defined for the new logger. - Level level = getLevelProperty(name+".level", null); - if (level != null) { - doSetLevel(logger, level); - } - - // Do we have a per logger handler too? - // Note: this will add a 200ms penalty - loadLoggerHandlers(logger, name, name+".handlers"); - processParentHandlers(logger, name); - - // Find the new node and its parent. - LogNode node = findNode(name); - node.loggerRef = ref; - Logger parent = null; - LogNode nodep = node.parent; - while (nodep != null) { - LoggerWeakRef nodeRef = nodep.loggerRef; - if (nodeRef != null) { - parent = nodeRef.get(); - if (parent != null) { - break; - } - } - nodep = nodep.parent; - } - - if (parent != null) { - doSetParent(logger, parent); + LoggerContext cx = getUserContext(); + if (cx.addLocalLogger(logger)) { + // Do we have a per logger handler too? + // Note: this will add a 200ms penalty + loadLoggerHandlers(logger, name, name + ".handlers"); + return true; + } else { + return false; } - // Walk over the children and tell them we are their new parent. - node.walkAndSetParent(logger); - - // new LogNode is ready so tell the LoggerWeakRef about it - ref.setNode(node); - - return true; } - // Private method to set a level on a logger. // If necessary, we raise privilege before doing the call. private static void doSetLevel(final Logger logger, final Level level) { @@ -694,8 +916,6 @@ public class LogManager { }}); } - - // Private method to set a parent on a logger. // If necessary, we raise privilege before doing the setParent call. private static void doSetParent(final Logger logger, final Logger parent) { @@ -714,36 +934,6 @@ public class LogManager { }}); } - // Find a node in our tree of logger nodes. - // If necessary, create it. - private LogNode findNode(String name) { - if (name == null || name.equals("")) { - return root; - } - LogNode node = root; - while (name.length() > 0) { - int ix = name.indexOf("."); - String head; - if (ix > 0) { - head = name.substring(0,ix); - name = name.substring(ix+1); - } else { - head = name; - name = ""; - } - if (node.children == null) { - node.children = new HashMap<>(); - } - LogNode child = node.children.get(head); - if (child == null) { - child = new LogNode(node); - node.children.put(head, child); - } - node = child; - } - return node; - } - /** * Method to find a named logger. *

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

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

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

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

    + * NOTE: MAC computation is the only place in the SSL protocol that the * sequence number is used. It's also reset to zero with each change of * a cipher spec, so this is the only place this state is needed. * @@ -58,6 +58,9 @@ final class MAC { // Value of the null MAC is fixed private static final byte nullMAC[] = new byte[0]; + // internal identifier for the MAC algorithm + private final MacAlg macAlg; + // stuff defined by the kind of MAC algorithm private final int macSize; @@ -82,6 +85,7 @@ final class MAC { private MAC() { macSize = 0; + macAlg = M_NULL; mac = null; block = null; } @@ -91,6 +95,7 @@ final class MAC { */ MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key) throws NoSuchAlgorithmException, InvalidKeyException { + this.macAlg = macAlg; this.macSize = macAlg.size; String algorithm; @@ -127,6 +132,20 @@ final class MAC { return macSize; } + /** + * Returns the hash function block length of the MAC alorithm. + */ + int hashBlockLen() { + return macAlg.hashBlockSize; + } + + /** + * Returns the hash function minimal padding length of the MAC alorithm. + */ + int minimalPaddingLen() { + return macAlg.minimalPaddingSize; + } + /** * Computes and returns the MAC for the data in this byte array. * @@ -134,9 +153,11 @@ final class MAC { * @param buf compressed record on which the MAC is computed * @param offset start of compressed record data * @param len the size of the compressed record + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, byte buf[], int offset, int len) { - return compute(type, null, buf, offset, len); + final byte[] compute(byte type, byte buf[], + int offset, int len, boolean isSimulated) { + return compute(type, null, buf, offset, len, isSimulated); } /** @@ -149,9 +170,10 @@ final class MAC { * @param type record type * @param bb a ByteBuffer in which the position and limit * demarcate the data to be MAC'd. + * @param isSimulated if true, simulate the the MAC computation */ - final byte[] compute(byte type, ByteBuffer bb) { - return compute(type, bb, null, 0, bb.remaining()); + final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { + return compute(type, bb, null, 0, bb.remaining(), isSimulated); } /** @@ -204,18 +226,21 @@ final class MAC { * or buf/offset/len. */ private byte[] compute(byte type, ByteBuffer bb, byte[] buf, - int offset, int len) { + int offset, int len, boolean isSimulated) { if (macSize == 0) { return nullMAC; } - block[BLOCK_OFFSET_TYPE] = type; - block[block.length - 2] = (byte)(len >> 8); - block[block.length - 1] = (byte)(len ); + // MUST NOT increase the sequence number for a simulated computation. + if (!isSimulated) { + block[BLOCK_OFFSET_TYPE] = type; + block[block.length - 2] = (byte)(len >> 8); + block[block.length - 1] = (byte)(len ); - mac.update(block); - incrementSequenceNumber(); + mac.update(block); + incrementSequenceNumber(); + } // content if (bb != null) { diff --git a/src/share/classes/sun/security/ssl/OutputRecord.java b/src/share/classes/sun/security/ssl/OutputRecord.java index 900003dfd0ff5cae05cd0059770e64017086bee5..0ff27be460d3f42b57def8324fcc345af946269b 100644 --- a/src/share/classes/sun/security/ssl/OutputRecord.java +++ b/src/share/classes/sun/security/ssl/OutputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record { } if (signer.MAClen() != 0) { byte[] hash = signer.compute(contentType, buf, - headerSize, count - headerSize); + headerSize, count - headerSize, false); write(hash); } } diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java index 2140214a05910de6079261f429c2d875d95b9c40..d77229adb8d0dfd93f0c32d8861c6ebb3ddf4b5a 100644 --- a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java +++ b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java @@ -34,7 +34,7 @@ import javax.crypto.*; import javax.net.ssl.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * This is the client key exchange message (CLIENT --> SERVER) used with @@ -191,7 +191,7 @@ final class RSAClientKeyExchange extends HandshakeMessage { "unable to get the plaintext of the premaster secret"); } - int keySize = KeyLength.getKeySize(secretKey); + int keySize = KeyUtil.getKeySize(secretKey); if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 if (debug != null && Debug.isOn("handshake")) { System.out.println( diff --git a/src/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/share/classes/sun/security/ssl/SSLEngineImpl.java index 41415337ca1d71469c127e0ff575448d56fa1d36..5534cab0384d4193c969d422bef26f55bbafe3b8 100644 --- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine { * throw a fatal alert if the integrity check fails. */ try { - decryptedBB = inputRecord.decrypt(readCipher, readBB); + decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - // - // rewind the BB if necessary. - readBB.rewind(); - - inputRecord.checkMAC(readMAC, readBB); - - // use the same alert types as for MAC failure below byte alertType = (inputRecord.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!inputRecord.checkMAC(readMAC, decryptedBB)) { - if (inputRecord.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } // if (!inputRecord.decompress(c)) // fatal(Alerts.alert_decompression_failure, diff --git a/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/share/classes/sun/security/ssl/SSLSocketImpl.java index f807c4c58ce842e4df35506394f9a31597a7bdf4..cbc3db69b96ea008bff3c2a69b0a16228dd379e6 100644 --- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -986,29 +986,13 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { * throw a fatal alert if the integrity check fails. */ try { - r.decrypt(readCipher); + r.decrypt(readMAC, readCipher); } catch (BadPaddingException e) { - // RFC 2246 states that decryption_failed should be used - // for this purpose. However, that allows certain attacks, - // so we just send bad record MAC. We also need to make - // sure to always check the MAC to avoid a timing attack - // for the same issue. See paper by Vaudenay et al. - r.checkMAC(readMAC); - // use the same alert types as for MAC failure below byte alertType = (r.contentType() == Record.ct_handshake) ? Alerts.alert_handshake_failure : Alerts.alert_bad_record_mac; - fatal(alertType, "Invalid padding", e); + fatal(alertType, e.getMessage(), e); } - if (!r.checkMAC(readMAC)) { - if (r.contentType() == Record.ct_handshake) { - fatal(Alerts.alert_handshake_failure, - "bad handshake record MAC"); - } else { - fatal(Alerts.alert_bad_record_mac, "bad record MAC"); - } - } - // if (!r.decompress(c)) // fatal(Alerts.alert_decompression_failure, diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java index 89d5890b0986ef8fa15167e390eec22b6c349333..7865de9682bde43f0e33faa6b9960eda848c4fde 100644 --- a/src/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java @@ -150,7 +150,7 @@ final class ServerHandshaker extends Handshaker { // In SSLv3 and TLS, messages follow strictly increasing // numerical order _except_ for one annoying special case. // - if ((state > type) + if ((state >= type) && (state != HandshakeMessage.ht_client_key_exchange && type != HandshakeMessage.ht_certificate_verify)) { throw new SSLProtocolException( @@ -250,13 +250,15 @@ final class ServerHandshaker extends Handshaker { } // - // Move the state machine forward except for that annoying - // special case. This means that clients could send extra - // cert verify messages; not a problem so long as all of - // them actually check out. + // Move state machine forward if the message handling + // code didn't already do so // - if (state < type && type != HandshakeMessage.ht_certificate_verify) { - state = type; + if (state < type) { + if(type == HandshakeMessage.ht_certificate_verify) { + state = type + 2; // an annoying special case + } else { + state = type; + } } } @@ -1406,7 +1408,7 @@ final class ServerHandshaker extends Handshaker { if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } - return dh.getAgreedSecret(mesg.getClientPublicKey()); + return dh.getAgreedSecret(mesg.getClientPublicKey(), false); } private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg) diff --git a/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index aeaa4f997a13a5ff25ad907ee90f16cb599ac85a..14a00d85a2be514b23e0d87245a42b7ddbcf2d2f 100644 --- a/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -38,7 +38,7 @@ import java.util.Collection; import java.util.Collections; import java.util.ArrayList; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; /** * Signature and hash algorithm. @@ -274,7 +274,7 @@ final class SignatureAndHashAlgorithm { * If key size is less than 512, the digest length should be * less than or equal to 20 bytes. */ - int keySize = KeyLength.getKeySize(signingKey); + int keySize = KeyUtil.getKeySize(signingKey); if (keySize >= 768) { maxDigestLength = HashAlgorithm.SHA512.length; } else if ((keySize >= 512) && (keySize < 768)) { diff --git a/src/share/classes/sun/security/util/DerIndefLenConverter.java b/src/share/classes/sun/security/util/DerIndefLenConverter.java index 50bb06ad7b31291c3531319913a68d5dfa191ca0..78d9e302d6c9094ce4a224bb6ca9fd8ba353bc60 100644 --- a/src/share/classes/sun/security/util/DerIndefLenConverter.java +++ b/src/share/classes/sun/security/util/DerIndefLenConverter.java @@ -325,6 +325,10 @@ class DerIndefLenConverter { } } + if (unresolved != 0) { + throw new IOException("not all indef len BER resolved"); + } + newData = new byte[dataSize + numOfTotalLenBytes + unused]; dataPos=0; newDataPos=0; index=0; diff --git a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index ca0393a323ddf6bc09b2a0ac8a06e63f3ef81b36..17b56974ea347e9099a876f74148a7547ed4abc3 100644 --- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -440,7 +440,7 @@ public class DisabledAlgorithmConstraints implements AlgorithmConstraints { // Does this key constraint disable the specified key? public boolean disables(Key key) { - int size = KeyLength.getKeySize(key); + int size = KeyUtil.getKeySize(key); if (size == 0) { return true; // we don't allow any key of size 0. diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java deleted file mode 100644 index 3ffbac3f30f82897d79080414d535ec2d06ea7de..0000000000000000000000000000000000000000 --- a/src/share/classes/sun/security/util/KeyLength.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.util; - -import java.security.Key; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.security.interfaces.ECKey; -import java.security.interfaces.RSAKey; -import java.security.interfaces.DSAKey; -import javax.crypto.SecretKey; -import javax.crypto.interfaces.DHKey; - -/** - * A utility class to get key length - */ -public final class KeyLength { - - /** - * Returns the key size of the given key object in bits. - * - * @param key the key object, cannot be null - * @return the key size of the given key object in bits, or -1 if the - * key size is not accessible - */ - final public static int getKeySize(Key key) { - int size = -1; - - if (key instanceof Length) { - try { - Length ruler = (Length)key; - size = ruler.length(); - } catch (UnsupportedOperationException usoe) { - // ignore the exception - } - - if (size >= 0) { - return size; - } - } - - // try to parse the length from key specification - if (key instanceof SecretKey) { - SecretKey sk = (SecretKey)key; - String format = sk.getFormat(); - if ("RAW".equals(format) && sk.getEncoded() != null) { - size = (sk.getEncoded().length * 8); - } // Otherwise, it may be a unextractable key of PKCS#11, or - // a key we are not able to handle. - } else if (key instanceof RSAKey) { - RSAKey pubk = (RSAKey)key; - size = pubk.getModulus().bitLength(); - } else if (key instanceof ECKey) { - ECKey pubk = (ECKey)key; - size = pubk.getParams().getOrder().bitLength(); - } else if (key instanceof DSAKey) { - DSAKey pubk = (DSAKey)key; - size = pubk.getParams().getP().bitLength(); - } else if (key instanceof DHKey) { - DHKey pubk = (DHKey)key; - size = pubk.getParams().getP().bitLength(); - } // Otherwise, it may be a unextractable key of PKCS#11, or - // a key we are not able to handle. - - return size; - } -} - diff --git a/src/share/classes/sun/security/util/KeyUtil.java b/src/share/classes/sun/security/util/KeyUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..6664dab38b6b24082e8fa2907e674b8b5aea7b6d --- /dev/null +++ b/src/share/classes/sun/security/util/KeyUtil.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.security.Key; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.security.InvalidKeyException; +import java.security.interfaces.ECKey; +import java.security.interfaces.RSAKey; +import java.security.interfaces.DSAKey; +import java.security.spec.KeySpec; +import javax.crypto.SecretKey; +import javax.crypto.interfaces.DHKey; +import javax.crypto.interfaces.DHPublicKey; +import javax.crypto.spec.DHParameterSpec; +import javax.crypto.spec.DHPublicKeySpec; +import java.math.BigInteger; + +/** + * A utility class to get key length, valiate keys, etc. + */ +public final class KeyUtil { + + /** + * Returns the key size of the given key object in bits. + * + * @param key the key object, cannot be null + * @return the key size of the given key object in bits, or -1 if the + * key size is not accessible + */ + public static final int getKeySize(Key key) { + int size = -1; + + if (key instanceof Length) { + try { + Length ruler = (Length)key; + size = ruler.length(); + } catch (UnsupportedOperationException usoe) { + // ignore the exception + } + + if (size >= 0) { + return size; + } + } + + // try to parse the length from key specification + if (key instanceof SecretKey) { + SecretKey sk = (SecretKey)key; + String format = sk.getFormat(); + if ("RAW".equals(format) && sk.getEncoded() != null) { + size = (sk.getEncoded().length * 8); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + } else if (key instanceof RSAKey) { + RSAKey pubk = (RSAKey)key; + size = pubk.getModulus().bitLength(); + } else if (key instanceof ECKey) { + ECKey pubk = (ECKey)key; + size = pubk.getParams().getOrder().bitLength(); + } else if (key instanceof DSAKey) { + DSAKey pubk = (DSAKey)key; + size = pubk.getParams().getP().bitLength(); + } else if (key instanceof DHKey) { + DHKey pubk = (DHKey)key; + size = pubk.getParams().getP().bitLength(); + } // Otherwise, it may be a unextractable key of PKCS#11, or + // a key we are not able to handle. + + return size; + } + + /** + * Returns whether the key is valid or not. + *

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

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

    + * Note that this method is only apply to SunJCE and SunPKCS11 at present. + * + * @param providerName + * the provider name + * @return true if, and only if, the provider of the specified + * {@code providerName} is Oracle provider + */ + public static final boolean isOracleJCEProvider(String providerName) { + return providerName != null && (providerName.equals("SunJCE") || + providerName.startsWith("SunPKCS11")); + } + + /** + * Returns whether the Diffie-Hellman public key is valid or not. + * + * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to + * validate Diffie-Hellman public keys: + * 1. Verify that y lies within the interval [2,p-1]. If it does not, + * the key is invalid. + * 2. Compute y^q mod p. If the result == 1, the key is valid. + * Otherwise the key is invalid. + */ + private static void validateDHPublicKey(DHPublicKey publicKey) + throws InvalidKeyException { + DHParameterSpec paramSpec = publicKey.getParams(); + + BigInteger p = paramSpec.getP(); + BigInteger g = paramSpec.getG(); + BigInteger y = publicKey.getY(); + + validateDHPublicKey(p, g, y); + } + + private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec) + throws InvalidKeyException { + validateDHPublicKey(publicKeySpec.getP(), + publicKeySpec.getG(), publicKeySpec.getY()); + } + + private static void validateDHPublicKey(BigInteger p, + BigInteger g, BigInteger y) throws InvalidKeyException { + + // For better interoperability, the interval is limited to [2, p-2]. + BigInteger leftOpen = BigInteger.ONE; + BigInteger rightOpen = p.subtract(BigInteger.ONE); + if (y.compareTo(leftOpen) <= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too small"); + } + if (y.compareTo(rightOpen) >= 0) { + throw new InvalidKeyException( + "Diffie-Hellman public key is too large"); + } + + // Don't bother to check against the y^q mod p if safe primes are used. + } +} + diff --git a/src/share/classes/sun/security/util/UntrustedCertificates.java b/src/share/classes/sun/security/util/UntrustedCertificates.java index 6aad34a73a4b53990596c0bdea379c83f2386821..03fdbc783320f353f19ed1b69ab7793c8c4c9974 100644 --- a/src/share/classes/sun/security/util/UntrustedCertificates.java +++ b/src/share/classes/sun/security/util/UntrustedCertificates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -737,5 +737,111 @@ public final class UntrustedCertificates { "B8WfedLHjFW/TMcnXlEWKz4=\n" + "-----END CERTIFICATE-----"); + // + // Revoked DigiCert code signing certificates used to sign malware + // + + // Subject: CN=Buster Paper Comercial Ltda, + // O=Buster Paper Comercial Ltda, + // L=S?o Jos? Dos Campos, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 + add("buster-paper-comercial-ltda-72A67312", + "-----BEGIN CERTIFICATE-----\n" + + "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" + + "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" + + "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" + + "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" + + "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" + + "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" + + "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" + + "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" + + "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" + + "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" + + "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" + + "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" + + "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" + + "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" + + "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" + + "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" + + "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" + + "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" + + "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" + + "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" + + "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" + + "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" + + "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" + + "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" + + "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" + + "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" + + "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" + + "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" + + "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" + + "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" + + "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" + + "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" + + "XMuKLxbh7g==\n" + + "-----END CERTIFICATE-----"); + + // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, + // L=S?o Paulo, + // ST=S?o Paulo, + // C=BR + // Issuer: CN=DigiCert Assured ID Code Signing CA-1, + // OU=www.digicert.com, + // O=DigiCert Inc, + // C=US + // Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f + add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F", + "-----BEGIN CERTIFICATE-----\n" + + "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" + + "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + + "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + + "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" + + "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" + + "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" + + "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" + + "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" + + "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" + + "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" + + "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" + + "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" + + "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" + + "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" + + "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" + + "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" + + "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" + + "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" + + "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" + + "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" + + "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" + + "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" + + "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" + + "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" + + "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" + + "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" + + "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" + + "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" + + "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" + + "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" + + "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" + + "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" + + "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" + + "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" + + "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" + + "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" + + "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + + "-----END CERTIFICATE-----"); + } } diff --git a/src/share/classes/sun/swing/JLightweightFrame.java b/src/share/classes/sun/swing/JLightweightFrame.java new file mode 100644 index 0000000000000000000000000000000000000000..f7ea0aead1ecbcec2f326215d8ce0e995fb31ea6 --- /dev/null +++ b/src/share/classes/sun/swing/JLightweightFrame.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.swing; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; + +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.LayoutFocusTraversalPolicy; +import javax.swing.RootPaneContainer; + +import sun.awt.LightweightFrame; + +/** + * The frame serves as a lightweight container which paints its content + * to an offscreen image and provides access to the image's data via the + * {@link LightweightContent} interface. Note, that it may not be shown + * as a standalone toplevel frame. Its purpose is to provide functionality + * for lightweight embedding. + * + * @author Artem Ananiev + * @author Anton Tarasov + */ +public final class JLightweightFrame extends LightweightFrame implements RootPaneContainer { + + private final JRootPane rootPane = new JRootPane(); + + private LightweightContent content; + + private Component component; + private JPanel contentPane; + + private BufferedImage bbImage; + + /** + * Constructs a new, initially invisible {@code JLightweightFrame} + * instance. + */ + public JLightweightFrame() { + super(); + add(rootPane, BorderLayout.CENTER); + setBackground(new Color(0, 0, 0, 0)); + setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); + } + + /** + * Sets the {@link LightweightContent} instance for this frame. + * The {@code JComponent} object returned by the + * {@link LightweightContent#getComponent()} method is immediately + * added to the frame's content pane. + * + * @param content the {@link LightweightContent} instance + */ + public void setContent(LightweightContent content) { + this.content = content; + this.component = content.getComponent(); + + initInterior(); + } + + @Override + public Graphics getGraphics() { + if (bbImage == null) return null; + + Graphics2D g = bbImage.createGraphics(); + g.setBackground(getBackground()); + g.setColor(getForeground()); + g.setFont(getFont()); + return g; + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusGrabbed() + */ + @Override + public void grabFocus() { + if (content != null) content.focusGrabbed(); + } + + /** + * {@inheritDoc} + * + * @see LightweightContent#focusUngrabbed() + */ + @Override + public void ungrabFocus() { + if (content != null) content.focusUngrabbed(); + } + + private void initInterior() { + contentPane = new JPanel() { + @Override + public void paint(Graphics g) { + content.paintLock(); + try { + super.paint(g); + + final Rectangle clip = g.getClipBounds() != null ? + g.getClipBounds() : new Rectangle(0, 0, contentPane.getWidth(), contentPane.getHeight()); + + clip.x = Math.max(0, clip.x); + clip.y = Math.max(0, clip.y); + clip.width = Math.min(contentPane.getWidth(), clip.width); + clip.height = Math.min(contentPane.getHeight(), clip.height); + + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + content.imageUpdated(clip.x, clip.y, clip.width, clip.height); + } + }); + } finally { + content.paintUnlock(); + } + } + @Override + protected boolean isPaintingOrigin() { + return true; + } + }; + contentPane.setLayout(new BorderLayout()); + contentPane.add(component); + setContentPane(contentPane); + } + + @SuppressWarnings("deprecation") + @Override public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + + if (width == 0 || height == 0) { + return; + } + + content.paintLock(); + try { + if ((bbImage == null) || (width != bbImage.getWidth()) || (height != bbImage.getHeight())) { + boolean createBB = true; + int newW = width; + int newH = height; + if (bbImage != null) { + int oldW = bbImage.getWidth(); + int oldH = bbImage.getHeight(); + if ((oldW >= newW) && (oldH >= newH)) { + createBB = false; + } else { + if (oldW >= newW) { + newW = oldW; + } else { + newW = Math.max((int)(oldW * 1.2), width); + } + if (oldH >= newH) { + newH = oldH; + } else { + newH = Math.max((int)(oldH * 1.2), height); + } + } + } + if (createBB) { + BufferedImage oldBB = bbImage; + bbImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB_PRE); + if (oldBB != null) { + Graphics g = bbImage.getGraphics(); + try { + g.drawImage(oldBB, 0, 0, newW, newH, null); + } finally { + g.dispose(); + oldBB.flush(); + } + } + DataBufferInt dataBuf = (DataBufferInt)bbImage.getRaster().getDataBuffer(); + content.imageBufferReset(dataBuf.getData(), 0, 0, width, height, bbImage.getWidth()); + } else { + content.imageReshaped(0, 0, width, height); + } + } + } finally { + content.paintUnlock(); + } + } + + @Override + public JRootPane getRootPane() { + return rootPane; + } + + @Override + public void setContentPane(Container contentPane) { + getRootPane().setContentPane(contentPane); + } + + @Override + public Container getContentPane() { + return getRootPane().getContentPane(); + } + + @Override + public void setLayeredPane(JLayeredPane layeredPane) { + getRootPane().setLayeredPane(layeredPane); + } + + @Override + public JLayeredPane getLayeredPane() { + return getRootPane().getLayeredPane(); + } + + @Override + public void setGlassPane(Component glassPane) { + getRootPane().setGlassPane(glassPane); + } + + @Override + public Component getGlassPane() { + return getRootPane().getGlassPane(); + } +} diff --git a/src/share/classes/sun/swing/LightweightContent.java b/src/share/classes/sun/swing/LightweightContent.java new file mode 100644 index 0000000000000000000000000000000000000000..2d443fba23ce1de9f9765df0b6727a56b6c4916e --- /dev/null +++ b/src/share/classes/sun/swing/LightweightContent.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.swing; + +import javax.swing.JComponent; + +/** + * The interface by means of which the {@link JLightweightFrame} class + * communicates to its client application. + *

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

    + * The {@code width} and {@code height} matches the size of the content + * (the component returned from the {@link #getComponent} method). The + * {@code x} and {@code y} is the origin of the content, {@code (0, 0)} + * in the coordinate space of the content, appearing at + * {@code data[y * linestride + x]} in the buffer. All indices + * {@code data[(y + j) * linestride + (x + i)]} where + * {@code (0 <= i < width)} and {@code (0 <= j < height)} will represent + * valid pixel data, {@code (i, j)} in the coordinate space of the content. + * + * @param data the content pixel data buffer of INT_ARGB_PRE type + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * @param linestride the line stride of the pixel buffer + */ + public void imageBufferReset(int[] data, + int x, int y, + int width, int height, + int linestride); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the content image bounds have been changed within the + * image's pixel buffer. + * + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the width of the image + * @param height the height of the image + * + * @see #imageBufferReset + */ + public void imageReshaped(int x, int y, int width, int height); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that a part of the content image, or the whole image has + * been updated. The method reports bounds of the rectangular dirty region. + * The {@code dirtyX} and {@code dirtyY} is the origin of the dirty + * rectangle, which is relative to the origin of the content, appearing + * at {@code data[(y + dirtyY] * linestride + (x + dirtyX)]} in the pixel + * buffer (see {@link #imageBufferReset}). All indices + * {@code data[(y + dirtyY + j) * linestride + (x + dirtyX + i)]} where + * {@code (0 <= i < dirtyWidth)} and {@code (0 <= j < dirtyHeight)} + * will represent valid pixel data, {@code (i, j)} in the coordinate space + * of the dirty rectangle. + * + * @param dirtyX the x coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyY the y coordinate of the dirty rectangle, + * relative to the image origin + * @param dirtyWidth the width of the dirty rectangle + * @param dirtyHeight the height of the dirty rectangle + * + * @see #imageBufferReset + * @see #imageReshaped + */ + public void imageUpdated(int dirtyX, int dirtyY, + int dirtyWidth, int dirtyHeight); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has grabbed focus. + */ + public void focusGrabbed(); + + /** + * {@code JLightweightFrame} calls this method to notify the client + * application that the frame has ungrabbed focus. + */ + public void focusUngrabbed(); +} diff --git a/src/share/demo/java2d/J2DBench/build.xml b/src/share/demo/java2d/J2DBench/build.xml index a36aca8cec7fb32c7861ccd65fe658afe8aab377..c29611d0f7a7775de32f4ecb9a8e28e900fc0ee4 100644 --- a/src/share/demo/java2d/J2DBench/build.xml +++ b/src/share/demo/java2d/J2DBench/build.xml @@ -52,7 +52,7 @@ - - + + + + - - diff --git a/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d61c9f120fd60e556ee88419c641f5253249774 Binary files /dev/null and b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_large.jpg differ diff --git a/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6b4ef3f38d14d03a7f990e4d50e25af75e1d3a8b Binary files /dev/null and b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_medium.jpg differ diff --git a/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41fb2eaccbafed7d86598d7e7642e197192f402e Binary files /dev/null and b/src/share/demo/java2d/J2DBench/resources/cmm_images/img_icc_small.jpg differ diff --git a/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java b/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java index e71b18857f18b99fbcb56f5977cd4f5f7826cc09..4916929c32f970d202612588b8f9ee5aebe5e20d 100644 --- a/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java +++ b/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/ColorConversionTests.java @@ -51,6 +51,7 @@ public class ColorConversionTests extends CMMTests { DataConversionTests.init(); ColorConvertOpTests.init(); + EmbeddedProfileTests.init(); } protected ColorConversionTests(Group parent, String nodeName, String description) { diff --git a/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java b/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java new file mode 100644 index 0000000000000000000000000000000000000000..3af6313eff19163f85f38072f9d1d2e9f2bb5f17 --- /dev/null +++ b/src/share/demo/java2d/J2DBench/src/j2dbench/tests/cmm/EmbeddedProfileTests.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This source code is provided to illustrate the usage of a given feature + * or technique and has been deliberately simplified. Additional steps + * required for a production-quality application, such as security checks, + * input validation and proper error handling, might not be present in + * this sample code. + */ + +package j2dbench.tests.cmm; + +import j2dbench.Group; +import j2dbench.Option; +import j2dbench.Result; +import j2dbench.TestEnvironment; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +/* This benchmark verifies how changes in cmm library affects image decoding */ +public class EmbeddedProfileTests extends ColorConversionTests { + + protected static Group grpRoot; + protected static Group grpOptionsRoot; + + protected static Option inputImages; + + public static void init() { + grpRoot = new Group(colorConvRoot, "embed", "Embedded Profile Tests"); + + grpOptionsRoot = new Group(grpRoot, "embedOptions", "Options"); + + inputImages = createImageList(); + + new ReadImageTest(); + } + + private static enum IccImageResource { + SMALL("images/img_icc_small.jpg", "512x512", "Small: 512x512"), + MEDIUM("images/img_icc_medium.jpg", "2048x2048", "Medium: 2048x2048"), + LARGE("images/img_icc_large.jpg", "4096x4096", "Large: 4096x4096"); + + private IccImageResource(String file, String name, String description) { + this.url = CMMTests.class.getResource(file); + this.abbrev = name; + this.description = description; + } + + public final URL url; + public final String abbrev; + public final String description; + } + + private static Option createImageList() { + IccImageResource[] images = IccImageResource.values(); + + int num = images.length; + + String[] names = new String[num]; + String[] abbrev = new String[num]; + String[] descr = new String[num]; + + for (int i = 0; i < num; i++) { + names[i] = images[i].toString(); + abbrev[i] = images[i].abbrev; + descr[i] = images[i].description; + } + + Option list = new Option.ObjectList(grpOptionsRoot, + "Images", "Input Images", + names, images, abbrev, descr, 1); + + return list; + } + + public EmbeddedProfileTests(Group parent, String nodeName, String description) { + super(parent, nodeName, description); + addDependencies(grpOptionsRoot, true); + } + + private static class Context { + URL input; + + public Context(TestEnvironment env, Result res) { + + IccImageResource icc_input = (IccImageResource) + env.getModifier(inputImages); + + input = icc_input.url; + } + } + + public Object initTest(TestEnvironment env, Result res) { + return new Context(env, res); + } + + public void cleanupTest(TestEnvironment env, Object o) { + Context ctx = (Context)o; + ctx.input = null; + } + + private static class ReadImageTest extends EmbeddedProfileTests { + public ReadImageTest() { + super(grpRoot, "embd_img_read", "ImageReader.read()"); + } + + public void runTest(Object octx, int numReps) { + final Context ctx = (Context)octx; + final URL url = ctx.input; + ImageInputStream iis = null; + ImageReader reader = null; + + try { + iis = ImageIO.createImageInputStream(url.openStream()); + reader = ImageIO.getImageReaders(iis).next(); + } catch (IOException e) { + throw new RuntimeException("Unable to run the becnhmark", e); + } + + do { + try { + reader.setInput(iis); + BufferedImage img = reader.read(0); + reader.reset(); + + iis = ImageIO.createImageInputStream(url.openStream()); + } catch (Exception e) { + e.printStackTrace(); + } + } while (--numReps >= 0); + } + } +} diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux index dd63fd4d1e2ff7ea44ac2326434a0d389c4c8e02..8fc53d736774a26cc29180227f1e173aa5603d16 100644 --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -145,7 +145,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -157,7 +169,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx index 00759d7b2154b4858b4d3bbcc844aba3e016ddce..5a319fa5445032b5a9470fa27ae9604d4dfa7cc8 100644 --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -146,7 +146,20 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ + apple. # # List of comma-separated packages that start with or equal this string @@ -158,7 +171,20 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal.,\ + apple. # # Determines whether this properties file can be appended to diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris index 241873676b7898a0d850366c643ac49b3e40ec9c..2a781cff75d667758247e5660e3924625d1730bf 100644 --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -147,7 +147,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -159,7 +171,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows index 62b8b51fee64baaec9eb6172a0e9dda37d713f22..a00f4628dd68fc6801cfbe3e7f8e039906f699aa 100644 --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -146,7 +146,19 @@ keystore.type=jks # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.access=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # List of comma-separated packages that start with or equal this string @@ -158,7 +170,19 @@ package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun. # by default, none of the class loaders supplied with the JDK call # checkPackageDefinition. # -package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal. +package.definition=sun.,\ + com.sun.xml.internal.bind.,\ + com.sun.xml.internal.org.jvnet.staxex.,\ + com.sun.xml.internal.ws.,\ + com.sun.imageio.,\ + com.sun.istack.internal.,\ + com.sun.jmx.,\ + com.sun.proxy.,\ + com.sun.org.apache.xerces.internal.utils.,\ + com.sun.org.apache.xalan.internal.utils.,\ + com.sun.org.glassfish.external.,\ + com.sun.org.glassfish.gmbal.,\ + jdk.internal. # # Determines whether this properties file can be appended to diff --git a/src/share/native/com/sun/java/util/jar/pack/bands.cpp b/src/share/native/com/sun/java/util/jar/pack/bands.cpp index 42340fa5cfd72439dd5dcc4a1238a7409f9ba125..f698c6d6cfbb8c11c9e9e4d29e1fdc5719368361 100644 --- a/src/share/native/com/sun/java/util/jar/pack/bands.cpp +++ b/src/share/native/com/sun/java/util/jar/pack/bands.cpp @@ -187,6 +187,10 @@ void band::setIndexByTag(byte tag) { entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { CHECK_0; + if (ix_ == NULL) { + abort("no index"); + return NULL; + } assert(ix_->ixTag == ixTag || ((ixTag == CONSTANT_All || ixTag == CONSTANT_LoadableValue || diff --git a/src/share/native/com/sun/java/util/jar/pack/bands.h b/src/share/native/com/sun/java/util/jar/pack/bands.h index 052cd5d71a5deac7d66dbf5e7af7e44848a9cca6..c10b93d18884925114e80681abe19c2695915671 100644 --- a/src/share/native/com/sun/java/util/jar/pack/bands.h +++ b/src/share/native/com/sun/java/util/jar/pack/bands.h @@ -99,8 +99,8 @@ struct band { int getByte() { assert(ix == null); return vs[0].getByte(); } int getInt() { assert(ix == null); return vs[0].getInt(); } - entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); } - entry* getRef() { assert(ix != null); return getRefCommon(ix, false); } + entry* getRefN() { return getRefCommon(ix, true); } + entry* getRef() { return getRefCommon(ix, false); } entry* getRefUsing(cpindex* ix2) { assert(ix == null); return getRefCommon(ix2, true); } entry* getRefCommon(cpindex* ix, bool nullOK); diff --git a/src/share/native/com/sun/java/util/jar/pack/jni.cpp b/src/share/native/com/sun/java/util/jar/pack/jni.cpp index bedecda53913702f1078708f29944eb8720e0f21..26c683f0ae976dee119f694a712d1a7069c05aaf 100644 --- a/src/share/native/com/sun/java/util/jar/pack/jni.cpp +++ b/src/share/native/com/sun/java/util/jar/pack/jni.cpp @@ -50,6 +50,7 @@ static jfieldID unpackerPtrFID; static jmethodID currentInstMID; static jmethodID readInputMID; static jclass NIclazz; +static jmethodID getUnpackerPtrMID; static char* dbg = null; @@ -60,8 +61,8 @@ static jlong read_input_via_jni(unpacker* self, static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) { unpacker* uPtr; - uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID)); - //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr); + jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID); + uPtr = (unpacker*)jlong2ptr(p); if (uPtr == null) { if (noCreate) return null; uPtr = new unpacker(); @@ -94,11 +95,15 @@ static unpacker* get_unpacker() { if (env == null) return null; jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID); - //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj); - if (pObj == null) - return null; - // Got pObj and env; now do it the easy way. - return get_unpacker(env, pObj); + //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj); + if (pObj != null) { + // Got pObj and env; now do it the easy way. + return get_unpacker(env, pObj); + } + // this should really not happen, if it does something is seriously + // wrong throw an exception + THROW_IOE(ERROR_INTERNAL); + return null; } static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) { @@ -127,18 +132,23 @@ static jlong read_input_via_jni(unpacker* self, JNIEXPORT void JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) { +#ifndef PRODUCT dbg = getenv("DEBUG_ATTACH"); while( dbg != null) { sleep(10); } +#endif NIclazz = (jclass) env->NewGlobalRef(clazz); unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J"); currentInstMID = env->GetStaticMethodID(clazz, "currentInstance", "()Ljava/lang/Object;"); readInputMID = env->GetMethodID(clazz, "readInputFn", "(Ljava/nio/ByteBuffer;J)J"); + getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J"); + if (unpackerPtrFID == null || currentInstMID == null || readInputMID == null || - NIclazz == null) { + NIclazz == null || + getUnpackerPtrMID == null) { THROW_IOE("cannot init class members"); } } @@ -146,8 +156,13 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) JNIEXPORT jlong JNICALL Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, jobject pBuf, jlong offset) { - unpacker* uPtr = get_unpacker(env, pObj); - + // try to get the unpacker pointer the hard way first, we do this to ensure + // valid object pointers and env is intact, if not now is good time to bail. + unpacker* uPtr = get_unpacker(); + //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr); + if (uPtr == null) { + return -1; + } // redirect our io to the default log file or whatever. uPtr->redirect_stdio(); @@ -163,7 +178,12 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj, else { buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; } } - + // before we start off we make sure there is no other error by the time we + // get here + if (uPtr->aborting()) { + THROW_IOE(uPtr->get_abort_message()); + return 0; + } uPtr->start(buf, buflen); if (uPtr->aborting()) { THROW_IOE(uPtr->get_abort_message()); @@ -230,11 +250,14 @@ Java_com_sun_java_util_jar_pack_NativeUnpack_getUnusedInput(JNIEnv *env, jobject // We have fetched all the files. // Now swallow up any remaining input. - if (uPtr->input_remaining() == 0) + if (uPtr->input_remaining() == 0) { return null; - else - return env->NewDirectByteBuffer(uPtr->input_scan(), - uPtr->input_remaining()); + } else { + bytes remaining_bytes; + remaining_bytes.malloc(uPtr->input_remaining()); + remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining()); + return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len); + } } JNIEXPORT jlong JNICALL diff --git a/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index aae7921ae43289af996e4550379429b83cd94433..44ea89866f07159f69e7221cd9ae63a4145e0e90 100644 --- a/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -281,11 +281,13 @@ int entry::typeSize() { } inline cpindex* cpool::getFieldIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+0]; } inline cpindex* cpool::getMethodIndex(entry* classRef) { + if (classRef == NULL) { abort("missing class reference"); return NULL; } assert(classRef->tagMatches(CONSTANT_Class)); assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]); return &member_indexes[classRef->inord*2+1]; @@ -1291,6 +1293,7 @@ void unpacker::read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 2); e.refs[0] = cp_band1.getRef(); + CHECK; e.refs[1] = cp_band2.getRef(); CHECK; } @@ -1371,6 +1374,7 @@ void unpacker::read_method_type(entry* cpMap, int len) { entry& e = cpMap[i]; e.refs = U_NEW(entry*, e.nrefs = 1); e.refs[0] = cp_MethodType.getRef(); + CHECK; } } @@ -2106,6 +2110,7 @@ void unpacker::read_attr_defs() { int attrc = ADH_BYTE_CONTEXT(header); int idx = ADH_BYTE_INDEX(header); entry* name = attr_definition_name.getRef(); + CHECK; entry* layout = attr_definition_layout.getRef(); CHECK; attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval()); @@ -2210,7 +2215,9 @@ void unpacker::read_ics() { if (ics[i].name == NO_ENTRY_YET) { // Long form. ics[i].outer = ic_outer_class.getRefN(); + CHECK; ics[i].name = ic_name.getRefN(); + CHECK; } else { // Fill in outer and name based on inner. bytes& n = ics[i].inner->value.b; @@ -2733,6 +2740,7 @@ void unpacker::putlayout(band** body) { e = b.getRefUsing(cp.getKQIndex()); else e = b.getRefN(); + CHECK; switch (b.le_len) { case 0: break; case 1: putu1ref(e); break; @@ -3121,7 +3129,7 @@ void unpacker::read_bcs() { void unpacker::read_bands() { byte* rp0 = rp; - + CHECK; read_file_header(); CHECK; @@ -3883,10 +3891,12 @@ void unpacker::dump_options() { // packed file and len is the length of the buffer. // If null, the callback is used to fill an internal buffer. void unpacker::start(void* packptr, size_t len) { + CHECK; NOT_PRODUCT(debug_u = this); if (packptr != null && len != 0) { inbytes.set((byte*) packptr, len); } + CHECK; read_bands(); } @@ -4018,6 +4028,7 @@ void unpacker::write_bc_ops() { NOT_PRODUCT(bc_superfield.setIndex(null)); NOT_PRODUCT(bc_supermethod.setIndex(null)); } + CHECK; for (int curIP = 0; ; curIP++) { int curPC = (int)(wpoffset() - codeBase); @@ -4131,7 +4142,8 @@ void unpacker::write_bc_ops() { int coding = bc_initref.getInt(); // Find the nth overloading of in classRef. entry* ref = null; - cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef); + cpindex* ix = cp.getMethodIndex(classRef); + CHECK; for (int j = 0, which_init = 0; ; j++) { ref = (ix == null)? null: ix->get(j); if (ref == null) break; // oops, bad input @@ -4414,6 +4426,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod): aname = cp.sym[cpool::s_EnclosingMethod]; putref(class_EnclosingMethod_RC.getRefN()); + CHECK_0; putref(class_EnclosingMethod_RDN.getRefN()); break; @@ -4432,6 +4445,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { putu2(count = method_Exceptions_N.getInt()); for (j = 0; j < count; j++) { putref(method_Exceptions_RC.getRefN()); + CHECK_0; } break; @@ -4464,16 +4478,18 @@ int unpacker::write_attrs(int attrc, julong indexBits) { // (253) [(1)(2)(2)] // (254) [(1)(2)(2)(2)] putu2(code_StackMapTable_offset.getInt()); + CHECK_0; for (int k = (tag - 251); k > 0; k--) { put_stackmap_type(); + CHECK_0; } } else { // (255) [(1)NH[(2)]NH[(2)]] putu2(code_StackMapTable_offset.getInt()); putu2(j2 = code_StackMapTable_local_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} putu2(j2 = code_StackMapTable_stack_N.getInt()); - while (j2-- > 0) put_stackmap_type(); + while (j2-- > 0) {put_stackmap_type(); CHECK_0;} } } break; @@ -4497,7 +4513,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTable_slot.getInt()); } break; @@ -4512,7 +4530,9 @@ int unpacker::write_attrs(int attrc, julong indexBits) { bii += code_LocalVariableTypeTable_span_O.getInt(); putu2(to_bci(bii) - bci); putref(code_LocalVariableTypeTable_name_RU.getRefN()); + CHECK_0; putref(code_LocalVariableTypeTable_type_RS.getRefN()); + CHECK_0; putu2(code_LocalVariableTypeTable_slot.getInt()); } break; @@ -4540,7 +4560,7 @@ int unpacker::write_attrs(int attrc, julong indexBits) { break; } } - + CHECK_0; if (aname == null) { // Unparse a compressor-defined attribute. layout_definition* lo = ad.getLayout(idx); @@ -4696,7 +4716,9 @@ int unpacker::write_ics(int naOffset, int na) { flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero extra_ic.flags = flags; extra_ic.outer = class_InnerClasses_outer_RCN.getRefN(); + CHECK_0; extra_ic.name = class_InnerClasses_name_RUN.getRefN(); + CHECK_0; // Detect if this is an exact copy of the global tuple. if (global_ic != null) { if (global_ic->flags != extra_ic.flags || @@ -4806,6 +4828,7 @@ void unpacker::write_classfile_tail() { julong indexMask = ad.flagIndexMask(); cur_class = class_this.getRef(); + CHECK; cur_super = class_super.getRef(); CHECK; @@ -4819,6 +4842,7 @@ void unpacker::write_classfile_tail() { putu2(num = class_interface_count.getInt()); for (i = 0; i < num; i++) { putref(class_interface.getRef()); + CHECK; } write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); diff --git a/src/share/native/sun/awt/image/awt_parseImage.c b/src/share/native/sun/awt/image/awt_parseImage.c index d6f6d60d3569bb1602c976e4ab2944fad15c1d4f..498ac717913acf76ff18d0fb79a3834347f7b81b 100644 --- a/src/share/native/sun/awt/image/awt_parseImage.c +++ b/src/share/native/sun/awt/image/awt_parseImage.c @@ -114,6 +114,62 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, return status; } +/* Verifies whether the channel offsets are sane and correspond to the type of + * the raster. + * + * Return value: + * 0: Failure: channel offsets are invalid + * 1: Success + */ +static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) { + int i, lastPixelOffset, lastScanOffset; + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) { + return 0; + } + if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) { + return 0; + } + + lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride; + lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride; + + + if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) { + return 0; + } + + lastPixelOffset += lastScanOffset; + + for (i = 0; i < rasterP->numDataElements; i++) { + int off = rasterP->chanOffsets[i]; + int size = lastPixelOffset + off; + + if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) { + return 0; + } + + if (size < lastPixelOffset || size >= dataArrayLength) { + // an overflow, or insufficient buffer capacity + return 0; + } + } + return 1; + case BANDED_RASTER_TYPE: + // NB:caller does not support the banded rasters yet, + // so this branch of the code must be re-defined in + // order to provide valid criteria for the data offsets + // verification, when/if banded rasters will be supported. + // At the moment, we prohibit banded rasters as well. + return 0; + default: + // PACKED_RASTER_TYPE: does not support channel offsets + // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error + return 0; + } +} + /* Parse the raster. All of the raster information is returned in the * rasterP structure. * @@ -125,7 +181,6 @@ int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { jobject joffs = NULL; /* int status;*/ - int isDiscrete = TRUE; if (JNU_IsNull(env, jraster)) { JNU_ThrowNullPointerException(env, "null Raster object"); @@ -155,6 +210,9 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return -1; } + // make sure that the raster type is initialized + rasterP->rasterType = UNKNOWN_RASTER_TYPE; + if (rasterP->numBands <= 0 || rasterP->numBands > MAX_NUMBANDS) { @@ -165,9 +223,14 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } + rasterP->sppsm.isUsed = 0; + if ((*env)->IsInstanceOf(env, rasterP->jsampleModel, (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) { jobject jmask, joffs, jnbits; + + rasterP->sppsm.isUsed = 1; + rasterP->sppsm.maxBitSize = (*env)->GetIntField(env, rasterP->jsampleModel, g_SPPSMmaxBitID); @@ -254,7 +317,6 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); rasterP->dataType = BYTE_DATA_TYPE; - isDiscrete = FALSE; } else { rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; @@ -265,7 +327,19 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { return 0; } - if (isDiscrete) { + // do basic validation of the raster structure + if (rasterP->width <= 0 || rasterP->height <= 0 || + rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0) + { + // invalid raster + return -1; + } + + // channel (data) offsets + switch (rasterP->rasterType) { + case COMPONENT_RASTER_TYPE: + case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment + // get channel (data) offsets rasterP->chanOffsets = NULL; if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { rasterP->chanOffsets = @@ -278,10 +352,21 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { } (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, rasterP->chanOffsets); + if (rasterP->jdata == NULL) { + // unable to verify the raster + return -1; + } + // verify whether channel offsets look sane + if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) { + return -1; + } + break; + default: + ; // PACKED_RASTER_TYPE does not use the channel offsets. } - /* additioanl check for sppsm fields validity: make sure that - * size of raster samples doesn't exceed the data type cpacity. + /* additional check for sppsm fields validity: make sure that + * size of raster samples doesn't exceed the data type capacity. */ if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */ rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */ @@ -696,6 +781,21 @@ setHints(JNIEnv *env, BufImageS_t *imageP) { } else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { int i; + + /* do some sanity check first: make sure that + * - sample model is SinglePixelPackedSampleModel + * - number of bands in the raster corresponds to the number + * of color components in the color model + */ + if (!rasterP->sppsm.isUsed || + rasterP->numBands != cmodelP->numComponents) + { + /* given raster is not compatible with the color model, + * so the operation has to be aborted. + */ + return -1; + } + if (cmodelP->maxNbits > 8) { hintP->needToExpand = TRUE; hintP->expandToNbits = cmodelP->maxNbits; diff --git a/src/share/native/sun/awt/image/awt_parseImage.h b/src/share/native/sun/awt/image/awt_parseImage.h index f58adabb754c3bc8d59225057a6c841e9c4a76b9..b92bb0c28333a671c2598448a3651121f407a0c6 100644 --- a/src/share/native/sun/awt/image/awt_parseImage.h +++ b/src/share/native/sun/awt/image/awt_parseImage.h @@ -95,6 +95,7 @@ typedef struct { jint offsets[MAX_NUMBANDS]; jint nBits[MAX_NUMBANDS]; jint maxBitSize; + jint isUsed; // flag to indicate whether the raster sample model is SPPSM } SPPSampleModelS_t; /* Struct that holds information for the Raster object */ diff --git a/src/share/native/sun/awt/medialib/safe_alloc.h b/src/share/native/sun/awt/medialib/safe_alloc.h index ce744af2c3bc9049dc953d544005a674a2ee1c5d..579d98638dc06b13373225f7c2e0ef7eca023e39 100644 --- a/src/share/native/sun/awt/medialib/safe_alloc.h +++ b/src/share/native/sun/awt/medialib/safe_alloc.h @@ -41,5 +41,10 @@ (((w) > 0) && ((h) > 0) && ((sz) > 0) && \ (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) +#define SAFE_TO_MULT(a, b) \ + (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b))) + +#define SAFE_TO_ADD(a, b) \ + (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b))) #endif // __SAFE_ALLOC_H__ diff --git a/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c b/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c index fcd7de01639ece7d91000721a7c9876934503053..b1a5909895557c74e1b794acffefeef6913d2ab4 100644 --- a/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +++ b/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c @@ -133,6 +133,10 @@ SplashDecodeJpeg(Splash * splash, struct jpeg_decompress_struct *cinfo) ImageFormat srcFormat; jpeg_read_header(cinfo, TRUE); + + // SplashScreen jpeg converter expects data in RGB format only + cinfo->out_color_space = JCS_RGB; + jpeg_start_decompress(cinfo); SplashCleanup(splash); diff --git a/src/share/native/sun/font/layout/LookupProcessor.cpp b/src/share/native/sun/font/layout/LookupProcessor.cpp index 60727aa3f3ade56e9a518a6dbc4573d168196149..88e9f25ddeb8fa348338d7fb4b73800583d9e35c 100644 --- a/src/share/native/sun/font/layout/LookupProcessor.cpp +++ b/src/share/native/sun/font/layout/LookupProcessor.cpp @@ -125,6 +125,10 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt } const LookupTable *lookupTable = lookupListTable->getLookupTable(lookupTableIndex); + if (lookupTable == NULL) { + success = LE_INTERNAL_ERROR; + return 0; + } le_uint16 lookupFlags = SWAPW(lookupTable->lookupFlags); GlyphIterator tempIterator(*glyphIterator, lookupFlags); le_uint32 delta = applyLookupTable(lookupTable, &tempIterator, fontInstance, success); diff --git a/src/share/native/sun/java2d/cmm/lcms/LCMS.c b/src/share/native/sun/java2d/cmm/lcms/LCMS.c index 7da0370baad578f82e50b6948fbd0bcd6b0f8ff0..1340c82a822232aed61c8299f838d4e837491b37 100644 --- a/src/share/native/sun/java2d/cmm/lcms/LCMS.c +++ b/src/share/native/sun/java2d/cmm/lcms/LCMS.c @@ -117,6 +117,7 @@ static jfieldID IL_offset_fID; static jfieldID IL_nextRowOffset_fID; static jfieldID IL_width_fID; static jfieldID IL_height_fID; +static jfieldID IL_imageAtOnce_fID; static jfieldID PF_ID_fID; JavaVM *javaVM; @@ -237,7 +238,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform * Method: loadProfile * Signature: ([B)J */ -JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile +JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative (JNIEnv *env, jobject obj, jbyteArray data) { jbyte* dataArray; @@ -284,7 +285,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile * Method: freeProfile * Signature: (J)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfile +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative (JNIEnv *env, jobject obj, jlong id) { storeID_t sProf; @@ -369,48 +370,22 @@ static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); -/* - * Class: sun_java2d_cmm_lcms_LCMS - * Method: getTagSize - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize - (JNIEnv *env, jobject obj, jlong id, jint tagSig) -{ - storeID_t sProf; - TagSignature_t sig; - jint result = -1; - - sProf.j = id; - sig.j = tagSig; - - if (tagSig == SigHead) { - result = sizeof(cmsICCHeader); - } else { - if (cmsIsTag(sProf.pf, sig.cms)) { - result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); - } else { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "ICC profile tag not found"); - } - } - - return result; -} /* * Class: sun_java2d_cmm_lcms_LCMS * Method: getTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData - (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) +JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative + (JNIEnv *env, jobject obj, jlong id, jint tagSig) { storeID_t sProf; TagSignature_t sig; cmsInt32Number tagSize; - jbyte* dataArray; + jbyte* dataArray = NULL; + jbyteArray data = NULL; + jint bufSize; sProf.j = id; @@ -419,12 +394,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (tagSig == SigHead) { cmsBool status; - bufSize =(*env)->GetArrayLength(env, data); + // allocate java array + bufSize = sizeof(cmsICCHeader); + data = (*env)->NewByteArray(env, bufSize); - if (bufSize < sizeof(cmsICCHeader)) { - JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity"); - return; + if (data == NULL) { + JNU_ThrowByName(env, "java/awt/color/CMMException", + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -432,7 +409,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } status = _getHeaderInfo(sProf.pf, dataArray, bufSize); @@ -442,9 +419,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (!status) { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC Profile header not found"); + return NULL; } - return; + return data; } if (cmsIsTag(sProf.pf, sig.cms)) { @@ -452,16 +430,15 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData } else { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); - return; + return NULL; } - // verify data buffer capacity - bufSize = (*env)->GetArrayLength(env, data); - - if (tagSize < 0 || 0 > bufSize || tagSize > bufSize) { + // allocate java array + data = (*env)->NewByteArray(env, tagSize); + if (data == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", - "Insufficient buffer capacity."); - return; + "Unable to allocate buffer"); + return NULL; } dataArray = (*env)->GetByteArrayElements (env, data, 0); @@ -469,7 +446,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (dataArray == NULL) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Unable to get buffer"); - return; + return NULL; } bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize); @@ -479,8 +456,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData if (bufSize != tagSize) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Can not get tag data."); + return NULL; } - return; + return data; } /* @@ -488,7 +466,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData * Method: setTagData * Signature: (JI[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) { storeID_t sProf; @@ -586,6 +564,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert char* inputRow; char* outputRow; jobject srcData, dstData; + jboolean srcAtOnce = JNI_FALSE, dstAtOnce = JNI_FALSE; srcOffset = (*env)->GetIntField (env, src, IL_offset_fID); srcNextRowOffset = (*env)->GetIntField (env, src, IL_nextRowOffset_fID); @@ -594,6 +573,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert width = (*env)->GetIntField (env, src, IL_width_fID); height = (*env)->GetIntField (env, src, IL_height_fID); + srcAtOnce = (*env)->GetBooleanField(env, src, IL_imageAtOnce_fID); + dstAtOnce = (*env)->GetBooleanField(env, dst, IL_imageAtOnce_fID); + sTrans.j = (*env)->GetLongField (env, trans, Trans_ID_fID); if (sTrans.xf == NULL) { @@ -625,10 +607,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert inputRow = (char*)inputBuffer + srcOffset; outputRow = (char*)outputBuffer + dstOffset; - for (i = 0; i < height; i++) { - cmsDoTransform(sTrans.xf, inputRow, outputRow, width); - inputRow += srcNextRowOffset; - outputRow += dstNextRowOffset; + if (srcAtOnce && dstAtOnce) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width * height); + } else { + for (i = 0; i < height; i++) { + cmsDoTransform(sTrans.xf, inputRow, outputRow, width); + inputRow += srcNextRowOffset; + outputRow += dstNextRowOffset; + } } releaseILData(env, inputBuffer, srcDType, srcData); @@ -670,6 +656,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS IL_width_fID = (*env)->GetFieldID (env, IL, "width", "I"); IL_height_fID = (*env)->GetFieldID (env, IL, "height", "I"); IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I"); + IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z"); IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I"); PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); diff --git a/src/share/native/sun/java2d/loops/AnyByteBinary.h b/src/share/native/sun/java2d/loops/AnyByteBinary.h index abe7f230beeb7551ae9c7d888fad6c8ed7567a46..3b1fa03b06a21a3d3b9030704dffcdb1d45bf331 100644 --- a/src/share/native/sun/java2d/loops/AnyByteBinary.h +++ b/src/share/native/sun/java2d/loops/AnyByteBinary.h @@ -153,7 +153,10 @@ jint PREFIX ## rgb; #define InitByteBinaryAlphaLoadData(TYPE, PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteBinaryFor4ByteArgb(TYPE, pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/ByteIndexed.h b/src/share/native/sun/java2d/loops/ByteIndexed.h index 3917c238e486a106ce01368a6cb3482c010dbdc0..215cfc0e1115a5abbcd9a4c8fdc8d96be87944e8 100644 --- a/src/share/native/sun/java2d/loops/ByteIndexed.h +++ b/src/share/native/sun/java2d/loops/ByteIndexed.h @@ -202,7 +202,10 @@ typedef jubyte ByteIndexedBmDataType; jint PREFIX ## rgb; #define InitByteIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromByteIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/IntArgb.h b/src/share/native/sun/java2d/loops/IntArgb.h index aec63431cb1015b6dd6e04ca8c52474bacd27028..f4ec00524cc4dbdbe8b2f0a0aef19a9e885fa013 100644 --- a/src/share/native/sun/java2d/loops/IntArgb.h +++ b/src/share/native/sun/java2d/loops/IntArgb.h @@ -122,7 +122,8 @@ typedef jint IntArgbDataType; #define DeclareIntArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/IntArgbBm.h b/src/share/native/sun/java2d/loops/IntArgbBm.h index 81d551820a841157d9032c3613c9e2d3e4189493..675fba1d228a294683d973903649b49a38eb90b8 100644 --- a/src/share/native/sun/java2d/loops/IntArgbBm.h +++ b/src/share/native/sun/java2d/loops/IntArgbBm.h @@ -133,7 +133,8 @@ typedef jint IntArgbBmDataType; #define DeclareIntArgbBmAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbBmAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbBmFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/IntArgbPre.h b/src/share/native/sun/java2d/loops/IntArgbPre.h index 5ffb9dacb0bd1ea0f98b71b698b4c4ed409cc288..c45013d0e004b1c5199be089fae0e09dcd0afb08 100644 --- a/src/share/native/sun/java2d/loops/IntArgbPre.h +++ b/src/share/native/sun/java2d/loops/IntArgbPre.h @@ -153,7 +153,8 @@ typedef jint IntArgbPreDataType; #define DeclareIntArgbPreAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) +#define InitIntArgbPreAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromIntArgbPreFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/TransformHelper.c b/src/share/native/sun/java2d/loops/TransformHelper.c index 23bba354756c6404f9126494d1210b99cdb600bd..7233455025088a5c6ce600d2da668c8754183926 100644 --- a/src/share/native/sun/java2d/loops/TransformHelper.c +++ b/src/share/native/sun/java2d/loops/TransformHelper.c @@ -353,6 +353,9 @@ Java_sun_java2d_loops_TransformHelper_Transform pInterpFunc = pBicubicFunc; maxlinepix = LINE_SIZE / 16; break; + default: + // Should not happen, but just in case. + return; } srcInfo.bounds.x1 = sx1; diff --git a/src/share/native/sun/java2d/loops/Ushort4444Argb.h b/src/share/native/sun/java2d/loops/Ushort4444Argb.h index 348e03b7df427438d3528c874d7272495f1b37b2..aa50d8b0ff32e3365ae564892f868eaef50ebcfd 100644 --- a/src/share/native/sun/java2d/loops/Ushort4444Argb.h +++ b/src/share/native/sun/java2d/loops/Ushort4444Argb.h @@ -120,7 +120,8 @@ typedef jushort Ushort4444ArgbDataType; #define DeclareUshort4444ArgbAlphaLoadData(PREFIX) \ jint PREFIX; -#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) +#define InitUshort4444ArgbAlphaLoadData(PREFIX, pRasInfo) \ + PREFIX = 0 #define LoadAlphaFromUshort4444ArgbFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/share/native/sun/java2d/loops/UshortIndexed.h b/src/share/native/sun/java2d/loops/UshortIndexed.h index 7786bda38290abf0c0e4a5e3e604a24de4aed108..6a4b5b13e5d148372c7429518ae1aaa0fa9e0944 100644 --- a/src/share/native/sun/java2d/loops/UshortIndexed.h +++ b/src/share/native/sun/java2d/loops/UshortIndexed.h @@ -170,7 +170,10 @@ typedef jushort UshortIndexedBmDataType; jint PREFIX ## rgb; #define InitUshortIndexedAlphaLoadData(PREFIX, pRasInfo) \ - PREFIX ## Lut = (pRasInfo)->lutBase + do { \ + PREFIX ## Lut = (pRasInfo)->lutBase; \ + PREFIX ## rgb = 0; \ + } while (0) #define LoadAlphaFromUshortIndexedFor4ByteArgb(pRas, PREFIX, COMP_PREFIX) \ do { \ diff --git a/src/solaris/classes/sun/awt/X11/XFramePeer.java b/src/solaris/classes/sun/awt/X11/XFramePeer.java index fdefb1047ceda052c4227ee0c7e03e9cabe2242f..0c540b1785540d35b0f85ec9849144d0c4454884 100644 --- a/src/solaris/classes/sun/awt/X11/XFramePeer.java +++ b/src/solaris/classes/sun/awt/X11/XFramePeer.java @@ -641,4 +641,6 @@ class XFramePeer extends XDecoratedPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + public void emulateActivation(boolean doActivate) {} } diff --git a/src/solaris/classes/sun/awt/X11/XToolkit.java b/src/solaris/classes/sun/awt/X11/XToolkit.java index 7c40e8260efba0a7990b84e2c5d543ba9e0a4b5d..b4fb9c76f179952f0efcb5260c9a4e8290ff39c3 100644 --- a/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -419,6 +419,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + return null; + } + public FramePeer createFrame(Frame target) { FramePeer peer = new XFramePeer(target); targetCreatedPeer(target, peer); diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 9035d0a44f8be066644f54e7e5c15ba0ceddc4f8..f71345c84c307659399a5f0cd1dbbaa4191a1b0e 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1026,13 +1026,21 @@ public class SctpChannelImpl extends SctpChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } + int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, -1 /*121*/, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, -1 /*121*/, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -1091,7 +1099,7 @@ public class SctpChannelImpl extends SctpChannel long address, int length, boolean peek) throws IOException; static native int send0(int fd, long address, int length, - SocketAddress target, int assocId, int streamNumber, + InetAddress addr, int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException; private static native int checkConnect(FileDescriptor fd, boolean block, diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index 6b42fcc02e305efaa8ff2a44446e3ccb9ce80d72..84552ba042ddd77c7fe0d88b17068980b18f22a2 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -889,13 +889,20 @@ public class SctpMultiChannelImpl extends SctpMultiChannel boolean unordered, int ppid) throws IOException { + InetAddress addr = null; // no preferred address + int port = 0; + if (target != null) { + InetSocketAddress isa = Net.checkAddress(target); + addr = isa.getAddress(); + port = isa.getPort(); + } int pos = bb.position(); int lim = bb.limit(); assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, - rem, target, assocId, streamNumber, unordered, ppid); + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, assocId, streamNumber, unordered, ppid); if (written > 0) bb.position(pos + written); return written; @@ -976,13 +983,14 @@ public class SctpMultiChannelImpl extends SctpMultiChannel private static int send0(int fd, long address, int length, - SocketAddress target, + InetAddress addr, + int port, int assocId, int streamNumber, boolean unordered, int ppid) throws IOException { - return SctpChannelImpl.send0(fd, address, length, target, assocId, + return SctpChannelImpl.send0(fd, address, length, addr, port, assocId, streamNumber, unordered, ppid); } diff --git a/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c b/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c index d8514a8412653ce8c6c68c0564723abbd4204449..cd2f4927bdbfaad96506c0450ac52aef847cb10c 100644 --- a/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c +++ b/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c @@ -46,8 +46,6 @@ #include "sun_nio_ch_DatagramChannelImpl.h" -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -61,9 +59,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -212,15 +207,13 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, jlong address, - jint len, jobject dest) + jint len, jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKADDR sa; int sa_len = SOCKADDR_LEN; jint n = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (len > MAX_PACKET_LEN) { len = MAX_PACKET_LEN; diff --git a/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c b/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c index b432403e9db8ea00350a929be2622db9d8313faa..225556b4d9f9ece73cbb8038e5b00e784a7a40ac 100644 --- a/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c +++ b/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c @@ -67,8 +67,6 @@ static jclass spc_class; /* sun.nio.ch.sctp.PeerAddressChanged */ static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged. */ static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */ static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown. */ -static jfieldID isa_addrID; /* java.net.InetSocketAddress.addr */ -static jfieldID isa_portID; /* java.net.InetSocketAddress.port */ /* defined in SctpNet.c */ jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr); @@ -138,13 +136,6 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_initIDs CHECK_NULL(ss_class); ss_ctrID = (*env)->GetMethodID(env, cls, "", "(I)V"); CHECK_NULL(ss_ctrID); - - /* InetSocketAddress */ - cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); - CHECK_NULL(cls); - isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL(isa_addrID); - isa_portID = (*env)->GetFieldID(env, cls, "port", "I"); } void getControlData @@ -509,12 +500,12 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0 /* * Class: sun_nio_ch_sctp_SctpChannelImpl * Method: send0 - * Signature: (IJILjava/net/SocketAddress;IIZI)I + * Signature: (IJILjava/net/InetAddress;IIIZI)I */ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 (JNIEnv *env, jclass klass, jint fd, jlong address, jint length, - jobject saTarget, jint assocId, jint streamNumber, jboolean unordered, - jint ppid) { + jobject targetAddress, jint targetPort, jint assocId, jint streamNumber, + jboolean unordered, jint ppid) { SOCKADDR sa; int sa_len = sizeof(sa); ssize_t rv = 0; @@ -526,17 +517,13 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0 struct controlData cdata[1]; /* SctpChannel: - * saTarget may contain the preferred address or NULL to use primary, + * targetAddress may contain the preferred address or NULL to use primary, * assocId will always be -1 * SctpMultiChannell: - * Setup new association, saTarget will contain address, assocId = -1 - * Association already existing, assocId != -1, saTarget = preferred addr + * Setup new association, targetAddress will contain address, assocId = -1 + * Association already existing, assocId != -1, targetAddress = preferred addr */ - if (saTarget != NULL /*&& assocId <= 0*/) { - - jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID); - jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID); - + if (targetAddress != NULL /*&& assocId <= 0*/) { if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) { diff --git a/src/windows/bin/java_md.c b/src/windows/bin/java_md.c index e236cab1f2ea77d5142fbc5b5b860341faecd5a2..4078ecc754bb11a8cb1abc2d699554b2fa224c52 100644 --- a/src/windows/bin/java_md.c +++ b/src/windows/bin/java_md.c @@ -101,7 +101,6 @@ int awtPreloadD3D = -1; /* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */ #define D3D_PRELOAD_FUNC "preloadD3D" - /* Extracts value of a parameter with the specified name * from command line argument (returns pointer in the argument). * Returns NULL if the argument does not contains the parameter. @@ -276,7 +275,8 @@ LoadMSVCRT() #endif #ifdef CRT_DLL if (GetJREPath(crtpath, MAXPATHLEN)) { - if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { + if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) { JLI_ReportErrorMessage(JRE_ERROR11); return JNI_FALSE; } @@ -347,7 +347,8 @@ GetJVMPath(const char *jrepath, const char *jvmtype, if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) { JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype); } else { - JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, + jrepath, jvmtype); } if (stat(jvmpath, &s) == 0) { return JNI_TRUE; @@ -525,6 +526,37 @@ jlong Counter2Micros(jlong counts) } return (counts * 1000 * 1000)/counterFrequency.QuadPart; } +/* + * windows snprintf does not guarantee a null terminator in the buffer, + * if the computed size is equal to or greater than the buffer size, + * as well as error conditions. This function guarantees a null terminator + * under all these conditions. An unreasonable buffer or size will return + * an error value. Under all other conditions this function will return the + * size of the bytes actually written minus the null terminator, similar + * to ansi snprintf api. Thus when calling this function the caller must + * ensure storage for the null terminator. + */ +int +JLI_Snprintf(char* buffer, size_t size, const char* format, ...) { + int rc; + va_list vl; + if (size == 0 || buffer == NULL) + return -1; + buffer[0] = '\0'; + va_start(vl, format); + rc = vsnprintf(buffer, size, format, vl); + va_end(vl); + /* force a null terminator, if something is amiss */ + if (rc < 0) { + /* apply ansi semantics */ + buffer[size - 1] = '\0'; + return size; + } else if (rc == size) { + /* force a null terminator */ + buffer[size - 1] = '\0'; + } + return rc; +} void JLI_ReportErrorMessage(const char* fmt, ...) { @@ -880,7 +912,7 @@ unquote(const char *s) { */ void ExecJRE(char *jre, char **argv) { - int len; + jint len; char path[MAXPATHLEN + 1]; const char *progname = GetProgramName(); @@ -1417,7 +1449,10 @@ CreateApplicationArgs(JNIEnv *env, char **strv, int argc) // we add the indicator tlen = 1 + JLI_StrLen(strv[i]) + 1; nargv[i] = (char *) JLI_MemAlloc(tlen); - JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]); + if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', + strv[i]) < 0) { + return NULL; + } JLI_TraceLauncher("%s\n", nargv[i]); } diff --git a/src/windows/classes/sun/awt/windows/WComponentPeer.java b/src/windows/classes/sun/awt/windows/WComponentPeer.java index 6f788c2ac5d5abbd0699303b6364dcd02d6e74be..37a257f1130cd0fee3d8cd6ddeaa24ab098f0d5a 100644 --- a/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -488,14 +488,15 @@ public abstract class WComponentPeer extends WObjectPeer try { replaceSurfaceData(); } catch (InvalidPipeException e) { - // REMIND : what do we do if our surface creation failed? + // REMIND : what do we do if our surface creation failed? } } } }; + Component c = (Component)target; // Fix 6255371. - if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r)); + if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { + postEvent(new InvocationEvent(c, r)); } } @@ -618,7 +619,7 @@ public abstract class WComponentPeer extends WObjectPeer } public void disposeLater() { - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() { + postEvent(new InvocationEvent(target, new Runnable() { public void run() { dispose(); } diff --git a/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java b/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java index b0f9cd3279d008c76d046b69d369709cbee61853..ce02e045e317fcd27cf5d95d2642a7618979a79a 100644 --- a/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java +++ b/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java @@ -27,6 +27,7 @@ package sun.awt.windows; import sun.awt.*; import java.awt.*; +import java.awt.event.InvocationEvent; import java.awt.peer.ComponentPeer; import java.awt.image.*; import sun.awt.image.ByteInterleavedRaster; @@ -226,17 +227,19 @@ public class WEmbeddedFrame extends EmbeddedFrame { } @SuppressWarnings("deprecation") - public void synthesizeWindowActivation(final boolean doActivate) { - if (!doActivate || EventQueue.isDispatchThread()) { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(doActivate); + public void synthesizeWindowActivation(final boolean activate) { + if (!activate || EventQueue.isDispatchThread()) { + ((WFramePeer)getPeer()).emulateActivation(activate); } else { // To avoid focus concurrence b/w IE and EmbeddedFrame // activation is postponed by means of posting it to EDT. - EventQueue.invokeLater(new Runnable() { - public void run() { - ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true); - } - }); + Runnable r = new Runnable() { + public void run() { + ((WFramePeer)getPeer()).emulateActivation(true); + } + }; + WToolkit.postEvent(WToolkit.targetToAppContext(this), + new InvocationEvent(this, r)); } } diff --git a/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java b/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java index 3b6d298bda812da3677f7d58a08d569d29df62da..ec551e30ced3be41af94524cad1a838749cc2da6 100644 --- a/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java +++ b/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java @@ -65,8 +65,6 @@ public class WEmbeddedFramePeer extends WFramePeer { public native Rectangle getBoundsPrivate(); - public native void synthesizeWmActivate(boolean doActivate); - @Override public boolean isAccelCapable() { // REMIND: Temp workaround for issues with using HW acceleration diff --git a/src/windows/classes/sun/awt/windows/WFramePeer.java b/src/windows/classes/sun/awt/windows/WFramePeer.java index 368b8f60696cd20edb74fcb91f917ea8764a4175..588b3caebdd527a4b2b2d24fa49fe452e782f4a8 100644 --- a/src/windows/classes/sun/awt/windows/WFramePeer.java +++ b/src/windows/classes/sun/awt/windows/WFramePeer.java @@ -200,4 +200,11 @@ class WFramePeer extends WWindowPeer implements FramePeer { public Rectangle getBoundsPrivate() { return getBounds(); } + + // TODO: implement it in peers. WLightweightFramePeer may implement lw version. + public void emulateActivation(boolean activate) { + synthesizeWmActivate(activate); + } + + private native void synthesizeWmActivate(boolean activate); } diff --git a/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java b/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java new file mode 100644 index 0000000000000000000000000000000000000000..c2c1604bef45972da6bf08d6b42ebd95c2eaf17c --- /dev/null +++ b/src/windows/classes/sun/awt/windows/WLightweightFramePeer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt.windows; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseEvent; + +import sun.awt.LightweightFrame; + +public class WLightweightFramePeer extends WFramePeer { + + public WLightweightFramePeer(LightweightFrame target) { + super(target); + } + + private LightweightFrame getLwTarget() { + return (LightweightFrame)target; + } + + @Override + public Graphics getGraphics() { + return getLwTarget().getGraphics(); + } + + @Override + public void show() { + super.show(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_SHOWN)); + } + + @Override + public void hide() { + super.hide(); + postEvent(new ComponentEvent((Component)getTarget(), ComponentEvent.COMPONENT_HIDDEN)); + } + + @Override + public void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_MOVED)); + postEvent(new ComponentEvent((Component) getTarget(), ComponentEvent.COMPONENT_RESIZED)); + } + + @Override + public void handleEvent(java.awt.AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_PRESSED) { + emulateActivation(true); + } + super.handleEvent(e); + } + + @Override + public void grab() { + getLwTarget().grabFocus(); + } + + @Override + public void ungrab() { + getLwTarget().ungrabFocus(); + } +} diff --git a/src/windows/classes/sun/awt/windows/WToolkit.java b/src/windows/classes/sun/awt/windows/WToolkit.java index afbdfa6c1f9c6a047b6d86c63f3d7aa44246ac6e..e87b0ad8c08ff9136c9a0281f723c65d90892882 100644 --- a/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/windows/classes/sun/awt/windows/WToolkit.java @@ -37,6 +37,7 @@ import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.PrivilegedAction; import sun.awt.AWTAutoShutdown; +import sun.awt.LightweightFrame; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; import sun.awt.Win32GraphicsEnvironment; @@ -398,6 +399,12 @@ public class WToolkit extends SunToolkit implements Runnable { return peer; } + public FramePeer createLightweightFrame(LightweightFrame target) { + FramePeer peer = new WLightweightFramePeer(target); + targetCreatedPeer(target, peer); + return peer; + } + public CanvasPeer createCanvas(Canvas target) { CanvasPeer peer = new WCanvasPeer(target); targetCreatedPeer(target, peer); diff --git a/src/windows/native/sun/nio/ch/DatagramChannelImpl.c b/src/windows/native/sun/nio/ch/DatagramChannelImpl.c index 9396cf82ea6400d1b6a1024a6723587e5f32024d..ab46f8d7faa57721ee811fdcc20c22afe22cc9f7 100644 --- a/src/windows/native/sun/nio/ch/DatagramChannelImpl.c +++ b/src/windows/native/sun/nio/ch/DatagramChannelImpl.c @@ -34,8 +34,6 @@ #include "net_util.h" #include -static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */ -static jfieldID isa_portID; /* port in java.net.InetSocketAddress */ static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */ static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */ @@ -50,9 +48,6 @@ Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz) isa_class = (*env)->NewGlobalRef(env, clazz); isa_ctorID = (*env)->GetMethodID(env, clazz, "", "(Ljava/net/InetAddress;I)V"); - isa_addrID = (*env)->GetFieldID(env, clazz, "addr", - "Ljava/net/InetAddress;"); - isa_portID = (*env)->GetFieldID(env, clazz, "port", "I"); clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl"); dci_senderID = (*env)->GetFieldID(env, clazz, "sender", @@ -214,15 +209,14 @@ Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this, JNIEXPORT jint JNICALL Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this, jboolean preferIPv6, jobject fdo, - jlong address, jint len, jobject dest) + jlong address, jint len, + jobject destAddress, jint destPort) { jint fd = fdval(env, fdo); void *buf = (void *)jlong_to_ptr(address); SOCKETADDRESS sa; int sa_len; jint rv = 0; - jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID); - jint destPort = (*env)->GetIntField(env, dest, isa_portID); if (NET_InetAddressToSockaddr(env, destAddress, destPort, (struct sockaddr *)&sa, diff --git a/src/windows/native/sun/windows/awt_Frame.cpp b/src/windows/native/sun/windows/awt_Frame.cpp index da1df839535a4a85acc390e79cf7df2826d61b94..41c5624f001c72a61908c06b40aa3e3d775acd61 100644 --- a/src/windows/native/sun/windows/awt_Frame.cpp +++ b/src/windows/native/sun/windows/awt_Frame.cpp @@ -105,6 +105,7 @@ AwtFrame::AwtFrame() { m_parentWnd = NULL; menuBar = NULL; m_isEmbedded = FALSE; + m_isLightweight = FALSE; m_ignoreWmSize = FALSE; m_isMenuDropped = FALSE; m_isInputMethodWindow = FALSE; @@ -170,14 +171,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) * area of the browser is a Java Frame for parenting purposes, but * really a Windows child window */ + BOOL isEmbeddedInstance = FALSE; + BOOL isEmbedded = FALSE; cls = env->FindClass("sun/awt/EmbeddedFrame"); - if (cls == NULL) { - return NULL; + if (cls) { + isEmbeddedInstance = env->IsInstanceOf(target, cls); } INT_PTR handle; - jboolean isEmbeddedInstance = env->IsInstanceOf(target, cls); - jboolean isEmbedded = FALSE; - if (isEmbeddedInstance) { handle = static_cast(env->GetLongField(target, AwtFrame::handleID)); if (handle != 0) { @@ -186,6 +186,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) } frame->m_isEmbedded = isEmbedded; + BOOL isLightweight = FALSE; + cls = env->FindClass("sun/awt/LightweightFrame"); + if (cls) { + isLightweight = env->IsInstanceOf(target, cls); + } + frame->m_isLightweight = isLightweight; + if (isEmbedded) { hwndParent = (HWND)handle; RECT rect; @@ -230,6 +237,23 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) rect.bottom-rect.top); frame->InitPeerGraphicsConfig(env, self); AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); + } else if (isLightweight) { + frame->m_isUndecorated = true; + frame->m_peerObject = env->NewGlobalRef(self); + frame->RegisterClass(); + + DWORD exStyle = 0; + DWORD style = WS_POPUP; + + frame->CreateHWnd(env, L"", + style, + exStyle, + 0, 0, 0, 0, + 0, + NULL, + ::GetSysColor(COLOR_WINDOWTEXT), + ::GetSysColor(COLOR_WINDOWFRAME), + self); } else { jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID); DWORD exStyle; @@ -345,16 +369,20 @@ LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, Ms case WM_SETFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtSetActiveWindow(); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtSetActiveWindow(); + } } mr = mrConsume; break; case WM_KILLFOCUS: if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain - if (!sm_suppressFocusAndActivation && IsEmbeddedFrame()) { - AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + if (!sm_suppressFocusAndActivation) { + if (IsLightweightFrame() || IsEmbeddedFrame()) { + AwtWindow::SynthesizeWmActivate(FALSE, GetHWnd(), NULL); + } } else if (sm_restoreFocusAndActivation) { if (AwtComponent::GetFocusedWindow() != NULL) { @@ -640,6 +668,10 @@ AwtFrame::Show() HWND hwnd = GetHWnd(); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + if (IsLightweightFrame()) { + return; + } + DTRACE_PRINTLN3("AwtFrame::Show:%s%s%s", m_iconic ? " iconic" : "", m_zoomed ? " zoomed" : "", @@ -992,6 +1024,9 @@ BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) // b) focus is requested to some of the frame's child. m_actualFocusedWindow = NULL; } + if (IsLightweightFrame()) { + return TRUE; + } return AwtWindow::AwtSetActiveWindow(isMouseEventCause); } @@ -1873,7 +1908,7 @@ Java_sun_awt_windows_WEmbeddedFramePeer_getBoundsPrivate(JNIEnv *env, jobject se } JNIEXPORT void JNICALL -Java_sun_awt_windows_WEmbeddedFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) +Java_sun_awt_windows_WFramePeer_synthesizeWmActivate(JNIEnv *env, jobject self, jboolean doActivate) { TRY; diff --git a/src/windows/native/sun/windows/awt_Frame.h b/src/windows/native/sun/windows/awt_Frame.h index f6d692b87eb359c9e1844a15751e3bb8b86d225b..e151c17c2a5b89c1456a18943c12322c2b1fb520 100644 --- a/src/windows/native/sun/windows/awt_Frame.h +++ b/src/windows/native/sun/windows/awt_Frame.h @@ -72,6 +72,8 @@ public: /* Returns whether this frame is embedded in an external native frame. */ INLINE BOOL IsEmbeddedFrame() { return m_isEmbedded; } + /* Returns whether this frame is lightweight. */ + INLINE virtual BOOL IsLightweightFrame() { return m_isLightweight; } INLINE BOOL IsSimpleWindow() { return FALSE; } @@ -169,6 +171,9 @@ private: /* The frame is an EmbeddedFrame. */ BOOL m_isEmbedded; + /* The frame is a LightweightFrame */ + BOOL m_isLightweight; + /* used so that calls to ::MoveWindow in SetMenuBar don't propogate because they are immediately followed by calls to Component.resize */ BOOL m_ignoreWmSize; diff --git a/src/windows/native/sun/windows/awt_TextComponent.cpp b/src/windows/native/sun/windows/awt_TextComponent.cpp index f16ba6c345ca98f57f11bbc630d85d20b25a6e55..eddcbca4088787bfd56eb4faf090d80f33c41dc9 100644 --- a/src/windows/native/sun/windows/awt_TextComponent.cpp +++ b/src/windows/native/sun/windows/awt_TextComponent.cpp @@ -53,14 +53,12 @@ struct EnableEditingStruct { * AwtTextComponent fields */ -/* java.awt.TextComponent fields */ -jfieldID AwtTextComponent::canAccessClipboardID; - - /************************************************************************ * AwtTextComponent methods */ +jmethodID AwtTextComponent::canAccessClipboardMID; + AwtTextComponent::AwtTextComponent() { m_synthetic = FALSE; m_lStartPos = -1; @@ -367,8 +365,7 @@ AwtTextComponent::WmPaste() } jobject target = GetTarget(env); jboolean canAccessClipboard = - env->GetBooleanField(target, - AwtTextComponent::canAccessClipboardID); + env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID); env->DeleteLocalRef(target); return (canAccessClipboard) ? mrDoDefault : mrConsume; } @@ -854,12 +851,13 @@ Java_sun_awt_windows_WTextComponentPeer_initIDs(JNIEnv *env, jclass cls) { TRY; - cls = env->FindClass("java/awt/TextComponent"); - if (cls != NULL) { - AwtTextComponent::canAccessClipboardID = - env->GetFieldID(cls, "canAccessClipboard", "Z"); - DASSERT(AwtTextComponent::canAccessClipboardID != NULL); - } + jclass textComponentClassID = env->FindClass("java/awt/TextComponent"); + AwtTextComponent::canAccessClipboardMID = + env->GetMethodID(textComponentClassID, + "canAccessClipboard", "()Z"); + env->DeleteLocalRef(textComponentClassID); + + DASSERT(AwtTextComponent::canAccessClipboardMID != NULL); CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_TextComponent.h b/src/windows/native/sun/windows/awt_TextComponent.h index e50219cd271889d635c8ed1b4a88fd7b0ab2deda..cc0fc97f780abd49e0d34b8dab0638b398a7091e 100644 --- a/src/windows/native/sun/windows/awt_TextComponent.h +++ b/src/windows/native/sun/windows/awt_TextComponent.h @@ -42,8 +42,7 @@ class AwtTextComponent : public AwtComponent { public: - /* java.awt.TextComponent canAccessClipboard field ID */ - static jfieldID canAccessClipboardID; + static jmethodID canAccessClipboardMID; AwtTextComponent(); diff --git a/src/windows/native/sun/windows/awt_Window.h b/src/windows/native/sun/windows/awt_Window.h index 8ad2b0902b2d5ac7aa219f2c9911917daf982961..0ee23322d4b16432efde613943fbc7fcb4501aae 100644 --- a/src/windows/native/sun/windows/awt_Window.h +++ b/src/windows/native/sun/windows/awt_Window.h @@ -143,6 +143,7 @@ public: INLINE HICON GetHIcon() {return m_hIcon;}; INLINE HICON GetHIconSm() {return m_hIconSm;}; INLINE BOOL IsIconInherited() {return m_iconInherited;}; + INLINE virtual BOOL IsLightweightFrame() {return FALSE;} /* Post events to the EventQueue */ void SendComponentEvent(jint eventId); @@ -193,8 +194,10 @@ public: // Execute on Toolkit only. INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) { + AwtWindow *win = static_cast(AwtComponent::GetComponent(targetHWnd)); if (doActivate && - (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT)))) + (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT))) && + (win == NULL || !win->IsLightweightFrame())) { // The activation is rejected if either: // - The toplevel is not visible diff --git a/test/Makefile b/test/Makefile index 093d4649b218d1f3042032ed557e42fa239c82e5..69d5dac3d579e5544c184d486218db100f95aae1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -513,6 +513,7 @@ jdk_other: $(call TestDirs, \ javax/script \ java/sql javax/sql \ javax/smartcardio \ + javax/xml/soap \ javax/xml/ws com/sun/internal/ws \ jdk/asm \ com/sun/org/apache/xerces \ diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 7adc6d2c660bc3127bfcddb8c80716a3304ab084..842ffbe253240253561c1982d643712f2f520802 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -330,6 +330,23 @@ tools/launcher/UnicodeTest.java macosx-all # 8007410 tools/launcher/FXLauncherTest.java linux-all +# 8004172 +sun/tools/jstat/jstatGcCapacityOutput1.sh generic-all +sun/tools/jstat/jstatGcCauseOutput1.sh generic-all +sun/tools/jstat/jstatGcOldOutput1.sh generic-all +sun/tools/jstat/jstatGcOutput1.sh generic-all +sun/tools/jstat/jstatGcPermCapacityOutput1.sh generic-all +sun/tools/jstat/jstatLineCounts1.sh generic-all +sun/tools/jstat/jstatLineCounts2.sh generic-all +sun/tools/jstat/jstatLineCounts3.sh generic-all +sun/tools/jstat/jstatLineCounts4.sh generic-all +sun/tools/jstat/jstatOptions1.sh generic-all +sun/tools/jstat/jstatTimeStamp1.sh generic-all +sun/tools/jstatd/jstatdExternalRegistry.sh generic-all +sun/tools/jstatd/jstatdDefaults.sh generic-all +sun/tools/jstatd/jstatdPort.sh generic-all +sun/tools/jstatd/jstatdServerName.sh generic-all + ############################################################################ # jdk_jdi diff --git a/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html b/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html new file mode 100644 index 0000000000000000000000000000000000000000..7049e827033e021ea0bb756fd3ba7514f864ccb2 --- /dev/null +++ b/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html @@ -0,0 +1,43 @@ + + + + + + ManualYesNoTest + + + +

    ManualYesNoTest
    Bug ID:

    + +

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

    + + + + diff --git a/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java b/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8b509a123112170a21f27ae54aed5cc5b23a8ece --- /dev/null +++ b/test/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 6243382 8006070 + @summary Dragging of mouse outside of a List and Choice area don't work properly on XAWT + @author Dmitry.Cherepanov@SUN.COM area=awt.list + @run applet/manual=yesno MouseDraggedOutCauseScrollingTest.html +*/ + +import java.applet.Applet; +import java.awt.*; + +public class MouseDraggedOutCauseScrollingTest extends Applet +{ + Choice choice; + List singleList; + List multipleList; + + public void init() + { + this.setLayout (new GridLayout (1, 3)); + + choice = new Choice(); + singleList = new List(3, false); + multipleList = new List(3, true); + + choice.add("Choice"); + for (int i = 1; i < 100; i++){ + choice.add(""+i); + } + + singleList.add("Single list"); + for (int i = 1; i < 100; i++) + singleList.add(""+i); + + multipleList.add("Multiple list"); + for (int i = 1; i < 100; i++) + multipleList.add(""+i); + + this.add(choice); + this.add(singleList); + this.add(multipleList); + + String toolkitName = Toolkit.getDefaultToolkit().getClass().getName(); + if (!toolkitName.equals("sun.awt.X11.XToolkit")) { + String[] instructions = + { + "This test is not applicable to the current platform. Press PASS" + }; + Sysout.createDialogWithInstructions( instructions ); + } else { + String[] instructions = + { + "0) Please note, that this is only Motif/XAWT test. At first, make the applet active", + "1.1) Click on the choice", + "1.2) Press the left button of the mouse and keep on any item of the choice, for example 5", + "1.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "1.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "1.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "2.1) Click on the single list", + "2.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "2.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "2.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", + "2.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", + "-----------------------------------", + "3.1) Click on the multiple list", + "3.2) Press the left button of the mouse and keep on any item of the list, for example 5", + "3.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", + "3.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the upper. If not, the test failed", + "3.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the lower. If not, the test failed", + "4) Test passed." + }; + Sysout.createDialogWithInstructions( instructions ); + } + + }//End init() + + public void start () + { + setSize (400,100); + setVisible(true); + validate(); + + }// start() + +}// class ManualYesNoTest + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class diff --git a/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java b/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java new file mode 100644 index 0000000000000000000000000000000000000000..156bfe5df0e9cdc77cdd6d0b87cc36a37c1d73b7 --- /dev/null +++ b/test/java/awt/Modal/ModalDialogMultiscreenTest/ModalDialogMultiscreenTest.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6430802 8008379 + @summary WM should not hang after show()/close() + @author anthony.petrov@sun.com: area=awt.modal + @run main/manual ModalDialogMultiscreenTest +*/ + + +/** + * ModalDialogMultiscreenTest.java + * + * summary: Tests whether a WM will hang on show()/close() a modal dialog in multiscreen mode + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + + +public class ModalDialogMultiscreenTest +{ + + private static class ButtonActionListener implements ActionListener { + JFrame frame; + JDialog dialog; + public ButtonActionListener(JFrame frame, JDialog dialog) { + this.frame = frame; + this.dialog = dialog; + } + public void actionPerformed(ActionEvent e) { + dialog.setLocationRelativeTo(frame); + dialog.setVisible(true); + } + } + public static class TestDialog extends JDialog { + public TestDialog(Frame owner, String title, boolean modal, GraphicsConfiguration gc) { + super(owner, title, modal, gc); + setSize(200, 100); + JButton button = new JButton("Close"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }); + getContentPane().add(button); + } + } + + private static void init() + { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gs = ge.getScreenDevices(); + + Sysout.createDialog( ); + + if (gs.length < 2) { + System.out.println("Not multi-head environment, test not valid!"); + ModalDialogMultiscreenTest.pass( ); + } + + String[] instructions = + { + "The test should be run on a multi-head X (non-xinerama) systems.", + "Otherwise click the Pass button right now.", + "You will see an open Frame on each screen your system has.", + "The frame has an 'Open dialog' button.", + "Clicking the button opens a modal dialog with a Close button.", + "The test procedure:", + "1. Open a dialog and close it with appropriate buttons.", + "2. Switch to another screen ($ DISPLAY=X.Y xprop)", + "3. Repeat steps 1-2 several times (about 3*)", + "If the test doesn't cause the window manager to hang, it's passed." + }; + Sysout.printInstructions( instructions ); + + + for (int i = 0; i < gs.length; i++) { + JFrame frame = new JFrame("Frame "+i,gs[i].getDefaultConfiguration()); + JButton button = new JButton("Open Dialog"); + button.setMinimumSize(new Dimension(200, 100)); + button.setPreferredSize(new Dimension(200, 100)); + button.setSize(new Dimension(200, 100)); + button.addActionListener(new ButtonActionListener(frame, new TestDialog(frame, "Dialog #"+i, true, gs[i].getDefaultConfiguration()))); + frame.getContentPane().add(button); + frame.pack(); + frame.setVisible(true); + } + + }//End init() + + + //ap203012: NO MORE CHANGES BELOW THIS LINE + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test-defined + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test passed nor test failed has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + //pass was called from a different thread, so set the flag and interrupt + // the main thead. + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class ModalDialogMultiscreenTest + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// make listeners in a class defined here, and instantiate them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + ModalDialogMultiscreenTest.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + ModalDialogMultiscreenTest.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog implements ActionListener +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + Panel buttonP = new Panel(); + Button passB = new Button( "pass" ); + Button failB = new Button( "fail" ); + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + passB = new Button( "pass" ); + passB.setActionCommand( "pass" ); + passB.addActionListener( this ); + buttonP.add( "East", passB ); + + failB = new Button( "fail" ); + failB.setActionCommand( "fail" ); + failB.addActionListener( this ); + buttonP.add( "West", failB ); + + add( "South", buttonP ); + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + + //catch presses of the passed and failed buttons. + //simply call the standard pass() or fail() static methods of + //ModalDialogMultiscreenTest + public void actionPerformed( ActionEvent e ) + { + if( e.getActionCommand() == "pass" ) + { + ModalDialogMultiscreenTest.pass(); + } + else + { + ModalDialogMultiscreenTest.fail(); + } + } + +}// TestDialog class diff --git a/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java b/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java index 9136e79f40e9a2dd6ea48f987878501eab658784..5b927f8d520e9fda922a2859e11c84b83b0a4b73 100644 --- a/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java +++ b/test/java/awt/Modal/WsDisabledStyle/Winkey/Winkey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,8 @@ */ /* - @test %I% %E% - @bug 6572263 6571808 + @test + @bug 6572263 6571808 8005920 @summary PIT:FileDialog minimized to taskbar(through 'Show Desktop')selecting the fileDialog using windowList @author dmitry.cherepanov: area=awt.modal @run main/manual Winkey @@ -48,12 +48,14 @@ public class Winkey String[] instructions = { + " 0. This test is for MS Windows only, if you use other OS, press \"pass\" button.", " 1. there is a frame with a 'show modal' button, ", " 2. press the button to show a modal dialog, ", " 3. the modal dialog will be shown over the frame, ", " 4. please verify that all (5.1, 5.2.1, 5.2.2) the following tests pass: ", " ", " 5.1. press combination Windows Key and M key to minimize all windows, ", + " note that the modal dialog and modal blocked windows are NOT minimized", " 5.2. press combination Windows Key and D key to show desktop, ", " 5.2.1. restore the dialog by choosing this one in the ALT-TAB list, ", " 5.2.2. restore the dialog by mouse click on taskbar (on java or any other item)", diff --git a/test/java/beans/Introspector/Test7192955.java b/test/java/beans/Introspector/Test7192955.java index 13e874ba71967c7b1a51df69ced4bc06b40150c9..afce427bf30d36d4a202f487b8f3ec4c428d395c 100644 --- a/test/java/beans/Introspector/Test7192955.java +++ b/test/java/beans/Introspector/Test7192955.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,20 @@ /* * @test - * @bug 7192955 + * @bug 7192955 8000183 * @summary Tests that all properties are bound * @author Sergey Malenkov */ +import java.beans.IntrospectionException; +import java.beans.Introspector; import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; import java.util.List; public class Test7192955 { - public static void main(String[] args) { + public static void main(String[] args) throws IntrospectionException { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) { throw new Error("a simple property is not bound"); } @@ -43,6 +46,12 @@ public class Test7192955 { if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) { throw new Error("a read-only property is not bound"); } + PropertyDescriptor[] pds = Introspector.getBeanInfo(MyBean.class, BaseBean.class).getPropertyDescriptors(); + for (PropertyDescriptor pd : pds) { + if (pd.getName().equals("test") && pd.isBound()) { + throw new Error("a simple property is bound without superclass"); + } + } } public static class BaseBean { diff --git a/test/java/nio/channels/DatagramChannel/SendToUnresolved.java b/test/java/nio/channels/DatagramChannel/SendToUnresolved.java index c916b2ef8aff202b0f17b59b2e9dd4c3ab4d946f..7b9ec6a9a36354c231d155a07474b5154b142c77 100644 --- a/test/java/nio/channels/DatagramChannel/SendToUnresolved.java +++ b/test/java/nio/channels/DatagramChannel/SendToUnresolved.java @@ -42,7 +42,7 @@ public class SendToUnresolved { try { dc.send(bb, sa); throw new RuntimeException("Expected exception not thrown"); - } catch (IOException e) { + } catch (IOException | UnresolvedAddressException e) { // Correct result } dc.close(); diff --git a/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy b/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy index f6e312ec6962d1b0cf56617cea10fe362e253551..3ba44491acaa5a2bd72f3d3ba4f3cf5f359f5883 100644 --- a/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy +++ b/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy @@ -13,6 +13,7 @@ grant { permission java.io.FilePermission ".${/}-", "read,write,delete"; permission java.lang.RuntimePermission "createClassLoader"; + permission java.lang.RuntimePermission "getClassLoader"; permission java.lang.RuntimePermission "setContextClassLoader"; // used by TestLibrary to determine test environment diff --git a/test/java/rmi/testlibrary/JavaVM.java b/test/java/rmi/testlibrary/JavaVM.java index c363f8e44203a5a49cad07b260dec5e4dd4f2622..a1b169823cdc4bd1bb50191275b1836a2548ba0e 100644 --- a/test/java/rmi/testlibrary/JavaVM.java +++ b/test/java/rmi/testlibrary/JavaVM.java @@ -110,6 +110,14 @@ public class JavaVM { return TestLibrary.getExtraProperty("jcov.options",""); } + public void start(Runnable runnable) throws IOException { + if (runnable == null) { + throw new NullPointerException("Runnable cannot be null."); + } + + start(); + new JavaVMCallbackHandler(runnable).start(); + } /** * Exec the VM as specified in this object's constructor. @@ -183,4 +191,35 @@ public class JavaVM { start(); return waitFor(); } + + /** + * Handles calling the callback. + */ + private class JavaVMCallbackHandler extends Thread { + Runnable runnable; + + JavaVMCallbackHandler(Runnable runnable) { + this.runnable = runnable; + } + + + /** + * Wait for the Process to terminate and notify the callback. + */ + @Override + public void run() { + if (vm != null) { + try { + vm.waitFor(); + } catch(InterruptedException ie) { + // Restore the interrupted status + Thread.currentThread().interrupt(); + } + } + + if (runnable != null) { + runnable.run(); + } + } + } } diff --git a/test/java/util/logging/CustomLogManager.java b/test/java/util/logging/CustomLogManager.java new file mode 100644 index 0000000000000000000000000000000000000000..9542e54ec02fc31fa1e6e6223894d3abf7320161 --- /dev/null +++ b/test/java/util/logging/CustomLogManager.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; +import java.util.logging.*; + +/* + * Custom LogManager implementation to verify that the implementation delegates + * to the LogManager subclass to register both system logger and user logger. + * + * The LogManager implementation is the one configuring the logger's property + * such as level, handler, etc. + */ +public class CustomLogManager extends LogManager { + static LogManager INSTANCE; + Map namedLoggers = new HashMap<>(); + Properties props = initConfig(); + public CustomLogManager() { + if (INSTANCE != null) { + throw new RuntimeException("CustomLogManager already created"); + } + INSTANCE = this; + } + + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + namedLoggers.put(name, logger); + // set level + if (props.get(name + ".level") != null) { + logger.setLevel(Level.parse(props.getProperty(name + ".level"))); + } + // add handlers + if (props.get(name + ".handlers") != null && logger.getHandlers().length == 0) { + logger.addHandler(new CustomHandler()); + } + // add parent loggers + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (props.get(pname + ".level") != null || + props.get(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + // + // The test doesn't set the parent for simplicity. + if (!namedLoggers.containsKey(pname)) { + Logger.getLogger(pname); + } + } + ix = ix2 + 1; + } + return true; + } + + public synchronized Logger getLogger(String name) { + return namedLoggers.get(name); + } + + public synchronized Enumeration getLoggerNames() { + return Collections.enumeration(namedLoggers.keySet()); + } + + public String getProperty(String name) { + return props.getProperty(name); + } + + public void readConfiguration() { + // do nothing + } + + public void readConfiguration(InputStream ins) { + // do nothing + } + + private Properties initConfig() { + Properties props = new Properties(); + props.put(".level", "CONFIG"); + props.put("CustomLogManagerTest.level", "WARNING"); + props.put("CustomLogManagerTest.handlers", "CustomLogManager$CustomHandler"); + props.put("SimpleLogManager.level", "INFO"); + props.put("SimpleLogManager.handlers", "CustomLogManager$CustomHandler"); + props.put("CustomLogManager$CustomHandler.level", "WARNING"); + props.put(".handlers", "CustomLogManager$CustomHandler"); + props.put("org.foo.bar.level", "SEVERE"); + props.put("org.foo.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.level", "SEVERE"); + props.put("org.openjdk.handlers", "CustomLogManager$CustomHandler"); + props.put("org.openjdk.core.level", "INFO"); + + return props; + } + + public static void checkLogger(String name) { + checkLogger(name, null); + } + + public static void checkLogger(String name, String resourceBundleName) { + Logger logger = INSTANCE.getLogger(name); + if (logger == null) { + throw new RuntimeException("Logger \"" + name + "\" not exist"); + } + System.out.format("Logger \"%s\" level=%s handlers=%s resourcebundle=%s%n", + name, logger.getLevel(), + Arrays.toString(logger.getHandlers()), + logger.getResourceBundleName()); + String rb = logger.getResourceBundleName(); + if (rb != resourceBundleName && (rb == null || rb.equals(resourceBundleName))) { + throw new RuntimeException("Logger \"" + name + + "\" unexpected resource bundle: " + rb); + } + + String value = INSTANCE.getProperty(name + ".level"); + String level = logger.getLevel() != null ? logger.getLevel().getName() : null; + if (level != value && (level == null || level.equals(value))) { + throw new RuntimeException("Logger \"" + name + "\" unexpected level: " + level); + } + + Handler[] handlers = logger.getHandlers(); + String hdl = INSTANCE.getProperty(name + ".handlers"); + if ((hdl == null && handlers.length != 0) || + (hdl != null && handlers.length != 1)) { + throw new RuntimeException("Logger \"" + name + "\" unexpected handler: " + + Arrays.toString(handlers)); + } + checkParents(name); + } + + private static void checkParents(String name) { + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (INSTANCE.getProperty(pname + ".level") != null || + INSTANCE.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + checkLogger(pname); + } + ix = ix2 + 1; + } + } + + // only CustomLogManager can create an instance of CustomHandler + private class CustomHandler extends StreamHandler { + } +} diff --git a/test/java/util/logging/CustomLogManagerTest.java b/test/java/util/logging/CustomLogManagerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2fa89a9a47b580a62582abf249ae3724d7f3ba70 --- /dev/null +++ b/test/java/util/logging/CustomLogManagerTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; + +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary Add loggers to custom log manager + * + * @compile -XDignore.symbol.file CustomLogManagerTest.java CustomLogManager.java + * @run main/othervm -Djava.util.logging.manager=CustomLogManager CustomLogManagerTest + */ +public class CustomLogManagerTest { + private static final String RESOURCE_BUNDLE = "sun.util.logging.resources.logging"; + public static void main(String[] args) { + String mgr = System.getProperty("java.util.logging.manager"); + if (!mgr.equals("CustomLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger.getLogger(CustomLogManagerTest.class.getName()); + Logger.getLogger("org.foo.Foo"); + Logger.getLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + // platform logger will be set with the default system resource bundle + PlatformLogger.getLogger("org.openjdk.core.logger"); + + if (LogManager.getLogManager() != CustomLogManager.INSTANCE) { + throw new RuntimeException(LogManager.getLogManager() + " not CustomLogManager"); + } + + CustomLogManager.checkLogger(CustomLogManagerTest.class.getName()); + CustomLogManager.checkLogger("org.foo.Foo"); + CustomLogManager.checkLogger("org.foo.bar.Foo", RESOURCE_BUNDLE); + CustomLogManager.checkLogger(Logger.GLOBAL_LOGGER_NAME); + CustomLogManager.checkLogger(""); + CustomLogManager.checkLogger("org.openjdk.core.logger", RESOURCE_BUNDLE); + } +} diff --git a/test/java/util/logging/SimpleLogManager.java b/test/java/util/logging/SimpleLogManager.java new file mode 100644 index 0000000000000000000000000000000000000000..f469727654f2fa352731474f42e690e2dd12c627 --- /dev/null +++ b/test/java/util/logging/SimpleLogManager.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.*; +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +/* + * @test + * @bug 8005615 + * @summary A LogManager subclass overrides its own implementation of named + * logger (see the subclassing information in the Logger class specification) + * + * @compile -XDignore.symbol.file CustomLogManager.java SimpleLogManager.java + * @run main/othervm -Djava.util.logging.manager=SimpleLogManager SimpleLogManager + */ +public class SimpleLogManager extends CustomLogManager { + public static void main(String[] args) { + String classname = System.getProperty("java.util.logging.manager"); + if (!classname.equals("SimpleLogManager")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + Logger logger = Logger.getLogger(SimpleLogManager.class.getName()); + Logger.getLogger("org.foo.bar.Foo"); + + // a platform logger used by the system code is just a Logger instance. + PlatformLogger.getLogger("org.openjdk.core.logger"); + + LogManager mgr = LogManager.getLogManager(); + if (mgr != CustomLogManager.INSTANCE || !(mgr instanceof SimpleLogManager)) { + throw new RuntimeException(LogManager.getLogManager() + " not SimpleLogManager"); + } + + checkCustomLogger(SimpleLogManager.class.getName(), null); + checkCustomLogger("org.foo.bar.Foo", null); + checkCustomLogger("org.openjdk.core.logger", "sun.util.logging.resources.logging"); + + // ## The LogManager.demandLogger method does not handle custom log manager + // ## that overrides the getLogger method to return a custom logger + // ## (see the test case in 8005640). Logger.getLogger may return + // ## a Logger instance but LogManager overrides it with a custom Logger + // ## instance like this case. + // + // However, the specification of LogManager and Logger subclassing is + // not clear whether this is supported or not. The following check + // just captures the current behavior. + if (logger instanceof CustomLogger) { + throw new RuntimeException(logger + " not CustomLogger"); + } + } + + private static void checkCustomLogger(String name, String resourceBundleName) { + CustomLogManager.checkLogger(name, resourceBundleName); + Logger logger1 = Logger.getLogger(name); + Logger logger2 = LogManager.getLogManager().getLogger(name); + if (logger1 != logger2) { + throw new RuntimeException(logger1 + " != " + logger2); + } + if (!(logger1 instanceof CustomLogger)) { + throw new RuntimeException(logger1 + " not CustomLogger"); + } + } + + /* + * This SimpleLogManager overrides the addLogger method to replace + * the given logger with a custom logger. + * + * It's unclear what the recommended way to use custom logger is. + * A LogManager subclass might override the getLogger method to return + * a custom Logger and create a new custom logger if not exist so that + * Logger.getLogger() can return a custom Logger instance but that violates + * the LogManager.getLogger() spec which should return null if not found. + */ + public synchronized boolean addLogger(Logger logger) { + String name = logger.getName(); + if (namedLoggers.containsKey(name)) { + return false; + } + CustomLogger newLogger = new CustomLogger(logger); + super.addLogger(newLogger); + return true; + } + + public class CustomLogger extends Logger { + CustomLogger(Logger logger) { + super(logger.getName(), logger.getResourceBundleName()); + } + CustomLogger(String name) { + super(name, null); + } + } +} diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java index ff56c46fbd26832817eeb869a44e092833daeab7..d91ae14ba57a1dc8b4cc3b8426e6da6b3f8cb386 100644 --- a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java +++ b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java @@ -119,9 +119,6 @@ public class SubjectDelegation2Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("monitorRole"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -132,6 +129,9 @@ public class SubjectDelegation2Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); diff --git a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java index b3a004e0467773870e128b201354639dd9e8ca4a..de1699877966d08bfc779703fe8b8d07d7408754 100644 --- a/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java +++ b/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java @@ -120,9 +120,6 @@ public class SubjectDelegation3Test { System.out.println("Create SimpleStandard MBean"); SimpleStandard s = new SimpleStandard("delegate"); mbs.registerMBean(s, new ObjectName("MBeans:type=SimpleStandard")); - // Set Security Manager - // - System.setSecurityManager(new SecurityManager()); // Create Properties containing the username/password entries // Properties props = new Properties(); @@ -133,6 +130,9 @@ public class SubjectDelegation3Test { HashMap env = new HashMap(); env.put("jmx.remote.authenticator", new JMXPluggableAuthenticator(props)); + // Set Security Manager + // + System.setSecurityManager(new SecurityManager()); // Create an RMI connector server // System.out.println("Create an RMI connector server"); diff --git a/test/javax/swing/text/html/7189299/bug7189299.java b/test/javax/swing/text/html/7189299/bug7189299.java new file mode 100644 index 0000000000000000000000000000000000000000..70d2057c89fb922728cd45563a3762ca6c649752 --- /dev/null +++ b/test/javax/swing/text/html/7189299/bug7189299.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2013 IBM Corporation + */ +import java.awt.BorderLayout; +import java.awt.Toolkit; + +import java.awt.event.ActionListener; +import javax.swing.DefaultButtonModel; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.html.HTMLEditorKit; +import sun.awt.SunToolkit; + + +/* + * @test + * @bug 8008289 + * @summary Shared ButtonModel instance should deregister previous listeners. + * @author Frank Ding + */ +public class bug7189299 { + + private static JEditorPane html; + private static JFrame frame; + + private static void setup() { + /** + * Note the input type is not restricted to "submit". Types "image", + * "checkbox", "radio" have the same problem. + */ + html = new JEditorPane("text/html", + "
    " + + "" + + "
    "); + frame = new JFrame(); + frame.setLayout(new BorderLayout()); + frame.add(html, BorderLayout.CENTER); + frame.setSize(200, 100); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } + + private static void doTest() { + /* + * Calling updateComponentTreeUI creates a new FormView instance with + * its own associated JButton instance. The same DefaultButtonModel + * instance is used for both FormView's. + * + * The action listeners associated with (the JButton for) the first + * FormView should be unregistered from this common DefaultButtonModel, + * such that only those for the new FormView remain. + */ + SwingUtilities.updateComponentTreeUI(html); + } + + private static void verifySingleDefaultButtonModelListener() { + HTMLEditorKit htmlEditorKit = (HTMLEditorKit) html.getEditorKit(); + StyleContext.NamedStyle style = ((StyleContext.NamedStyle) htmlEditorKit + .getInputAttributes()); + DefaultButtonModel model = ((DefaultButtonModel) style + .getAttribute(StyleConstants.ModelAttribute)); + ActionListener[] listeners = model.getActionListeners(); + int actionListenerNum = listeners.length; + if (actionListenerNum != 1) { + throw new RuntimeException( + "Expected single ActionListener object registered with " + + "DefaultButtonModel; found " + actionListenerNum + + " listeners registered."); + } + + int changeListenerNum = model.getChangeListeners().length; + if (changeListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ChangeListener object registered " + + "with DefaultButtonModel; found " + changeListenerNum + + " listeners registered."); + } + int itemListenerNum = model.getItemListeners().length; + if (itemListenerNum != 1) { + throw new RuntimeException( + "Expected at most one ItemListener object registered " + + "with DefaultButtonModel; found " + itemListenerNum + + " listeners registered."); + } + } + + public static void main(String[] args) throws Exception { + final SunToolkit toolkit = ((SunToolkit) Toolkit.getDefaultToolkit()); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + setup(); + } + }); + toolkit.realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + verifySingleDefaultButtonModelListener(); + doTest(); + verifySingleDefaultButtonModelListener(); + } finally { + frame.dispose(); + } + } + }); + } +} diff --git a/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java b/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java new file mode 100644 index 0000000000000000000000000000000000000000..75f63496bfa2a5514131aa5b129663ca598cac33 --- /dev/null +++ b/test/sun/awt/datatransfer/SuplementaryCharactersTransferTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6877495 + @summary JTextField and JTextArea does not support supplementary characters + @author Alexander Scherbatiy + @run main SuplementaryCharactersTransferTest +*/ + + +import java.io.*; +import java.util.*; +import java.awt.*; +import java.awt.datatransfer.*; +import sun.awt.datatransfer.*; +import sun.awt.datatransfer.DataTransferer.ReencodingInputStream; + +public class SuplementaryCharactersTransferTest { + + public static final long TEXT_FORMAT = 13; + + public static void main(String[] args) throws Exception { + + DataTransferer dataTransferer = new TestDataTransferer(); + dataTransferer.registerTextFlavorProperties("UNICODE TEXT", "utf-16le", "\r\n", "2"); + ByteTransferable transferable = new ByteTransferable(); + ReencodingInputStream is = dataTransferer.new ReencodingInputStream(transferable.getByteInputStream(), TEXT_FORMAT, + DataTransferer.getTextCharset(transferable.getDataFlavor()), transferable); + + byte[] bytes = transferable.getBytes(); + byte[] result = new byte[bytes.length]; + + is.read(result); + + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] != result[i]) { + throw new RuntimeException("Characters are not equal!"); + } + } + + } + + static class ByteTransferable implements Transferable, ClipboardOwner { + + private final DataFlavor dataFlavor; + + public ByteTransferable() throws Exception { + dataFlavor = DataFlavor.getTextPlainUnicodeFlavor(); + } + + public DataFlavor getDataFlavor() { + return dataFlavor; + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{dataFlavor}; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(dataFlavor); + } + + public byte[] getBytes() { + return new byte[]{97, 0, 64, -40, 32, -36, 98, 0}; + } + + public InputStream getByteInputStream() { + return new ByteArrayInputStream(getBytes()); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + if (flavor.equals(dataFlavor)) { + return getByteInputStream(); + } else { + throw new UnsupportedFlavorException(flavor); + } + } + + public void lostOwnership(Clipboard clipboard, Transferable contents) { + } + } + + static class TestDataTransferer extends DataTransferer { + + @Override + public String getDefaultUnicodeEncoding() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isLocaleDependentTextFormat(long format) { + return false; + } + + @Override + public boolean isFileFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isImageFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Long getFormatForNativeAsLong(String str) { + return TEXT_FORMAT; + } + + @Override + protected String getNativeForFormat(long format) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected ByteArrayOutputStream convertFileListToBytes( + ArrayList fileList) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected String[] dragQueryFile(byte[] bytes) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected Image platformImageBytesOrStreamToImage(InputStream str, + byte[] bytes, long format) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected byte[] imageToPlatformBytes(Image image, long format) + throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} \ No newline at end of file diff --git a/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java b/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java index e4f7eb1a773ce58ff577323b0e5c2ba426d79f7c..8958718ae7aaf5f39843acc67f3aff918358647b 100644 --- a/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java +++ b/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java @@ -29,7 +29,7 @@ import javax.net.*; import javax.net.ssl.*; import java.lang.reflect.*; -import sun.security.util.KeyLength; +import sun.security.util.KeyUtil; public class ShortRSAKeyWithinTLS { @@ -175,13 +175,13 @@ public class ShortRSAKeyWithinTLS { privateKey = (PrivateKey)ks.getKey(keyAlias, null); publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey(); - int privateKeySize = KeyLength.getKeySize(privateKey); + int privateKeySize = KeyUtil.getKeySize(privateKey); if (privateKeySize != keySize) { throw new Exception("Expected key size is " + keySize + ", but the private key size is " + privateKeySize); } - int publicKeySize = KeyLength.getKeySize(publicKey); + int publicKeySize = KeyUtil.getKeySize(publicKey); if (publicKeySize != keySize) { throw new Exception("Expected key size is " + keySize + ", but the public key size is " + publicKeySize); diff --git a/test/tools/launcher/ToolsOpts.java b/test/tools/launcher/ToolsOpts.java index 4535990dbca7ecfef3e1729d3ad4d96a3df758b7..f01931d5482d2bd752b20f0743a8fcbbf2714852 100644 --- a/test/tools/launcher/ToolsOpts.java +++ b/test/tools/launcher/ToolsOpts.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8002091 * @summary Test options patterns for javac,javah,javap and javadoc using * javac as a test launcher. Create a dummy javac and intercept options to check * reception of options as passed through the launcher without having to launch