OpenJDK / lambda / lambda / jdk
changeset 8050:9859856920ed
Merge
author | mullan |
---|---|
date | Wed, 20 Mar 2013 11:23:16 -0400 |
parents | 38116bfe5323 fb23896a01f5 |
children | 38c1d0c2d6a6 |
files | src/share/classes/sun/security/util/KeyLength.java |
diffstat | 238 files changed, 9358 insertions(+), 2580 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Mar 20 10:58:20 2013 -0400 +++ b/.hgtags Wed Mar 20 11:23:16 2013 -0400 @@ -201,3 +201,5 @@ b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77 00b7535d743f83eda763c10b3c9ea19ba4b67f55 jdk8-b78 c933505d75c2a0a671f06d6dac5d2237a9228d2d jdk8-b79 +dfb40f066c6ce129822f0f5dc2ac89173808781a jdk8-b80 +c0f8022eba536dcdc8aae659005b33f3982b9368 jdk8-b81
--- a/make/common/shared/Defs-utils.gmk Wed Mar 20 10:58:20 2013 -0400 +++ b/make/common/shared/Defs-utils.gmk Wed Mar 20 11:23:16 2013 -0400 @@ -74,24 +74,24 @@ 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
--- a/make/sun/cmm/lcms/Makefile Wed Mar 20 10:58:20 2013 -0400 +++ b/make/sun/cmm/lcms/Makefile Wed Mar 20 11:23:16 2013 -0400 @@ -28,6 +28,9 @@ LIBRARY = lcms PRODUCT = sun +# Use highest level of optimization on this library +OPTIMIZATION_LEVEL = HIGHEST + include $(BUILDDIR)/common/Defs.gmk #
--- a/make/sun/cmm/lcms/mapfile-vers Wed Mar 20 10:58:20 2013 -0400 +++ b/make/sun/cmm/lcms/mapfile-vers Wed Mar 20 11:23:16 2013 -0400 @@ -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;
--- a/makefiles/CompileNativeLibraries.gmk Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/CompileNativeLibraries.gmk Wed Mar 20 11:23:16 2013 -0400 @@ -464,12 +464,13 @@ $(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 @@ 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 @@ -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 @@ 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,\
--- a/makefiles/CreateJars.gmk Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/CreateJars.gmk Wed Mar 20 11:23:16 2013 -0400 @@ -76,8 +76,6 @@ $(IMAGES_OUTPUTDIR)/lib/tzdb.jar: $(JDK_OUTPUTDIR)/lib/tzdb.jar $(install-file) -JARS += $(IMAGES_OUTPUTDIR)/lib/tzdb.jar - ########################################################################################## LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in is it \ @@ -1120,8 +1118,6 @@ $(IMAGES_OUTPUTDIR)/lib/ext/nashorn.jar: $(NASHORN_DIST)/nashorn.jar $(install-file) -JARS += $(IMAGES_OUTPUTDIR)/lib/ext/nashorn.jar - ########################################################################################## -include $(CUSTOM_MAKE_DIR)/CreateJars.gmk
--- a/makefiles/Images.gmk Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/Images.gmk Wed Mar 20 11:23:16 2013 -0400 @@ -264,6 +264,13 @@ $(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 @@ $(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
--- a/makefiles/Profiles.gmk Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/Profiles.gmk Wed Mar 20 11:23:16 2013 -0400 @@ -84,7 +84,7 @@ # The full set of "jar" files needed for a complete JDK (ct.sym and src.zip # are also included.) # Note we need to add back the regular form of all the custom profile jars e.g. -# rt.jar and resources.jar +# rt.jar and resources.jar that we filtered out above ALL_JARS := $(FULL_JRE_JARS) \ $(IMAGES_OUTPUTDIR)/lib/rt.jar \ @@ -94,7 +94,6 @@ $(IMAGES_OUTPUTDIR)/lib/tools.jar \ $(IMAGES_OUTPUTDIR)/lib/ct.sym \ $(IMAGES_OUTPUTDIR)/src.zip \ - $(IMAGES_OUTPUTDIR)/lib/ext/cldrdata.jar \ $(IMAGES_OUTPUTDIR)/lib/sa-jdi.jar ifeq ($(OPENJDK_TARGET_OS),solaris)
--- a/makefiles/mapfiles/liblcms/mapfile-vers Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/mapfiles/liblcms/mapfile-vers Wed Mar 20 11:23:16 2013 -0400 @@ -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;
--- a/makefiles/profile-includes.txt Wed Mar 20 10:58:20 2013 -0400 +++ b/makefiles/profile-includes.txt Wed Mar 20 11:23:16 2013 -0400 @@ -178,6 +178,7 @@ cmm/sRGB.pf \ ext/cldrdata.jar \ ext/dnsns.jar \ + ext/nashorn.jar \ ext/sunec.jar \ ext/sunpkcs11.jar \ ext/zipfs.jar \ @@ -251,6 +252,7 @@ charsets.jar \ ext/cldrdata.jar \ ext/dnsns.jar \ + ext/nashorn.jar \ ext/sunec.jar \ ext/sunpkcs11.jar \ ext/zipfs.jar
--- a/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java Wed Mar 20 11:23:16 2013 -0400 @@ -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.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 @@ 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();
--- a/src/macosx/classes/sun/awt/CGraphicsConfig.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/awt/CGraphicsConfig.java Wed Mar 20 11:23:16 2013 -0400 @@ -53,7 +53,7 @@ @Override public Rectangle getBounds() { - final Rectangle2D nativeBounds = nativeGetBounds(device.getCoreGraphicsScreen()); + final Rectangle2D nativeBounds = nativeGetBounds(device.getCGDisplayID()); return nativeBounds.getBounds(); // does integer rounding }
--- a/src/macosx/classes/sun/awt/CGraphicsDevice.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/awt/CGraphicsDevice.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ } /** + * 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 @@ 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 @@ return nativeGetDisplayModes(displayID); } - private native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); + private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate); - private native DisplayMode nativeGetDisplayMode(int displayID); + private static native DisplayMode nativeGetDisplayMode(int displayID); - private native DisplayMode[] nativeGetDisplayModes(int displayID); + private static native DisplayMode[] nativeGetDisplayModes(int displayID); + + private static native double nativeGetXResolution(int displayID); + + private static native double nativeGetYResolution(int displayID); + + private static native Insets nativeGetScreenInsets(int displayID); }
--- a/src/macosx/classes/sun/font/CStrike.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/font/CStrike.java Wed Mar 20 11:23:16 2013 -0400 @@ -500,7 +500,10 @@ final Iterator<Long> 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 @@ 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 + } } }
--- a/src/macosx/classes/sun/font/CStrikeDisposer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/font/CStrikeDisposer.java Wed Mar 20 11:23:16 2013 -0400 @@ -85,4 +85,6 @@ } private native void freeNativeScalerContext(long pContext); + + protected static native void removeGlyphInfoFromCache(long glyphInfo); }
--- a/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java Wed Mar 20 11:23:16 2013 -0400 @@ -80,10 +80,8 @@ 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 @@ // 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 @@ @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 @@ @Override public void addDeviceEventListener(AccelDeviceEventListener l) { - int screen = getDevice().getCoreGraphicsScreen(); - AccelDeviceEventNotifier.addListener(l, screen); + int displayID = getDevice().getCGDisplayID(); + AccelDeviceEventNotifier.addListener(l, displayID); } @Override
--- a/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/LWComponentPeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -439,7 +439,7 @@ } @Override - public final Graphics getGraphics() { + public Graphics getGraphics() { final Graphics g = getOnscreenGraphics(); if (g != null) { synchronized (getPeerTreeLock()){ @@ -1227,10 +1227,10 @@ } 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 @@ } } - 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -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(); + } +}
--- a/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Mar 20 11:23:16 2013 -0400 @@ -218,6 +218,23 @@ 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 @@ protected abstract PlatformComponent createPlatformComponent(); + protected abstract PlatformComponent createLwPlatformComponent(); + protected abstract FileDialogPeer createFileDialogPeer(FileDialog target); // ---- UTILITY METHODS ---- //
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -48,7 +48,8 @@ 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 @@ 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 @@ 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); }
--- a/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CDropTargetContextPeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -128,6 +128,15 @@ } } + @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();
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformComponent.java Wed Mar 20 11:23:16 2013 -0400 @@ -35,7 +35,7 @@ * 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWComponent.java Wed Mar 20 11:23:16 2013 -0400 @@ -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() { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWView.java Wed Mar 20 11:23:16 2013 -0400 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java Wed Mar 20 11:23:16 2013 -0400 @@ -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; + } +}
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Wed Mar 20 11:23:16 2013 -0400 @@ -54,8 +54,7 @@ } 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 @@ 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; }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Mar 20 11:23:16 2013 -0400 @@ -30,6 +30,7 @@ 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.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 @@ */ @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 @@ 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 @@ 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 @@ 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(); + } } }
--- a/src/macosx/classes/sun/lwawt/macosx/CRobot.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CRobot.java Wed Mar 20 11:23:16 2013 -0400 @@ -65,7 +65,7 @@ mouseLastX = x; mouseLastY = y; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, mouseButtonsState, true, true); } @@ -79,7 +79,7 @@ public void mousePress(int buttons) { mouseButtonsState |= buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, true, false); } @@ -93,7 +93,7 @@ public void mouseRelease(int buttons) { mouseButtonsState &= ~buttons; - mouseEvent(fDevice.getCoreGraphicsScreen(), mouseLastX, mouseLastY, + mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY, buttons, false, false); } @@ -163,7 +163,7 @@ } 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);
--- a/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java Wed Mar 20 11:23:16 2013 -0400 @@ -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; } }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ private static native void initIDs(); - static native void executeNextAppKitEvent(); - private static CInputMethodDescriptor sInputMethodDescriptor; static { @@ -160,6 +158,8 @@ 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(); @@ -172,6 +172,11 @@ } @Override + protected PlatformComponent createLwPlatformComponent() { + return new CPlatformLWComponent(); + } + + @Override protected FileDialogPeer createFileDialogPeer(FileDialog target) { return new CFileDialog(target); } @@ -346,22 +351,7 @@ @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 @@ 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> T invokeAndWait(final Callable<T> callable, Component component) throws Exception { final CallableWrapper<T> wrapper = new CallableWrapper<T>(callable); invokeAndWait(wrapper, component); @@ -548,10 +514,27 @@ } } - 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 @@ ((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 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 @@ 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 @@ * 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);
--- a/src/macosx/native/sun/awt/AWTView.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/AWTView.m Wed Mar 20 11:23:16 2013 -0400 @@ -227,7 +227,7 @@ - (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 @@ - (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 @@ 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]; }
--- a/src/macosx/native/sun/awt/ApplicationDelegate.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/ApplicationDelegate.m Wed Mar 20 11:23:16 2013 -0400 @@ -567,10 +567,9 @@ { 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); }
--- a/src/macosx/native/sun/awt/CClipboard.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CClipboard.m Wed Mar 20 11:23:16 2013 -0400 @@ -120,7 +120,7 @@ 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 @@ - (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 @@ - (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 @@ - (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];
--- a/src/macosx/native/sun/awt/CDropTarget.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CDropTarget.m Wed Mar 20 11:23:16 2013 -0400 @@ -390,8 +390,7 @@ // 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 {
--- a/src/macosx/native/sun/awt/CGraphicsDevice.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CGraphicsDevice.m Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ -148,6 +149,47 @@ /* * 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 * Signature: (IIIII)V */
--- a/src/macosx/native/sun/awt/CMenu.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CMenu.m Wed Mar 20 11:23:16 2013 -0400 @@ -55,11 +55,11 @@ //- (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 @@ - (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 @@ - (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 @@ // 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];
--- a/src/macosx/native/sun/awt/CMenuBar.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CMenuBar.m Wed Mar 20 11:23:16 2013 -0400 @@ -197,7 +197,7 @@ 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 @@ 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 @@ - (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 @@ // 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];
--- a/src/macosx/native/sun/awt/CMenuItem.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CMenuItem.m Wed Mar 20 11:23:16 2013 -0400 @@ -386,7 +386,7 @@ 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];
--- a/src/macosx/native/sun/awt/CRobot.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/CRobot.m Wed Mar 20 11:23:16 2013 -0400 @@ -135,7 +135,7 @@ 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 @@ CGError err = kCGErrorSuccess; - CGDirectDisplayID displayID = - FindCGDirectDisplayIDForScreenIndex(screenIndex); CGRect globalDeviceBounds = CGDisplayBounds(displayID); // Set unknown mouse location, if needed.
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m Wed Mar 20 11:23:16 2013 -0400 @@ -1113,18 +1113,10 @@ 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 @@ { 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 @@ (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 @@ (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 @@ (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); }
--- a/src/macosx/native/sun/awt/LWCToolkit.h Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/LWCToolkit.h Wed Mar 20 11:23:16 2013 -0400 @@ -44,8 +44,6 @@ + (void) eventCountPlusPlus; @end -CGDirectDisplayID FindCGDirectDisplayIDForScreenIndex(jint screenIndex); - /* * Utility Macros */
--- a/src/macosx/native/sun/awt/LWCToolkit.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/awt/LWCToolkit.m Wed Mar 20 11:23:16 2013 -0400 @@ -177,39 +177,6 @@ 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 @@ * 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 @@ if (mediatorObject == nil) return; - if (!sInPerformFromJava || !detectDeadlocks) { + // Don't use acceptInputForMode because that doesn't setup autorelease pools properly + BOOL isRunning = true; + while (![mediatorObject shouldEndRunLoop] && isRunning) { + isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode] + beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; + if (processEvents) { + //We do not spin a runloop here as date is nil, so does not matter which mode to use + NSEvent *event; + if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]) != nil) { + [NSApp sendEvent:event]; + } - NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; - NSDate *distantFuture = [NSDate distantFuture]; - NSString *mode = (awtMode) ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode; + } + } - BOOL isRunning = YES; - while (isRunning && ![mediatorObject shouldEndRunLoop]) { - // Don't use acceptInputForMode because that doesn't setup autorelease pools properly - isRunning = [currentRunLoop runMode:mode beforeDate:distantFuture]; - } - - } -#ifndef PRODUCT_BUILD - if (sInPerformFromJava) { - NSLog(@"Apple AWT: Short-circuiting CToolkit.invokeAndWait trampoline deadlock!!!!!"); - NSLog(@"\tPlease file a bug report with this message and a reproducible test case."); - } -#endif - + CFRelease(mediatorObject); JNF_COCOA_EXIT(env); @@ -379,7 +345,7 @@ 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 @@ } -/* - * 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]; - } -}
--- a/src/macosx/native/sun/font/AWTStrike.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/font/AWTStrike.m Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ 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); +}
--- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m Wed Mar 20 11:23:16 2013 -0400 @@ -192,12 +192,12 @@ 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 @@ + (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 @@ 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 @@ return; } memset(cglinfo, 0, sizeof(CGLGraphicsConfigInfo)); - cglinfo->screen = screennum; + cglinfo->screen = displayID; cglinfo->pixfmt = sharedPixelFormat; cglinfo->context = oglc; @@ -422,17 +417,6 @@ } @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)
--- a/src/macosx/native/sun/osxapp/ThreadUtilities.h Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/osxapp/ThreadUtilities.h Wed Mar 20 11:23:16 2013 -0400 @@ -122,19 +122,12 @@ #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;
--- a/src/macosx/native/sun/osxapp/ThreadUtilities.m Wed Mar 20 10:58:20 2013 -0400 +++ b/src/macosx/native/sun/osxapp/ThreadUtilities.m Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ 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();
--- a/src/share/bin/jli_util.h Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/bin/jli_util.h Wed Mar 20 11:23:16 2013 -0400 @@ -66,7 +66,7 @@ #include <io.h> #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 */
--- a/src/share/bin/parse_manifest.c Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/bin/parse_manifest.c Wed Mar 20 11:23:16 2013 -0400 @@ -569,9 +569,9 @@ #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 @@ 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 @@ #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);
--- a/src/share/classes/com/sun/beans/finder/MethodFinder.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/beans/finder/MethodFinder.java Wed Mar 20 11:23:16 2013 -0400 @@ -66,11 +66,14 @@ 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; }
--- a/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Wed Mar 20 11:23:16 2013 -0400 @@ -41,6 +41,8 @@ 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 @@ throw new InvalidKeyException("Incompatible parameters"); } + // validate the Diffie-Hellman public key + KeyUtil.validate(dhPubKey); + // store the y value this.y = dhPubKey.getY();
--- a/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Wed Mar 20 11:23:16 2013 -0400 @@ -1000,7 +1000,6 @@ /** 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 @@ 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);
--- a/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Wed Mar 20 11:23:16 2013 -0400 @@ -1409,6 +1409,8 @@ /** 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);
--- a/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Wed Mar 20 11:23:16 2013 -0400 @@ -109,6 +109,10 @@ 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
--- a/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Wed Mar 20 11:23:16 2013 -0400 @@ -83,7 +83,7 @@ * @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 @@ * @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();
--- a/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ * @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 @@ * @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"); }
--- a/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/jmx/mbeanserver/ClassLoaderRepositorySupport.java Wed Mar 20 11:23:16 2013 -0400 @@ -36,6 +36,7 @@ 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 ClassLoader without, final ClassLoader stop) throws ClassNotFoundException { + ReflectUtil.checkPackageAccess(className); final int size = list.length; for(int i=0; i<size; i++) { try {
--- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Mar 20 11:23:16 2013 -0400 @@ -54,6 +54,8 @@ import java.lang.reflect.InvocationTargetException; import javax.management.AttributeNotFoundException; import javax.management.openmbean.CompositeData; +import sun.reflect.misc.MethodUtil; +import sun.reflect.misc.ReflectUtil; /** * This class contains the methods for performing all the tests needed to verify @@ -526,8 +528,10 @@ // to locate method readMethod = SimpleIntrospector.getReadMethod(clazz, element); } - if (readMethod != null) - return readMethod.invoke(complex); + if (readMethod != null) { + ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass()); + return MethodUtil.invoke(readMethod, complex, new Class[0]); + } throw new AttributeNotFoundException( "Could not find the getter method for the property " +
--- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Mar 20 11:23:16 2013 -0400 @@ -51,6 +51,7 @@ import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MBeanServerDelegate; +import javax.management.MBeanServerPermission; import javax.management.NotCompliantMBeanException; import javax.management.NotificationFilter; import javax.management.NotificationListener; @@ -1409,6 +1410,8 @@ // Default is true. final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY; + checkNewMBeanServerPermission(); + // This constructor happens to disregard the value of the interceptors // flag - that is, it always uses the default value - false. // This is admitedly a bug, but we chose not to fix it for now @@ -1494,4 +1497,11 @@ } } + private static void checkNewMBeanServerPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + Permission perm = new MBeanServerPermission("newMBeanServer"); + sm.checkPermission(perm); + } + } }
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Mar 20 11:23:16 2013 -0400 @@ -32,11 +32,13 @@ import java.io.ObjectInputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.security.Permission; import java.util.Map; import java.util.logging.Level; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; +import javax.management.MBeanPermission; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.OperationsException; @@ -44,7 +46,7 @@ import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; - +import sun.reflect.misc.ConstructorUtil; import sun.reflect.misc.ReflectUtil; /** @@ -56,7 +58,6 @@ * @since 1.5 */ public class MBeanInstantiator { - private final ModifiableClassLoaderRepository clr; // private MetaData meta = null; @@ -88,6 +89,7 @@ "Exception occurred during object instantiation"); } + ReflectUtil.checkPackageAccess(className); try { if (clr == null) throw new ClassNotFoundException(className); theClass = clr.loadClass(className); @@ -162,6 +164,7 @@ continue; } + ReflectUtil.checkPackageAccess(signature[i]); // Ok we do not have a primitive type ! We need to build // the signature of the method // @@ -205,6 +208,9 @@ */ public Object instantiate(Class<?> theClass) throws ReflectionException, MBeanException { + + checkMBeanPermission(theClass, null, null, "instantiate"); + Object moi; @@ -260,6 +266,9 @@ 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 @@ 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 @@ **/ 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 @@ // 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 @@ 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 @@ 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); + } + } }
--- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Mar 20 11:23:16 2013 -0400 @@ -38,6 +38,7 @@ 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 @@ " is not an instance of " + mbeanInterfaceType.getName(); throw new NotCompliantMBeanException(msg); } + ReflectUtil.checkPackageAccess(mbeanInterfaceType); this.resource = resource; MBeanIntrospector<M> introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
--- a/src/share/classes/com/sun/tools/script/shell/init.js Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/com/sun/tools/script/shell/init.js Wed Mar 20 11:23:16 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ */ /** - * Creates an object that delegates all method calls on + * Creates an object that delegates all method calls on * it to the 'invoke' method on the given delegate object.<br> * * Example: @@ -43,13 +43,13 @@ * @constructor */ function JSInvoker(obj) { - return new JSAdapter({ - __get__ : function(name) { - return function() { - return obj.invoke(name, arguments); - } - } - }); + return new JSAdapter({ + __get__ : function(name) { + return function() { + return obj.invoke(name, arguments); + } + } + }); } /** @@ -58,24 +58,24 @@ * example, env.PATH will return PATH value configured. */ var env = new JSAdapter({ - __get__ : function (name) { - return java.lang.System.getenv(name); - }, - __has__ : function (name) { - return java.lang.System.getenv().containsKey(name); - }, - __getIds__ : function() { - return java.lang.System.getenv().keySet().toArray(); - }, - __delete__ : function(name) { - println("can't delete env item"); - }, - __put__ : function (name, value) { - println("can't change env item"); - }, - toString: function() { - return java.lang.System.getenv().toString(); - } + __get__ : function (name) { + return java.lang.System.getenv(name); + }, + __has__ : function (name) { + return java.lang.System.getenv().containsKey(name); + }, + __getIds__ : function() { + return java.lang.System.getenv().keySet().toArray(); + }, + __delete__ : function(name) { + println("can't delete env item"); + }, + __put__ : function (name, value) { + println("can't change env item"); + }, + toString: function() { + return java.lang.System.getenv().toString(); + } }); /** @@ -91,36 +91,36 @@ * delete y['java.class.path']; // remove java.class.path System property * </code> * </pre> - * + * * @param map java.util.Map instance that will be wrapped * @constructor */ -function jmap(map) { - return new JSAdapter({ - __get__ : function(name) { - if (map.containsKey(name)) { - return map.get(name); - } else { - return undefined; - } - }, - __has__ : function(name) { - return map.containsKey(name); - }, +function jmap(map) { + return new JSAdapter({ + __get__ : function(name) { + if (map.containsKey(name)) { + return map.get(name); + } else { + return undefined; + } + }, + __has__ : function(name) { + return map.containsKey(name); + }, - __delete__ : function (name) { - return map.remove(name); - }, - __put__ : function(name, value) { - map.put(name, value); - }, - __getIds__ : function() { - return map.keySet().toArray(); - }, - toString: function() { - return map.toString(); - } - }); + __delete__ : function (name) { + return map.remove(name); + }, + __put__ : function(name, value) { + map.put(name, value); + }, + __getIds__ : function() { + return map.keySet().toArray(); + }, + toString: function() { + return map.toString(); + } + }); } /** @@ -146,52 +146,72 @@ * @constructor */ function jlist(list) { - function isValid(index) { - return typeof(index) == 'number' && - index > -1 && index < list.size(); - } - return new JSAdapter({ - __get__ : function(name) { - if (isValid(name)) { - return list.get(name); - } else if (name == 'length') { - return list.size(); - } else { - return undefined; - } - }, - __has__ : function (name) { - return isValid(name) || name == 'length'; - }, - __delete__ : function(name) { - if (isValid(name)) { - list.remove(name); - } - }, - __put__ : function(name, value) { - if (isValid(name)) { - list.set(name, value); - } - }, - __getIds__: function() { - var res = new Array(list.size()); - for (var i = 0; i < res.length; i++) { - res[i] = i; - } - return res; - }, - toString: function() { - return list.toString(); - } - }); + function isValid(index) { + return typeof(index) == 'number' && + index > -1 && index < list.size(); + } + return new JSAdapter({ + __get__ : function(name) { + if (isValid(name)) { + return list.get(name); + } else if (name == 'length') { + return list.size(); + } else { + return undefined; + } + }, + __has__ : function (name) { + return isValid(name) || name == 'length'; + }, + __delete__ : function(name) { + if (isValid(name)) { + list.remove(name); + } + }, + __put__ : function(name, value) { + if (isValid(name)) { + list.set(name, value); + } + }, + __getIds__: function() { + var res = new Array(list.size()); + for (var i = 0; i < res.length; i++) { + res[i] = i; + } + return res; + }, + toString: function() { + return list.toString(); + } + }); } /** - * This is java.lang.System properties wrapped by jmap. + * This is java.lang.System properties wrapped by JSAdapter. * For eg. to access java.class.path property, you can use * the syntax sysProps["java.class.path"] */ -var sysProps = jmap(java.lang.System.getProperties()); +var sysProps = new JSAdapter({ + __get__ : function (name) { + return java.lang.System.getProperty(name); + }, + __has__ : function (name) { + return java.lang.System.getProperty(name) != null; + }, + __getIds__ : function() { + return java.lang.System.getProperties().keySet().toArray(); + }, + __delete__ : function(name) { + java.lang.System.clearProperty(name); + return true; + }, + __put__ : function (name, value) { + java.lang.System.setProperty(name, value); + }, + toString: function() { + return "<system properties>"; + } +}); // stdout, stderr & stdin var out = java.lang.System.out; @@ -199,76 +219,85 @@ // can't use 'in' because it is a JavaScript keyword :-( var inp = java.lang.System["in"]; -// useful imports for often used io, net classes -importPackage(java.io); -importPackage(java.net); +var BufferedInputStream = java.io.BufferedInputStream; +var BufferedOutputStream = java.io.BufferedOutputStream; +var BufferedReader = java.io.BufferedReader; +var DataInputStream = java.io.DataInputStream; +var File = java.io.File; +var FileInputStream = java.io.FileInputStream; +var FileOutputStream = java.io.FileOutputStream; +var InputStream = java.io.InputStream; +var InputStreamReader = java.io.InputStreamReader; +var OutputStream = java.io.OutputStream; +var Reader = java.io.Reader; +var URL = java.net.URL; /** * Generic any object to input stream mapper - * @param str input file name, URL or InputStream + * @param str input file name, URL or InputStream * @return InputStream object * @private */ function inStream(str) { - if (typeof(str) == "string") { - // '-' means standard input - if (str == '-') { - return java.lang.System["in"]; - } - // try file first - var file = null; - try { - file = pathToFile(str); - } catch (e) { - } - if (file && file.exists()) { - return new FileInputStream(file); - } else { - try { - // treat the string as URL - return new URL(str).openStream(); - } catch (e) { - throw 'file or URL ' + str + ' not found'; - } - } - } else { - if (str instanceof InputStream) { - return str; - } else if (str instanceof URL) { - return str.openStream(); - } else if (str instanceof File) { - return new FileInputStream(str); - } - } - // everything failed, just give input stream - return java.lang.System["in"]; + if (typeof(str) == "string") { + // '-' means standard input + if (str == '-') { + return java.lang.System["in"]; + } + // try file first + var file = null; + try { + file = pathToFile(str); + } catch (e) { + } + if (file && file.exists()) { + return new FileInputStream(file); + } else { + try { + // treat the string as URL + return new URL(str).openStream(); + } catch (e) { + throw 'file or URL ' + str + ' not found'; + } + } + } else { + if (str instanceof InputStream) { + return str; + } else if (str instanceof URL) { + return str.openStream(); + } else if (str instanceof File) { + return new FileInputStream(str); + } + } + // everything failed, just give input stream + return java.lang.System["in"]; } /** * Generic any object to output stream mapper - * + * * @param out output file name or stream * @return OutputStream object * @private */ function outStream(out) { - if (typeof(out) == "string") { - if (out == '>') { - return java.lang.System.out; - } else { - // treat it as file - return new FileOutputStream(pathToFile(out)); - } - } else { - if (out instanceof OutputStream) { - return out; - } else if (out instanceof File) { - return new FileOutputStream(out); - } - } + if (typeof(out) == "string") { + if (out == '>') { + return java.lang.System.out; + } else { + // treat it as file + return new FileOutputStream(pathToFile(out)); + } + } else { + if (out instanceof OutputStream) { + return out; + } else if (out instanceof File) { + return new FileOutputStream(out); + } + } - // everything failed, just return System.out - return java.lang.System.out; + // everything failed, just return System.out + return java.lang.System.out; } /** @@ -276,17 +305,17 @@ * @private */ function streamClose(stream) { - if (stream) { - if (stream != java.lang.System["in"] && - stream != java.lang.System.out && - stream != java.lang.System.err) { - try { - stream.close(); - } catch (e) { - println(e); - } - } - } + if (stream) { + if (stream != java.lang.System["in"] && + stream != java.lang.System.out && + stream != java.lang.System.err) { + try { + stream.close(); + } catch (e) { + println(e); + } + } + } } /** @@ -302,18 +331,20 @@ * * @param str input from which script is loaded and evaluated */ -function load(str) { - var stream = inStream(str); - var bstream = new BufferedInputStream(stream); - var reader = new BufferedReader(new InputStreamReader(bstream)); - var oldFilename = engine.get(engine.FILENAME); - engine.put(engine.FILENAME, str); - try { - engine.eval(reader); - } finally { - engine.put(engine.FILENAME, oldFilename); - streamClose(stream); - } +if (typeof(load) == 'undefined') { + var load = function(str) { + var stream = inStream(str); + var bstream = new BufferedInputStream(stream); + var reader = new BufferedReader(new InputStreamReader(bstream)); + var oldFilename = engine.get(engine.FILENAME); + engine.put(engine.FILENAME, str); + try { + engine.eval(reader); + } finally { + engine.put(engine.FILENAME, oldFilename); + streamClose(stream); + } + } } // file system utilities @@ -324,7 +355,7 @@ * @private */ function javaByteArray(len) { - return java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, len); + return java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, len); } var curDir = new File('.'); @@ -333,7 +364,7 @@ * Print present working directory */ function pwd() { - println(curDir.getAbsolutePath()); + println(curDir.getAbsolutePath()); } /** @@ -341,17 +372,17 @@ * @param target directory to change to. optional, defaults to user's HOME */ function cd(target) { - if (target == undefined) { - target = sysProps["user.home"]; - } - if (!(target instanceof File)) { - target = pathToFile(target); - } - if (target.exists() && target.isDirectory()) { - curDir = target; - } else { - println(target + " is not a directory"); - } + if (target == undefined) { + target = sysProps["user.home"]; + } + if (!(target instanceof File)) { + target = pathToFile(target); + } + if (target.exists() && target.isDirectory()) { + curDir = target; + } else { + println(target + " is not a directory"); + } } /** @@ -361,15 +392,15 @@ * @private */ function pathToFile(pathname) { - var tmp = pathname; - if (!(tmp instanceof File)) { - tmp = new File(tmp); - } - if (!tmp.isAbsolute()) { - return new File(curDir, pathname); - } else { - return tmp; - } + var tmp = pathname; + if (!(tmp instanceof File)) { + tmp = new File(tmp); + } + if (!tmp.isAbsolute()) { + return new File(curDir, pathname); + } else { + return tmp; + } } /** @@ -379,22 +410,22 @@ * @param to output stream or file */ function cp(from, to) { - if (from == to) { - println("file " + from + " cannot be copied onto itself!"); - return; - } - var inp = inStream(from); - var out = outStream(to); - var binp = new BufferedInputStream(inp); - var bout = new BufferedOutputStream(out); - var buff = javaByteArray(1024); - var len; - while ((len = binp.read(buff)) > 0 ) - bout.write(buff, 0, len); + if (from == to) { + println("file " + from + " cannot be copied onto itself!"); + return; + } + var inp = inStream(from); + var out = outStream(to); + var binp = new BufferedInputStream(inp); + var bout = new BufferedOutputStream(out); + var buff = javaByteArray(1024); + var len; + while ((len = binp.read(buff)) > 0 ) + bout.write(buff, 0, len); - bout.flush(); - streamClose(inp); - streamClose(out); + bout.flush(); + streamClose(inp); + streamClose(out); } /** @@ -403,37 +434,37 @@ * <pre> * <code> * cat('test.txt'); // show test.txt file contents - * cat('http://java.net'); // show the contents from the URL http://java.net + * cat('http://java.net'); // show the contents from the URL http://java.net * </code> * </pre> * @param obj input to show * @param pattern optional. show only the lines matching the pattern */ function cat(obj, pattern) { - if (obj instanceof File && obj.isDirectory()) { - ls(obj); - return; - } - - var inp = null; - if (!(obj instanceof Reader)) { - inp = inStream(obj); - obj = new BufferedReader(new InputStreamReader(inp)); - } - var line; - if (pattern) { - var count = 1; - while ((line=obj.readLine()) != null) { - if (line.match(pattern)) { - println(count + "\t: " + line); - } - count++; - } - } else { - while ((line=obj.readLine()) != null) { - println(line); - } - } + if (obj instanceof File && obj.isDirectory()) { + ls(obj); + return; + } + + var inp = null; + if (!(obj instanceof Reader)) { + inp = inStream(obj); + obj = new BufferedReader(new InputStreamReader(inp)); + } + var line; + if (pattern) { + var count = 1; + while ((line=obj.readLine()) != null) { + if (line.match(pattern)) { + println(count + "\t: " + line); + } + count++; + } + } else { + while ((line=obj.readLine()) != null) { + println(line); + } + } } /** @@ -443,13 +474,13 @@ * @return directory part of the given file name */ function dirname(pathname) { - var dirName = "."; - // Normalize '/' to local file separator before work. - var i = pathname.replace('/', File.separatorChar ).lastIndexOf( - File.separator ); - if ( i != -1 ) - dirName = pathname.substring(0, i); - return dirName; + var dirName = "."; + // Normalize '/' to local file separator before work. + var i = pathname.replace('/', File.separatorChar ).lastIndexOf( + File.separator ); + if ( i != -1 ) + dirName = pathname.substring(0, i); + return dirName; } /** @@ -458,34 +489,34 @@ * @param dir name of the new directory */ function mkdir(dir) { - var dir = pathToFile(dir); - println(dir.mkdir()? "created" : "can not create dir"); + dir = pathToFile(dir); + println(dir.mkdir()? "created" : "can not create dir"); } /** - * Creates the directory named by given pathname, including + * Creates the directory named by given pathname, including * any necessary but nonexistent parent directories. * * @param dir input path name */ function mkdirs(dir) { - var dir = pathToFile(dir); - println(dir.mkdirs()? "created" : "can not create dirs"); + dir = pathToFile(dir); + println(dir.mkdirs()? "created" : "can not create dirs"); } - + /** - * Removes a given file + * Removes a given file * - * @param pathname name of the file + * @param pathname name of the file */ function rm(pathname) { - file = pathToFile(pathname); - if (!file.exists()) { - println("file not found: " + pathname); - return false; - } - // note that delete is a keyword in JavaScript! - println(file["delete"]()? "deleted" : "can not delete"); + var file = pathToFile(pathname); + if (!file.exists()) { + println("file not found: " + pathname); + return false; + } + // note that delete is a keyword in JavaScript! + println(file["delete"]()? "deleted" : "can not delete"); } /** @@ -494,14 +525,14 @@ * @param pathname name of the directory */ function rmdir(pathname) { - rm(pathname); + rm(pathname); } /** * Synonym for 'rm' */ function del(pathname) { - rm(pathname); + rm(pathname); } /** @@ -511,62 +542,62 @@ * @param to new name for the file */ function mv(from, to) { - println(pathToFile(from).renameTo(pathToFile(to))? - "moved" : "can not move"); + println(pathToFile(from).renameTo(pathToFile(to))? + "moved" : "can not move"); } /** * Synonym for 'mv'. */ function ren(from, to) { - mv(from, to); + mv(from, to); } -var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; +var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; /** * Helper function called by ls * @private - */ + */ function printFile(f) { - var sb = new java.lang.StringBuffer(); - sb.append(f.isDirectory()? "d" : "-"); - sb.append(f.canRead() ? "r": "-" ); - sb.append(f.canWrite() ? "w": "-" ); - sb.append(" "); + var sb = new java.lang.StringBuffer(); + sb.append(f.isDirectory()? "d" : "-"); + sb.append(f.canRead() ? "r": "-" ); + sb.append(f.canWrite() ? "w": "-" ); + sb.append(" "); - var d = new java.util.Date(f.lastModified()); - var c = new java.util.GregorianCalendar(); - c.setTime(d); - var day = c.get(java.util.Calendar.DAY_OF_MONTH); - sb.append(months[c.get(java.util.Calendar.MONTH)] - + " " + day ); - if (day < 10) { - sb.append(" "); - } + var d = new java.util.Date(f.lastModified()); + var c = new java.util.GregorianCalendar(); + c.setTime(d); + var day = c.get(java.util.Calendar.DAY_OF_MONTH); + sb.append(months[c.get(java.util.Calendar.MONTH)] + + " " + day ); + if (day < 10) { + sb.append(" "); + } - // to get fixed length 'length' field - var fieldlen = 8; - var len = new java.lang.StringBuffer(); - for(var j=0; j<fieldlen; j++) - len.append(" "); - len.insert(0, java.lang.Long.toString(f.length())); - len.setLength(fieldlen); - // move the spaces to the front - var si = len.toString().indexOf(" "); - if ( si != -1 ) { - var pad = len.toString().substring(si); - len.setLength(si); - len.insert(0, pad); - } - sb.append(len.toString()); - sb.append(" "); - sb.append(f.getName()); - if (f.isDirectory()) { - sb.append('/'); - } - println(sb.toString()); + // to get fixed length 'length' field + var fieldlen = 8; + var len = new java.lang.StringBuffer(); + for(var j=0; j<fieldlen; j++) + len.append(" "); + len.insert(0, java.lang.Long.toString(f.length())); + len.setLength(fieldlen); + // move the spaces to the front + var si = len.toString().indexOf(" "); + if ( si != -1 ) { + var pad = len.toString().substring(si); + len.setLength(si); + len.insert(0, pad); + } + sb.append(len.toString()); + sb.append(" "); + sb.append(f.getName()); + if (f.isDirectory()) { + sb.append('/'); + } + println(sb.toString()); } /** @@ -576,32 +607,32 @@ * @param filter pattern to filter the files listed. optional, default is '.'. */ function ls(dir, filter) { - if (dir) { - dir = pathToFile(dir); - } else { - dir = curDir; - } - if (dir.isDirectory()) { - var files = dir.listFiles(); - for (var i in files) { - var f = files[i]; - if (filter) { - if(!f.getName().match(filter)) { - continue; - } - } - printFile(f); - } - } else { - printFile(dir); - } + if (dir) { + dir = pathToFile(dir); + } else { + dir = curDir; + } + if (dir.isDirectory()) { + var files = dir.listFiles(); + for (var i in files) { + var f = files[i]; + if (filter) { + if(!f.getName().match(filter)) { + continue; + } + } + printFile(f); + } + } else { + printFile(dir); + } } /** * Synonym for 'ls'. */ function dir(d, filter) { - ls(d, filter); + ls(d, filter); } /** @@ -611,24 +642,24 @@ * @param files one or more files */ function grep(pattern, files /*, one or more files */) { - if (arguments.length < 2) return; - for (var i = 1; i < arguments.length; i++) { - println(arguments[i] + ":"); - cat(arguments[i], pattern); - } + if (arguments.length < 2) return; + for (var i = 1; i < arguments.length; i++) { + println(arguments[i] + ":"); + cat(arguments[i], pattern); + } } /** * Find in files. Calls arbitrary callback function * for each matching file.<br> * - * Examples: + * Examples: * <pre> * <code> - * find('.') - * find('.', '.*\.class', rm); // remove all .class files - * find('.', '.*\.java'); // print fullpath of each .java file - * find('.', '.*\.java', cat); // print all .java files + * find('.') + * find('.', '.*\.class', rm); // remove all .class files + * find('.', '.*\.java'); // print fullpath of each .java file + * find('.', '.*\.java', cat); // print all .java files * </code> * </pre> * @@ -637,23 +668,23 @@ * @param callback function to call for matching files */ function find(dir, pattern, callback) { - dir = pathToFile(dir); - if (!callback) callback = print; - var files = dir.listFiles(); - for (var f in files) { - var file = files[f]; - if (file.isDirectory()) { - find(file, pattern, callback); - } else { - if (pattern) { - if (file.getName().match(pattern)) { - callback(file); - } - } else { - callback(file); - } - } - } + dir = pathToFile(dir); + if (!callback) callback = print; + var files = dir.listFiles(); + for (var f in files) { + var file = files[f]; + if (file.isDirectory()) { + find(file, pattern, callback); + } else { + if (pattern) { + if (file.getName().match(pattern)) { + callback(file); + } + } else { + callback(file); + } + } + } } // process utilities @@ -664,40 +695,44 @@ * @param cmd command to execute in child process */ function exec(cmd) { - var process = java.lang.Runtime.getRuntime().exec(cmd); - var inp = new DataInputStream(process.getInputStream()); - var line = null; - while ((line = inp.readLine()) != null) { - println(line); - } - process.waitFor(); - $exit = process.exitValue(); + var process = java.lang.Runtime.getRuntime().exec(cmd); + var inp = new DataInputStream(process.getInputStream()); + var line = null; + while ((line = inp.readLine()) != null) { + println(line); + } + process.waitFor(); + $exit = process.exitValue(); } -/** - * Exit the shell program. - * - * @param exitCode integer code returned to OS shell. - * optional, defaults to 0 - */ -function exit(code) { - if (code) { - java.lang.System.exit(code + 0); - } else { - java.lang.System.exit(0); - } +if (typeof(exit) == 'undefined') { + /** + * Exit the shell program. + * + * @param exitCode integer code returned to OS shell. + * optional, defaults to 0 + */ + var exit = function (code) { + if (code) { + java.lang.System.exit(code + 0); + } else { + java.lang.System.exit(0); + } + } } -/** - * synonym for exit - */ -function quit(code) { - exit(code); +if (typeof(quit) == 'undefined') { + /** + * synonym for exit + */ + var quit = function (code) { + exit(code); + } } // XML utilities -/** +/** * Converts input to DOM Document object * * @param inp file or reader. optional, without this param, @@ -705,17 +740,17 @@ * @return returns a DOM Document object */ function XMLDocument(inp) { - var factory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); - var builder = factory.newDocumentBuilder(); - if (inp) { - if (typeof(inp) == "string") { - return builder.parse(pathToFile(inp)); - } else { - return builder.parse(inp); - } - } else { - return builder.newDocument(); - } + var factory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); + var builder = factory.newDocumentBuilder(); + if (inp) { + if (typeof(inp) == "string") { + return builder.parse(pathToFile(inp)); + } else { + return builder.parse(inp); + } + } else { + return builder.newDocument(); + } } /** @@ -725,14 +760,14 @@ * @return XMLSource object */ function XMLSource(inp) { - if (inp instanceof javax.xml.transform.Source) { - return inp; - } else if (inp instanceof Packages.org.w3c.dom.Document) { - return new javax.xml.transform.dom.DOMSource(inp); - } else { - inp = new BufferedInputStream(inStream(inp)); - return new javax.xml.transform.stream.StreamSource(inp); - } + if (inp instanceof javax.xml.transform.Source) { + return inp; + } else if (inp instanceof Packages.org.w3c.dom.Document) { + return new javax.xml.transform.dom.DOMSource(inp); + } else { + inp = new BufferedInputStream(inStream(inp)); + return new javax.xml.transform.stream.StreamSource(inp); + } } /** @@ -742,73 +777,73 @@ * @return XMLResult object */ function XMLResult(out) { - if (out instanceof javax.xml.transform.Result) { - return out; - } else if (out instanceof Packages.org.w3c.dom.Document) { - return new javax.xml.transform.dom.DOMResult(out); - } else { - out = new BufferedOutputStream(outStream(out)); - return new javax.xml.transform.stream.StreamResult(out); - } + if (out instanceof javax.xml.transform.Result) { + return out; + } else if (out instanceof Packages.org.w3c.dom.Document) { + return new javax.xml.transform.dom.DOMResult(out); + } else { + out = new BufferedOutputStream(outStream(out)); + return new javax.xml.transform.stream.StreamResult(out); + } } /** - * Perform XSLT transform + * Perform XSLT transform * * @param inp Input XML to transform (URL, File or InputStream) * @param style XSL Stylesheet to be used (URL, File or InputStream). optional. * @param out Output XML (File or OutputStream */ function XSLTransform(inp, style, out) { - switch (arguments.length) { - case 2: - inp = arguments[0]; - out = arguments[1]; - break; - case 3: - inp = arguments[0]; - style = arguments[1]; - out = arguments[2]; - break; - default: - println("XSL tranform requires 2 or 3 arguments"); - return; - } + switch (arguments.length) { + case 2: + inp = arguments[0]; + out = arguments[1]; + break; + case 3: + inp = arguments[0]; + style = arguments[1]; + out = arguments[2]; + break; + default: + println("XSL tranform requires 2 or 3 arguments"); + return; + } - var factory = javax.xml.transform.TransformerFactory.newInstance(); - var tranformer; - if (style) { - transformer = factory.newTransformer(XMLSource(style)); - } else { - transformer = factory.newTransformer(); - } - var source = XMLSource(inp); - var result = XMLResult(out); - transformer.transform(source, result); - if (source.getInputStream) { - streamClose(source.getInputStream()); - } - if (result.getOutputStream) { - streamClose(result.getOutputStream()); - } + var factory = javax.xml.transform.TransformerFactory.newInstance(); + var transformer; + if (style) { + transformer = factory.newTransformer(XMLSource(style)); + } else { + transformer = factory.newTransformer(); + } + var source = XMLSource(inp); + var result = XMLResult(out); + transformer.transform(source, result); + if (source.getInputStream) { + streamClose(source.getInputStream()); + } + if (result.getOutputStream) { + streamClose(result.getOutputStream()); + } } // miscellaneous utilities /** - * Prints which command is selected from PATH + * Prints which command is selected from PATH * * @param cmd name of the command searched from PATH */ function which(cmd) { - var st = new java.util.StringTokenizer(env.PATH, File.pathSeparator); - while (st.hasMoreTokens()) { - var file = new File(st.nextToken(), cmd); - if (file.exists()) { - println(file.getAbsolutePath()); - return; - } - } + var st = new java.util.StringTokenizer(env.PATH, File.pathSeparator); + while (st.hasMoreTokens()) { + var file = new File(st.nextToken(), cmd); + if (file.exists()) { + println(file.getAbsolutePath()); + return; + } + } } /** @@ -817,41 +852,43 @@ * @param name domain name */ function ip(name) { - var addrs = InetAddress.getAllByName(name); - for (var i in addrs) { - println(addrs[i]); - } + var addrs = InetAddress.getAllByName(name); + for (var i in addrs) { + println(addrs[i]); + } } /** * Prints current date in current locale */ function date() { - println(new Date().toLocaleString()); + println(new Date().toLocaleString()); } /** * Echoes the given string arguments */ function echo(x) { - for (var i = 0; i < arguments.length; i++) { - println(arguments[i]); - } + for (var i = 0; i < arguments.length; i++) { + println(arguments[i]); + } } -/** - * This is C-like printf - * - * @param format string to format the rest of the print items - * @param args variadic argument list - */ -function printf(format, args/*, more args*/) { - var array = java.lang.reflect.Array.newInstance(java.lang.Object, - arguments.length - 1); - for (var i = 0; i < array.length; i++) { - array[i] = arguments[i+1]; - } - return java.lang.System.out.printf(format, array); +if (typeof(printf) == 'undefined') { + /** + * This is C-like printf + * + * @param format string to format the rest of the print items + * @param args variadic argument list + */ + var printf = function (format, args/*, more args*/) { + var array = java.lang.reflect.Array.newInstance(java.lang.Object, + arguments.length - 1); + for (var i = 0; i < array.length; i++) { + array[i] = arguments[i+1]; + } + java.lang.System.out.printf(format, array); + } } /** @@ -861,24 +898,48 @@ * @param multiline to tell whether to read single line or multiple lines */ function read(prompt, multiline) { - if (!prompt) { - prompt = '>'; - } - var inp = java.lang.System["in"]; - var reader = new BufferedReader(new InputStreamReader(inp)); - if (multiline) { - var line = ''; - while (true) { - java.lang.System.err.print(prompt); - java.lang.System.err.flush(); - var tmp = reader.readLine(); - if (tmp == '' || tmp == null) break; - line += tmp + '\n'; - } - return line; - } else { - java.lang.System.err.print(prompt); - java.lang.System.err.flush(); - return reader.readLine(); - } + if (!prompt) { + prompt = '>'; + } + var inp = java.lang.System["in"]; + var reader = new BufferedReader(new InputStreamReader(inp)); + if (multiline) { + var line = ''; + while (true) { + java.lang.System.err.print(prompt); + java.lang.System.err.flush(); + var tmp = reader.readLine(); + if (tmp == '' || tmp == null) break; + line += tmp + '\n'; + } + return line; + } else { + java.lang.System.err.print(prompt); + java.lang.System.err.flush(); + return reader.readLine(); + } } + +if (typeof(println) == 'undefined') { + var print = function(str, newline) { + if (typeof(str) == 'undefined') { + str = 'undefined'; + } else if (str == null) { + str = 'null'; + } + + if (!(out instanceof java.io.PrintWriter)) { + out = new java.io.PrintWriter(out); + } + + out.print(String(str)); + if (newline) { + out.print('\n'); + } + out.flush(); + } + + var println = function(str) { + print(str, true); + }; +}
--- a/src/share/classes/java/awt/CheckboxMenuItem.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/CheckboxMenuItem.java Wed Mar 20 11:23:16 2013 -0400 @@ -277,7 +277,7 @@ * @since 1.4 */ public synchronized ItemListener[] getItemListeners() { - return (ItemListener[])(getListeners(ItemListener.class)); + return getListeners(ItemListener.class); } /**
--- a/src/share/classes/java/awt/Cursor.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/Cursor.java Wed Mar 20 11:23:16 2013 -0400 @@ -163,11 +163,11 @@ * hashtable, filesystem dir prefix, filename, and properties for custom cursors support */ - private static final Hashtable systemCustomCursors = new Hashtable(1); + private static final Hashtable<String,Cursor> 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 @@ 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 @@ 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 @@ 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.<Cursor>doPrivileged( + new java.security.PrivilegedExceptionAction<Cursor>() { + public Cursor run() throws Exception { Toolkit toolkit = Toolkit.getDefaultToolkit(); Image image = toolkit.getImage( systemCustomCursorDirPrefix + fileName); @@ -447,8 +447,8 @@ systemCustomCursorProperties = new Properties(); try { - AccessController.doPrivileged( - new java.security.PrivilegedExceptionAction() { + AccessController.<Object>doPrivileged( + new java.security.PrivilegedExceptionAction<Object>() { public Object run() throws Exception { FileInputStream fis = null; try {
--- a/src/share/classes/java/awt/Dialog.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/Dialog.java Wed Mar 20 11:23:16 2013 -0400 @@ -39,6 +39,7 @@ 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 @@ */ 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 @@ this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -722,6 +726,7 @@ this.title = title; setModalityType(modalityType); SunToolkit.checkAndSetPolicy(this); + initialized = true; } /** @@ -851,12 +856,9 @@ 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 @@ */ @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 @@ } } + 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; + } /*
--- a/src/share/classes/java/awt/EventQueue.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/EventQueue.java Wed Mar 20 11:23:16 2013 -0400 @@ -171,7 +171,7 @@ * The modifiers field of the current event, if the current event is an * InputEvent or ActionEvent. */ - private WeakReference currentEvent; + private WeakReference<AWTEvent> currentEvent; /* * Non-zero if a thread is waiting in getNextEvent(int) for an event of @@ -194,7 +194,8 @@ } 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 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 @@ pushPopLock.lock(); try { return (Thread.currentThread() == dispatchThread) - ? ((AWTEvent)currentEvent.get()) + ? currentEvent.get() : null; } finally { pushPopLock.unlock(); @@ -1167,7 +1173,7 @@ 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 @@ * @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 @@ 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);
--- a/src/share/classes/java/awt/Menu.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/Menu.java Wed Mar 20 11:23:16 2013 -0400 @@ -66,7 +66,7 @@ AWTAccessor.setMenuAccessor( new AWTAccessor.MenuAccessor() { - public Vector getItems(Menu menu) { + public Vector<MenuComponent> getItems(Menu menu) { return menu.items; } }); @@ -78,7 +78,7 @@ * @serial * @see #countItems() */ - Vector items = new Vector(); + Vector<MenuComponent> items = new Vector<>(); /** * This field indicates whether the menu has the @@ -313,7 +313,7 @@ } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector<MenuItem> tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -330,7 +330,7 @@ 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 @@ } int nitems = getItemCount(); - Vector tempItems = new Vector(); + Vector<MenuItem> tempItems = new Vector<>(); /* Remove the item at index, nitems-index times storing them in a temporary vector in the @@ -396,7 +396,7 @@ 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 @@ return null; } - synchronized Enumeration shortcuts() { - Vector shortcuts = new Vector(); + synchronized Enumeration<MenuShortcut> shortcuts() { + Vector<MenuShortcut> 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<MenuShortcut> e = ((Menu)mi).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); }
--- a/src/share/classes/java/awt/MenuBar.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/MenuBar.java Wed Mar 20 11:23:16 2013 -0400 @@ -81,7 +81,7 @@ return menuBar.helpMenu; } - public Vector getMenus(MenuBar menuBar) { + public Vector<Menu> getMenus(MenuBar menuBar) { return menuBar.menus; } }); @@ -94,7 +94,7 @@ * @serial * @see #countMenus() */ - Vector menus = new Vector(); + Vector<Menu> menus = new Vector<>(); /** * This menu is a special menu dedicated to @@ -309,7 +309,7 @@ * be called on the toolkit thread. */ final Menu getMenuImpl(int i) { - return (Menu)menus.elementAt(i); + return menus.elementAt(i); } /** @@ -321,10 +321,10 @@ * @since JDK1.1 */ public synchronized Enumeration<MenuShortcut> shortcuts() { - Vector shortcuts = new Vector(); + Vector<MenuShortcut> shortcuts = new Vector<>(); int nmenus = getMenuCount(); for (int i = 0 ; i < nmenus ; i++) { - Enumeration e = getMenu(i).shortcuts(); + Enumeration<MenuShortcut> e = getMenu(i).shortcuts(); while (e.hasMoreElements()) { shortcuts.addElement(e.nextElement()); } @@ -438,7 +438,7 @@ // 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; } }
--- a/src/share/classes/java/awt/MenuComponent.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/MenuComponent.java Wed Mar 20 11:23:16 2013 -0400 @@ -290,7 +290,7 @@ 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 void removeNotify() { synchronized (getTreeLock()) { - MenuComponentPeer p = (MenuComponentPeer)this.peer; + MenuComponentPeer p = this.peer; if (p != null) { Toolkit.getEventQueue().removeSourceEvents(this, true); this.peer = null;
--- a/src/share/classes/java/awt/MenuItem.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/MenuItem.java Wed Mar 20 11:23:16 2013 -0400 @@ -564,7 +564,7 @@ * @since 1.4 */ public synchronized ActionListener[] getActionListeners() { - return (ActionListener[])(getListeners(ActionListener.class)); + return getListeners(ActionListener.class); } /**
--- a/src/share/classes/java/awt/RenderingHints.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/RenderingHints.java Wed Mar 20 11:23:16 2013 -0400 @@ -92,7 +92,7 @@ * {@code equals()} method. */ public abstract static class Key { - private static HashMap identitymap = new HashMap(17); + private static HashMap<Object,Object> identitymap = new HashMap<>(17); private String getIdentity() { // Note that the identity string is dependent on 3 variables: @@ -138,7 +138,7 @@ } // 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<Key>(k)); } private int privatekey; @@ -195,7 +195,7 @@ } } - HashMap hintmap = new HashMap(7); + HashMap<Object,Object> hintmap = new HashMap<>(7); /** * Antialiasing hint key. @@ -1267,12 +1267,13 @@ * 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<Object,Object>) hintmap.clone(); } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable
--- a/src/share/classes/java/awt/TextComponent.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/TextComponent.java Wed Mar 20 11:23:16 2013 -0400 @@ -109,12 +109,6 @@ // the background color of non-editable TextComponents. boolean backgroundSetByClientCode = false; - /** - * True if this <code>TextComponent</code> has access - * to the System clipboard. - */ - transient private boolean canAccessClipboard; - transient protected TextListener textListener; /* @@ -139,7 +133,6 @@ GraphicsEnvironment.checkHeadless(); this.text = (text != null) ? text : ""; setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); - checkSystemClipboardAccess(); } private void enableInputMethodsIfNecessary() { @@ -734,17 +727,14 @@ /** * 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 @@ } } enableInputMethodsIfNecessary(); - checkSystemClipboardAccess(); }
--- a/src/share/classes/java/awt/Window.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/Window.java Wed Mar 20 11:23:16 2013 -0400 @@ -1206,7 +1206,7 @@ } else { try { - EventQueue.invokeAndWait(action); + EventQueue.invokeAndWait(this, action); } catch (InterruptedException e) { System.err.println("Disposal was interrupted:");
--- a/src/share/classes/java/awt/datatransfer/Clipboard.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/datatransfer/Clipboard.java Wed Mar 20 11:23:16 2013 -0400 @@ -71,7 +71,7 @@ * * @since 1.5 */ - private Set currentDataFlavors; + private Set<DataFlavor> currentDataFlavors; /** * Creates a clipboard object. @@ -313,7 +313,7 @@ if (flavorListeners == null) { return; } - Set prevDataFlavors = currentDataFlavors; + Set<DataFlavor> prevDataFlavors = currentDataFlavors; currentDataFlavors = getAvailableDataFlavorSet(); if (prevDataFlavors.equals(currentDataFlavors)) { return; @@ -339,8 +339,8 @@ * * @since 1.5 */ - private Set getAvailableDataFlavorSet() { - Set set = new HashSet(); + private Set<DataFlavor> getAvailableDataFlavorSet() { + Set<DataFlavor> set = new HashSet<>(); Transferable contents = getContents(null); if (contents != null) { DataFlavor[] flavors = contents.getTransferDataFlavors();
--- a/src/share/classes/java/awt/dnd/DragGestureEvent.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/dnd/DragGestureEvent.java Wed Mar 20 11:23:16 2013 -0400 @@ -165,7 +165,7 @@ * <P> * @return an Iterator for the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Iterator<InputEvent> iterator() { return events.iterator(); } /** @@ -184,7 +184,7 @@ * <P> * @return an array of the events comprising the gesture */ - + @SuppressWarnings("unchecked") public Object[] toArray(Object[] array) { return events.toArray(array); } /** @@ -333,7 +333,6 @@ 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 @@ /* * fields */ - + @SuppressWarnings("rawtypes") private transient List events; /**
--- a/src/share/classes/java/awt/dnd/DragGestureRecognizer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/dnd/DragGestureRecognizer.java Wed Mar 20 11:23:16 2013 -0400 @@ -297,7 +297,7 @@ * @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
--- a/src/share/classes/java/awt/dnd/DragSource.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/dnd/DragSource.java Wed Mar 20 11:23:16 2013 -0400 @@ -600,7 +600,7 @@ * @since 1.4 */ public DragSourceListener[] getDragSourceListeners() { - return (DragSourceListener[])getListeners(DragSourceListener.class); + return getListeners(DragSourceListener.class); } /** @@ -660,8 +660,7 @@ * @since 1.4 */ public DragSourceMotionListener[] getDragSourceMotionListeners() { - return (DragSourceMotionListener[]) - getListeners(DragSourceMotionListener.class); + return getListeners(DragSourceMotionListener.class); } /** @@ -896,8 +895,8 @@ * @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 {
--- a/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/dnd/InvalidDnDOperationException.java Wed Mar 20 11:23:16 2013 -0400 @@ -36,6 +36,8 @@ 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"; /**
--- a/src/share/classes/java/awt/geom/AffineTransform.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/geom/AffineTransform.java Wed Mar 20 11:23:16 2013 -0400 @@ -876,6 +876,7 @@ * they have not been cached. * @see #getType */ + @SuppressWarnings("fallthrough") private void calculateType() { int ret = TYPE_IDENTITY; boolean sgn0, sgn1; @@ -1038,6 +1039,7 @@ * @see #TYPE_UNIFORM_SCALE * @since 1.2 */ + @SuppressWarnings("fallthrough") public double getDeterminant() { switch (state) { default: @@ -1250,6 +1252,7 @@ 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 @@ * 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 @@ default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): double M0, M1; @@ -2224,6 +2229,7 @@ * @see #preConcatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void concatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2432,6 +2438,7 @@ * @see #concatenate * @since 1.2 */ + @SuppressWarnings("fallthrough") public void preConcatenate(AffineTransform Tx) { double M0, M1; double T00, T01, T10, T11; @@ -2655,6 +2662,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * inverted. * @since 1.2 */ + @SuppressWarnings("fallthrough") public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst) throws NoninvertibleTransformException { @@ -3547,6 +3563,7 @@ 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 @@ 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 @@ default: stateError(); /* NOTREACHED */ + return; case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE): case (APPLY_SHEAR | APPLY_SCALE): M00 = m00; M01 = m01;
--- a/src/share/classes/java/awt/peer/FramePeer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/peer/FramePeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -125,4 +125,10 @@ // 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); }
--- a/src/share/classes/java/awt/peer/WindowPeer.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/awt/peer/WindowPeer.java Wed Mar 20 11:23:16 2013 -0400 @@ -27,8 +27,6 @@ import java.awt.*; -import java.awt.image.BufferedImage; - /** * The peer interface for {@link Window}. *
--- a/src/share/classes/java/beans/PropertyDescriptor.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/beans/PropertyDescriptor.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ 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 @@ setReadMethod(read); setWriteMethod(write); this.baseName = base; - boundInitialization(bean); } /**
--- a/src/share/classes/java/io/ObjectInputStream.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/io/ObjectInputStream.java Wed Mar 20 11:23:16 2013 -0400 @@ -1752,6 +1752,12 @@ 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;
--- a/src/share/classes/java/lang/Class.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/Class.java Wed Mar 20 11:23:16 2013 -0400 @@ -64,7 +64,9 @@ 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 @@ 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 @@ throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { - checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); + checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); } return newInstance0(); } @@ -1300,7 +1302,7 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ * <p> 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()); + } } }
--- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java Wed Mar 20 11:23:16 2013 -0400 @@ -51,6 +51,17 @@ private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form); if (!member.isResolved()) throw new InternalError(); + + if (member.getDeclaringClass().isInterface() && + member.isMethod() && !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; }
--- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Mar 20 11:23:16 2013 -0400 @@ -807,12 +807,11 @@ 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 @@ 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())
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Mar 20 11:23:16 2013 -0400 @@ -393,15 +393,33 @@ */ // 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 @@ 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 @@ 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 @@ 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 + } }
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ <T> T asInterfaceInstance(final Class<T> 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 @@ 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<Object>() { + 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; } /**
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Wed Mar 20 11:23:16 2013 -0400 @@ -598,7 +598,8 @@ 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 @@ 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 @@ 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 @@ Class<? extends Object> 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 @@ 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 @@ 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); } /** @@ -1040,7 +1046,29 @@ } /** + * 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 <a href="MethodHandles.Lookup.html#secmgr">access checks</a>. + * 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 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 @@ 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 @@ } 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("<init>")); MemberName ctor = (resolved != null) ? resolved
--- a/src/share/classes/java/lang/management/ManagementFactory.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/management/ManagementFactory.java Wed Mar 20 11:23:16 2013 -0400 @@ -802,20 +802,20 @@ */ 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<Void>() { 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; }
--- a/src/share/classes/java/lang/reflect/Proxy.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/lang/reflect/Proxy.java Wed Mar 20 11:23:16 2013 -0400 @@ -27,6 +27,9 @@ 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.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 @@ * @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<String>() { + 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 @@ 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 @@ } } - if (proxyPkg == null) { // if no non-public proxy interfaces, - proxyPkg = ""; // use the unnamed package + if (proxyPkg == null) { + // if no non-public proxy interfaces, use com.sun.proxy package + proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } { @@ -598,22 +710,46 @@ /* * 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<Object>() { + public Object run() { + return newInstance(cons, ih); + } + }); + } else { + return newInstance(cons, ih); + } + } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } } + private static Object newInstance(Constructor<?> cons, InvocationHandler h) { + try { + return cons.newInstance(new Object[] {h} ); + } catch (IllegalAccessException | InstantiationException e) { + throw new InternalError(e.toString(), e); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } else { + throw new InternalError(t.toString(), t); + } + } + } + /** * Returns true if and only if the specified class was dynamically * generated to be a proxy class using the {@code getProxyClass}
--- a/src/share/classes/java/net/InetSocketAddress.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/net/InetSocketAddress.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ * @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 @@ * 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 @@ * @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 @@ * @since 1.5 */ public static InetSocketAddress createUnresolved(String host, int port) { - if (port < 0 || port > 0xFFFF) { - throw new IllegalArgumentException("port out of range:" + port); - } - if (host == null) { - throw new IllegalArgumentException("hostname can't be null"); - } - InetSocketAddress s = new InetSocketAddress(); - s.port = port; - s.hostname = host; - s.addr = null; - return s; + return new InetSocketAddress(checkPort(port), checkHost(host)); } - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); + /** + * @serialField hostname String + * @serialField addr InetAddress + * @serialField port int + */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("hostname", String.class), + new ObjectStreamField("addr", InetAddress.class), + new ObjectStreamField("port", int.class)}; + + private void writeObject(ObjectOutputStream out) + throws IOException + { + // Don't call defaultWriteObject() + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("hostname", holder.hostname); + pfields.put("addr", holder.addr); + pfields.put("port", holder.port); + out.writeFields(); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = in.readFields(); + final String oisHostname = (String)oisFields.get("hostname", null); + final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null); + final int oisPort = oisFields.get("port", -1); // Check that our invariants are satisfied - if (port < 0 || port > 0xFFFF) { - throw new InvalidObjectException("port out of range:" + port); - } - - if (hostname == null && addr == null) { + checkPort(oisPort); + if (oisHostname == null && oisAddr == null) throw new InvalidObjectException("hostname and addr " + "can't both be null"); + + InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname, + oisAddr, + oisPort); + UNSAFE.putObject(this, FIELDS_OFFSET, h); + } + + private void readObjectNoData() + throws ObjectStreamException + { + throw new InvalidObjectException("Stream data required"); + } + + private static final long FIELDS_OFFSET; + private static final sun.misc.Unsafe UNSAFE; + static { + try { + sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + FIELDS_OFFSET = unsafe.objectFieldOffset( + InetSocketAddress.class.getDeclaredField("holder")); + UNSAFE = unsafe; + } catch (ReflectiveOperationException e) { + throw new Error(e); } } @@ -203,7 +321,7 @@ * @return the port number. */ public final int getPort() { - return port; + return holder.getPort(); } /** @@ -213,7 +331,7 @@ * @return the InetAdress or <code>null</code> if it is unresolved. */ public final InetAddress getAddress() { - return addr; + return holder.getAddress(); } /** @@ -224,31 +342,19 @@ * @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 <b>not</b> attemptimg a reverse lookup. + * This has the benefit of <b>not</b> 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 @@ * an <code>InetAddress</code>. */ public final boolean isUnresolved() { - return addr == null; + return holder.isUnresolved(); } /** @@ -269,12 +375,9 @@ * * @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 @@ * <code>false</code> 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 @@ * * @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(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/util/Optional.java Wed Mar 20 11:23:16 2013 -0400 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * A container object which may or may not contain a non-null value. + * If a value is present, {@code isPresent()} will return {@code true} and + * {@code get()} will return the value. + * + * <p>Additional methods that depend on the presence or absence of a contained + * value are provided, such as {@link #orElse(java.lang.Object) orElse()} + * (return a default value if value not present) and + * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block + * of code if the value is present). + * + * @since 1.8 + */ +public final class Optional<T> { + /** + * Common instance for {@code empty()}. + */ + private static final Optional<?> EMPTY = new Optional<>(); + + /** + * If non-null, the value; if null, indicates no value is present + */ + private final T value; + + /** + * Construct an empty instance. + * + * @implNote Generally only one empty instance, {@link Optional#EMPTY}, + * should exist per VM. + */ + private Optional() { + this.value = null; + } + + /** + * Returns an empty {@code Optional} instance. No value is present for this + * Optional. + * + * @apiNote Though it may be tempting to do so, avoid testing if an object + * is empty by comparing with {@code ==} against instances returned by + * {@code Option.empty()}. There is no guarantee that it is a singleton. + * Instead, use {@link #isPresent()}. + * + * @param <T> Type of the non-existent value + * @return an empty {@code Optional} + */ + public static<T> Optional<T> empty() { + @SuppressWarnings("unchecked") + Optional<T> t = (Optional<T>) EMPTY; + return t; + } + + /** + * Construct an instance with the value present. + * + * @param value the non-null value to be present + */ + private Optional(T value) { + this.value = Objects.requireNonNull(value); + } + + /** + * Return an {@code Optional} with the specified present value. + * + * @param value the value to be present, which must be non-null + * @return an {@code Optional} with the value present + */ + public static <T> Optional<T> of(T value) { + return new Optional<>(value); + } + + /** + * If a value is present in this {@code Optional}, returns the value, + * otherwise throws {@code NoSuchElementException}. + * + * @return the non-null value held by this {@code Optional} + * @throws NoSuchElementException if there is no value present + * + * @see Optional#isPresent() + */ + public T get() { + if (value == null) { + throw new NoSuchElementException("No value present"); + } + return value; + } + + /** + * Return {@code true} if there is a value present, otherwise {@code false}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return value != null; + } + + /** + * Have the specified consumer accept the value if a value is present, + * otherwise do nothing. + * + * @param consumer block to be executed if a value is present + * @throws NullPointerException if value is present and {@code consumer} is + * null + */ + public void ifPresent(Consumer<? super T> consumer) { + if (value != null) + consumer.accept(value); + } + + /** + * Return the value if present, otherwise return {@code other}. + * + * @param other the value to be returned if there is no value present, may + * be null + * @return the value, if present, otherwise {@code other} + */ + public T orElse(T other) { + return value != null ? value : other; + } + + /** + * Return the value if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code Supplier} whose result is returned if no value + * is present + * @return the value if present otherwise the result of {@code other.get()} + * @throws NullPointerException if value is not present and {@code other} is + * null + */ + public T orElseGet(Supplier<? extends T> other) { + return value != null ? value : other.get(); + } + + /** + * Return the contained value, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + * + * @param <X> Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present value + * @throws X if there is no value present + * @throws NullPointerException if no value is present and + * {@code exceptionSupplier} is null + */ + public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { + if (value != null) { + return value; + } else { + throw exceptionSupplier.get(); + } + } + + /** + * Indicates whether some other object is "equal to" this Optional. The + * other object is considered equal if: + * <ul> + * <li>it is also an {@code Optional} and; + * <li>both instances have no value present or; + * <li>the present values are "equal to" each other via {@code equals()}. + * </ul> + * + * @param obj an object to be tested for equality + * @return {code true} if the other object is "equal to" this object + * otherwise {@code false} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof Optional)) { + return false; + } + + Optional other = (Optional) obj; + return Objects.equals(value, other.value); + } + + /** + * Returns the hash code value of the present value, if any, or 0 (zero) if + * no value is present. + * + * @return hash code value of the present value or 0 if no value is present + */ + @Override + public int hashCode() { + return Objects.hashCode(value); + } + + /** + * Returns a non-empty string representation of this Optional suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + * + * @implSpec If a value is present the result must include its string + * representation in the result. Empty and present Optionals must be + * unambiguously differentiable. + * + * @return the string representation of this instance + */ + @Override + public String toString() { + return value != null + ? String.format("Optional[%s]", value) + : "Optional.empty"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/util/OptionalDouble.java Wed Mar 20 11:23:16 2013 -0400 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util; + +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; + +/** + * A container object which may or may not contain a {@code double} value. + * If a value is present, {@code isPresent()} will return {@code true} and + * {@code get()} will return the value. + * + * <p>Additional methods that depend on the presence or absence of a contained + * value are provided, such as {@link #orElse(double) orElse()} + * (return a default value if value not present) and + * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (execute a block + * of code if the value is present). + * + * @since 1.8 + */ +public final class OptionalDouble { + /** + * Common instance for {@code empty()}. + */ + private static final OptionalDouble EMPTY = new OptionalDouble(); + + /** + * If true then the value is present, otherwise indicates no value is present + */ + private final boolean isPresent; + private final double value; + + /** + * Construct an empty instance. + * + * @implNote generally only one empty instance, {@link OptionalDouble#EMPTY}, + * should exist per VM. + */ + private OptionalDouble() { + this.isPresent = false; + this.value = Double.NaN; + } + + /** + * Returns an empty {@code OptionalDouble} instance. No value is present for this + * OptionalDouble. + * + * @apiNote Though it may be tempting to do so, avoid testing if an object + * is empty by comparing with {@code ==} against instances returned by + * {@code Option.empty()}. There is no guarantee that it is a singleton. + * Instead, use {@link #isPresent()}. + * + * @return an empty {@code OptionalDouble}. + */ + public static OptionalDouble empty() { + return EMPTY; + } + + /** + * Construct an instance with the value present. + * + * @param value the double value to be present. + */ + private OptionalDouble(double value) { + this.isPresent = true; + this.value = value; + } + + /** + * Return an {@code OptionalDouble} with the specified value present. + * + * @param value the value to be present + * @return an {@code OptionalDouble} with the value present + */ + public static OptionalDouble of(double value) { + return new OptionalDouble(value); + } + + /** + * If a value is present in this {@code OptionalDouble}, returns the value, + * otherwise throws {@code NoSuchElementException}. + * + * @return the value held by this {@code OptionalDouble} + * @throws NoSuchElementException if there is no value present + * + * @see OptionalDouble#isPresent() + */ + public double getAsDouble() { + if (!isPresent) { + throw new NoSuchElementException("No value present"); + } + return value; + } + + /** + * Return {@code true} if there is a value present, otherwise {@code false}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return isPresent; + } + + /** + * Have the specified consumer accept the value if a value is present, + * otherwise do nothing. + * + * @param consumer block to be executed if a value is present + * @throws NullPointerException if value is present and {@code consumer} is + * null + */ + public void ifPresent(DoubleConsumer consumer) { + if (isPresent) + consumer.accept(value); + } + + /** + * Return the value if present, otherwise return {@code other}. + * + * @param other the value to be returned if there is no value present + * @return the value, if present, otherwise {@code other} + */ + public double orElse(double other) { + return isPresent ? value : other; + } + + /** + * Return the value if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code DoubleSupplier} whose result is returned if no value + * is present + * @return the value if present otherwise the result of {@code other.getAsDouble()} + * @throws NullPointerException if value is not present and {@code other} is + * null + */ + public double orElseGet(DoubleSupplier other) { + return isPresent ? value : other.getAsDouble(); + } + + /** + * Return the contained value, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + * + * @param <X> Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present value + * @throws X if there is no value present + * @throws NullPointerException if no value is present and + * {@code exceptionSupplier} is null + */ + public<X extends Throwable> double orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (isPresent) { + return value; + } else { + throw exceptionSupplier.get(); + } + } + + /** + * Indicates whether some other object is "equal to" this Optional. The + * other object is considered equal if: + * <ul> + * <li>it is also an {@code OptionalInt} and; + * <li>both instances have no value present or; + * <li>the present values are "equal to" each other via {@code Double.compare() == 0}. + * </ul> + * + * @param obj an object to be tested for equality + * @return {code true} if the other object is "equal to" this object + * otherwise {@code false} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof OptionalDouble)) { + return false; + } + + OptionalDouble other = (OptionalDouble) obj; + return (isPresent && other.isPresent) + ? Double.compare(value, other.value) == 0 + : isPresent == other.isPresent; + } + + /** + * Returns the hash code value of the present value, if any, or 0 (zero) if + * no value is present. + * + * @return hash code value of the present value or 0 if no value is present + */ + @Override + public int hashCode() { + return isPresent ? Double.hashCode(value) : 0; + } + + /** + * Returns a non-empty string representation of this OptionalDouble suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + * + * @implSpec If a value is present the result must include its string + * representation in the result. Empty and present OptionalDoubless must be + * unambiguously differentiable. + * + * @return the string representation of this instance + */ + @Override + public String toString() { + return isPresent + ? String.format("OptionalDouble[%s]", value) + : "OptionalDouble.empty"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/util/OptionalInt.java Wed Mar 20 11:23:16 2013 -0400 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util; + +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; +import java.util.function.Supplier; + +/** + * A container object which may or may not contain a {@code int} value. + * If a value is present, {@code isPresent()} will return {@code true} and + * {@code get()} will return the value. + * + * <p>Additional methods that depend on the presence or absence of a contained + * value are provided, such as {@link #orElse(int) orElse()} + * (return a default value if value not present) and + * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (execute a block + * of code if the value is present). + * + * @since 1.8 + */ +public final class OptionalInt { + /** + * Common instance for {@code empty()}. + */ + private static final OptionalInt EMPTY = new OptionalInt(); + + /** + * If true then the value is present, otherwise indicates no value is present + */ + private final boolean isPresent; + private final int value; + + /** + * Construct an empty instance. + * + * @implNote Generally only one empty instance, {@link OptionalInt#EMPTY}, + * should exist per VM. + */ + private OptionalInt() { + this.isPresent = false; + this.value = 0; + } + + /** + * Returns an empty {@code OptionalInt} instance. No value is present for this + * OptionalInt. + * + * @apiNote Though it may be tempting to do so, avoid testing if an object + * is empty by comparing with {@code ==} against instances returned by + * {@code Option.empty()}. There is no guarantee that it is a singleton. + * Instead, use {@link #isPresent()}. + * + * @return an empty {@code OptionalInt} + */ + public static OptionalInt empty() { + return EMPTY; + } + + /** + * Construct an instance with the value present. + * + * @param value the int value to be present + */ + private OptionalInt(int value) { + this.isPresent = true; + this.value = value; + } + + /** + * Return an {@code OptionalInt} with the specified value present. + * + * @param value the value to be present + * @return an {@code OptionalInt} with the value present + */ + public static OptionalInt of(int value) { + return new OptionalInt(value); + } + + /** + * If a value is present in this {@code OptionalInt}, returns the value, + * otherwise throws {@code NoSuchElementException}. + * + * @return the value held by this {@code OptionalInt} + * @throws NoSuchElementException if there is no value present + * + * @see OptionalInt#isPresent() + */ + public int getAsInt() { + if (!isPresent) { + throw new NoSuchElementException("No value present"); + } + return value; + } + + /** + * Return {@code true} if there is a value present, otherwise {@code false}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return isPresent; + } + + /** + * Have the specified consumer accept the value if a value is present, + * otherwise do nothing. + * + * @param consumer block to be executed if a value is present + * @throws NullPointerException if value is present and {@code consumer} is + * null + */ + public void ifPresent(IntConsumer consumer) { + if (isPresent) + consumer.accept(value); + } + + /** + * Return the value if present, otherwise return {@code other}. + * + * @param other the value to be returned if there is no value present + * @return the value, if present, otherwise {@code other} + */ + public int orElse(int other) { + return isPresent ? value : other; + } + + /** + * Return the value if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code IntSupplier} whose result is returned if no value + * is present + * @return the value if present otherwise the result of {@code other.getAsInt()} + * @throws NullPointerException if value is not present and {@code other} is + * null + */ + public int orElseGet(IntSupplier other) { + return isPresent ? value : other.getAsInt(); + } + + /** + * Return the contained value, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + * + * @param <X> Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present value + * @throws X if there is no value present + * @throws NullPointerException if no value is present and + * {@code exceptionSupplier} is null + */ + public<X extends Throwable> int orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (isPresent) { + return value; + } else { + throw exceptionSupplier.get(); + } + } + + /** + * Indicates whether some other object is "equal to" this Optional. The + * other object is considered equal if: + * <ul> + * <li>it is also an {@code OptionalInt} and; + * <li>both instances have no value present or; + * <li>the present values are "equal to" each other via {@code ==}. + * </ul> + * + * @param obj an object to be tested for equality + * @return {code true} if the other object is "equal to" this object + * otherwise {@code false} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof OptionalInt)) { + return false; + } + + OptionalInt other = (OptionalInt) obj; + return (isPresent && other.isPresent) + ? value == other.value + : isPresent == other.isPresent; + } + + /** + * Returns the hash code value of the present value, if any, or 0 (zero) if + * no value is present. + * + * @return hash code value of the present value or 0 if no value is present + */ + @Override + public int hashCode() { + return isPresent ? Integer.hashCode(value) : 0; + } + + /** + * Returns a non-empty string representation of this OptionalInt suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + * + * @implSpec If a value is present the result must include its string + * representation in the result. Empty and present OptionalInts must be + * unambiguously differentiable. + * + * @return the string representation of this instance + */ + @Override + public String toString() { + return isPresent + ? String.format("OptionalInt[%s]", value) + : "OptionalInt.empty"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/util/OptionalLong.java Wed Mar 20 11:23:16 2013 -0400 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util; + +import java.util.function.LongConsumer; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +/** + * A container object which may or may not contain a {@code long} value. + * If a value is present, {@code isPresent()} will return {@code true} and + * {@code get()} will return the value. + * + * <p>Additional methods that depend on the presence or absence of a contained + * value are provided, such as {@link #orElse(long) orElse()} + * (return a default value if value not present) and + * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (execute a block + * of code if the value is present). + * + * @since 1.8 + */ +public final class OptionalLong { + /** + * Common instance for {@code empty()}. + */ + private static final OptionalLong EMPTY = new OptionalLong(); + + /** + * If true then the value is present, otherwise indicates no value is present + */ + private final boolean isPresent; + private final long value; + + /** + * Construct an empty instance. + * + * @implNote generally only one empty instance, {@link OptionalLong#EMPTY}, + * should exist per VM. + */ + private OptionalLong() { + this.isPresent = false; + this.value = 0; + } + + /** + * Returns an empty {@code OptionalLong} instance. No value is present for this + * OptionalLong. + * + * @apiNote Though it may be tempting to do so, avoid testing if an object + * is empty by comparing with {@code ==} against instances returned by + * {@code Option.empty()}. There is no guarantee that it is a singleton. + * Instead, use {@link #isPresent()}. + * + * @return an empty {@code OptionalLong}. + */ + public static OptionalLong empty() { + return EMPTY; + } + + /** + * Construct an instance with the value present. + * + * @param value the long value to be present + */ + private OptionalLong(long value) { + this.isPresent = true; + this.value = value; + } + + /** + * Return an {@code OptionalLong} with the specified value present. + * + * @param value the value to be present + * @return an {@code OptionalLong} with the value present + */ + public static OptionalLong of(long value) { + return new OptionalLong(value); + } + + /** + * If a value is present in this {@code OptionalLong}, returns the value, + * otherwise throws {@code NoSuchElementException}. + * + * @return the value held by this {@code OptionalLong} + * @throws NoSuchElementException if there is no value present + * + * @see OptionalLong#isPresent() + */ + public long getAsLong() { + if (!isPresent) { + throw new NoSuchElementException("No value present"); + } + return value; + } + + /** + * Return {@code true} if there is a value present, otherwise {@code false}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return isPresent; + } + + /** + * Have the specified consumer accept the value if a value is present, + * otherwise do nothing. + * + * @param consumer block to be executed if a value is present + * @throws NullPointerException if value is present and {@code consumer} is + * null + */ + public void ifPresent(LongConsumer consumer) { + if (isPresent) + consumer.accept(value); + } + + /** + * Return the value if present, otherwise return {@code other}. + * + * @param other the value to be returned if there is no value present + * @return the value, if present, otherwise {@code other} + */ + public long orElse(long other) { + return isPresent ? value : other; + } + + /** + * Return the value if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code LongSupplier} whose result is returned if no value + * is present + * @return the value if present otherwise the result of {@code other.getAsLong()} + * @throws NullPointerException if value is not present and {@code other} is + * null + */ + public long orElseGet(LongSupplier other) { + return isPresent ? value : other.getAsLong(); + } + + /** + * Return the contained value, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + * + * @param <X> Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present value + * @throws X if there is no value present + * @throws NullPointerException if no value is present and + * {@code exceptionSupplier} is null + */ + public<X extends Throwable> long orElseThrow(Supplier<X> exceptionSupplier) throws X { + if (isPresent) { + return value; + } else { + throw exceptionSupplier.get(); + } + } + + /** + * Indicates whether some other object is "equal to" this Optional. The + * other object is considered equal if: + * <ul> + * <li>it is also an {@code OptionalInt} and; + * <li>both instances have no value present or; + * <li>the present values are "equal to" each other via {@code ==}. + * </ul> + * + * @param obj an object to be tested for equality + * @return {code true} if the other object is "equal to" this object + * otherwise {@code false} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof OptionalLong)) { + return false; + } + + OptionalLong other = (OptionalLong) obj; + return (isPresent && other.isPresent) + ? value == other.value + : isPresent == other.isPresent; + } + + /** + * Returns the hash code value of the present value, if any, or 0 (zero) if + * no value is present. + * + * @return hash code value of the present value or 0 if no value is present + */ + @Override + public int hashCode() { + return isPresent ? Long.hashCode(value) : 0; + } + + /** + * Returns a non-empty string representation of this OptionalLong suitable for + * debugging. The exact presentation format is unspecified and may vary + * between implementations and versions. + * + * @implSpec If a value is present the result must include its string + * representation in the result. Empty and present OptionalLongs must be + * unambiguously differentiable. + * + * @return the string representation of this instance + */ + @Override + public String toString() { + return isPresent + ? String.format("OptionalLong[%s]", value) + : "OptionalLong.empty"; + } +}
--- a/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ * 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 @@ * 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 @@ * @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 @@ // 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 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 @@ 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 @@ 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 @@ * 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 @@ } } - 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 @@ * @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 @@ } } } +
--- a/src/share/classes/java/util/jar/JarFile.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/jar/JarFile.java Wed Mar 20 11:23:16 2013 -0400 @@ -34,6 +34,7 @@ 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 @@ 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 @@ // 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 @@ * 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 @@ 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))
--- a/src/share/classes/java/util/logging/Level.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/Level.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ */ public class Level implements java.io.Serializable { - private static java.util.ArrayList<Level> known = new java.util.ArrayList<>(); private static String defaultBundle = "sun.util.logging.resources.logging"; /** @@ -77,6 +80,9 @@ */ 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 <CODE>Integer.MAX_VALUE</CODE>. @@ -202,9 +208,8 @@ 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 @@ * @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 @@ // 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 @@ * <li> "SEVERE" * <li> "1000" * </ul> + * * @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 @@ // 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 @@ // 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 @@ // 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 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<String, List<KnownLevel>> nameToLevels = new HashMap<>(); + private static Map<Integer, List<KnownLevel>> 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<KnownLevel> 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<KnownLevel> 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<KnownLevel> 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<KnownLevel> 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<KnownLevel> 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<KnownLevel> 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; + } + } + }
--- a/src/share/classes/java/util/logging/LogManager.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/LogManager.java Wed Mar 20 11:23:16 2013 -0400 @@ -35,6 +35,10 @@ 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 @@ // count to allow for cases where the same listener is registered many times. private final Map<Object,Integer> listenerMap = new HashMap<>(); - // Table of named Loggers that maps names to Loggers. - private Hashtable<String,LoggerWeakRef> 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 @@ // 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.<clinit> // would deadlock with the LogManager.<clinit>. - 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 @@ return; } readPrimordialConfiguration = true; + try { - AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { - public Object run() throws Exception { + AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { + 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 @@ } } - // 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<LoggerContext> contexts() { + List<LoggerContext> 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 @@ 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); } - String pname = name.substring(0,ix2); + } while (logger == null); - if (getProperty(pname+".level") != null || - getProperty(pname+".handlers") != null) { - // This pname has a level/handlers definition. - // Make sure it exists. - demandLogger(pname); + // 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<Void>() { + 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<String,LoggerWeakRef> 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; } - ix = ix2+1; + 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<String> 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<Void>() { + public Void run() { + if (logger != manager.rootLogger) { + boolean useParent = manager.getBooleanProperty(name + ".useParentHandlers", true); + if (!useParent) { + logger.setUseParentHandlers(false); + } + } + return null; + } + }); + + int ix = 1; + for (;;) { + int ix2 = name.indexOf(".", ix); + if (ix2 < 0) { + break; + } + String pname = name.substring(0, ix2); + if (manager.getProperty(pname + ".level") != null || + manager.getProperty(pname + ".handlers") != null) { + // This pname has a level/handlers definition. + // Make sure it exists. + demandLogger(pname, null); + } + ix = ix2+1; + } + } + + // Gets a node in our tree of logger nodes. + // If necessary, create it. + LogNode getNode(String name) { + if (name == null || name.equals("")) { + return root; + } + LogNode node = root; + while (name.length() > 0) { + int ix = name.indexOf("."); + String head; + if (ix > 0) { + head = name.substring(0, ix); + name = name.substring(ix + 1); + } else { + head = name; + name = ""; + } + if (node.children == null) { + node.children = new HashMap<>(); + } + LogNode child = node.children.get(head); + if (child == null) { + child = new LogNode(node, this); + node.children.put(head, child); + } + node = child; + } + return node; + } + } + + static class SystemLoggerContext extends LoggerContext { + // Add a system logger in the system context's namespace as well as + // in the LogManager's namespace if not exist so that there is only + // one single logger of the given name. System loggers are visible + // to applications unless a logger of the same name has been added. + Logger demandLogger(String name, String resourceBundleName) { + Logger result = findLogger(name); + if (result == null) { + // only allocate the new system logger once + Logger newLogger = new Logger(name, resourceBundleName); + do { + if (addLocalLogger(newLogger)) { + // We successfully added the new Logger that we + // created above so return it without refetching. + result = newLogger; + } else { + // We didn't add the new Logger that we created above + // because another thread added a Logger with the same + // name after our null check above and before our call + // to addLogger(). We have to refetch the Logger because + // addLogger() returns a boolean instead of the Logger + // reference itself. However, if the thread that created + // the other Logger is not holding a strong reference to + // the other Logger, then it is possible for the other + // Logger to be GC'ed after we saw it in addLogger() and + // before we can refetch it. If it has been GC'ed then + // we'll just loop around and try again. + result = findLogger(name); + } + } while (result == null); + } + return result; } } @@ -439,32 +716,27 @@ // 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<Object>() { 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 @@ } } return null; - }}); + } + }); } @@ -520,7 +793,7 @@ 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 @@ * false if a logger of that name already exists. * @exception NullPointerException if the logger name is null. */ - public synchronized boolean addLogger(Logger logger) { + public boolean addLogger(Logger logger) { final String name = logger.getName(); if (name == null) { throw new NullPointerException(); } - - // cleanup some Loggers that have been GC'ed - drainLoggerRefQueueBounded(); - - LoggerWeakRef ref = namedLoggers.get(name); - if (ref != null) { - if (ref.get() == null) { - // It's possible that the Logger was GC'ed after the - // drainLoggerRefQueueBounded() call above so allow - // a new one to be registered. - namedLoggers.remove(name); - } else { - // We already have a registered logger with the given name. - return false; - } + LoggerContext cx = getUserContext(); + if (cx.addLocalLogger(logger)) { + // Do we have a per logger handler too? + // Note: this will add a 200ms penalty + loadLoggerHandlers(logger, name, name + ".handlers"); + return true; + } else { + return false; } - - // We're adding a new logger. - // Note that we are creating a weak reference here. - ref = new LoggerWeakRef(logger); - namedLoggers.put(name, ref); - - // Apply any initial level defined for the new logger. - Level level = getLevelProperty(name+".level", null); - if (level != null) { - doSetLevel(logger, level); - } - - // Do we have a per logger handler too? - // Note: this will add a 200ms penalty - loadLoggerHandlers(logger, name, name+".handlers"); - processParentHandlers(logger, name); - - // Find the new node and its parent. - LogNode node = findNode(name); - node.loggerRef = ref; - Logger parent = null; - LogNode nodep = node.parent; - while (nodep != null) { - LoggerWeakRef nodeRef = nodep.loggerRef; - if (nodeRef != null) { - parent = nodeRef.get(); - if (parent != null) { - break; - } - } - nodep = nodep.parent; - } - - if (parent != null) { - doSetParent(logger, parent); - } - // Walk over the children and tell them we are their new parent. - node.walkAndSetParent(logger); - - // new LogNode is ready so tell the LoggerWeakRef about it - ref.setNode(node); - - return true; } - // Private method to set a level on a logger. // If necessary, we raise privilege before doing the call. private static void doSetLevel(final Logger logger, final Level level) { @@ -694,8 +916,6 @@ }}); } - - // 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 @@ }}); } - // 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. * <p> @@ -759,18 +949,8 @@ * @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 @@ * <p> * @return enumeration of logger name strings */ - public synchronized Enumeration<String> getLoggerNames() { - return namedLoggers.keys(); + public Enumeration<String> getLoggerNames() { + return getUserContext().getLoggerNames(); } /** @@ -875,20 +1055,20 @@ // the global handlers, if they haven't been initialized yet. initializedGlobalHandlers = true; } - Enumeration<String> enum_ = getLoggerNames(); - while (enum_.hasMoreElements()) { - String name = enum_.nextElement(); - resetLogger(name); + for (LoggerContext cx : contexts()) { + Enumeration<String> 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 @@ // 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 @@ 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 @@ HashMap<String,LogNode> 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 @@ // 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 @@ 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); } }
--- a/src/share/classes/java/util/logging/Logger.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/Logger.java Wed Mar 20 11:23:16 2013 -0400 @@ -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 @@ } } + // 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<String>() { + 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 @@ // 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 @@ // 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 @@ 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 @@ 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 @@ 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<ResourceBundle>() { + 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 @@ 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();
--- a/src/share/classes/java/util/logging/Logging.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/Logging.java Wed Mar 20 11:23:16 2013 -0400 @@ -34,7 +34,7 @@ * * The <tt>LoggingMXBean</tt> 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 @@ if (level == null) { return EMPTY_STRING; } else { - return level.getName(); + return level.getLevelName(); } } @@ -85,7 +85,6 @@ } Logger logger = logManager.getLogger(loggerName); - if (logger == null) { throw new IllegalArgumentException("Logger " + loggerName + "does not exist"); @@ -94,7 +93,10 @@ 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);
--- a/src/share/classes/java/util/logging/LoggingProxyImpl.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/LoggingProxyImpl.java Wed Mar 20 11:23:16 2013 -0400 @@ -37,7 +37,8 @@ @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 @@ @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
--- a/src/share/classes/java/util/logging/SimpleFormatter.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/java/util/logging/SimpleFormatter.java Wed Mar 20 11:23:16 2013 -0400 @@ -162,7 +162,7 @@ dat, source, record.getLoggerName(), - record.getLevel().getLocalizedName(), + record.getLevel().getLocalizedLevelName(), message, throwable); }
--- a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Wed Mar 20 11:23:16 2013 -0400 @@ -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.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.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 @@ 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 @@ 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<Class<?>>() { + + @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 @@ 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 @@ 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<Void>() { + + @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]); } - final String msg = "Parameter class not found"; - throw new ReflectionException(e, msg); + 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); + } + } } + return null; } + }, stack, acc); + + if (caughtException[0] != null) { + throw caughtException[0]; } } @@ -1133,7 +1176,7 @@ /* 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 @@ 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<Class<?>>() { + + @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 @@ * 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<Object>() { + + @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 @@ } // 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 @@ // 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<Class<?>>() { + + @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 @@ 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<Class<?>>() { + + @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; }
--- a/src/share/classes/javax/swing/JFrame.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/JFrame.java Wed Mar 20 11:23:16 2013 -0400 @@ -387,13 +387,14 @@ 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 (operation == EXIT_ON_CLOSE) { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkExit(0); + } + } if (this.defaultCloseOperation != operation) { - if (operation == EXIT_ON_CLOSE) { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkExit(0); - } - } int oldValue = this.defaultCloseOperation; this.defaultCloseOperation = operation; firePropertyChange("defaultCloseOperation", oldValue, operation);
--- a/src/share/classes/javax/swing/JTable.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/JTable.java Wed Mar 20 11:23:16 2013 -0400 @@ -781,15 +781,11 @@ 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);
--- a/src/share/classes/javax/swing/RepaintManager.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/RepaintManager.java Wed Mar 20 11:23:16 2013 -0400 @@ -27,11 +27,12 @@ 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.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 @@ */ private final ProcessingRunnable processingRunnable; + private final static JavaSecurityAccess javaSecurityAccess = + SharedSecrets.getJavaSecurityAccess(); + static { volatileImageBufferEnabled = "true".equals(AccessController. @@ -548,13 +554,26 @@ // 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<Runnable>(); } - runnableList.add(r); + runnableList.add(new Runnable() { + public void run() { + AccessControlContext stack = AccessController.getContext(); + AccessControlContext acc = + AWTAccessor.getComponentAccessor().getAccessControlContext(c); + javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() { + public Void run() { + r.run(); + return null; + } + }, stack, acc); + } + }); } scheduleProcessingRunnable(appContext); } @@ -652,9 +671,9 @@ * @see #addInvalidComponent */ public void validateInvalidComponents() { - java.util.List<Component> ic; + final java.util.List<Component> ic; synchronized(this) { - if(invalidComponents == null) { + if (invalidComponents == null) { return; } ic = invalidComponents; @@ -662,7 +681,17 @@ } 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<Void>() { + public Void run() { + c.validate(); + return null; + } + }, stack, acc); } } @@ -740,78 +769,78 @@ paintDirtyRegions(tmpDirtyComponents); } - private void paintDirtyRegions(Map<Component,Rectangle> - tmpDirtyComponents){ - int i, count; - java.util.List<Component> roots; - Component dirtyComponent; - - count = tmpDirtyComponents.size(); - if (count == 0) { + private void paintDirtyRegions( + final Map<Component,Rectangle> tmpDirtyComponents) + { + if (tmpDirtyComponents.isEmpty()) { return; } - Rectangle rect; - int localBoundsX = 0; - int localBoundsY = 0; - int localBoundsH; - int localBoundsW; - - roots = new ArrayList<Component>(count); - + final java.util.List<Component> roots = + new ArrayList<Component>(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(); + 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<Void>() { + 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; + } - 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(); + 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;
--- a/src/share/classes/javax/swing/SwingUtilities.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/SwingUtilities.java Wed Mar 20 11:23:16 2013 -0400 @@ -356,7 +356,7 @@ sourceEvent.getYOnScreen(), sourceEvent.getClickCount(), sourceEvent.isPopupTrigger(), - MouseEvent.NOBUTTON ); + sourceEvent.getButton()); } return newEvent; }
--- a/src/share/classes/javax/swing/UIDefaults.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/UIDefaults.java Wed Mar 20 11:23:16 2013 -0400 @@ -677,6 +677,8 @@ try { String className = (String)get(uiClassID); if (className != null) { + ReflectUtil.checkPackageAccess(className); + Class cls = (Class)get(className); if (cls == null) { if (uiClassLoader == null) {
--- a/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Wed Mar 20 11:23:16 2013 -0400 @@ -159,7 +159,12 @@ // 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
--- a/src/share/classes/javax/swing/text/html/FormView.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/javax/swing/text/html/FormView.java Wed Mar 20 11:23:16 2013 -0400 @@ -159,6 +159,10 @@ 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 @@ 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 @@ /** - * 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"
--- a/src/share/classes/sun/applet/AppletPanel.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/sun/applet/AppletPanel.java Wed Mar 20 11:23:16 2013 -0400 @@ -45,6 +45,7 @@ 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 @@ // 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 @@ try { final AppletPanel p = this; final Applet a = applet; + Runnable r = new Runnable() { + public void run() { + p.validate(); + a.setVisible(true); - EventQueue.invokeAndWait(new Runnable() { - public void run() { - p.validate(); - a.setVisible(true); - - // Fix for BugTraq ID 4041703. - // Set the default focus for an applet. - if (hasInitialFocus()) - setDefaultFocus(); + // Fix for BugTraq ID 4041703. + // Set the default focus for an applet. + if (hasInitialFocus()) { + setDefaultFocus(); } - }); + } + }; + AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r); } catch(InterruptedException ie) { } @@ -512,13 +514,12 @@ // 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 @@ } 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) {
--- a/src/share/classes/sun/awt/AWTAccessor.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/sun/awt/AWTAccessor.java Wed Mar 20 11:23:16 2013 -0400 @@ -34,6 +34,8 @@ 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 @@ * appeared. */ void wakeup(EventQueue eventQueue, boolean isShutdown); + + /** + * Static in EventQueue + */ + void invokeAndWait(Object source, Runnable r) + throws InterruptedException, InvocationTargetException; } /*
--- a/src/share/classes/sun/awt/AppContext.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/sun/awt/AppContext.java Wed Mar 20 11:23:16 2013 -0400 @@ -327,21 +327,27 @@ // 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 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); + } }); } }
--- a/src/share/classes/sun/awt/EmbeddedFrame.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/sun/awt/EmbeddedFrame.java Wed Mar 20 11:23:16 2013 -0400 @@ -582,5 +582,8 @@ public void repositionSecurityWarning() { } - } + + public void emulateActivation(boolean activate) { + } + } } // class EmbeddedFrame
--- a/src/share/classes/sun/awt/HToolkit.java Wed Mar 20 10:58:20 2013 -0400 +++ b/src/share/classes/sun/awt/HToolkit.java Wed Mar 20 11:23:16 2013 -0400 @@ -64,6 +64,11 @@ throw new HeadlessException(); } + public FramePeer createLightweightFrame(LightweightFrame target) + throws HeadlessException { + throw new HeadlessException(); + } + public FramePeer createFrame(Frame target) throws HeadlessException { throw new HeadlessException();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/awt/LightweightFrame.java Wed Mar 20 11:23:16 2013 -0400 @@ -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