# HG changeset patch # User katleman # Date 1336594421 25200 # Node ID 5904985dac0a34c7a8b317e92b07f94d1c9657cb # Parent 070b00370caee190d33452d4868335c9ddf706d0# Parent fa146bd069e0221e8a82369b5f0761aab61700c8 Merge diff -r 070b00370cae -r 5904985dac0a jdk/make/common/Defs-macosx.gmk --- a/jdk/make/common/Defs-macosx.gmk Wed May 09 13:07:57 2012 -0700 +++ b/jdk/make/common/Defs-macosx.gmk Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 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 @@ -111,10 +111,10 @@ # For all platforms, do not omit the frame pointer register usage. # We need this frame pointer to make it easy to walk the stacks. -# This should be the default on X86, but ia64 and amd64 may not have this -# as the default. -CFLAGS_REQUIRED_amd64 += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN -LDFLAGS_COMMON_amd64 += -m64 +# This should be the default on X86, but ia64, and x86_64 +# may not have this as the default. +CFLAGS_REQUIRED_x86_64 += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN +LDFLAGS_COMMON_x86_64 += -m64 CFLAGS_REQUIRED_i586 += -m32 -fno-omit-frame-pointer -D_LITTLE_ENDIAN LDFLAGS_COMMON_i586 += -m32 CFLAGS_REQUIRED_ia64 += -m64 -fno-omit-frame-pointer -D_LITTLE_ENDIAN @@ -168,7 +168,7 @@ PIC_CODE_SMALL = -fpic GLOBAL_KPIC = $(PIC_CODE_LARGE) CFLAGS_COMMON += $(GLOBAL_KPIC) $(GCC_WARNINGS) -ifeq ($(ARCH), amd64) +ifeq ($(ARCH), x86_64) CFLAGS_COMMON += -pipe endif diff -r 070b00370cae -r 5904985dac0a jdk/make/common/Release-macosx.gmk --- a/jdk/make/common/Release-macosx.gmk Wed May 09 13:07:57 2012 -0700 +++ b/jdk/make/common/Release-macosx.gmk Wed May 09 13:13:41 2012 -0700 @@ -29,14 +29,14 @@ # Defines the release targets for Mac OS X build products -JDK_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2sdk-bundle/$(THIS_JDK_VERSION).jdk/Contents -JRE_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2re-bundle/$(THIS_JDK_VERSION).jre/Contents +JDK_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2sdk-bundle/jdk$(JDK_VERSION).jdk/Contents +JRE_BUNDLE_DIR = $(ABS_OUTPUTDIR)/j2re-bundle/jre$(JDK_VERSION).jre/Contents MACOSX_SRC = $(JDK_TOPDIR)/src/macosx BUNDLE_ID ?= net.java.openjdk -BUNLDE_ID_JRE ?= $(BUNDLE_ID).jre -BUNLDE_ID_JDK ?= $(BUNDLE_ID).jdk +BUNDLE_ID_JRE ?= $(BUNDLE_ID).jre +BUNDLE_ID_JDK ?= $(BUNDLE_ID).jdk BUNDLE_NAME ?= OpenJDK $(JDK_MINOR_VERSION) BUNDLE_NAME_JRE ?= $(BUNDLE_NAME) diff -r 070b00370cae -r 5904985dac0a jdk/make/common/shared/Platform.gmk --- a/jdk/make/common/shared/Platform.gmk Wed May 09 13:07:57 2012 -0700 +++ b/jdk/make/common/shared/Platform.gmk Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -264,7 +264,7 @@ echo sparc \ ;; \ x86_64) \ - echo amd64 \ + echo x86_64 \ ;; \ universal) \ echo universal \ diff -r 070b00370cae -r 5904985dac0a jdk/make/launchers/Makefile.launcher --- a/jdk/make/launchers/Makefile.launcher Wed May 09 13:07:57 2012 -0700 +++ b/jdk/make/launchers/Makefile.launcher Wed May 09 13:13:41 2012 -0700 @@ -81,6 +81,7 @@ # SA tools ifeq ($(PROGRAM),jstack) SA_TOOL=true + INFO_PLIST_FILE=Info-privileged.plist endif ifeq ($(PROGRAM),jsadebugd) SA_TOOL=true diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/bin/amd64/jvm.cfg --- a/jdk/src/macosx/bin/amd64/jvm.cfg Wed May 09 13:07:57 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -# List of JVMs that can be used as an option to java, javac, etc. -# Order is important -- first in this list is the default JVM. -# NOTE that this both this file and its format are UNSUPPORTED and -# WILL GO AWAY in a future release. -# -# You may also select a JVM in an arbitrary location with the -# "-XXaltjvm=" option, but that too is unsupported -# and may not be available in a future release. -# --server KNOWN --client IGNORE --hotspot ERROR --classic WARN --native ERROR --green ERROR diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/bin/java_md_macosx.c --- a/jdk/src/macosx/bin/java_md_macosx.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/bin/java_md_macosx.c Wed May 09 13:13:41 2012 -0700 @@ -906,11 +906,41 @@ { char envVar[80]; if (strstr(arg, "-Xdock:name=") == arg) { + /* + * The APP_NAME_ environment variable is used to pass + * an application name as specified with the -Xdock:name command + * line option from Java launcher code to the AWT code in order + * to assign this name to the app's dock tile on the Mac. + * The _ part is added to avoid collisions with child processes. + * + * WARNING: This environment variable is an implementation detail and + * isn't meant for use outside of the core platform. The mechanism for + * passing this information from Java launcher to other modules may + * change drastically between update release, and it may even be + * removed or replaced with another mechanism. + * + * NOTE: It is used by SWT, and JavaFX. + */ snprintf(envVar, sizeof(envVar), "APP_NAME_%d", getpid()); setenv(envVar, (arg + 12), 1); } if (strstr(arg, "-Xdock:icon=") == arg) { + /* + * The APP_ICON_ environment variable is used to pass + * an application icon as specified with the -Xdock:icon command + * line option from Java launcher code to the AWT code in order + * to assign this icon to the app's dock tile on the Mac. + * The _ part is added to avoid collisions with child processes. + * + * WARNING: This environment variable is an implementation detail and + * isn't meant for use outside of the core platform. The mechanism for + * passing this information from Java launcher to other modules may + * change drastically between update release, and it may even be + * removed or replaced with another mechanism. + * + * NOTE: It is used by SWT, and JavaFX. + */ snprintf(envVar, sizeof(envVar), "APP_ICON_%d", getpid()); setenv(envVar, (arg + 12), 1); } @@ -931,6 +961,22 @@ NULL_CHECK(mainClassName = (*env)->GetStringUTFChars(env, mainClassString, NULL)); char envVar[80]; + /* + * The JAVA_MAIN_CLASS_ environment variable is used to pass + * the name of a Java class whose main() method is invoked by + * the Java launcher code to start the application, to the AWT code + * in order to assign the name to the Apple menu bar when the app + * is active on the Mac. + * The _ part is added to avoid collisions with child processes. + * + * WARNING: This environment variable is an implementation detail and + * isn't meant for use outside of the core platform. The mechanism for + * passing this information from Java launcher to other modules may + * change drastically between update release, and it may even be + * removed or replaced with another mechanism. + * + * NOTE: It is used by SWT, and JavaFX. + */ snprintf(envVar, sizeof(envVar), "JAVA_MAIN_CLASS_%d", getpid()); setenv(envVar, mainClassName, 1); diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/bin/x86_64/jvm.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/macosx/bin/x86_64/jvm.cfg Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,38 @@ +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# List of JVMs that can be used as an option to java, javac, etc. +# Order is important -- first in this list is the default JVM. +# NOTE that this both this file and its format are UNSUPPORTED and +# WILL GO AWAY in a future release. +# +# You may also select a JVM in an arbitrary location with the +# "-XXaltjvm=" option, but that too is unsupported +# and may not be available in a future release. +# +-server KNOWN +-client IGNORE +-hotspot ERROR +-classic WARN +-native ERROR +-green ERROR diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/apple/launcher/JavaAppLauncher.java --- a/jdk/src/macosx/classes/apple/launcher/JavaAppLauncher.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/apple/launcher/JavaAppLauncher.java Wed May 09 13:13:41 2012 -0700 @@ -27,7 +27,6 @@ import java.io.*; import java.lang.reflect.*; -import java.security.PrivilegedAction; import java.text.MessageFormat; import java.util.*; import java.util.jar.*; @@ -36,7 +35,13 @@ class JavaAppLauncher implements Runnable { static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osx")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); } private static native T nativeConvertAndRelease(final long ptr); diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/apple/security/KeychainStore.java --- a/jdk/src/macosx/classes/apple/security/KeychainStore.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/apple/security/KeychainStore.java Wed May 09 13:13:41 2012 -0700 @@ -103,7 +103,13 @@ private static final int SALT_LEN = 20; static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osx")); + AccessController.doPrivileged( + new PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); try { PKCS8ShroudedKeyBag_OID = new ObjectIdentifier(keyBag); pbeWithSHAAnd3KeyTripleDESCBC_OID = new ObjectIdentifier(pbeWithSHAAnd3KeyTripleDESCBC); diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/concurrent/LibDispatchNative.java --- a/jdk/src/macosx/classes/com/apple/concurrent/LibDispatchNative.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/concurrent/LibDispatchNative.java Wed May 09 13:13:41 2012 -0700 @@ -26,17 +26,23 @@ package com.apple.concurrent; final class LibDispatchNative { - static { - java.security.AccessController.doPrivileged((java.security.PrivilegedAction)new sun.security.action.LoadLibraryAction("osx")); - } + static { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); + } - static native boolean nativeIsDispatchSupported(); - static native long nativeGetMainQueue(); - static native long nativeCreateConcurrentQueue(int priority); - static native long nativeCreateSerialQueue(String name); - static native void nativeReleaseQueue(long nativeQueue); - static native void nativeExecuteAsync(long nativeQueue, Runnable task); - static native void nativeExecuteSync(long nativeQueue, Runnable task); + static native boolean nativeIsDispatchSupported(); + static native long nativeGetMainQueue(); + static native long nativeCreateConcurrentQueue(int priority); + static native long nativeCreateSerialQueue(String name); + static native void nativeReleaseQueue(long nativeQueue); + static native void nativeExecuteAsync(long nativeQueue, Runnable task); + static native void nativeExecuteSync(long nativeQueue, Runnable task); - private LibDispatchNative() { } + private LibDispatchNative() { } } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/eawt/Application.java --- a/jdk/src/macosx/classes/com/apple/eawt/Application.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/eawt/Application.java Wed May 09 13:13:41 2012 -0700 @@ -28,7 +28,6 @@ import java.awt.*; import java.awt.peer.*; import java.beans.Beans; -import java.security.PrivilegedAction; import javax.swing.JMenuBar; @@ -59,7 +58,13 @@ static Application sApplication = null; static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("awt")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); checkSecurity(); if (!Beans.isDesignTime()) { diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/eio/FileManager.java --- a/jdk/src/macosx/classes/com/apple/eio/FileManager.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/eio/FileManager.java Wed May 09 13:13:41 2012 -0700 @@ -55,7 +55,13 @@ */ public class FileManager { static { - java.security.AccessController.doPrivileged((java.security.PrivilegedAction)new sun.security.action.LoadLibraryAction("osx")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); } /** diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/laf/AquaFileView.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaFileView.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaFileView.java Wed May 09 13:13:41 2012 -0700 @@ -26,7 +26,6 @@ package com.apple.laf; import java.io.*; -import java.security.PrivilegedAction; import java.util.*; import java.util.Map.Entry; @@ -57,7 +56,13 @@ static final int kLSItemInfoExtensionIsHidden = 0x00100000; /* Item has a hidden extension*/ static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osxui")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osxui"); + return null; + } + }); } // TODO: Un-comment this out when the native version exists diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java Wed May 09 13:13:41 2012 -0700 @@ -134,10 +134,16 @@ * @see UIManager#setLookAndFeel */ public void initialize() { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osxui")); - java.security.AccessController.doPrivileged(new PrivilegedAction(){ + java.security.AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("osxui"); + return null; + } + }); + + java.security.AccessController.doPrivileged(new PrivilegedAction(){ @Override - public Object run() { + public Void run() { JRSUIControl.initJRSUI(); return null; } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/laf/AquaNativeResources.java --- a/jdk/src/macosx/classes/com/apple/laf/AquaNativeResources.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaNativeResources.java Wed May 09 13:13:41 2012 -0700 @@ -27,7 +27,6 @@ import java.awt.*; import java.awt.image.BufferedImage; -import java.security.PrivilegedAction; import javax.swing.plaf.UIResource; @@ -35,7 +34,13 @@ public class AquaNativeResources { static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osxui")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osxui"); + return null; + } + }); } // TODO: removing CColorPaint for now diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java --- a/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java Wed May 09 13:13:41 2012 -0700 @@ -28,7 +28,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.peer.MenuComponentPeer; -import java.security.PrivilegedAction; import java.util.Hashtable; import javax.swing.*; @@ -38,7 +37,13 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, ScreenMenuPropertyHandler { static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("awt")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } // screen menu stuff diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/com/apple/laf/ScreenPopupFactory.java --- a/jdk/src/macosx/classes/com/apple/laf/ScreenPopupFactory.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/com/apple/laf/ScreenPopupFactory.java Wed May 09 13:13:41 2012 -0700 @@ -26,15 +26,19 @@ package com.apple.laf; import java.awt.*; -import java.security.PrivilegedAction; - import javax.swing.*; import sun.lwawt.macosx.CPlatformWindow; class ScreenPopupFactory extends PopupFactory { static { - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("osxui")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osxui"); + return null; + } + }); } static final Float TRANSLUCENT = new Float(248f/255f); diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java --- a/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferences.java Wed May 09 13:13:41 2012 -0700 @@ -25,6 +25,8 @@ package java.util.prefs; +import java.util.Objects; + class MacOSXPreferences extends AbstractPreferences { // fixme need security checks? @@ -147,6 +149,7 @@ // AbstractPreferences implementation protected void removeSpi(String key) { + Objects.requireNonNull(key, "Specified key cannot be null"); file.removeKeyFromNode(path, key); } @@ -228,8 +231,14 @@ if (isRemoved()) throw new IllegalStateException("Node has been removed"); // fixme! overkill - if (!MacOSXPreferencesFile.syncWorld()) { - throw new BackingStoreException("Synchronization failed for node '" + path + "'"); + if (isUser) { + if (!MacOSXPreferencesFile.syncUser()) { + throw new BackingStoreException("Synchronization failed for node '" + path + "'"); + } + } else { + if (!MacOSXPreferencesFile.syncWorld()) { + throw new BackingStoreException("Synchronization failed for node '" + path + "'"); + } } } } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java --- a/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java Wed May 09 13:13:41 2012 -0700 @@ -79,7 +79,13 @@ class MacOSXPreferencesFile { static { - java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("osx")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); } private class FlushTask extends TimerTask { @@ -192,6 +198,39 @@ } + // Sync only current user preferences + static synchronized boolean syncUser() { + boolean ok = true; + if (cachedFiles != null && !cachedFiles.isEmpty()) { + Iterator iter = cachedFiles.values().iterator(); + while (iter.hasNext()) { + WeakReference ref = iter.next(); + MacOSXPreferencesFile f = (MacOSXPreferencesFile)ref.get(); + if (f != null && f.user == cfCurrentUser) { + if (!f.synchronize()) { + ok = false; + } + } else { + iter.remove(); + } + } + } + // Remove synchronized file from changed file list. The changed files were + // guaranteed to have been in the cached file list (because there was a strong + // reference from changedFiles. + if (changedFiles != null) { + Iterator iterChanged = changedFiles.iterator(); + while (iterChanged.hasNext()) { + MacOSXPreferencesFile f = iterChanged.next(); + if (f != null && f.user == cfCurrentUser) + iterChanged.remove(); + } + } + return ok; + } + + + // Write all prefs changes to disk, but do not clear all cached prefs // values. Also kills any scheduled flush task. // There's no CFPreferencesFlush() (), so lots of cached prefs diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java --- a/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java Wed May 09 13:13:41 2012 -0700 @@ -58,9 +58,15 @@ public static void init() { } static { - java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("awt")); - java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); + + java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Void run() { if (isHeadless()) return null; initCocoa(); return null; diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java Wed May 09 13:13:41 2012 -0700 @@ -211,6 +211,15 @@ } @Override + public void replaceSelection(String content) { + getDocument().removeDocumentListener(LWTextAreaPeer.this); + super.replaceSelection(content); + // post only one text event in this case + postTextEvent(); + getDocument().addDocumentListener(LWTextAreaPeer.this); + } + + @Override public boolean hasFocus() { return getTarget().hasFocus(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java Wed May 09 13:13:41 2012 -0700 @@ -187,7 +187,7 @@ } } - private void sendTextEvent(final DocumentEvent e) { + protected final void postTextEvent() { postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); synchronized (getDelegateLock()) { revalidate(); @@ -196,17 +196,17 @@ @Override public final void changedUpdate(final DocumentEvent e) { - sendTextEvent(e); + postTextEvent(); } @Override public final void insertUpdate(final DocumentEvent e) { - sendTextEvent(e); + postTextEvent(); } @Override public final void removeUpdate(final DocumentEvent e) { - sendTextEvent(e); + postTextEvent(); } @Override diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextFieldPeer.java Wed May 09 13:13:41 2012 -0700 @@ -95,7 +95,7 @@ @Override public void actionPerformed(final ActionEvent e) { postEvent(new ActionEvent(getTarget(), ActionEvent.ACTION_PERFORMED, - getText(), e.getWhen(), e.getModifiers())); + getText(), e.getWhen(), e.getModifiers())); } /** @@ -122,6 +122,15 @@ } @Override + public void replaceSelection(String content) { + getDocument().removeDocumentListener(LWTextFieldPeer.this); + super.replaceSelection(content); + // post only one text event in this case + postTextEvent(); + getDocument().addDocumentListener(LWTextFieldPeer.this); + } + + @Override public boolean hasFocus() { return getTarget().hasFocus(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed May 09 13:13:41 2012 -0700 @@ -669,39 +669,42 @@ } } else { if (targetPeer != lastMouseEventPeer) { - // lastMouseEventPeer may be null if mouse was out of Java windows - if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { - // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit - // later), in which case lastWindowPeer is another window - if (lastWindowPeer != this) { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer); - // Additionally translate from this to lastWindowPeer coordinates - Rectangle lr = lastWindowPeer.getBounds(); - oldp.x += r.x - lr.x; - oldp.y += r.y - lr.y; - postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), - MouseEvent.MOUSE_EXITED, + + if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) { + // lastMouseEventPeer may be null if mouse was out of Java windows + if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { + // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit + // later), in which case lastWindowPeer is another window + if (lastWindowPeer != this) { + Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer); + // Additionally translate from this to lastWindowPeer coordinates + Rectangle lr = lastWindowPeer.getBounds(); + oldp.x += r.x - lr.x; + oldp.y += r.y - lr.y; + postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), + MouseEvent.MOUSE_EXITED, + when, modifiers, + oldp.x, oldp.y, screenX, screenY, + clickCount, popupTrigger, button)); + } else { + Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); + postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), + MouseEvent.MOUSE_EXITED, + when, modifiers, + oldp.x, oldp.y, screenX, screenY, + clickCount, popupTrigger, button)); + } + } + if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) { + Point newp = targetPeer.windowToLocal(x, y, curWindowPeer); + postEvent(new MouseEvent(targetPeer.getTarget(), + MouseEvent.MOUSE_ENTERED, when, modifiers, - oldp.x, oldp.y, screenX, screenY, - clickCount, popupTrigger, button)); - } else { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); - postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), - MouseEvent.MOUSE_EXITED, - when, modifiers, - oldp.x, oldp.y, screenX, screenY, + newp.x, newp.y, screenX, screenY, clickCount, popupTrigger, button)); } } lastMouseEventPeer = targetPeer; - if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) { - Point newp = targetPeer.windowToLocal(x, y, curWindowPeer); - postEvent(new MouseEvent(targetPeer.getTarget(), - MouseEvent.MOUSE_ENTERED, - when, modifiers, - newp.x, newp.y, screenX, screenY, - clickCount, popupTrigger, button)); - } } // TODO: fill "bdata" member of AWTEvent diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/macosx/CAccessibility.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CAccessibility.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CAccessibility.java Wed May 09 13:13:41 2012 -0700 @@ -29,7 +29,6 @@ import java.beans.*; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; -import java.security.PrivilegedAction; import java.util.*; import java.util.concurrent.Callable; @@ -41,7 +40,13 @@ static { // Need to load the native library for this code. - java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.LoadLibraryAction("awt")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } static CAccessibility sAccessibility; diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CCursorManager.java Wed May 09 13:13:41 2012 -0700 @@ -36,6 +36,7 @@ private static native Point2D nativeGetCursorPosition(); private static native void nativeSetBuiltInCursor(final int type, final String name); private static native void nativeSetCustomCursor(final long imgPtr, final double x, final double y); + public static native void nativeSetAllowsCursorSetInBackground(final boolean allows); private static final int NAMED_CURSOR = -1; diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Wed May 09 13:13:41 2012 -0700 @@ -76,6 +76,12 @@ int screenX = locationOnScreen.x + x; int screenY = locationOnScreen.y + y; + if (eventType == CocoaConstants.NPCocoaEventMouseEntered) { + CCursorManager.nativeSetAllowsCursorSetInBackground(true); + } else if (eventType == CocoaConstants.NPCocoaEventMouseExited) { + CCursorManager.nativeSetAllowsCursorSetInBackground(false); + } + responder.handleMouseEvent(eventType, modifierFlags, buttonNumber, clickCount, x, y, screenX, screenY); } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed May 09 13:13:41 2012 -0700 @@ -61,6 +61,7 @@ private static native void nativeSetNSWindowMinimizedIcon(long nsWindowPtr, long nsImage); private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY); + private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr); private static native int nativeGetScreenNSWindowIsOn_AppKitThread(long nsWindowPtr); @@ -582,6 +583,8 @@ } } + nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + // 6. Configure stuff #2 updateFocusabilityForAutoRequestFocus(true); @@ -791,6 +794,8 @@ throw new RuntimeException("Unknown window state: " + windowState); } + nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + // NOTE: the SWP.windowState field gets updated to the newWindowState // value when the native notification comes to us } diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -656,6 +656,14 @@ return ((mods & (InputEvent.META_MASK | InputEvent.CTRL_MASK)) == 0); } + /** + * Returns whether popup is allowed to be shown above the task bar. + */ + @Override + public boolean canPopupOverlapTaskBar() { + 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 { diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/AWTView.h --- a/jdk/src/macosx/native/sun/awt/AWTView.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTView.h Wed May 09 13:13:41 2012 -0700 @@ -52,9 +52,12 @@ BOOL fPAHNeedsToSelect; id cglLayer; // is a sublayer of view.layer + + BOOL mouseIsOver; } @property (nonatomic, retain) id cglLayer; +@property (nonatomic) BOOL mouseIsOver; - (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer; - (void) deliverJavaMouseEvent: (NSEvent *) event; diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/AWTView.m --- a/jdk/src/macosx/native/sun/awt/AWTView.m Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTView.m Wed May 09 13:13:41 2012 -0700 @@ -61,6 +61,7 @@ @synthesize _dropTarget; @synthesize _dragSource; @synthesize cglLayer; +@synthesize mouseIsOver; // Note: Must be called on main (AppKit) thread only - (id) initWithRect: (NSRect) rect @@ -80,6 +81,8 @@ fEnablePressAndHold = shouldUsePressAndHold(); fInPressAndHold = NO; fPAHNeedsToSelect = NO; + + mouseIsOver = NO; if (windowLayer != nil) { self.cglLayer = windowLayer; @@ -299,6 +302,16 @@ */ -(void) deliverJavaMouseEvent: (NSEvent *) event { + + NSEventType type = [event type]; + + // check synthesized mouse entered/exited events + if ((type == NSMouseEntered && mouseIsOver) || (type == NSMouseExited && !mouseIsOver)) { + return; + }else if ((type == NSMouseEntered && !mouseIsOver) || (type == NSMouseExited && mouseIsOver)) { + mouseIsOver = !mouseIsOver; + } + [AWTToolkit eventCountPlusPlus]; JNIEnv *env = [ThreadUtilities getJNIEnv]; @@ -306,7 +319,6 @@ NSPoint eventLocation = [event locationInWindow]; NSPoint localPoint = [self convertPoint: eventLocation fromView: nil]; NSPoint absP = [NSEvent mouseLocation]; - NSEventType type = [event type]; // Convert global numbers between Cocoa's coordinate system and Java. // TODO: need consitent way for doing that both with global as well as with local coordinates. diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/AWTWindow.h --- a/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.h Wed May 09 13:13:41 2012 -0700 @@ -56,6 +56,7 @@ contentView:(NSView *)contentView; - (void) adjustGrowBoxWindow; +- (BOOL) isTopmostWindowUnderMouse; @end #endif _AWTWINDOW_H diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/AWTWindow.m --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Wed May 09 13:13:41 2012 -0700 @@ -170,6 +170,66 @@ return self; } +// checks that this window is under the mouse cursor and this point is not overlapped by others windows +- (BOOL) isTopmostWindowUnderMouse { + + int currentWinID = [self windowNumber]; + + NSRect screenRect = [[NSScreen mainScreen] frame]; + NSPoint nsMouseLocation = [NSEvent mouseLocation]; + CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y); + + NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); + + + for (NSDictionary *window in windows) { + int layer = [[window objectForKey:(id)kCGWindowLayer] intValue]; + if (layer == 0) { + int winID = [[window objectForKey:(id)kCGWindowNumber] intValue]; + CGRect rect; + CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect); + if (CGRectContainsPoint(rect, cgMouseLocation)) { + return currentWinID == winID; + } else if (currentWinID == winID) { + return NO; + } + } + } + return NO; +} + +- (void) synthesizeMouseEnteredExitedEvents { + + int eventType = 0; + BOOL isUnderMouse = [self isTopmostWindowUnderMouse]; + BOOL mouseIsOver = [[self contentView] mouseIsOver]; + + if (isUnderMouse && !mouseIsOver) { + eventType = NSMouseEntered; + } else if (!isUnderMouse && mouseIsOver) { + eventType = NSMouseExited; + } else { + return; + } + + NSPoint screenLocation = [NSEvent mouseLocation]; + NSPoint windowLocation = [self convertScreenToBase: screenLocation]; + int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask; + + NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType + location: windowLocation + modifierFlags: modifierFlags + timestamp: 0 + windowNumber: [self windowNumber] + context: nil + eventNumber: 0 + trackingNumber: 0 + userData: nil + ]; + + [[self contentView] deliverJavaMouseEvent: mouseEvent]; +} + - (void) dealloc { AWT_ASSERT_APPKIT_THREAD; @@ -669,6 +729,8 @@ // ensure we repaint the whole window after the resize operation // (this will also re-enable screen updates, which were disabled above) // TODO: send PaintEvent + + [window synthesizeMouseEnteredExitedEvents]; }]; JNF_COCOA_EXIT(env); @@ -899,6 +961,27 @@ /* * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeSynthesizeMouseEnteredExitedEvents + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents +(JNIEnv *env, jclass clazz, jlong windowPtr) +{ + JNF_COCOA_ENTER(env); + AWT_ASSERT_NOT_APPKIT_THREAD; + + AWTWindow *window = OBJC(windowPtr); + [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + AWT_ASSERT_APPKIT_THREAD; + + [window synthesizeMouseEnteredExitedEvents]; + }]; + + JNF_COCOA_EXIT(env); +} + +/* + * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeGetScreenNSWindowIsOn_AppKitThread * Signature: (J)I */ diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/CCursorManager.m --- a/jdk/src/macosx/native/sun/awt/CCursorManager.m Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/CCursorManager.m Wed May 09 13:13:41 2012 -0700 @@ -137,3 +137,30 @@ return jpt; } + + +JNIEXPORT void JNICALL +Java_sun_lwawt_macosx_CCursorManager_nativeSetAllowsCursorSetInBackground +(JNIEnv *env, jclass class, jboolean allows) +{ + +JNF_COCOA_ENTER(env); +AWT_ASSERT_NOT_APPKIT_THREAD; + + SEL allowsSetInBackground_SEL = @selector(javaSetAllowsCursorSetInBackground:); + if ([[NSCursor class] respondsToSelector:allowsSetInBackground_SEL]) { + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + NSMethodSignature *allowsSetInBackground_sig = + [[NSCursor class] methodSignatureForSelector:allowsSetInBackground_SEL]; + NSInvocation *invocation = + [NSInvocation invocationWithMethodSignature:allowsSetInBackground_sig]; + BOOL arg = (BOOL)allows; + [invocation setSelector:allowsSetInBackground_SEL]; + [invocation setArgument:&arg atIndex:2]; + [invocation invokeWithTarget:[NSCursor class]]; + }]; + } + +JNF_COCOA_EXIT(env); + +} diff -r 070b00370cae -r 5904985dac0a jdk/src/macosx/native/sun/awt/PrinterView.m --- a/jdk/src/macosx/native/sun/awt/PrinterView.m Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/macosx/native/sun/awt/PrinterView.m Wed May 09 13:13:41 2012 -0700 @@ -27,6 +27,7 @@ #import "java_awt_print_Pageable.h" #import "java_awt_print_Printable.h" +#import "java_awt_print_PageFormat.h" #import @@ -35,6 +36,7 @@ static JNF_CLASS_CACHE(sjc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob"); +static JNF_CLASS_CACHE(sjc_PageFormat, "java/awt/print/PageFormat"); @implementation PrinterView @@ -152,6 +154,7 @@ static JNF_MEMBER_CACHE(jm_getPageformatPrintablePeekgraphics, sjc_CPrinterJob, "getPageformatPrintablePeekgraphics", "(I)[Ljava/lang/Object;"); static JNF_MEMBER_CACHE(jm_printAndGetPageFormatArea, sjc_CPrinterJob, "printAndGetPageFormatArea", "(Ljava/awt/print/Printable;Ljava/awt/Graphics;Ljava/awt/print/PageFormat;I)Ljava/awt/geom/Rectangle2D;"); + static JNF_MEMBER_CACHE(jm_getOrientation, sjc_PageFormat, "getOrientation", "()I"); // Assertions removed, and corresponding JNFDeleteGlobalRefs added, for radr://3962543 // Actual fix that will keep these assertions from being true is radr://3205462 , @@ -201,6 +204,26 @@ // Actually print and get the PageFormatArea jobject pageFormatArea = JNFCallObjectMethod(env, fPrinterJob, jm_printAndGetPageFormatArea, fCurPainter, fCurPeekGraphics, fCurPageFormat, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode) if (pageFormatArea != NULL) { + NSPrintingOrientation currentOrientation = + [[[NSPrintOperation currentOperation] printInfo] orientation]; + // set page orientation + switch (JNFCallIntMethod(env, fCurPageFormat, jm_getOrientation)) { + case java_awt_print_PageFormat_PORTRAIT: + default: + if (currentOrientation != NSPortraitOrientation) { + [[[NSPrintOperation currentOperation] printInfo] + setOrientation:NSPortraitOrientation]; + } + break; + + case java_awt_print_PageFormat_LANDSCAPE: + case java_awt_print_PageFormat_REVERSE_LANDSCAPE: + if (currentOrientation != NSLandscapeOrientation) { + [[[NSPrintOperation currentOperation] printInfo] + setOrientation:NSLandscapeOrientation]; + } + break; + } result = JavaToNSRect(env, pageFormatArea); (*env)->DeleteLocalRef(env, pageFormatArea); } else { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/bin/java.c --- a/jdk/src/share/bin/java.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/bin/java.c Wed May 09 13:13:41 2012 -0700 @@ -695,6 +695,13 @@ char *def; const char *orig = s; static const char format[] = "-Djava.class.path=%s"; + /* + * usually we should not get a null pointer, but there are cases where + * we might just get one, in which case we simply ignore it, and let the + * caller deal with it + */ + if (s == NULL) + return; s = JLI_WildcardExpandClasspath(s); def = JLI_MemAlloc(sizeof(format) - 2 /* strlen("%s") */ diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java Wed May 09 13:13:41 2012 -0700 @@ -87,7 +87,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("jpeg")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("jpeg"); + return null; + } + }); initReaderIDs(ImageInputStream.class, JPEGQTable.class, JPEGHuffmanTable.class); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java Wed May 09 13:13:41 2012 -0700 @@ -177,7 +177,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("jpeg")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("jpeg"); + return null; + } + }); initWriterIDs(ImageOutputStream.class, JPEGQTable.class, JPEGHuffmanTable.class); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Attribute.java Wed May 09 13:13:41 2012 -0700 @@ -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 @@ -166,6 +166,7 @@ define(sd, ATTR_CONTEXT_CLASS, "SourceFile", "RUH"); define(sd, ATTR_CONTEXT_CLASS, "EnclosingMethod", "RCHRDNH"); define(sd, ATTR_CONTEXT_CLASS, "InnerClasses", "NH[RCHRCNHRUNHFH]"); + define(sd, ATTR_CONTEXT_CLASS, "BootstrapMethods", "NH[RMHNH[KLH]]"); define(sd, ATTR_CONTEXT_FIELD, "Signature", "RSH"); define(sd, ATTR_CONTEXT_FIELD, "Synthetic", ""); @@ -203,6 +204,8 @@ // Their layout specs. are given here for completeness. // The Code spec is incomplete, in that it does not distinguish // bytecode bytes or locate CP references. + // The BootstrapMethods attribute is also special-cased + // elsewhere as an appendix to the local constant pool. } // Metadata. @@ -822,9 +825,9 @@ reference_type: ( constant_ref | schema_ref | utf8_ref | untyped_ref ) constant_ref: - ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' ) + ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' ) schema_ref: - ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' ) + ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' ) utf8_ref: 'RU' untyped_ref: @@ -1012,7 +1015,12 @@ case 'F': e.refKind = CONSTANT_Float; break; case 'D': e.refKind = CONSTANT_Double; break; case 'S': e.refKind = CONSTANT_String; break; - case 'Q': e.refKind = CONSTANT_Literal; break; + case 'Q': e.refKind = CONSTANT_FieldSpecific; break; + + // new in 1.7: + case 'M': e.refKind = CONSTANT_MethodHandle; break; + case 'T': e.refKind = CONSTANT_MethodType; break; + case 'L': e.refKind = CONSTANT_LoadableValue; break; default: { i = -i; continue; } // fail } break; @@ -1029,6 +1037,11 @@ case 'U': e.refKind = CONSTANT_Utf8; break; //utf8_ref case 'Q': e.refKind = CONSTANT_All; break; //untyped_ref + // new in 1.7: + case 'Y': e.refKind = CONSTANT_InvokeDynamic; break; + case 'B': e.refKind = CONSTANT_BootstrapMethod; break; + case 'N': e.refKind = CONSTANT_AnyMember; break; + default: { i = -i; continue; } // fail } break; @@ -1279,10 +1292,12 @@ // Cf. ClassReader.readSignatureRef. String typeName = globalRef.stringValue(); globalRef = ConstantPool.getSignatureEntry(typeName); - } else if (e.refKind == CONSTANT_Literal) { + } else if (e.refKind == CONSTANT_FieldSpecific) { assert(globalRef.getTag() >= CONSTANT_Integer); - assert(globalRef.getTag() <= CONSTANT_String); - } else if (e.refKind != CONSTANT_All) { + assert(globalRef.getTag() <= CONSTANT_String || + globalRef.getTag() >= CONSTANT_MethodHandle); + assert(globalRef.getTag() <= CONSTANT_MethodType); + } else if (e.refKind < CONSTANT_GroupFirst) { assert(e.refKind == globalRef.getTag()); } } @@ -1462,27 +1477,29 @@ "NH[PHPOHIIH]", // CharacterRangeTable "NH[PHHII]", // CoverageTable "NH[RCHRCNHRUNHFH]", // InnerClasses + "NH[RMHNH[KLH]]", // BootstrapMethods "HHNI[B]NH[PHPOHPOHRCNH]NH[RUHNI[B]]", // Code "=AnnotationDefault", // Like metadata, but with a compact tag set: "[NH[(1)]]" - +"[NH[(2)]]" - +"[RSHNH[RUH(3)]]" - +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(2)](6)[NH[(3)]]()[]]", + +"[NH[(1)]]" + +"[RSHNH[RUH(1)]]" + +"[TB(0,1,3)[KIH](2)[KDH](5)[KFH](4)[KJH](7)[RSH](8)[RSHRUH](9)[RUH](10)[(-1)](6)[NH[(0)]]()[]]", "" }; ap = 0; } + Utils.currentInstance.set(new PackerImpl()); final int[][] counts = new int[2][3]; // int bci ref final Entry[] cpMap = new Entry[maxVal+1]; for (int i = 0; i < cpMap.length; i++) { if (i == 0) continue; // 0 => null cpMap[i] = ConstantPool.getLiteralEntry(new Integer(i)); } - Class cls = new Package().new Class(""); + Package.Class cls = new Package().new Class(""); cls.cpMap = cpMap; class TestValueStream extends ValueStream { - Random rand = new Random(0); + java.util.Random rand = new java.util.Random(0); ArrayList history = new ArrayList(); int ckidx = 0; int maxVal; @@ -1570,8 +1587,7 @@ String layout = av[i]; if (layout.startsWith("=")) { String name = layout.substring(1); - for (Iterator j = standardDefs.values().iterator(); j.hasNext(); ) { - Attribute a = (Attribute) j.next(); + for (Attribute a : standardDefs.values()) { if (a.name().equals(name)) { layout = a.layout().layout(); break; @@ -1604,7 +1620,7 @@ if (verbose) { System.out.print(" parse: {"); } - self.parse(0, cls, bytes, 0, bytes.length, tts); + self.parse(cls, bytes, 0, bytes.length, tts); if (verbose) { System.out.println("}"); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -1372,17 +1372,17 @@ protected long archiveSize1; // size reported in archive_header protected int archiveNextCount; // reported in archive_header - static final int AH_LENGTH_0 = 3; //minver, majver, options - static final int AH_ARCHIVE_SIZE_HI = 0; - static final int AH_ARCHIVE_SIZE_LO = 1; - static final int AH_LENGTH_S = 2; //optional size hi/lo - static final int AH_LENGTH = 26; // mentioned in spec + static final int AH_LENGTH_0 = 3; // archive_header_0 = {minver, majver, options} + static final int AH_LENGTH_MIN = 15; // observed in spec {header_0[3], cp_counts[8], class_counts[4]} + // Length contributions from optional archive size fields: + static final int AH_LENGTH_S = 2; // archive_header_S = optional {size_hi, size_lo} + static final int AH_ARCHIVE_SIZE_HI = 0; // offset in archive_header_S + static final int AH_ARCHIVE_SIZE_LO = 1; // offset in archive_header_S // Length contributions from optional header fields: - static final int AH_FILE_HEADER_LEN = 5; // sizehi/lo/next/modtime/files - static final int AH_SPECIAL_FORMAT_LEN = 2; // layouts/band-headers - static final int AH_CP_NUMBER_LEN = 4; // int/float/long/double - static final int AH_LENGTH_MIN = AH_LENGTH - -(AH_SPECIAL_FORMAT_LEN+AH_FILE_HEADER_LEN+AH_CP_NUMBER_LEN); + static final int AH_FILE_HEADER_LEN = 5; // file_counts = {{size_hi, size_lo}, next, modtime, files} + static final int AH_SPECIAL_FORMAT_LEN = 2; // special_counts = {layouts, band_headers} + static final int AH_CP_NUMBER_LEN = 4; // cp_number_counts = {int, float, long, double} + static final int AH_CP_EXTRA_LEN = 4; // cp_attr_counts = {MH, MT, InDy, BSM} // Common structure of attribute band groups: static final int AB_FLAGS_HI = 0; @@ -1446,6 +1446,14 @@ CPRefBand cp_Method_desc = cp_bands.newCPRefBand("cp_Method_desc", UDELTA5, CONSTANT_NameandType); CPRefBand cp_Imethod_class = cp_bands.newCPRefBand("cp_Imethod_class", CONSTANT_Class); CPRefBand cp_Imethod_desc = cp_bands.newCPRefBand("cp_Imethod_desc", UDELTA5, CONSTANT_NameandType); + IntBand cp_MethodHandle_refkind = cp_bands.newIntBand("cp_MethodHandle_refkind", DELTA5); + CPRefBand cp_MethodHandle_member = cp_bands.newCPRefBand("cp_MethodHandle_member", UDELTA5, CONSTANT_AnyMember); + CPRefBand cp_MethodType = cp_bands.newCPRefBand("cp_MethodType", UDELTA5, CONSTANT_Signature); + CPRefBand cp_BootstrapMethod_ref = cp_bands.newCPRefBand("cp_BootstrapMethod_ref", DELTA5, CONSTANT_MethodHandle); + IntBand cp_BootstrapMethod_arg_count = cp_bands.newIntBand("cp_BootstrapMethod_arg_count", UDELTA5); + CPRefBand cp_BootstrapMethod_arg = cp_bands.newCPRefBand("cp_BootstrapMethod_arg", DELTA5, CONSTANT_LoadableValue); + CPRefBand cp_InvokeDynamic_spec = cp_bands.newCPRefBand("cp_InvokeDynamic_spec", DELTA5, CONSTANT_BootstrapMethod); + CPRefBand cp_InvokeDynamic_desc = cp_bands.newCPRefBand("cp_InvokeDynamic_desc", UDELTA5, CONSTANT_NameandType); // bands for carrying attribute definitions: MultiBand attr_definition_bands = all_bands.newMultiBand("(attr_definition_bands)", UNSIGNED5); @@ -1481,7 +1489,7 @@ IntBand field_attr_calls = field_attr_bands.newIntBand("field_attr_calls"); // bands for predefined field attributes - CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_Literal); + CPRefBand field_ConstantValue_KQ = field_attr_bands.newCPRefBand("field_ConstantValue_KQ", CONSTANT_FieldSpecific); CPRefBand field_Signature_RS = field_attr_bands.newCPRefBand("field_Signature_RS", CONSTANT_Signature); MultiBand field_metadata_bands = field_attr_bands.newMultiBand("(field_metadata_bands)", UNSIGNED5); @@ -1585,12 +1593,14 @@ CPRefBand bc_longref = bc_bands.newCPRefBand("bc_longref", DELTA5, CONSTANT_Long); CPRefBand bc_doubleref = bc_bands.newCPRefBand("bc_doubleref", DELTA5, CONSTANT_Double); CPRefBand bc_stringref = bc_bands.newCPRefBand("bc_stringref", DELTA5, CONSTANT_String); + CPRefBand bc_loadablevalueref = bc_bands.newCPRefBand("bc_loadablevalueref", DELTA5, CONSTANT_LoadableValue); // nulls produced by bc_classref are taken to mean the current class CPRefBand bc_classref = bc_bands.newCPRefBand("bc_classref", UNSIGNED5, CONSTANT_Class, NULL_IS_OK); // new, *anew*, c*cast, i*of, ldc CPRefBand bc_fieldref = bc_bands.newCPRefBand("bc_fieldref", DELTA5, CONSTANT_Fieldref); // get*, put* CPRefBand bc_methodref = bc_bands.newCPRefBand("bc_methodref", CONSTANT_Methodref); // invoke[vs]* CPRefBand bc_imethodref = bc_bands.newCPRefBand("bc_imethodref", DELTA5, CONSTANT_InterfaceMethodref); // invokeinterface + CPRefBand bc_indyref = bc_bands.newCPRefBand("bc_indyref", DELTA5, CONSTANT_InvokeDynamic); // invokedynamic // _self_linker_op family CPRefBand bc_thisfield = bc_bands.newCPRefBand("bc_thisfield", CONSTANT_None); // any field within cur. class @@ -1633,7 +1643,7 @@ protected void setBandIndex(CPRefBand b, byte which) { Object[] need = { b, Byte.valueOf(which) }; - if (which == CONSTANT_Literal) { + if (which == CONSTANT_FieldSpecific) { // I.e., attribute layouts KQ (no null) or KQN (null ok). allKQBands.add(b); } else if (needPredefIndex != null) { @@ -1856,12 +1866,20 @@ attrClassFileVersionMask = (1< 0) Utils.log.fine("Legacy package version"); // Revoke definition of pre-1.6 attribute type. undefineAttribute(CODE_ATTR_StackMapTable, ATTR_CONTEXT_CODE); } + if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) { + if (testBit(archiveOptions, AO_HAVE_CP_EXTRAS)) + // this bit was reserved for future use in previous versions + throw new IOException("Format bits for Java 7 must be zero in previous releases"); + } + if (testBit(archiveOptions, AO_UNUSED_MBZ)) { + throw new IOException("High archive option bits are reserved and must be zero: "+Integer.toHexString(archiveOptions)); + } } protected void initAttrIndexLimit() { @@ -2323,7 +2341,9 @@ return bc_methodref; case CONSTANT_InterfaceMethodref: return bc_imethodref; - case CONSTANT_Literal: + case CONSTANT_InvokeDynamic: + return bc_indyref; + case CONSTANT_LoadableValue: switch (bc) { case _ildc: case _ildc_w: return bc_intref; @@ -2333,10 +2353,12 @@ return bc_longref; case _dldc2_w: return bc_doubleref; - case _aldc: case _aldc_w: + case _sldc: case _sldc_w: return bc_stringref; case _cldc: case _cldc_w: return bc_classref; + case _qldc: case _qldc_w: + return bc_loadablevalueref; } break; } @@ -2623,15 +2645,23 @@ } static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end) { + printArrayTo(ps, cpMap, start, end, false); + } + static void printArrayTo(PrintStream ps, Entry[] cpMap, int start, int end, boolean showTags) { StringBuffer buf = new StringBuffer(); int len = end-start; for (int i = 0; i < len; i++) { - String s = cpMap[start+i].stringValue(); + Entry e = cpMap[start+i]; + ps.print(start+i); ps.print("="); + if (showTags) { ps.print(e.tag); ps.print(":"); } + String s = e.stringValue(); buf.setLength(0); for (int j = 0; j < s.length(); j++) { char ch = s.charAt(j); if (!(ch < ' ' || ch > '~' || ch == '\\')) { buf.append(ch); + } else if (ch == '\\') { + buf.append("\\\\"); } else if (ch == '\n') { buf.append("\\n"); } else if (ch == '\t') { @@ -2639,7 +2669,8 @@ } else if (ch == '\r') { buf.append("\\r"); } else { - buf.append("\\x"+Integer.toHexString(ch)); + String str = "000"+Integer.toHexString(ch); + buf.append("\\u"+str.substring(str.length()-4)); } } ps.println(buf); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,9 @@ import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; import com.sun.java.util.jar.pack.ConstantPool.Entry; import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; +import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; +import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; +import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.InnerClass; @@ -37,6 +40,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Map; import static com.sun.java.util.jar.pack.Constants.*; @@ -114,6 +118,7 @@ private Entry readRef(byte tag) throws IOException { Entry e = readRef(); assert(e != null); + assert(!(e instanceof UnresolvedEntry)); assert(e.tagMatches(tag)); return e; } @@ -151,6 +156,7 @@ readMembers(false); // fields readMembers(true); // methods readAttributes(ATTR_CONTEXT_CLASS, cls); + fixUnresolvedEntries(); cls.finishReading(); assert(0 >= in.read(new byte[1])); ok = true; @@ -236,6 +242,7 @@ // just read the refs; do not attempt to resolve while reading case CONSTANT_Class: case CONSTANT_String: + case CONSTANT_MethodType: fixups[fptr++] = i; fixups[fptr++] = tag; fixups[fptr++] = in.readUnsignedShort(); @@ -250,6 +257,18 @@ fixups[fptr++] = in.readUnsignedShort(); fixups[fptr++] = in.readUnsignedShort(); break; + case CONSTANT_InvokeDynamic: + fixups[fptr++] = i; + fixups[fptr++] = tag; + fixups[fptr++] = -1 ^ in.readUnsignedShort(); // not a ref + fixups[fptr++] = in.readUnsignedShort(); + break; + case CONSTANT_MethodHandle: + fixups[fptr++] = i; + fixups[fptr++] = tag; + fixups[fptr++] = -1 ^ in.readUnsignedByte(); + fixups[fptr++] = in.readUnsignedShort(); + break; default: throw new ClassFormatException("Bad constant pool tag " + tag + " in File: " + cls.file.nameString + @@ -270,7 +289,7 @@ int ref2 = fixups[fi++]; if (verbose > 3) Utils.log.fine(" cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}"); - if (cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) { + if (ref >= 0 && cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) { // Defer. fixups[fptr++] = cpi; fixups[fptr++] = tag; @@ -297,6 +316,19 @@ Utf8Entry mtype = (Utf8Entry) cpMap[ref2]; cpMap[cpi] = ConstantPool.getDescriptorEntry(mname, mtype); break; + case CONSTANT_MethodType: + cpMap[cpi] = ConstantPool.getMethodTypeEntry((Utf8Entry) cpMap[ref]); + break; + case CONSTANT_MethodHandle: + byte refKind = (byte)(-1 ^ ref); + MemberEntry memRef = (MemberEntry) cpMap[ref2]; + cpMap[cpi] = ConstantPool.getMethodHandleEntry(refKind, memRef); + break; + case CONSTANT_InvokeDynamic: + DescriptorEntry idescr = (DescriptorEntry) cpMap[ref2]; + cpMap[cpi] = new UnresolvedEntry((byte)tag, (-1 ^ ref), idescr); + // Note that ref must be resolved later, using the BootstrapMethods attribute. + break; default: assert(false); } @@ -307,6 +339,50 @@ cls.cpMap = cpMap; } + private /*non-static*/ + class UnresolvedEntry extends Entry { + final Object[] refsOrIndexes; + UnresolvedEntry(byte tag, Object... refsOrIndexes) { + super(tag); + this.refsOrIndexes = refsOrIndexes; + ClassReader.this.haveUnresolvedEntry = true; + } + Entry resolve() { + Class cls = ClassReader.this.cls; + Entry res; + switch (tag) { + case CONSTANT_InvokeDynamic: + BootstrapMethodEntry iboots = cls.bootstrapMethods.get((Integer) refsOrIndexes[0]); + DescriptorEntry idescr = (DescriptorEntry) refsOrIndexes[1]; + res = ConstantPool.getInvokeDynamicEntry(iboots, idescr); + break; + default: + throw new AssertionError(); + } + return res; + } + private void unresolved() { throw new RuntimeException("unresolved entry has no string"); } + public int compareTo(Object x) { unresolved(); return 0; } + public boolean equals(Object x) { unresolved(); return false; } + protected int computeValueHash() { unresolved(); return 0; } + public String stringValue() { unresolved(); return toString(); } + public String toString() { return "(unresolved "+ConstantPool.tagName(tag)+")"; } + } + + boolean haveUnresolvedEntry; + private void fixUnresolvedEntries() { + if (!haveUnresolvedEntry) return; + Entry[] cpMap = cls.getCPMap(); + for (int i = 0; i < cpMap.length; i++) { + Entry e = cpMap[i]; + if (e instanceof UnresolvedEntry) { + cpMap[i] = e = ((UnresolvedEntry)e).resolve(); + assert(!(e instanceof UnresolvedEntry)); + } + } + haveUnresolvedEntry = false; + } + void readHeader() throws IOException { cls.flags = readUnsignedShort(); cls.thisClass = readClassRef(); @@ -416,25 +492,31 @@ unknownAttrCommand); } } - if (a.layout() == Package.attrCodeEmpty || - a.layout() == Package.attrInnerClassesEmpty) { + long pos0 = inPos; // in case we want to check it + if (a.layout() == Package.attrCodeEmpty) { // These are hardwired. - long pos0 = inPos; - if ("Code".equals(a.name())) { - Class.Method m = (Class.Method) h; - m.code = new Code(m); - try { - readCode(m.code); - } catch (Instruction.FormatException iie) { - String message = iie.getMessage() + " in " + h; - throw new ClassReader.ClassFormatException(message, iie); - } - } else { - assert(h == cls); - readInnerClasses(cls); + Class.Method m = (Class.Method) h; + m.code = new Code(m); + try { + readCode(m.code); + } catch (Instruction.FormatException iie) { + String message = iie.getMessage() + " in " + h; + throw new ClassReader.ClassFormatException(message, iie); } assert(length == inPos - pos0); // Keep empty attribute a... + } else if (a.layout() == Package.attrBootstrapMethodsEmpty) { + assert(h == cls); + readBootstrapMethods(cls); + assert(length == inPos - pos0); + // Delete the attribute; it is logically part of the constant pool. + continue; + } else if (a.layout() == Package.attrInnerClassesEmpty) { + // These are hardwired also. + assert(h == cls); + readInnerClasses(cls); + assert(length == inPos - pos0); + // Keep empty attribute a... } else if (length > 0) { byte[] bytes = new byte[length]; in.readFully(bytes); @@ -467,6 +549,19 @@ readAttributes(ATTR_CONTEXT_CODE, code); } + void readBootstrapMethods(Class cls) throws IOException { + BootstrapMethodEntry[] bsms = new BootstrapMethodEntry[readUnsignedShort()]; + for (int i = 0; i < bsms.length; i++) { + MethodHandleEntry bsmRef = (MethodHandleEntry) readRef(CONSTANT_MethodHandle); + Entry[] argRefs = new Entry[readUnsignedShort()]; + for (int j = 0; j < argRefs.length; j++) { + argRefs[j] = readRef(); + } + bsms[i] = ConstantPool.getBootstrapMethodEntry(bsmRef, argRefs); + } + cls.setBootstrapMethods(Arrays.asList(bsms)); + } + void readInnerClasses(Class cls) throws IOException { int nc = readUnsignedShort(); ArrayList ics = new ArrayList<>(nc); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ClassWriter.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import com.sun.java.util.jar.pack.ConstantPool.Entry; import com.sun.java.util.jar.pack.ConstantPool.Index; import com.sun.java.util.jar.pack.ConstantPool.NumberEntry; +import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; +import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.InnerClass; import java.io.BufferedOutputStream; @@ -49,6 +51,7 @@ Class cls; DataOutputStream out; Index cpIndex; + Index bsmIndex; ClassWriter(Class cls, OutputStream out) throws IOException { this.pkg = cls.getPackage(); @@ -57,6 +60,10 @@ this.out = new DataOutputStream(new BufferedOutputStream(out)); this.cpIndex = ConstantPool.makeIndex(cls.toString(), cls.getCPMap()); this.cpIndex.flattenSigs = true; + if (cls.hasBootstrapMethods()) { + this.bsmIndex = ConstantPool.makeIndex(cpIndex.debugName+".BootstrapMethods", + cls.getBootstrapMethodMap()); + } if (verbose > 1) Utils.log.fine("local CP="+(verbose > 2 ? cpIndex.dumpString() : cpIndex.toString())); } @@ -71,6 +78,11 @@ /** Write a 2-byte int representing a CP entry, using the local cpIndex. */ private void writeRef(Entry e) throws IOException { + writeRef(e, cpIndex); + } + + /** Write a 2-byte int representing a CP entry, using the given cpIndex. */ + private void writeRef(Entry e, Index cpIndex) throws IOException { int i = (e == null) ? 0 : cpIndex.indexOf(e); writeShort(i); } @@ -117,8 +129,7 @@ out.write(tag); switch (tag) { case CONSTANT_Signature: - assert(false); // should not reach here - break; + throw new AssertionError("CP should have Signatures remapped to Utf8"); case CONSTANT_Utf8: out.writeUTF(e.stringValue()); break; @@ -138,8 +149,14 @@ break; case CONSTANT_Class: case CONSTANT_String: + case CONSTANT_MethodType: writeRef(e.getRef(0)); break; + case CONSTANT_MethodHandle: + MethodHandleEntry mhe = (MethodHandleEntry) e; + out.writeByte(mhe.refKind); + writeRef(mhe.getRef(0)); + break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: @@ -147,6 +164,12 @@ writeRef(e.getRef(0)); writeRef(e.getRef(1)); break; + case CONSTANT_InvokeDynamic: + writeRef(e.getRef(0), bsmIndex); + writeRef(e.getRef(1)); + break; + case CONSTANT_BootstrapMethod: + throw new AssertionError("CP should have BootstrapMethods moved to side-table"); default: throw new IOException("Bad constant pool tag "+tag); } @@ -198,6 +221,7 @@ a.finishRefs(cpIndex); writeRef(a.getNameRef()); if (a.layout() == Package.attrCodeEmpty || + a.layout() == Package.attrBootstrapMethodsEmpty || a.layout() == Package.attrInnerClassesEmpty) { // These are hardwired. DataOutputStream savedOut = out; @@ -207,9 +231,14 @@ if ("Code".equals(a.name())) { Class.Method m = (Class.Method) h; writeCode(m.code); - } else { + } else if ("BootstrapMethods".equals(a.name())) { + assert(h == cls); + writeBootstrapMethods(cls); + } else if ("InnerClasses".equals(a.name())) { assert(h == cls); writeInnerClasses(cls); + } else { + throw new AssertionError(); } out = savedOut; if (verbose > 2) @@ -242,6 +271,18 @@ writeAttributes(ATTR_CONTEXT_CODE, code); } + void writeBootstrapMethods(Class cls) throws IOException { + List bsms = cls.getBootstrapMethods(); + writeShort(bsms.size()); + for (BootstrapMethodEntry e : bsms) { + writeRef(e.bsmRef); + writeShort(e.argRefs.length); + for (Entry argRef : e.argRefs) { + writeRef(argRef); + } + } + } + void writeInnerClasses(Class cls) throws IOException { List ics = cls.getInnerClasses(); writeShort(ics.size()); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -52,7 +52,7 @@ * Also used to back up more complex constant pool entries, like Class. */ public static synchronized Utf8Entry getUtf8Entry(String value) { - Map utf8Entries = Utils.getUtf8Entries(); + Map utf8Entries = Utils.getTLGlobals().getUtf8Entries(); Utf8Entry e = utf8Entries.get(value); if (e == null) { e = new Utf8Entry(value); @@ -61,8 +61,8 @@ return e; } /** Factory for Class constants. */ - public static synchronized ClassEntry getClassEntry(String name) { - Map classEntries = Utils.getClassEntries(); + public static ClassEntry getClassEntry(String name) { + Map classEntries = Utils.getTLGlobals().getClassEntries(); ClassEntry e = classEntries.get(name); if (e == null) { e = new ClassEntry(getUtf8Entry(name)); @@ -72,8 +72,8 @@ return e; } /** Factory for literal constants (String, Integer, etc.). */ - public static synchronized LiteralEntry getLiteralEntry(Comparable value) { - Map literalEntries = Utils.getLiteralEntries(); + public static LiteralEntry getLiteralEntry(Comparable value) { + Map literalEntries = Utils.getTLGlobals().getLiteralEntries(); LiteralEntry e = literalEntries.get(value); if (e == null) { if (value instanceof String) @@ -85,13 +85,13 @@ return e; } /** Factory for literal constants (String, Integer, etc.). */ - public static synchronized StringEntry getStringEntry(String value) { + public static StringEntry getStringEntry(String value) { return (StringEntry) getLiteralEntry(value); } /** Factory for signature (type) constants. */ - public static synchronized SignatureEntry getSignatureEntry(String type) { - Map signatureEntries = Utils.getSignatureEntries(); + public static SignatureEntry getSignatureEntry(String type) { + Map signatureEntries = Utils.getTLGlobals().getSignatureEntries(); SignatureEntry e = signatureEntries.get(type); if (e == null) { e = new SignatureEntry(type); @@ -106,8 +106,8 @@ } /** Factory for descriptor (name-and-type) constants. */ - public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) { - Map descriptorEntries = Utils.getDescriptorEntries(); + public static DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) { + Map descriptorEntries = Utils.getTLGlobals().getDescriptorEntries(); String key = DescriptorEntry.stringValueOf(nameRef, typeRef); DescriptorEntry e = descriptorEntries.get(key); if (e == null) { @@ -124,8 +124,8 @@ } /** Factory for member reference constants. */ - public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { - Map memberEntries = Utils.getMemberEntries(); + public static MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) { + Map memberEntries = Utils.getTLGlobals().getMemberEntries(); String key = MemberEntry.stringValueOf(tag, classRef, descRef); MemberEntry e = memberEntries.get(key); if (e == null) { @@ -137,6 +137,61 @@ return e; } + /** Factory for MethodHandle constants. */ + public static MethodHandleEntry getMethodHandleEntry(byte refKind, MemberEntry memRef) { + Map methodHandleEntries = Utils.getTLGlobals().getMethodHandleEntries(); + String key = MethodHandleEntry.stringValueOf(refKind, memRef); + MethodHandleEntry e = methodHandleEntries.get(key); + if (e == null) { + e = new MethodHandleEntry(refKind, memRef); + assert(e.stringValue().equals(key)); + methodHandleEntries.put(key, e); + } + return e; + } + + /** Factory for MethodType constants. */ + public static MethodTypeEntry getMethodTypeEntry(SignatureEntry sigRef) { + Map methodTypeEntries = Utils.getTLGlobals().getMethodTypeEntries(); + String key = sigRef.stringValue(); + MethodTypeEntry e = methodTypeEntries.get(key); + if (e == null) { + e = new MethodTypeEntry(sigRef); + assert(e.stringValue().equals(key)); + methodTypeEntries.put(key, e); + } + return e; + } + public static MethodTypeEntry getMethodTypeEntry(Utf8Entry typeRef) { + return getMethodTypeEntry(getSignatureEntry(typeRef.stringValue())); + } + + /** Factory for InvokeDynamic constants. */ + public static InvokeDynamicEntry getInvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) { + Map invokeDynamicEntries = Utils.getTLGlobals().getInvokeDynamicEntries(); + String key = InvokeDynamicEntry.stringValueOf(bssRef, descRef); + InvokeDynamicEntry e = invokeDynamicEntries.get(key); + if (e == null) { + e = new InvokeDynamicEntry(bssRef, descRef); + assert(e.stringValue().equals(key)); + invokeDynamicEntries.put(key, e); + } + return e; + } + + /** Factory for BootstrapMethod pseudo-constants. */ + public static BootstrapMethodEntry getBootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) { + Map bootstrapMethodEntries = Utils.getTLGlobals().getBootstrapMethodEntries(); + String key = BootstrapMethodEntry.stringValueOf(bsmRef, argRefs); + BootstrapMethodEntry e = bootstrapMethodEntries.get(key); + if (e == null) { + e = new BootstrapMethodEntry(bsmRef, argRefs); + assert(e.stringValue().equals(key)); + bootstrapMethodEntries.put(key, e); + } + return e; + } + /** Entries in the constant pool. */ public static abstract @@ -251,6 +306,10 @@ throw new RuntimeException("bad literal value "+value); } + static boolean isRefKind(byte refKind) { + return (REF_getField <= refKind && refKind <= REF_invokeInterface); + } + public static abstract class LiteralEntry extends Entry { protected LiteralEntry(byte tag) { @@ -404,7 +463,7 @@ } static String stringValueOf(Entry nameRef, Entry typeRef) { - return typeRef.stringValue()+","+nameRef.stringValue(); + return qualifiedStringValue(typeRef, nameRef); } public String prettyString() { @@ -420,6 +479,15 @@ } } + static String qualifiedStringValue(Entry e1, Entry e2) { + return qualifiedStringValue(e1.stringValue(), e2.stringValue()); + } + static String qualifiedStringValue(String s1, String s234) { + // Qualification by dot must decompose uniquely. Second string might already be qualified. + assert(s1.indexOf(".") < 0); + return s1+"."+s234; + } + public static class MemberEntry extends Entry { final ClassEntry classRef; @@ -453,8 +521,12 @@ int x = superCompareTo(o); if (x == 0) { MemberEntry that = (MemberEntry)o; + if (Utils.SORT_MEMBERS_DESCR_MAJOR) + // descRef is transmitted as UDELTA5; sort it first? + x = this.descRef.compareTo(that.descRef); // Primary key is classRef. - x = this.classRef.compareTo(that.classRef); + if (x == 0) + x = this.classRef.compareTo(that.classRef); if (x == 0) x = this.descRef.compareTo(that.descRef); } @@ -473,7 +545,7 @@ case CONSTANT_InterfaceMethodref: pfx = "IMethod:"; break; default: pfx = tag+"???"; break; } - return pfx+classRef.stringValue()+","+descRef.stringValue(); + return pfx+qualifiedStringValue(classRef, descRef); } public boolean isMethod() { @@ -581,13 +653,26 @@ } public byte getLiteralTag() { switch (formRef.stringValue().charAt(0)) { - case 'L': return CONSTANT_String; case 'I': return CONSTANT_Integer; case 'J': return CONSTANT_Long; case 'F': return CONSTANT_Float; case 'D': return CONSTANT_Double; case 'B': case 'S': case 'C': case 'Z': return CONSTANT_Integer; + case 'L': + /* + switch (classRefs[0].stringValue()) { + case "java/lang/String": + return CONSTANT_String; + case "java/lang/invoke/MethodHandle": + return CONSTANT_MethodHandle; + case "java/lang/invoke/MethodType": + return CONSTANT_MethodType; + default: // java/lang/Object, etc. + return CONSTANT_LoadableValue; + } + */ + return CONSTANT_String; // JDK 7 ConstantValue limited to String } assert(false); return CONSTANT_None; @@ -724,6 +809,218 @@ return parts; } + /** @since JDK 7, JSR 292 */ + public static + class MethodHandleEntry extends Entry { + final int refKind; + final MemberEntry memRef; + public Entry getRef(int i) { return i == 0 ? memRef : null; } + + protected int computeValueHash() { + int hc2 = refKind; + return (memRef.hashCode() + (hc2 << 8)) ^ hc2; + } + + MethodHandleEntry(byte refKind, MemberEntry memRef) { + super(CONSTANT_MethodHandle); + assert(isRefKind(refKind)); + this.refKind = refKind; + this.memRef = memRef; + hashCode(); // force computation of valueHash + } + public boolean equals(Object o) { + if (o == null || o.getClass() != MethodHandleEntry.class) { + return false; + } + MethodHandleEntry that = (MethodHandleEntry)o; + return this.refKind == that.refKind + && this.memRef.eq(that.memRef); + } + public int compareTo(Object o) { + int x = superCompareTo(o); + if (x == 0) { + MethodHandleEntry that = (MethodHandleEntry)o; + if (Utils.SORT_HANDLES_KIND_MAJOR) + // Primary key could be refKind. + x = this.refKind - that.refKind; + // Primary key is memRef, which is transmitted as UDELTA5. + if (x == 0) + x = this.memRef.compareTo(that.memRef); + if (x == 0) + x = this.refKind - that.refKind; + } + return x; + } + public static String stringValueOf(int refKind, MemberEntry memRef) { + return refKindName(refKind)+":"+memRef.stringValue(); + } + public String stringValue() { + return stringValueOf(refKind, memRef); + } + } + + /** @since JDK 7, JSR 292 */ + public static + class MethodTypeEntry extends Entry { + final SignatureEntry typeRef; + public Entry getRef(int i) { return i == 0 ? typeRef : null; } + + protected int computeValueHash() { + return typeRef.hashCode() + tag; + } + + MethodTypeEntry(SignatureEntry typeRef) { + super(CONSTANT_MethodType); + this.typeRef = typeRef; + hashCode(); // force computation of valueHash + } + public boolean equals(Object o) { + if (o == null || o.getClass() != MethodTypeEntry.class) { + return false; + } + MethodTypeEntry that = (MethodTypeEntry)o; + return this.typeRef.eq(that.typeRef); + } + public int compareTo(Object o) { + int x = superCompareTo(o); + if (x == 0) { + MethodTypeEntry that = (MethodTypeEntry)o; + x = this.typeRef.compareTo(that.typeRef); + } + return x; + } + public String stringValue() { + return typeRef.stringValue(); + } + } + + /** @since JDK 7, JSR 292 */ + public static + class InvokeDynamicEntry extends Entry { + final BootstrapMethodEntry bssRef; + final DescriptorEntry descRef; + public Entry getRef(int i) { + if (i == 0) return bssRef; + if (i == 1) return descRef; + return null; + } + protected int computeValueHash() { + int hc2 = descRef.hashCode(); + return (bssRef.hashCode() + (hc2 << 8)) ^ hc2; + } + + InvokeDynamicEntry(BootstrapMethodEntry bssRef, DescriptorEntry descRef) { + super(CONSTANT_InvokeDynamic); + this.bssRef = bssRef; + this.descRef = descRef; + hashCode(); // force computation of valueHash + } + public boolean equals(Object o) { + if (o == null || o.getClass() != InvokeDynamicEntry.class) { + return false; + } + InvokeDynamicEntry that = (InvokeDynamicEntry)o; + return this.bssRef.eq(that.bssRef) + && this.descRef.eq(that.descRef); + } + public int compareTo(Object o) { + int x = superCompareTo(o); + if (x == 0) { + InvokeDynamicEntry that = (InvokeDynamicEntry)o; + if (Utils.SORT_INDY_BSS_MAJOR) + // Primary key could be bsmRef. + x = this.bssRef.compareTo(that.bssRef); + // Primary key is descriptor, which is transmitted as UDELTA5. + if (x == 0) + x = this.descRef.compareTo(that.descRef); + if (x == 0) + x = this.bssRef.compareTo(that.bssRef); + } + return x; + } + public String stringValue() { + return stringValueOf(bssRef, descRef); + } + static + String stringValueOf(BootstrapMethodEntry bssRef, DescriptorEntry descRef) { + return "Indy:"+bssRef.stringValue()+"."+descRef.stringValue(); + } + } + + /** @since JDK 7, JSR 292 */ + public static + class BootstrapMethodEntry extends Entry { + final MethodHandleEntry bsmRef; + final Entry[] argRefs; + public Entry getRef(int i) { + if (i == 0) return bsmRef; + if (i-1 < argRefs.length) return argRefs[i-1]; + return null; + } + protected int computeValueHash() { + int hc2 = bsmRef.hashCode(); + return (Arrays.hashCode(argRefs) + (hc2 << 8)) ^ hc2; + } + + BootstrapMethodEntry(MethodHandleEntry bsmRef, Entry[] argRefs) { + super(CONSTANT_BootstrapMethod); + this.bsmRef = bsmRef; + this.argRefs = argRefs.clone(); + hashCode(); // force computation of valueHash + } + public boolean equals(Object o) { + if (o == null || o.getClass() != BootstrapMethodEntry.class) { + return false; + } + BootstrapMethodEntry that = (BootstrapMethodEntry)o; + return this.bsmRef.eq(that.bsmRef) + && Arrays.equals(this.argRefs, that.argRefs); + } + public int compareTo(Object o) { + int x = superCompareTo(o); + if (x == 0) { + BootstrapMethodEntry that = (BootstrapMethodEntry)o; + if (Utils.SORT_BSS_BSM_MAJOR) + // Primary key is bsmRef. + x = this.bsmRef.compareTo(that.bsmRef); + // Primary key is args array length, which is transmitted as UDELTA5. + if (x == 0) + x = compareArgArrays(this.argRefs, that.argRefs); + if (x == 0) + x = this.bsmRef.compareTo(that.bsmRef); + } + return x; + } + public String stringValue() { + return stringValueOf(bsmRef, argRefs); + } + static + String stringValueOf(MethodHandleEntry bsmRef, Entry[] argRefs) { + StringBuffer sb = new StringBuffer(bsmRef.stringValue()); + // Arguments are formatted as "" instead of "[foo,bar,baz]". + // This ensures there will be no confusion if "[,]" appear inside of names. + char nextSep = '<'; + boolean didOne = false; + for (Entry argRef : argRefs) { + sb.append(nextSep).append(argRef.stringValue()); + nextSep = ';'; + } + if (nextSep == '<') sb.append(nextSep); + sb.append('>'); + return sb.toString(); + } + static + int compareArgArrays(Entry[] a1, Entry[] a2) { + int x = a1.length - a2.length; + if (x != 0) return x; + for (int i = 0; i < a1.length; i++) { + x = a1[i].compareTo(a2[i]); + if (x != 0) break; + } + return x; + } + } + // Handy constants: protected static final Entry[] noRefs = {}; protected static final ClassEntry[] noClassRefs = {}; @@ -964,35 +1261,51 @@ /** Coherent group of constant pool indexes. */ public static class IndexGroup { - private Index indexUntyped; private Index[] indexByTag = new Index[CONSTANT_Limit]; + private Index[] indexByTagGroup; private int[] untypedFirstIndexByTag; - private int totalSize; + private int totalSizeQQ; private Index[][] indexByTagAndClass; /** Index of all CP entries of all types, in definition order. */ - public Index getUntypedIndex() { - if (indexUntyped == null) { + private Index makeTagGroupIndex(byte tagGroupTag, byte[] tagsInGroup) { + if (indexByTagGroup == null) + indexByTagGroup = new Index[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; + int which = tagGroupTag - CONSTANT_GroupFirst; + assert(indexByTagGroup[which] == null); + int fillp = 0; + Entry[] cpMap = null; + for (int pass = 1; pass <= 2; pass++) { untypedIndexOf(null); // warm up untypedFirstIndexByTag - Entry[] cpMap = new Entry[totalSize]; - for (int tag = 0; tag < indexByTag.length; tag++) { + for (byte tag : tagsInGroup) { Index ix = indexByTag[tag]; if (ix == null) continue; int ixLen = ix.cpMap.length; if (ixLen == 0) continue; - int fillp = untypedFirstIndexByTag[tag]; - assert(cpMap[fillp] == null); - assert(cpMap[fillp+ixLen-1] == null); - System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen); + assert(tagGroupTag == CONSTANT_All + ? fillp == untypedFirstIndexByTag[tag] + : fillp < untypedFirstIndexByTag[tag]); + if (cpMap != null) { + assert(cpMap[fillp] == null); + assert(cpMap[fillp+ixLen-1] == null); + System.arraycopy(ix.cpMap, 0, cpMap, fillp, ixLen); + } + fillp += ixLen; } - indexUntyped = new Index("untyped", cpMap); + if (cpMap == null) { + assert(pass == 1); + // get ready for pass 2 + cpMap = new Entry[fillp]; + fillp = 0; + } } - return indexUntyped; + indexByTagGroup[which] = new Index(tagName(tagGroupTag), cpMap); + return indexByTagGroup[which]; } public int untypedIndexOf(Entry e) { if (untypedFirstIndexByTag == null) { - untypedFirstIndexByTag = new int[CONSTANT_Limit]; + untypedFirstIndexByTag = new int[CONSTANT_Limit+1]; int fillp = 0; for (int i = 0; i < TAGS_IN_ORDER.length; i++) { byte tag = TAGS_IN_ORDER[i]; @@ -1002,7 +1315,7 @@ untypedFirstIndexByTag[tag] = fillp; fillp += ixLen; } - totalSize = fillp; + untypedFirstIndexByTag[CONSTANT_Limit] = fillp; } if (e == null) return -1; int tag = e.tag; @@ -1028,16 +1341,15 @@ indexByTag[tag] = ix; // decache indexes derived from this one: untypedFirstIndexByTag = null; - indexUntyped = null; + indexByTagGroup = null; if (indexByTagAndClass != null) indexByTagAndClass[tag] = null; } /** Index of all CP entries of a given tag. */ public Index getIndexByTag(byte tag) { - if (tag == CONSTANT_All) { - return getUntypedIndex(); - } + if (tag >= CONSTANT_GroupFirst) + return getIndexByTagGroup(tag); Index ix = indexByTag[tag]; if (ix == null) { // Make an empty one by default. @@ -1047,6 +1359,26 @@ return ix; } + private Index getIndexByTagGroup(byte tag) { + // pool groups: + if (indexByTagGroup != null) { + Index ix = indexByTagGroup[tag - CONSTANT_GroupFirst]; + if (ix != null) return ix; + } + switch (tag) { + case CONSTANT_All: + return makeTagGroupIndex(CONSTANT_All, TAGS_IN_ORDER); + case CONSTANT_LoadableValue: + return makeTagGroupIndex(CONSTANT_LoadableValue, LOADABLE_VALUE_TAGS); + case CONSTANT_AnyMember: + return makeTagGroupIndex(CONSTANT_AnyMember, ANY_MEMBER_TAGS); + case CONSTANT_FieldSpecific: + // This one does not have any fixed index, since it is context-specific. + return null; + } + throw new AssertionError("bad tag group "+tag); + } + /** Index of all CP entries of a given tag and class. */ public Index getMemberIndex(byte tag, ClassEntry classRef) { if (indexByTagAndClass == null) @@ -1107,16 +1439,14 @@ } public boolean haveNumbers() { - for (byte tag = CONSTANT_Integer; tag <= CONSTANT_Double; tag++) { - switch (tag) { - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_Long: - case CONSTANT_Double: - break; - default: - assert(false); - } + for (byte tag : NUMBER_TAGS) { + if (getIndexByTag(tag).size() > 0) return true; + } + return false; + } + + public boolean haveExtraTags() { + for (byte tag : EXTRA_TAGS) { if (getIndexByTag(tag).size() > 0) return true; } return false; @@ -1129,8 +1459,13 @@ * by their equivalent Utf8s. * Also, discard null from cpRefs. */ + public static void completeReferencesIn(Set cpRefs, boolean flattenSigs) { + completeReferencesIn(cpRefs, flattenSigs, null); + } + public static - void completeReferencesIn(Set cpRefs, boolean flattenSigs) { + void completeReferencesIn(Set cpRefs, boolean flattenSigs, + Listbsms) { cpRefs.remove(null); for (ListIterator work = new ArrayList<>(cpRefs).listIterator(cpRefs.size()); @@ -1146,6 +1481,14 @@ cpRefs.add(ue); e = ue; // do not descend into the sig } + if (bsms != null && e.tag == CONSTANT_BootstrapMethod) { + BootstrapMethodEntry bsm = (BootstrapMethodEntry)e; + cpRefs.remove(bsm); + // move it away to the side table where it belongs + if (!bsms.contains(bsm)) + bsms.add(bsm); + // fall through to recursively add refs for this entry + } // Recursively add the refs of e to cpRefs: for (int i = 0; ; i++) { Entry re = e.getRef(i); @@ -1174,15 +1517,37 @@ case CONSTANT_Methodref: return "Methodref"; case CONSTANT_InterfaceMethodref: return "InterfaceMethodref"; case CONSTANT_NameandType: return "NameandType"; + case CONSTANT_MethodHandle: return "MethodHandle"; + case CONSTANT_MethodType: return "MethodType"; + case CONSTANT_InvokeDynamic: return "InvokeDynamic"; // pseudo-tags: - case CONSTANT_All: return "*All"; - case CONSTANT_None: return "*None"; + case CONSTANT_All: return "**All"; + case CONSTANT_None: return "**None"; + case CONSTANT_LoadableValue: return "**LoadableValue"; + case CONSTANT_AnyMember: return "**AnyMember"; + case CONSTANT_FieldSpecific: return "*FieldSpecific"; case CONSTANT_Signature: return "*Signature"; + case CONSTANT_BootstrapMethod: return "*BootstrapMethod"; } return "tag#"+tag; } + public static String refKindName(int refKind) { + switch (refKind) { + case REF_getField: return "getField"; + case REF_getStatic: return "getStatic"; + case REF_putField: return "putField"; + case REF_putStatic: return "putStatic"; + case REF_invokeVirtual: return "invokeVirtual"; + case REF_invokeStatic: return "invokeStatic"; + case REF_invokeSpecial: return "invokeSpecial"; + case REF_newInvokeSpecial: return "newInvokeSpecial"; + case REF_invokeInterface: return "invokeInterface"; + } + return "refKind#"+refKind; + } + // archive constant pool definition order static final byte TAGS_IN_ORDER[] = { CONSTANT_Utf8, @@ -1190,13 +1555,19 @@ CONSTANT_Float, CONSTANT_Long, CONSTANT_Double, - CONSTANT_String, + CONSTANT_String, // note that String=8 precedes Class=7 CONSTANT_Class, CONSTANT_Signature, CONSTANT_NameandType, // cp_Descr CONSTANT_Fieldref, // cp_Field CONSTANT_Methodref, // cp_Method - CONSTANT_InterfaceMethodref // cp_Imethod + CONSTANT_InterfaceMethodref, // cp_Imethod + + // Constants defined in JDK 7 and later: + CONSTANT_MethodHandle, + CONSTANT_MethodType, + CONSTANT_BootstrapMethod, // pseudo-tag, really stored in a class attribute + CONSTANT_InvokeDynamic }; static final byte TAG_ORDER[]; static { @@ -1211,4 +1582,45 @@ System.out.println("};"); */ } + static final byte[] NUMBER_TAGS = { + CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double + }; + static final byte[] EXTRA_TAGS = { + CONSTANT_MethodHandle, CONSTANT_MethodType, + CONSTANT_BootstrapMethod, // pseudo-tag + CONSTANT_InvokeDynamic + }; + static final byte[] LOADABLE_VALUE_TAGS = { // for CONSTANT_LoadableValue + CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double, + CONSTANT_String, CONSTANT_Class, + CONSTANT_MethodHandle, CONSTANT_MethodType + }; + static final byte[] ANY_MEMBER_TAGS = { // for CONSTANT_AnyMember + CONSTANT_Fieldref, CONSTANT_Methodref, CONSTANT_InterfaceMethodref + }; + static final byte[] FIELD_SPECIFIC_TAGS = { // for CONSTANT_FieldSpecific + CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long, CONSTANT_Double, + CONSTANT_String + }; + static { + assert( + verifyTagOrder(TAGS_IN_ORDER) && + verifyTagOrder(NUMBER_TAGS) && + verifyTagOrder(EXTRA_TAGS) && + verifyTagOrder(LOADABLE_VALUE_TAGS) && + verifyTagOrder(ANY_MEMBER_TAGS) && + verifyTagOrder(FIELD_SPECIFIC_TAGS) + ); + } + private static boolean verifyTagOrder(byte[] tags) { + int prev = -1; + for (byte tag : tags) { + int next = TAG_ORDER[tag]; + assert(next > 0) : "tag not found: "+tag; + assert(TAGS_IN_ORDER[next-1] == tag) : "tag repeated: "+tag+" => "+next+" => "+TAGS_IN_ORDER[next-1]; + assert(prev < next) : "tags not in order: "+Arrays.toString(tags)+" at "+tag; + prev = next; + } + return true; + } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Constants.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -65,6 +65,9 @@ public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160; public final static int JAVA6_PACKAGE_MINOR_VERSION = 1; + public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170; + public final static int JAVA7_PACKAGE_MINOR_VERSION = 1; + public final static int CONSTANT_POOL_INDEX_LIMIT = 0x10000; public final static int CONSTANT_POOL_NARROW_LIMIT = 0x00100; @@ -82,14 +85,36 @@ public final static byte CONSTANT_Methodref = 10; public final static byte CONSTANT_InterfaceMethodref = 11; public final static byte CONSTANT_NameandType = 12; + public final static byte CONSTANT_unused13 = 13; + public final static byte CONSTANT_unused14 = 14; + public final static byte CONSTANT_MethodHandle = 15; + public final static byte CONSTANT_MethodType = 16; + public final static byte CONSTANT_unused17 = 17; // unused + public final static byte CONSTANT_InvokeDynamic = 18; // pseudo-constants: public final static byte CONSTANT_None = 0; - public final static byte CONSTANT_Signature = 13; - public final static byte CONSTANT_Limit = 14; + public final static byte CONSTANT_Signature = CONSTANT_unused13; + public final static byte CONSTANT_BootstrapMethod = CONSTANT_unused17; // used only in InvokeDynamic constants + public final static byte CONSTANT_Limit = 19; + + public final static byte CONSTANT_All = 50; // combined global map + public final static byte CONSTANT_LoadableValue = 51; // used for 'KL' and qldc operands + public final static byte CONSTANT_AnyMember = 52; // union of refs to field or (interface) method + public final static byte CONSTANT_FieldSpecific = 53; // used only for 'KQ' ConstantValue attrs + public final static byte CONSTANT_GroupFirst = CONSTANT_All; + public final static byte CONSTANT_GroupLimit = CONSTANT_FieldSpecific+1; - public final static byte CONSTANT_All = 19; // combined global map - public final static byte CONSTANT_Literal = 20; // used only for ldc fields + // CONSTANT_MethodHandle reference kinds + public final static byte REF_getField = 1; + public final static byte REF_getStatic = 2; + public final static byte REF_putField = 3; + public final static byte REF_putStatic = 4; + public final static byte REF_invokeVirtual = 5; + public final static byte REF_invokeStatic = 6; + public final static byte REF_invokeSpecial = 7; + public final static byte REF_newInvokeSpecial = 8; + public final static byte REF_invokeInterface = 9; // pseudo-access bits public final static int ACC_IC_LONG_FORM = (1<<16); //for ic_flags @@ -133,7 +158,7 @@ public static final int AO_HAVE_SPECIAL_FORMATS = 1<<0; public static final int AO_HAVE_CP_NUMBERS = 1<<1; public static final int AO_HAVE_ALL_CODE_FLAGS = 1<<2; - public static final int AO_3_UNUSED_MBZ = 1<<3; + public static final int AO_HAVE_CP_EXTRAS = 1<<3; public static final int AO_HAVE_FILE_HEADERS = 1<<4; public static final int AO_DEFLATE_HINT = 1<<5; public static final int AO_HAVE_FILE_MODTIME = 1<<6; @@ -143,6 +168,7 @@ public static final int AO_HAVE_FIELD_FLAGS_HI = 1<<10; public static final int AO_HAVE_METHOD_FLAGS_HI = 1<<11; public static final int AO_HAVE_CODE_FLAGS_HI = 1<<12; + public static final int AO_UNUSED_MBZ = (-1)<<13; // option bits reserved for future use public static final int LG_AO_HAVE_XXX_FLAGS_HI = 9; @@ -357,7 +383,7 @@ _invokespecial = 183, // 0xb7 _invokestatic = 184, // 0xb8 _invokeinterface = 185, // 0xb9 - _xxxunusedxxx = 186, // 0xba + _invokedynamic = 186, // 0xba _new = 187, // 0xbb _newarray = 188, // 0xbc _anewarray = 189, // 0xbd @@ -422,15 +448,18 @@ // Ldc variants gain us only 0.007% improvement in compression ratio, // but they simplify the file format greatly. public final static int _xldc_op = _invokeinit_limit; - public final static int _aldc = _ldc; + public final static int _sldc = _ldc; // previously named _aldc public final static int _cldc = _xldc_op+0; public final static int _ildc = _xldc_op+1; public final static int _fldc = _xldc_op+2; - public final static int _aldc_w = _ldc_w; + public final static int _sldc_w = _ldc_w; // previously named _aldc_w public final static int _cldc_w = _xldc_op+3; public final static int _ildc_w = _xldc_op+4; public final static int _fldc_w = _xldc_op+5; public final static int _lldc2_w = _ldc2_w; public final static int _dldc2_w = _xldc_op+6; - public final static int _xldc_limit = _xldc_op+7; + // anything other than primitive, string, or class must be handled with qldc: + public final static int _qldc = _xldc_op+7; + public final static int _qldc_w = _xldc_op+8; + public final static int _xldc_limit = _xldc_op+9; } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Instruction.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -451,7 +451,7 @@ public static byte getCPRefOpTag(int bc) { if (bc < BC_INDEX[0].length && BC_INDEX[0][bc] > 0) return BC_TAG[0][bc]; - if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_Literal; + if (bc >= _xldc_op && bc < _xldc_limit) return CONSTANT_LoadableValue; return CONSTANT_None; } @@ -500,7 +500,7 @@ def("bkf", _getstatic, _putfield); // pack kf (base=Field) def("bkm", _invokevirtual, _invokestatic); // pack kn (base=Method) def("bkixx", _invokeinterface); // pack ki (base=IMethod), omit xx - def("", _xxxunusedxxx); + def("bkyxx", _invokedynamic); // pack ky (base=Any), omit xx def("bkc", _new); // pack kc def("bx", _newarray); def("bkc", _anewarray); // pack kc @@ -515,7 +515,6 @@ //System.out.println(i+": l="+BC_LENGTH[0][i]+" i="+BC_INDEX[0][i]); //assert(BC_LENGTH[0][i] != -1); if (BC_LENGTH[0][i] == -1) { - assert(i == _xxxunusedxxx); continue; // unknown opcode } @@ -543,7 +542,7 @@ "if_icmpne if_icmplt if_icmpge if_icmpgt if_icmple if_acmpeq if_acmpne "+ "goto jsr ret tableswitch lookupswitch ireturn lreturn freturn dreturn "+ "areturn return getstatic putstatic getfield putfield invokevirtual "+ - "invokespecial invokestatic invokeinterface xxxunusedxxx new newarray "+ + "invokespecial invokestatic invokeinterface invokedynamic new newarray "+ "anewarray arraylength athrow checkcast instanceof monitorenter "+ "monitorexit wide multianewarray ifnull ifnonnull goto_w jsr_w "; for (int bc = 0; names.length() > 0; bc++) { @@ -588,6 +587,8 @@ case _dldc2_w: iname = "*dldc2_w"; break; case _cldc: iname = "*cldc"; break; case _cldc_w: iname = "*cldc_w"; break; + case _qldc: iname = "*qldc"; break; + case _qldc_w: iname = "*qldc_w"; break; case _byte_escape: iname = "*byte_escape"; break; case _ref_escape: iname = "*ref_escape"; break; case _end_marker: iname = "*end"; break; @@ -618,15 +619,16 @@ if (index > 0 && index+1 < length) { switch (fmt.charAt(index+1)) { case 'c': tag = CONSTANT_Class; break; - case 'k': tag = CONSTANT_Literal; break; + case 'k': tag = CONSTANT_LoadableValue; break; case 'f': tag = CONSTANT_Fieldref; break; case 'm': tag = CONSTANT_Methodref; break; case 'i': tag = CONSTANT_InterfaceMethodref; break; + case 'y': tag = CONSTANT_InvokeDynamic; break; } assert(tag != CONSTANT_None); } else if (index > 0 && length == 2) { assert(from_bc == _ldc); - tag = CONSTANT_Literal; // _ldc opcode only + tag = CONSTANT_LoadableValue; // _ldc opcode only } for (int bc = from_bc; bc <= to_bc; bc++) { BC_FORMAT[w][bc] = fmt; @@ -649,7 +651,7 @@ Instruction i = at(code, 0); while (i != null) { int opcode = i.getBC(); - if (opcode == _xxxunusedxxx || opcode < _nop || opcode > _jsr_w) { + if (opcode < _nop || opcode > _jsr_w) { String message = "illegal opcode: " + opcode + " " + i; throw new FormatException(message); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Wed May 09 13:13:41 2012 -0700 @@ -87,7 +87,12 @@ // If loading from stand alone build uncomment this. // System.loadLibrary("unpack"); java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("unpack")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("unpack"); + return null; + } + }); initIDs(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Package.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import com.sun.java.util.jar.pack.Attribute.Layout; import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; +import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; import com.sun.java.util.jar.pack.ConstantPool.Index; import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry; import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; @@ -100,6 +101,8 @@ classes.clear(); files.clear(); BandStructure.nextSeqForDebug = 0; + package_minver = -1; // fill in later + package_majver = 0; // fill in later } int getPackageVersion() { @@ -108,6 +111,7 @@ // Special empty versions of Code and InnerClasses, used for markers. public static final Attribute.Layout attrCodeEmpty; + public static final Attribute.Layout attrBootstrapMethodsEmpty; public static final Attribute.Layout attrInnerClassesEmpty; public static final Attribute.Layout attrSourceFileSpecial; public static final Map attrDefs; @@ -115,6 +119,8 @@ Map ad = new HashMap<>(3); attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD, "Code", "").layout(); + attrBootstrapMethodsEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS, + "BootstrapMethods", "").layout(); attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS, "InnerClasses", "").layout(); attrSourceFileSpecial = Attribute.define(ad, ATTR_CONTEXT_CLASS, @@ -153,9 +159,8 @@ package_minver = JAVA6_PACKAGE_MINOR_VERSION; } else { // Normal case. Use the newest archive format, when available - // TODO: replace the following with JAVA7* when the need arises - package_majver = JAVA6_PACKAGE_MAJOR_VERSION; - package_minver = JAVA6_PACKAGE_MINOR_VERSION; + package_majver = JAVA7_PACKAGE_MAJOR_VERSION; + package_minver = JAVA7_PACKAGE_MINOR_VERSION; } } @@ -168,13 +173,22 @@ String expMag = Integer.toHexString(JAVA_PACKAGE_MAGIC); throw new IOException("Unexpected package magic number: got "+gotMag+"; expected "+expMag); } - if ((package_majver != JAVA6_PACKAGE_MAJOR_VERSION && - package_majver != JAVA5_PACKAGE_MAJOR_VERSION) || - (package_minver != JAVA6_PACKAGE_MINOR_VERSION && - package_minver != JAVA5_PACKAGE_MINOR_VERSION)) { - + int[] majminFound = null; + for (int[] majmin : new int[][]{ + { JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION }, + { JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION }, + { JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION } + }) { + if (package_majver == majmin[0] && package_minver == majmin[1]) { + majminFound = majmin; + break; + } + } + if (majminFound == null) { String gotVer = package_majver+"."+package_minver; - String expVer = JAVA6_PACKAGE_MAJOR_VERSION+"."+JAVA6_PACKAGE_MINOR_VERSION+ + String expVer = JAVA7_PACKAGE_MAJOR_VERSION+"."+JAVA7_PACKAGE_MINOR_VERSION+ + " OR "+ + JAVA6_PACKAGE_MAJOR_VERSION+"."+JAVA6_PACKAGE_MINOR_VERSION+ " OR "+ JAVA5_PACKAGE_MAJOR_VERSION+"."+JAVA5_PACKAGE_MINOR_VERSION; throw new IOException("Unexpected package minor version: got "+gotVer+"; expected "+expVer); @@ -213,6 +227,7 @@ //ArrayList attributes; // in Attribute.Holder.this.attributes // Note that InnerClasses may be collected at the package level. ArrayList innerClasses; + ArrayList bootstrapMethods; Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) { this.magic = JAVA_MAGIC; @@ -313,6 +328,25 @@ this.cpMap = cpMap; } + boolean hasBootstrapMethods() { + return bootstrapMethods != null && !bootstrapMethods.isEmpty(); + } + + List getBootstrapMethods() { + return bootstrapMethods; + } + + BootstrapMethodEntry[] getBootstrapMethodMap() { + return (hasBootstrapMethods()) + ? bootstrapMethods.toArray(new BootstrapMethodEntry[bootstrapMethods.size()]) + : null; + } + + void setBootstrapMethods(Collection bsms) { + assert(bootstrapMethods == null); // do not do this twice + bootstrapMethods = new ArrayList<>(bsms); + } + boolean hasInnerClasses() { return innerClasses != null; } @@ -1283,7 +1317,8 @@ byTagU[tag] = null; // done with it } for (int i = 0; i < byTagU.length; i++) { - assert(byTagU[i] == null); // all consumed + Index ix = byTagU[i]; + assert(ix == null); // all consumed } for (int i = 0; i < ConstantPool.TAGS_IN_ORDER.length; i++) { byte tag = ConstantPool.TAGS_IN_ORDER[i]; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -25,13 +25,7 @@ package com.sun.java.util.jar.pack; -import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; -import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; -import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; -import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; +import com.sun.java.util.jar.pack.ConstantPool.*; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.File; import com.sun.java.util.jar.pack.Package.InnerClass; @@ -46,6 +40,7 @@ import java.util.Map; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.HashMap; @@ -266,7 +261,6 @@ // #band_headers_size :UNSIGNED5[1] // #attr_definition_count :UNSIGNED5[1] // - assert(AH_LENGTH == 8+(ConstantPool.TAGS_IN_ORDER.length)+6); archive_header_0.expectLength(AH_LENGTH_0); archive_header_0.readFrom(in); @@ -282,6 +276,7 @@ boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS); boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS); boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS); + boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS); initAttrIndexLimit(); // now we are ready to use the data: @@ -300,11 +295,11 @@ archive_header_S.doneDisbursing(); archiveSize0 = in.getBytesServed(); - int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S; - if (!haveFiles) remainingHeaders -= AH_FILE_HEADER_LEN-AH_LENGTH_S; - if (!haveSpecial) remainingHeaders -= AH_SPECIAL_FORMAT_LEN; - if (!haveNumbers) remainingHeaders -= AH_CP_NUMBER_LEN; - assert(remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0); + int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; + if (haveFiles) remainingHeaders += AH_FILE_HEADER_LEN; + if (haveSpecial) remainingHeaders += AH_SPECIAL_FORMAT_LEN; + if (haveNumbers) remainingHeaders += AH_CP_NUMBER_LEN; + if (haveCPExtra) remainingHeaders += AH_CP_EXTRA_LEN; archive_header_1.expectLength(remainingHeaders); archive_header_1.readFrom(in); @@ -325,7 +320,7 @@ numAttrDefs = 0; } - readConstantPoolCounts(haveNumbers); + readConstantPoolCounts(haveNumbers, haveCPExtra); numInnerClasses = archive_header_1.getInt(); @@ -351,7 +346,7 @@ band_headers.doneDisbursing(); } - void readConstantPoolCounts(boolean haveNumbers) throws IOException { + void readConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException { // size the constant pools: for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { // cp_counts: @@ -364,6 +359,7 @@ // #cp_Field_count :UNSIGNED5[1] // #cp_Method_count :UNSIGNED5[1] // #cp_Imethod_count :UNSIGNED5[1] + // (cp_attr_counts) ** (#have_cp_attr_counts) // // cp_number_counts: // #cp_Int_count :UNSIGNED5[1] @@ -371,6 +367,12 @@ // #cp_Long_count :UNSIGNED5[1] // #cp_Double_count :UNSIGNED5[1] // + // cp_extra_counts: + // #cp_MethodHandle_count :UNSIGNED5[1] + // #cp_MethodType_count :UNSIGNED5[1] + // #cp_InvokeDynamic_count :UNSIGNED5[1] + // #cp_BootstrapMethod_count :UNSIGNED5[1] + // byte tag = ConstantPool.TAGS_IN_ORDER[k]; if (!haveNumbers) { // These four counts are optional. @@ -382,6 +384,16 @@ continue; } } + if (!haveCPExtra) { + // These four counts are optional. + switch (tag) { + case CONSTANT_MethodHandle: + case CONSTANT_MethodType: + case CONSTANT_InvokeDynamic: + case CONSTANT_BootstrapMethod: + continue; + } + } tagCount[tag] = archive_header_1.getInt(); } } @@ -401,6 +413,11 @@ return index; } + void checkLegacy(String bandname) { + if (this.pkg.package_majver < JAVA7_PACKAGE_MAJOR_VERSION) { + throw new RuntimeException("unexpected band " + bandname); + } + } void readConstantPool() throws IOException { // cp_bands: // cp_Utf8 @@ -533,8 +550,82 @@ case CONSTANT_InterfaceMethodref: readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); break; + case CONSTANT_MethodHandle: + if (cpMap.length > 0) { + checkLegacy(cp_MethodHandle_refkind.name()); + } + cp_MethodHandle_refkind.expectLength(cpMap.length); + cp_MethodHandle_refkind.readFrom(in); + cp_MethodHandle_member.expectLength(cpMap.length); + cp_MethodHandle_member.readFrom(in); + cp_MethodHandle_member.setIndex(getCPIndex(CONSTANT_AnyMember)); + for (int i = 0; i < cpMap.length; i++) { + byte refKind = (byte) cp_MethodHandle_refkind.getInt(); + MemberEntry memRef = (MemberEntry) cp_MethodHandle_member.getRef(); + cpMap[i] = ConstantPool.getMethodHandleEntry(refKind, memRef); + } + cp_MethodHandle_refkind.doneDisbursing(); + cp_MethodHandle_member.doneDisbursing(); + break; + case CONSTANT_MethodType: + if (cpMap.length > 0) { + checkLegacy(cp_MethodType.name()); + } + cp_MethodType.expectLength(cpMap.length); + cp_MethodType.readFrom(in); + cp_MethodType.setIndex(getCPIndex(CONSTANT_Signature)); + for (int i = 0; i < cpMap.length; i++) { + SignatureEntry typeRef = (SignatureEntry) cp_MethodType.getRef(); + cpMap[i] = ConstantPool.getMethodTypeEntry(typeRef); + } + cp_MethodType.doneDisbursing(); + break; + case CONSTANT_InvokeDynamic: + if (cpMap.length > 0) { + checkLegacy(cp_InvokeDynamic_spec.name()); + } + cp_InvokeDynamic_spec.expectLength(cpMap.length); + cp_InvokeDynamic_spec.readFrom(in); + cp_InvokeDynamic_spec.setIndex(getCPIndex(CONSTANT_BootstrapMethod)); + cp_InvokeDynamic_desc.expectLength(cpMap.length); + cp_InvokeDynamic_desc.readFrom(in); + cp_InvokeDynamic_desc.setIndex(getCPIndex(CONSTANT_NameandType)); + for (int i = 0; i < cpMap.length; i++) { + BootstrapMethodEntry bss = (BootstrapMethodEntry) cp_InvokeDynamic_spec.getRef(); + DescriptorEntry descr = (DescriptorEntry) cp_InvokeDynamic_desc.getRef(); + cpMap[i] = ConstantPool.getInvokeDynamicEntry(bss, descr); + } + cp_InvokeDynamic_spec.doneDisbursing(); + cp_InvokeDynamic_desc.doneDisbursing(); + break; + case CONSTANT_BootstrapMethod: + if (cpMap.length > 0) { + checkLegacy(cp_BootstrapMethod_ref.name()); + } + cp_BootstrapMethod_ref.expectLength(cpMap.length); + cp_BootstrapMethod_ref.readFrom(in); + cp_BootstrapMethod_ref.setIndex(getCPIndex(CONSTANT_MethodHandle)); + cp_BootstrapMethod_arg_count.expectLength(cpMap.length); + cp_BootstrapMethod_arg_count.readFrom(in); + int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal(); + cp_BootstrapMethod_arg.expectLength(totalArgCount); + cp_BootstrapMethod_arg.readFrom(in); + cp_BootstrapMethod_arg.setIndex(getCPIndex(CONSTANT_LoadableValue)); + for (int i = 0; i < cpMap.length; i++) { + MethodHandleEntry bsm = (MethodHandleEntry) cp_BootstrapMethod_ref.getRef(); + int argc = cp_BootstrapMethod_arg_count.getInt(); + Entry[] argRefs = new Entry[argc]; + for (int j = 0; j < argc; j++) { + argRefs[j] = cp_BootstrapMethod_arg.getRef(); + } + cpMap[i] = ConstantPool.getBootstrapMethodEntry(bsm, argRefs); + } + cp_BootstrapMethod_ref.doneDisbursing(); + cp_BootstrapMethod_arg_count.doneDisbursing(); + cp_BootstrapMethod_arg.doneDisbursing(); + break; default: - assert(false); + throw new AssertionError("unexpected CP tag in package"); } Index index = initCPIndex(tag, cpMap); @@ -548,6 +639,21 @@ cp_bands.doneDisbursing(); + if (optDumpBands || verbose > 1) { + for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) { + Index index = pkg.cp.getIndexByTag(tag); + if (index == null || index.isEmpty()) continue; + Entry[] cpMap = index.cpMap; + if (verbose > 1) + Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries."); + if (optDumpBands) { + try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) { + printArrayTo(ps, cpMap, 0, cpMap.length, true); + } + } + } + } + setBandIndexes(); } @@ -1056,8 +1162,16 @@ // look for constant pool entries: cls.visitRefs(VRM_CLASSIC, cpRefs); + ArrayList bsms = new ArrayList<>(); + /* + * BootstrapMethod(BSMs) are added here before InnerClasses(ICs), + * so as to ensure the order. Noting that the BSMs may be + * removed if they are not found in the CP, after the ICs expansion. + */ + cls.addAttribute(Package.attrBootstrapMethodsEmpty.canonicalInstance()); + // flesh out the local constant pool - ConstantPool.completeReferencesIn(cpRefs, true); + ConstantPool.completeReferencesIn(cpRefs, true, bsms); // Now that we know all our local class references, // compute the InnerClasses attribute. @@ -1074,14 +1188,23 @@ } // flesh out the local constant pool, again - ConstantPool.completeReferencesIn(cpRefs, true); + ConstantPool.completeReferencesIn(cpRefs, true, bsms); + } + + // remove the attr previously set, otherwise add the bsm and + // references as required + if (bsms.isEmpty()) { + cls.attributes.remove(Package.attrBootstrapMethodsEmpty.canonicalInstance()); + } else { + cpRefs.add(Package.getRefString("BootstrapMethods")); + Collections.sort(bsms); + cls.setBootstrapMethods(bsms); } // construct a local constant pool int numDoubles = 0; for (Entry e : cpRefs) { if (e.isDoubleWord()) numDoubles++; - assert(e.tag != CONSTANT_Signature) : (e); } Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()]; int fillp = 1; @@ -1154,7 +1277,8 @@ int totalNM = class_method_count.getIntTotal(); field_descr.expectLength(totalNF); method_descr.expectLength(totalNM); - if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+" and #methods="+totalNM+" in #classes="+numClasses); + if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+ + " and #methods="+totalNM+" in #classes="+numClasses); List fields = new ArrayList<>(totalNF); field_descr.readFrom(in); @@ -1393,7 +1517,8 @@ MultiBand xxx_attr_bands = attrBands[ctype]; long flagMask = attrFlagMask[ctype]; if (verbose > 1) { - Utils.log.fine("scanning flags and attrs for "+Attribute.contextName(ctype)+"["+holders.size()+"]"); + Utils.log.fine("scanning flags and attrs for "+ + Attribute.contextName(ctype)+"["+holders.size()+"]"); } // Fetch the attribute layout definitions which govern the bands @@ -1751,8 +1876,10 @@ bc_local, bc_label, bc_intref, bc_floatref, bc_longref, bc_doubleref, bc_stringref, + bc_loadablevalueref, bc_classref, bc_fieldref, bc_methodref, bc_imethodref, + bc_indyref, bc_thisfield, bc_superfield, bc_thismethod, bc_supermethod, bc_initref, @@ -2099,7 +2226,8 @@ case _ildc: case _cldc: case _fldc: - case _aldc: + case _sldc: + case _qldc: origBC = _ldc; size = 1; ldcRefSet.add(ref); @@ -2107,7 +2235,8 @@ case _ildc_w: case _cldc_w: case _fldc_w: - case _aldc_w: + case _sldc_w: + case _qldc_w: origBC = _ldc_w; break; case _lldc2_w: @@ -2136,6 +2265,9 @@ int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true); buf[pc++] = (byte)( 1 + argSize ); buf[pc++] = 0; + } else if (origBC == _invokedynamic) { + buf[pc++] = 0; + buf[pc++] = 0; } assert(Instruction.opLength(origBC) == (pc - curPC)); continue; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -25,15 +25,7 @@ package com.sun.java.util.jar.pack; -import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; -import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; -import com.sun.java.util.jar.pack.ConstantPool.Entry; -import com.sun.java.util.jar.pack.ConstantPool.Index; -import com.sun.java.util.jar.pack.ConstantPool.IndexGroup; -import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; -import com.sun.java.util.jar.pack.ConstantPool.NumberEntry; -import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; -import com.sun.java.util.jar.pack.ConstantPool.StringEntry; +import com.sun.java.util.jar.pack.ConstantPool.*; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.File; import com.sun.java.util.jar.pack.Package.InnerClass; @@ -281,7 +273,7 @@ void writeArchiveHeader() throws IOException { // for debug only: number of words optimized away - int headerDiscountForDebug = 0; + int headerSizeForDebug = AH_LENGTH_MIN; // AO_HAVE_SPECIAL_FORMATS is set if non-default // coding techniques are used, or if there are @@ -293,8 +285,8 @@ if (haveSpecial) archiveOptions |= AO_HAVE_SPECIAL_FORMATS; } - if (!haveSpecial) - headerDiscountForDebug += AH_SPECIAL_FORMAT_LEN; + if (haveSpecial) + headerSizeForDebug += AH_SPECIAL_FORMAT_LEN; // AO_HAVE_FILE_HEADERS is set if there is any // file or segment envelope information present. @@ -305,8 +297,8 @@ if (haveFiles) archiveOptions |= AO_HAVE_FILE_HEADERS; } - if (!haveFiles) - headerDiscountForDebug += AH_FILE_HEADER_LEN; + if (haveFiles) + headerSizeForDebug += AH_FILE_HEADER_LEN; // AO_HAVE_CP_NUMBERS is set if there are any numbers // in the global constant pool. (Numbers are in 15% of classes.) @@ -316,8 +308,19 @@ if (haveNumbers) archiveOptions |= AO_HAVE_CP_NUMBERS; } - if (!haveNumbers) - headerDiscountForDebug += AH_CP_NUMBER_LEN; + if (haveNumbers) + headerSizeForDebug += AH_CP_NUMBER_LEN; + + // AO_HAVE_CP_EXTRAS is set if there are constant pool entries + // beyond the Java 6 version of the class file format. + boolean haveCPExtra = testBit(archiveOptions, AO_HAVE_CP_EXTRAS); + if (!haveCPExtra) { + haveCPExtra |= pkg.cp.haveExtraTags(); + if (haveCPExtra) + archiveOptions |= AO_HAVE_CP_EXTRAS; + } + if (haveCPExtra) + headerSizeForDebug += AH_CP_EXTRA_LEN; assert(pkg.package_majver > 0); // caller must specify! archive_header_0.putInt(pkg.package_minver); @@ -355,18 +358,18 @@ assert(attrDefsWritten.length == 0); } - writeConstantPoolCounts(haveNumbers); + writeConstantPoolCounts(haveNumbers, haveCPExtra); archive_header_1.putInt(pkg.getAllInnerClasses().size()); archive_header_1.putInt(pkg.default_class_minver); archive_header_1.putInt(pkg.default_class_majver); archive_header_1.putInt(pkg.classes.size()); - // Sanity: Make sure we came out to 26 (less optional fields): + // Sanity: Make sure we came out to 29 (less optional fields): assert(archive_header_0.length() + archive_header_S.length() + archive_header_1.length() - == AH_LENGTH - headerDiscountForDebug); + == headerSizeForDebug); // Figure out all the sizes now, first cut: archiveSize0 = 0; @@ -394,9 +397,8 @@ assert(all_bands.outputSize() == archiveSize0+archiveSize1); } - void writeConstantPoolCounts(boolean haveNumbers) throws IOException { - for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { - byte tag = ConstantPool.TAGS_IN_ORDER[k]; + void writeConstantPoolCounts(boolean haveNumbers, boolean haveCPExtra) throws IOException { + for (byte tag : ConstantPool.TAGS_IN_ORDER) { int count = pkg.cp.getIndexByTag(tag).size(); switch (tag) { case CONSTANT_Utf8: @@ -416,6 +418,17 @@ continue; } break; + + case CONSTANT_MethodHandle: + case CONSTANT_MethodType: + case CONSTANT_InvokeDynamic: + case CONSTANT_BootstrapMethod: + // Omit counts for newer entities if possible. + if (!haveCPExtra) { + assert(count == 0); + continue; + } + break; } archive_header_1.putInt(count); } @@ -449,8 +462,7 @@ if (verbose > 0) Utils.log.info("Writing CP"); - for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { - byte tag = ConstantPool.TAGS_IN_ORDER[k]; + for (byte tag : ConstantPool.TAGS_IN_ORDER) { Index index = cp.getIndexByTag(tag); Entry[] cpMap = index.cpMap; @@ -530,8 +542,52 @@ case CONSTANT_InterfaceMethodref: writeMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); break; + case CONSTANT_MethodHandle: + for (int i = 0; i < cpMap.length; i++) { + MethodHandleEntry e = (MethodHandleEntry) cpMap[i]; + cp_MethodHandle_refkind.putInt(e.refKind); + cp_MethodHandle_member.putRef(e.memRef); + } + break; + case CONSTANT_MethodType: + for (int i = 0; i < cpMap.length; i++) { + MethodTypeEntry e = (MethodTypeEntry) cpMap[i]; + cp_MethodType.putRef(e.typeRef); + } + break; + case CONSTANT_InvokeDynamic: + for (int i = 0; i < cpMap.length; i++) { + InvokeDynamicEntry e = (InvokeDynamicEntry) cpMap[i]; + cp_InvokeDynamic_spec.putRef(e.bssRef); + cp_InvokeDynamic_desc.putRef(e.descRef); + } + break; + case CONSTANT_BootstrapMethod: + for (int i = 0; i < cpMap.length; i++) { + BootstrapMethodEntry e = (BootstrapMethodEntry) cpMap[i]; + cp_BootstrapMethod_ref.putRef(e.bsmRef); + cp_BootstrapMethod_arg_count.putInt(e.argRefs.length); + for (Entry argRef : e.argRefs) { + cp_BootstrapMethod_arg.putRef(argRef); + } + } + break; default: - assert(false); + throw new AssertionError("unexpected CP tag in package"); + } + } + if (optDumpBands || verbose > 1) { + for (byte tag = CONSTANT_GroupFirst; tag < CONSTANT_GroupLimit; tag++) { + Index index = cp.getIndexByTag(tag); + if (index == null || index.isEmpty()) continue; + Entry[] cpMap = index.cpMap; + if (verbose > 1) + Utils.log.info("Index group "+ConstantPool.tagName(tag)+" contains "+cpMap.length+" entries."); + if (optDumpBands) { + try (PrintStream ps = new PrintStream(getDumpStream(index.debugName, tag, ".gidx", index))) { + printArrayTo(ps, cpMap, 0, cpMap.length, true); + } + } } } } @@ -988,6 +1044,8 @@ for (Class cls : pkg.classes) { // Replace "obvious" SourceFile attrs by null. cls.minimizeSourceFile(); + // BootstrapMethods should never have been inserted. + assert(cls.getAttribute(Package.attrBootstrapMethodsEmpty) == null); } } @@ -1325,9 +1383,7 @@ // %%% Add a stress mode which issues _ref/_byte_escape. if (verbose > 3) Utils.log.fine(i.toString()); - if (i.isNonstandard() - && (!p200.getBoolean(Utils.COM_PREFIX+"invokedynamic") - || i.getBC() != _xxxunusedxxx)) { + if (i.isNonstandard()) { // Crash and burn with a complaint if there are funny // bytecodes in this class file. String complaint = code.getMethod() @@ -1427,24 +1483,6 @@ continue; } - switch (bc) { - case _xxxunusedxxx: // %%% pretend this is invokedynamic - { - i.setNonstandardLength(3); - int refx = i.getShortAt(1); - Entry ref = (refx == 0)? null: curCPMap[refx]; - // transmit the opcode, carefully: - bc_codes.putByte(_byte_escape); - bc_escsize.putInt(1); // one byte of opcode - bc_escbyte.putByte(bc); // the opcode - // transmit the CP reference, carefully: - bc_codes.putByte(_ref_escape); - bc_escrefsize.putInt(2); // two bytes of ref - bc_escref.putRef(ref); // the ref - continue; - } - } - int branch = i.getBranchLabel(); if (branch >= 0) { bc_codes.putByte(bc); @@ -1458,7 +1496,7 @@ CPRefBand bc_which; int vbc = bc; switch (i.getCPTag()) { - case CONSTANT_Literal: + case CONSTANT_LoadableValue: switch (ref.tag) { case CONSTANT_Integer: bc_which = bc_intref; @@ -1489,8 +1527,8 @@ case CONSTANT_String: bc_which = bc_stringref; switch (bc) { - case _ldc: vbc = _aldc; break; - case _ldc_w: vbc = _aldc_w; break; + case _ldc: vbc = _sldc; break; + case _ldc_w: vbc = _sldc_w; break; default: assert(false); } break; @@ -1503,8 +1541,16 @@ } break; default: - bc_which = null; - assert(false); + // CONSTANT_MethodHandle, etc. + if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) { + throw new IOException("bad package major version for Java 7 ldc"); + } + bc_which = bc_loadablevalueref; + switch (bc) { + case _ldc: vbc = _qldc; break; + case _ldc_w: vbc = _qldc_w; break; + default: assert(false); + } } break; case CONSTANT_Class: @@ -1517,6 +1563,8 @@ bc_which = bc_methodref; break; case CONSTANT_InterfaceMethodref: bc_which = bc_imethodref; break; + case CONSTANT_InvokeDynamic: + bc_which = bc_indyref; break; default: bc_which = null; assert(false); @@ -1532,6 +1580,12 @@ assert(i.getLength() == 5); // Make sure the discarded bytes are sane: assert(i.getConstant() == (1+((MemberEntry)ref).descRef.typeRef.computeSize(true)) << 8); + } else if (bc == _invokedynamic) { + if (getPackageMajver() < JAVA7_PACKAGE_MAJOR_VERSION) { + throw new IOException("bad package major version for Java 7 invokedynamic"); + } + assert(i.getLength() == 5); + assert(i.getConstant() == 0); // last 2 bytes MBZ } else { // Make sure there is nothing else to write. assert(i.getLength() == ((bc == _ldc)?2:3)); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/TLGlobals.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,10 @@ import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry; import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; +import com.sun.java.util.jar.pack.ConstantPool.MethodHandleEntry; +import com.sun.java.util.jar.pack.ConstantPool.MethodTypeEntry; +import com.sun.java.util.jar.pack.ConstantPool.InvokeDynamicEntry; +import com.sun.java.util.jar.pack.ConstantPool.BootstrapMethodEntry; import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; import java.util.HashMap; @@ -56,6 +60,10 @@ private final Map signatureEntries; private final Map descriptorEntries; private final Map memberEntries; + private final Map methodHandleEntries; + private final Map methodTypeEntries; + private final Map invokeDynamicEntries; + private final Map bootstrapMethodEntries; TLGlobals() { utf8Entries = new HashMap<>(); @@ -64,6 +72,10 @@ signatureEntries = new HashMap<>(); descriptorEntries = new HashMap<>(); memberEntries = new HashMap<>(); + methodHandleEntries = new HashMap<>(); + methodTypeEntries = new HashMap<>(); + invokeDynamicEntries = new HashMap<>(); + bootstrapMethodEntries = new HashMap<>(); props = new PropMap(); } @@ -94,4 +106,20 @@ Map getMemberEntries() { return memberEntries; } + + Map getMethodHandleEntries() { + return methodHandleEntries; + } + + Map getMethodTypeEntries() { + return methodTypeEntries; + } + + Map getInvokeDynamicEntries() { + return invokeDynamicEntries; + } + + Map getBootstrapMethodEntries() { + return bootstrapMethodEntries; + } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java Wed May 09 13:13:41 2012 -0700 @@ -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 @@ -60,7 +60,7 @@ * If >3, print tons of comments (e.g., processing of references). * (installer only) */ - static final String DEBUG_VERBOSE = Utils.COM_PREFIX+"verbose"; + static final String DEBUG_VERBOSE = COM_PREFIX+"verbose"; /* * Disables use of native code, prefers the Java-coded implementation. @@ -134,35 +134,11 @@ // to the engine code, especially the native code. static final ThreadLocal currentInstance = new ThreadLocal<>(); - // convenience methods to access the TL globals + // convenience method to access the TL globals static TLGlobals getTLGlobals() { return currentInstance.get(); } - static Map getUtf8Entries() { - return getTLGlobals().getUtf8Entries(); - } - - static Map getClassEntries() { - return getTLGlobals().getClassEntries(); - } - - static Map getLiteralEntries() { - return getTLGlobals().getLiteralEntries(); - } - - static Map getDescriptorEntries() { - return getTLGlobals().getDescriptorEntries(); - } - - static Map getSignatureEntries() { - return getTLGlobals().getSignatureEntries(); - } - - static Map getMemberEntries() { - return getTLGlobals().getMemberEntries(); - } - static PropMap currentPropMap() { Object obj = currentInstance.get(); if (obj instanceof PackerImpl) @@ -173,8 +149,19 @@ } static final boolean nolog - = Boolean.getBoolean(Utils.COM_PREFIX+"nolog"); + = Boolean.getBoolean(COM_PREFIX+"nolog"); + + static final boolean SORT_MEMBERS_DESCR_MAJOR + = Boolean.getBoolean(COM_PREFIX+"sort.members.descr.major"); + static final boolean SORT_HANDLES_KIND_MAJOR + = Boolean.getBoolean(COM_PREFIX+"sort.handles.kind.major"); + + static final boolean SORT_INDY_BSS_MAJOR + = Boolean.getBoolean(COM_PREFIX+"sort.indy.bss.major"); + + static final boolean SORT_BSS_BSM_MAJOR + = Boolean.getBoolean(COM_PREFIX+"sort.bss.bsm.major"); static class Pack200Logger { private final String name; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/awt/SplashScreen.java --- a/jdk/src/share/classes/java/awt/SplashScreen.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/awt/SplashScreen.java Wed May 09 13:13:41 2012 -0700 @@ -119,7 +119,12 @@ // SplashScreen class is now a singleton if (!wasClosed && theInstance == null) { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("splashscreen")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("splashscreen"); + return null; + } + }); long ptr = _getInstance(); if (ptr != 0 && _isVisible(ptr)) { theInstance = new SplashScreen(ptr); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/awt/Toolkit.java --- a/jdk/src/share/classes/java/awt/Toolkit.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/awt/Toolkit.java Wed May 09 13:13:41 2012 -0700 @@ -1646,7 +1646,12 @@ static void loadLibraries() { if (!loaded) { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); loaded = true; } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/awt/event/NativeLibLoader.java --- a/jdk/src/share/classes/java/awt/event/NativeLibLoader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/awt/event/NativeLibLoader.java Wed May 09 13:13:41 2012 -0700 @@ -54,6 +54,11 @@ */ static void loadLibraries() { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/awt/image/ColorModel.java --- a/jdk/src/share/classes/java/awt/image/ColorModel.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/awt/image/ColorModel.java Wed May 09 13:13:41 2012 -0700 @@ -204,7 +204,12 @@ static void loadLibraries() { if (!loaded) { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); loaded = true; } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java --- a/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,14 +60,19 @@ /** * flag set if the native connect() call not to be used */ - private final static boolean connectDisabled = os.startsWith("Mac OS"); + private final static boolean connectDisabled = os.contains("OS X"); /** * Load net library into runtime. */ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); } /** diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java --- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java Wed May 09 13:13:41 2012 -0700 @@ -78,7 +78,12 @@ */ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); } /** diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/net/DatagramPacket.java --- a/jdk/src/share/classes/java/net/DatagramPacket.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/net/DatagramPacket.java Wed May 09 13:13:41 2012 -0700 @@ -47,7 +47,12 @@ */ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); init(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/net/InetAddress.java --- a/jdk/src/share/classes/java/net/InetAddress.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/net/InetAddress.java Wed May 09 13:13:41 2012 -0700 @@ -234,7 +234,13 @@ static { preferIPv6Address = java.security.AccessController.doPrivileged( new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); - AccessController.doPrivileged(new LoadLibraryAction("net")); + AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); init(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/net/NetworkInterface.java --- a/jdk/src/share/classes/java/net/NetworkInterface.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/net/NetworkInterface.java Wed May 09 13:13:41 2012 -0700 @@ -53,7 +53,14 @@ private static final int defaultIndex; /* index of defaultInterface */ static { - AccessController.doPrivileged(new LoadLibraryAction("net")); + AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); + init(); defaultInterface = DefaultInterface.getDefault(); if (defaultInterface != null) { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/nio/Bits.java --- a/jdk/src/share/classes/java/nio/Bits.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/nio/Bits.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, 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 @@ -609,7 +609,7 @@ String arch = AccessController.doPrivileged( new sun.security.action.GetPropertyAction("os.arch")); unaligned = arch.equals("i386") || arch.equals("x86") - || arch.equals("amd64"); + || arch.equals("amd64") || arch.equals("x86_64"); unalignedKnown = true; return unaligned; } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/nio/file/Path.java --- a/jdk/src/share/classes/java/nio/file/Path.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/nio/file/Path.java Wed May 09 13:13:41 2012 -0700 @@ -54,7 +54,7 @@ * resolveSibling} methods to combine paths. The {@link #relativize relativize} * method that can be used to construct a relative path between two paths. * Paths can be {@link #compareTo compared}, and tested against each other using - * the {@link #startsWith startsWith} and {@link #endsWith endWith} methods. + * the {@link #startsWith startsWith} and {@link #endsWith endsWith} methods. * *

This interface extends {@link Watchable} interface so that a directory * located by a path can be {@link #register registered} with a {@link diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/java/text/DateFormatSymbols.java --- a/jdk/src/share/classes/java/text/DateFormatSymbols.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Wed May 09 13:13:41 2012 -0700 @@ -647,6 +647,8 @@ private static final ConcurrentMap> cachedInstances = new ConcurrentHashMap>(3); + private transient int lastZoneIndex = 0; + private void initializeData(Locale desiredLocale) { locale = desiredLocale; @@ -692,12 +694,24 @@ * the given time zone ID can't be located in the DateFormatSymbols object. * @see java.util.SimpleTimeZone */ - final int getZoneIndex(String ID) - { + final int getZoneIndex(String ID) { String[][] zoneStrings = getZoneStringsWrapper(); - for (int index=0; indexSSLContext object. * * @exception NoSuchAlgorithmException if no Provider supports a - * TrustManagerFactorySpi implementation for the + * SSLContextSpi implementation for the * specified protocol. * @exception NullPointerException if protocol is null. * @@ -222,11 +222,11 @@ * * @return the new SSLContext object. * - * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi + * @throws NoSuchAlgorithmException if a SSLContextSpi * implementation for the specified protocol is not available * from the specified Provider object. * - * @throws IllegalArgumentException if the provider name is null. + * @throws IllegalArgumentException if the provider is null. * @throws NullPointerException if protocol is null. * * @see java.security.Provider diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/javax/swing/JComponent.java --- a/jdk/src/share/classes/javax/swing/JComponent.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/JComponent.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2638,17 +2638,16 @@ * attribute: visualUpdate true */ public void setVisible(boolean aFlag) { - if(aFlag != isVisible()) { + if (aFlag != isVisible()) { super.setVisible(aFlag); - Container parent = getParent(); - if(parent != null) { - Rectangle r = getBounds(); - parent.repaint(r.x,r.y,r.width,r.height); + if (aFlag) { + Container parent = getParent(); + if (parent != null) { + Rectangle r = getBounds(); + parent.repaint(r.x, r.y, r.width, r.height); + } + revalidate(); } - // Some (all should) LayoutManagers do not consider components - // that are not visible. As such we need to revalidate when the - // visible bit changes. - revalidate(); } } @@ -5568,4 +5567,21 @@ ",preferredSize=" + preferredSizeString; } + /** + * {@inheritDoc} + */ + @Override + public void hide() { + boolean showing = isShowing(); + super.hide(); + if (showing) { + Container parent = getParent(); + if (parent != null) { + Rectangle r = getBounds(); + parent.repaint(r.x, r.y, r.width, r.height); + } + revalidate(); + } + } + } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/javax/swing/JDesktopPane.java --- a/jdk/src/share/classes/javax/swing/JDesktopPane.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/JDesktopPane.java Wed May 09 13:13:41 2012 -0700 @@ -27,7 +27,8 @@ import java.util.List; import java.util.ArrayList; -import java.util.Vector; +import java.util.Collection; +import java.util.Iterator; import javax.swing.plaf.*; import javax.accessibility.*; @@ -42,7 +43,6 @@ import java.beans.PropertyVetoException; import java.util.Set; import java.util.TreeSet; - /** * A container used to create a multiple-document interface or a virtual desktop. * You create JInternalFrame objects and add them to the @@ -261,25 +261,26 @@ * @return an array of JInternalFrame objects */ public JInternalFrame[] getAllFrames() { - int i, count; - JInternalFrame[] results; - Vector vResults = new Vector(10); + return getAllFrames(this).toArray(new JInternalFrame[0]); + } - count = getComponentCount(); - for(i = 0; i < count; i++) { - Component next = getComponent(i); - if(next instanceof JInternalFrame) - vResults.addElement((JInternalFrame) next); - else if(next instanceof JInternalFrame.JDesktopIcon) { - JInternalFrame tmp = ((JInternalFrame.JDesktopIcon)next).getInternalFrame(); - if(tmp != null) - vResults.addElement(tmp); + private static Collection getAllFrames(Container parent) { + int i, count; + Collection results = new ArrayList(); + count = parent.getComponentCount(); + for (i = 0; i < count; i++) { + Component next = parent.getComponent(i); + if (next instanceof JInternalFrame) { + results.add((JInternalFrame) next); + } else if (next instanceof JInternalFrame.JDesktopIcon) { + JInternalFrame tmp = ((JInternalFrame.JDesktopIcon) next).getInternalFrame(); + if (tmp != null) { + results.add(tmp); + } + } else if (next instanceof Container) { + results.addAll(getAllFrames((Container) next)); } } - - results = new JInternalFrame[vResults.size()]; - vResults.copyInto(results); - return results; } @@ -322,27 +323,14 @@ * @see JLayeredPane */ public JInternalFrame[] getAllFramesInLayer(int layer) { - int i, count; - JInternalFrame[] results; - Vector vResults = new Vector(10); - - count = getComponentCount(); - for(i = 0; i < count; i++) { - Component next = getComponent(i); - if(next instanceof JInternalFrame) { - if(((JInternalFrame)next).getLayer() == layer) - vResults.addElement((JInternalFrame) next); - } else if(next instanceof JInternalFrame.JDesktopIcon) { - JInternalFrame tmp = ((JInternalFrame.JDesktopIcon)next).getInternalFrame(); - if(tmp != null && tmp.getLayer() == layer) - vResults.addElement(tmp); + Collection allFrames = getAllFrames(this); + Iterator iterator = allFrames.iterator(); + while (iterator.hasNext()) { + if (iterator.next().getLayer() != layer) { + iterator.remove(); } } - - results = new JInternalFrame[vResults.size()]; - vResults.copyInto(results); - - return results; + return allFrames.toArray(new JInternalFrame[0]); } private List getFrames() { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/javax/swing/JPopupMenu.java --- a/jdk/src/share/classes/javax/swing/JPopupMenu.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/JPopupMenu.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.event.*; + +import sun.awt.SunToolkit; import sun.security.util.SecurityConstants; import java.applet.Applet; @@ -347,6 +349,7 @@ long popupBottomY = (long)popupLocation.y + (long)popupSize.height; int scrWidth = scrBounds.width; int scrHeight = scrBounds.height; + if (!canPopupOverlapTaskBar()) { // Insets include the task bar. Take them into account. Insets scrInsets = toolkit.getScreenInsets(gc); @@ -407,25 +410,19 @@ } /** - * Checks that there are enough security permissions - * to make popup "always on top", which allows to show it above the task bar. + * Returns whether popup is allowed to be shown above the task bar. */ static boolean canPopupOverlapTaskBar() { boolean result = true; - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission( - SecurityConstants.AWT.SET_WINDOW_ALWAYS_ON_TOP_PERMISSION); - } - } catch (SecurityException se) { - // There is no permission to show popups over the task bar - result = false; + + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + result = ((SunToolkit)tk).canPopupOverlapTaskBar(); } + return result; } - /** * Factory method which creates the JMenuItem for * Actions added to the JPopupMenu. diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/javax/swing/JTable.java --- a/jdk/src/share/classes/javax/swing/JTable.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/javax/swing/JTable.java Wed May 09 13:13:41 2012 -0700 @@ -5470,7 +5470,7 @@ if (constructor.getDeclaringClass() == String.class) { value = s; } - super.stopCellEditing(); + return super.stopCellEditing(); } try { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/awt/NativeLibLoader.java --- a/jdk/src/share/classes/sun/awt/NativeLibLoader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/NativeLibLoader.java Wed May 09 13:13:41 2012 -0700 @@ -54,6 +54,11 @@ */ static void loadLibraries() { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/awt/OSInfo.java --- a/jdk/src/share/classes/sun/awt/OSInfo.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/OSInfo.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ return SOLARIS; } - if (osName.startsWith("Mac OS X")) { + if (osName.contains("OS X")) { return MACOSX; } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/awt/SunToolkit.java --- a/jdk/src/share/classes/sun/awt/SunToolkit.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,8 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; + +import sun.security.util.SecurityConstants; import sun.util.logging.PlatformLogger; import sun.misc.SoftCache; import sun.font.FontDesignMetrics; @@ -1136,6 +1138,26 @@ } /** + * Returns whether popup is allowed to be shown above the task bar. + * This is a default implementation of this method, which checks + * corresponding security permission. + */ + public boolean canPopupOverlapTaskBar() { + boolean result = true; + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission( + SecurityConstants.AWT.SET_WINDOW_ALWAYS_ON_TOP_PERMISSION); + } + } catch (SecurityException se) { + // There is no permission to show popups over the task bar + result = false; + } + return result; + } + + /** * Returns a new input method window, with behavior as specified in * {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}. * If the inputContext is not null, the window should return it from its diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/awt/image/JPEGImageDecoder.java --- a/jdk/src/share/classes/sun/awt/image/JPEGImageDecoder.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/image/JPEGImageDecoder.java Wed May 09 13:13:41 2012 -0700 @@ -54,7 +54,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("jpeg")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("jpeg"); + return null; + } + }); initIDs(InputStreamClass); RGBcolormodel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff); ARGBcolormodel = ColorModel.getRGBdefault(); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/awt/image/NativeLibLoader.java --- a/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java Wed May 09 13:13:41 2012 -0700 @@ -53,7 +53,12 @@ * that the name of the library is "awt". -br. */ static void loadLibraries() { - java.security.AccessController.doPrivileged - (new sun.security.action.LoadLibraryAction("awt")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/font/FontUtilities.java --- a/jdk/src/share/classes/sun/font/FontUtilities.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/font/FontUtilities.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -78,7 +78,7 @@ isLinux = osName.startsWith("Linux"); - isMacOSX = osName.startsWith("Mac OS X"); // TODO: MacOSX + isMacOSX = osName.contains("OS X"); // TODO: MacOSX String t2kStr = System.getProperty("sun.java2d.font.scaler"); if (t2kStr != null) { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/java2d/Disposer.java --- a/jdk/src/share/classes/sun/java2d/Disposer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/java2d/Disposer.java Wed May 09 13:13:41 2012 -0700 @@ -57,7 +57,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); initIDs(); String type = (String) java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("sun.java2d.reftype")); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/launcher/LauncherHelper.java --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -381,7 +381,7 @@ PrintStream ostream = (printToStderr) ? System.err : System.out; ostream.println(getLocalizedMessage("java.launcher.X.usage", File.pathSeparator)); - if (System.getProperty("os.name").startsWith("Mac OS")) { + if (System.getProperty("os.name").contains("OS X")) { ostream.println(getLocalizedMessage("java.launcher.X.macosx.usage", File.pathSeparator)); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/management/ManagementFactoryHelper.java --- a/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/management/ManagementFactoryHelper.java Wed May 09 13:13:41 2012 -0700 @@ -37,7 +37,6 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import sun.security.action.LoadLibraryAction; import sun.util.logging.LoggingSupport; @@ -422,7 +421,13 @@ } static { - AccessController.doPrivileged(new LoadLibraryAction("management")); + AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); jvm = new VMManagementImpl(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/net/sdp/SdpSupport.java --- a/jdk/src/share/classes/sun/net/sdp/SdpSupport.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/net/sdp/SdpSupport.java Wed May 09 13:13:41 2012 -0700 @@ -76,6 +76,11 @@ static { AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java --- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Wed May 09 13:13:41 2012 -0700 @@ -95,7 +95,12 @@ }}); if (b != null && b.booleanValue()) { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); hasSystemProxies = init(); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed May 09 13:13:41 2012 -0700 @@ -744,7 +744,8 @@ if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - disconnect0(fd); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + disconnect0(fd, isIPv6); remoteAddress = null; state = ST_UNCONNECTED; @@ -1079,7 +1080,7 @@ private static native void initIDs(); - private static native void disconnect0(FileDescriptor fd) + private static native void disconnect0(FileDescriptor fd, boolean isIPv6) throws IOException; private native int receive0(FileDescriptor fd, long address, int len, diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/nio/ch/Util.java --- a/jdk/src/share/classes/sun/nio/ch/Util.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/nio/ch/Util.java Wed May 09 13:13:41 2012 -0700 @@ -472,10 +472,15 @@ if (loaded) return; loaded = true; - java.security.AccessController - .doPrivileged(new sun.security.action.LoadLibraryAction("net")); - java.security.AccessController - .doPrivileged(new sun.security.action.LoadLibraryAction("nio")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + System.loadLibrary("nio"); + return null; + } + }); + // IOUtil must be initialized; Its native methods are called from // other places in native nio code so they must be set up. IOUtil.initIDs(); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java --- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -1280,7 +1280,7 @@ String osName = AccessController.doPrivileged( new GetPropertyAction("os.name")); if ("SunOS".equals(osName) || "Linux".equals(osName) - || osName.startsWith("Mac OS")) { + || osName.contains("OS X")) { charset("x-COMPOUND_TEXT", "COMPOUND_TEXT", new String[] { "COMPOUND_TEXT", // JDK historical diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/PSPrinterJob.java --- a/jdk/src/share/classes/sun/print/PSPrinterJob.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/PSPrinterJob.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -1567,7 +1567,7 @@ } String osname = System.getProperty("os.name"); - if (osname.equals("Linux") || osname.startsWith("Mac OS X")) { + if (osname.equals("Linux") || osname.contains("OS X")) { execCmd = new String[ncomps]; execCmd[n++] = "/usr/bin/lpr"; if ((pFlags & PRINTER) != 0) { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/ServiceDialog.java --- a/jdk/src/share/classes/sun/print/ServiceDialog.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/ServiceDialog.java Wed May 09 13:13:41 2012 -0700 @@ -72,6 +72,7 @@ import sun.print.SunPageSelection; import java.awt.event.KeyEvent; import java.net.URISyntaxException; +import java.lang.reflect.Field; /** @@ -479,20 +480,45 @@ */ public static String getMsg(String key) { try { - return messageRB.getString(key); + return removeMnemonics(messageRB.getString(key)); } catch (java.util.MissingResourceException e) { throw new Error("Fatal: Resource for ServiceUI is broken; " + "there is no " + key + " key in resource"); } } + private static String removeMnemonics(String s) { + int i = s.indexOf('&'); + int len = s.length(); + if (i < 0 || i == (len - 1)) { + return s; + } + int j = s.indexOf('&', i+1); + if (j == i+1) { + if (j+1 == len) { + return s.substring(0, i+1); // string ends with && + } else { + return s.substring(0, i+1) + removeMnemonics(s.substring(j+1)); + } + } + // ok first & not double && + if (i == 0) { + return removeMnemonics(s.substring(1)); + } else { + return (s.substring(0, i) + removeMnemonics(s.substring(i+1))); + } + } + + /** * Returns mnemonic character from resource */ private static char getMnemonic(String key) { - String str = getMsg(key + ".mnemonic"); - if ((str != null) && (str.length() > 0)) { - return str.charAt(0); + String str = messageRB.getString(key).replace("&&", ""); + int index = str.indexOf('&'); + if (0 <= index && index < str.length() - 1) { + char c = str.charAt(index + 1); + return Character.toUpperCase(c); } else { return (char)0; } @@ -501,12 +527,23 @@ /** * Returns the mnemonic as a KeyEvent.VK constant from the resource. */ + static Class _keyEventClazz = null; private static int getVKMnemonic(String key) { - String str = getMsg(key + ".vkMnemonic"); - if ((str != null) && (str.length() > 0)) { - try { - return Integer.parseInt(str); - } catch (NumberFormatException nfe) {} + String s = String.valueOf(getMnemonic(key)); + if ( s == null || s.length() != 1) { + return 0; + } + String vkString = "VK_" + s.toUpperCase(); + + try { + if (_keyEventClazz == null) { + _keyEventClazz= Class.forName("java.awt.event.KeyEvent", + true, (ServiceDialog.class).getClassLoader()); + } + Field field = _keyEventClazz.getDeclaredField(vkString); + int value = field.getInt(null); + return value; + } catch (Exception e) { } return 0; } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Cancel button.ok=OK button.print=Print -button.properties=Properties... -button.properties.mnemonic=R +button.properties=P&roperties... # -checkbox.collate=Collate -checkbox.collate.mnemonic=C -checkbox.jobsheets=Banner Page -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=Print To File -checkbox.printtofile.mnemonic=F +checkbox.collate=&Collate +checkbox.jobsheets=&Banner Page +checkbox.printtofile=Print To &File # dialog.printtitle=Print dialog.pstitle=Page Setup @@ -33,70 +29,42 @@ dialog.writeerror=Cannot write to file: # label.info=Info: -label.jobname=Job Name: -label.jobname.mnemonic=J -label.numcopies=Number of copies: -label.numcopies.mnemonic=O -label.priority=Priority: -label.priority.mnemonic=R -label.psname=Name: -label.psname.mnemonic=N +label.jobname=&Job Name: +label.numcopies=Number &of copies: +label.priority=P&riority: +label.psname=&Name: label.pstype=Type: label.rangeto=To -label.size=Size: -label.size.mnemonic=Z -label.source=Source: -label.source.mnemonic=C +label.size=Si&ze: +label.source=Sour&ce: label.status=Status: -label.username=User Name: -label.username.mnemonic=U +label.username=&User Name: label.millimetres=(mm) label.inches=(in) -label.topmargin=top -label.topmargin.mnemonic=T -label.bottommargin=bottom -label.bottommargin.mnemonic=B -label.leftmargin=left -label.leftmargin.mnemonic=F -label.rightmargin=right -label.rightmargin.mnemonic=R +label.topmargin=&top +label.bottommargin=&bottom +label.leftmargin=le&ft +label.rightmargin=&right # -radiobutton.color=Color -radiobutton.color.mnemonic=C -radiobutton.draftq=Draft -radiobutton.draftq.mnemonic=F -radiobutton.duplex=Duplex -radiobutton.duplex.mnemonic=D -radiobutton.highq=High -radiobutton.highq.mnemonic=H -radiobutton.landscape=Landscape -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=Monochrome -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=N -radiobutton.oneside=One Side -radiobutton.oneside.mnemonic=O -radiobutton.portrait=Portrait -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=All -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=Pages -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=Reverse Landscape -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=Reverse Portrait -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=Tumble -radiobutton.tumble.mnemonic=T +radiobutton.color=&Color +radiobutton.draftq=Dra&ft +radiobutton.duplex=&Duplex +radiobutton.highq=&High +radiobutton.landscape=&Landscape +radiobutton.monochrome=&Monochrome +radiobutton.normalq=&Normal +radiobutton.oneside=&One Side +radiobutton.portrait=&Portrait +radiobutton.rangeall=A&ll +radiobutton.rangepages=Pag&es +radiobutton.revlandscape=Reverse La&ndscape +radiobutton.revportrait=Reverse Portra&it +radiobutton.tumble=&Tumble # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Appearance -tab.appearance.vkMnemonic=65 -tab.general=General -tab.general.vkMnemonic=71 -tab.pagesetup=Page Setup -tab.pagesetup.vkMnemonic=83 +tab.appearance=&Appearance +tab.general=&General +tab.pagesetup=Page &Setup # error.pagerange=Invalid page range; please re-enter values (e.g. 1-3,5,7-10) error.destination=Invalid filename; please try again diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_de.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_de.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_de.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Abbrechen button.ok=OK button.print=Drucken -button.properties=Eigenschaften... -button.properties.mnemonic=I +button.properties=E&igenschaften... # -checkbox.collate=Sortieren -checkbox.collate.mnemonic=R -checkbox.jobsheets=Bannerseite -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=Ausgabe in Datei -checkbox.printtofile.mnemonic=U +checkbox.collate=So&rtieren +checkbox.jobsheets=&Bannerseite +checkbox.printtofile=A&usgabe in Datei # dialog.printtitle=Drucken dialog.pstitle=Seite einrichten @@ -33,70 +29,42 @@ dialog.writeerror=Schreiben in Datei nicht m\u00F6glich: # label.info=Info: -label.jobname=Job-Name: -label.jobname.mnemonic=J -label.numcopies=Anzahl Kopien: -label.numcopies.mnemonic=K -label.priority=Priorit\u00E4t: -label.priority.mnemonic=R -label.psname=Name: -label.psname.mnemonic=N +label.jobname=&Job-Name: +label.numcopies=Anzahl &Kopien: +label.priority=P&riorit\u00E4t: +label.psname=&Name: label.pstype=Typ: label.rangeto=Bis -label.size=Gr\u00F6\u00DFe: -label.size.mnemonic=E -label.source=Quelle: -label.source.mnemonic=U +label.size=Gr\u00F6\u00DF&e: +label.source=Q&uelle: label.status=Status: -label.username=Benutzername: -label.username.mnemonic=U +label.username=Ben&utzername: label.millimetres=(mm) label.inches=(Zoll) -label.topmargin=oben -label.topmargin.mnemonic=O -label.bottommargin=unten -label.bottommargin.mnemonic=N -label.leftmargin=links -label.leftmargin.mnemonic=L -label.rightmargin=rechts -label.rightmargin.mnemonic=R +label.topmargin=&oben +label.bottommargin=u&nten +label.leftmargin=&links +label.rightmargin=&rechts # -radiobutton.color=Farbe -radiobutton.color.mnemonic=F -radiobutton.draftq=Entwurf -radiobutton.draftq.mnemonic=W -radiobutton.duplex=Duplex -radiobutton.duplex.mnemonic=P -radiobutton.highq=Hoch -radiobutton.highq.mnemonic=H -radiobutton.landscape=Querformat -radiobutton.landscape.mnemonic=Q -radiobutton.monochrome=Monochrom -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=N -radiobutton.oneside=Einseitig -radiobutton.oneside.mnemonic=E -radiobutton.portrait=Hochformat -radiobutton.portrait.mnemonic=H -radiobutton.rangeall=Alle -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=Seiten -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=Umgekehrtes Querformat -radiobutton.revlandscape.mnemonic=M -radiobutton.revportrait=Umgekehrtes Hochformat -radiobutton.revportrait.mnemonic=K -radiobutton.tumble=Kalenderdruck -radiobutton.tumble.mnemonic=K +radiobutton.color=&Farbe +radiobutton.draftq=Ent&wurf +radiobutton.duplex=Du&plex +radiobutton.highq=&Hoch +radiobutton.landscape=&Querformat +radiobutton.monochrome=&Monochrom +radiobutton.normalq=&Normal +radiobutton.oneside=&Einseitig +radiobutton.portrait=&Hochformat +radiobutton.rangeall=A&lle +radiobutton.rangepages=S&eiten +radiobutton.revlandscape=U&mgekehrtes Querformat +radiobutton.revportrait=Umge&kehrtes Hochformat +radiobutton.tumble=&Kalenderdruck # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Darstellung -tab.appearance.vkMnemonic=68 -tab.general=Allgemein -tab.general.vkMnemonic=65 -tab.pagesetup=Seite einrichten -tab.pagesetup.vkMnemonic=83 +tab.appearance=&Darstellung +tab.general=&Allgemein +tab.pagesetup=&Seite einrichten # error.pagerange=Ung\u00FCltiger Seitenbereich. Geben Sie die Werte erneut ein (Beispiel: 1-3,5,7-10) error.destination=Ung\u00FCltiger Dateiname. Wiederholen Sie den Vorgang diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_es.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_es.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_es.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Cancelar button.ok=Aceptar button.print=Imprimir -button.properties=Propiedades... -button.properties.mnemonic=R +button.properties=P&ropiedades... # -checkbox.collate=Intercalar -checkbox.collate.mnemonic=C -checkbox.jobsheets=P\u00E1gina de R\u00F3tulo -checkbox.jobsheets.mnemonic=E -checkbox.printtofile=Imprimir en Archivo -checkbox.printtofile.mnemonic=M +checkbox.collate=Inter&calar +checkbox.jobsheets=P\u00E1gina d&e R\u00F3tulo +checkbox.printtofile=I&mprimir en Archivo # dialog.printtitle=Imprimir dialog.pstitle=Preparar P\u00E1gina @@ -33,70 +29,42 @@ dialog.writeerror=No se puede escribir en el archivo: # label.info=Informaci\u00F3n: -label.jobname=Nombre del Trabajo: -label.jobname.mnemonic=T -label.numcopies=N\u00FAmero de Copias: -label.numcopies.mnemonic=O -label.priority=Prioridad: -label.priority.mnemonic=I -label.psname=Nombre: -label.psname.mnemonic=N +label.jobname=Nombre del &Trabajo: +label.numcopies=N\u00FAmer&o de Copias: +label.priority=Pr&ioridad: +label.psname=&Nombre: label.pstype=Tipo: label.rangeto=A -label.size=Tama\u00F1o: -label.size.mnemonic=T +label.size=&Tama\u00F1o: label.source=Origen: -label.source.mnemonic=O label.status=Estado: -label.username=Usuario: -label.username.mnemonic=S +label.username=U&suario: label.millimetres=(mm) label.inches=(pulg.) label.topmargin=superior -label.topmargin.mnemonic=S -label.bottommargin=inferior -label.bottommargin.mnemonic=F -label.leftmargin=izquierdo -label.leftmargin.mnemonic=Q -label.rightmargin=derecho -label.rightmargin.mnemonic=E +label.bottommargin=in&ferior +label.leftmargin=iz&quierdo +label.rightmargin=d&erecho # -radiobutton.color=Color -radiobutton.color.mnemonic=C -radiobutton.draftq=Borrador -radiobutton.draftq.mnemonic=R -radiobutton.duplex=D\u00FAplex -radiobutton.duplex.mnemonic=D -radiobutton.highq=Alta -radiobutton.highq.mnemonic=L -radiobutton.landscape=Horizontal -radiobutton.landscape.mnemonic=Z -radiobutton.monochrome=Monocromo -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=N -radiobutton.oneside=Una Cara -radiobutton.oneside.mnemonic=U -radiobutton.portrait=Vertical -radiobutton.portrait.mnemonic=V -radiobutton.rangeall=Todo -radiobutton.rangeall.mnemonic=T -radiobutton.rangepages=P\u00E1ginas -radiobutton.rangepages.mnemonic=G -radiobutton.revlandscape=Horizontal Inverso -radiobutton.revlandscape.mnemonic=H -radiobutton.revportrait=Vertical Inverso -radiobutton.revportrait.mnemonic=R -radiobutton.tumble=Cambio de Cara -radiobutton.tumble.mnemonic=B +radiobutton.color=&Color +radiobutton.draftq=Bo&rrador +radiobutton.duplex=&D\u00FAplex +radiobutton.highq=A<a +radiobutton.landscape=Hori&zontal +radiobutton.monochrome=&Monocromo +radiobutton.normalq=&Normal +radiobutton.oneside=&Una Cara +radiobutton.portrait=&Vertical +radiobutton.rangeall=&Todo +radiobutton.rangepages=P\u00E1&ginas +radiobutton.revlandscape=&Horizontal Inverso +radiobutton.revportrait=Ve&rtical Inverso +radiobutton.tumble=Cam&bio de Cara # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Apariencia -tab.appearance.vkMnemonic=65 -tab.general=General -tab.general.vkMnemonic=71 -tab.pagesetup=Preparar P\u00E1gina -tab.pagesetup.vkMnemonic=80 +tab.appearance=&Apariencia +tab.general=&General +tab.pagesetup=&Preparar P\u00E1gina # error.pagerange=Rango de p\u00E1ginas no v\u00E1lido; vuelva a introducir los valores (por ejemplo, 1-3, 5, 7-10) error.destination=Nombre de archivo no v\u00E1lido; int\u00E9ntelo de nuevo diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_fr.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_fr.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_fr.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Annuler button.ok=OK button.print=Imprimer -button.properties=Propri\u00E9t\u00E9s... -button.properties.mnemonic=R +button.properties=P&ropri\u00E9t\u00E9s... # -checkbox.collate=Collationner -checkbox.collate.mnemonic=C -checkbox.jobsheets=Page de banni\u00E8re -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=Imprimer dans un fichier -checkbox.printtofile.mnemonic=F +checkbox.collate=&Collationner +checkbox.jobsheets=Page de &banni\u00E8re +checkbox.printtofile=Imprimer dans un &fichier # dialog.printtitle=Imprimer dialog.pstitle=Mise en page @@ -33,70 +29,42 @@ dialog.writeerror=Impossible d'\u00E9crire dans le fichier : # label.info=Infos : -label.jobname=Nom du travail : -label.jobname.mnemonic=T -label.numcopies=Nombre de copies : -label.numcopies.mnemonic=O -label.priority=Priorit\u00E9 : -label.priority.mnemonic=R -label.psname=Nom : -label.psname.mnemonic=N +label.jobname=Nom du &travail : +label.numcopies=N&ombre de copies : +label.priority=P&riorit\u00E9 : +label.psname=&Nom : label.pstype=Type : label.rangeto=A -label.size=Taille : -label.size.mnemonic=L -label.source=Source : -label.source.mnemonic=C +label.size=Tai&lle : +label.source=Sour&ce : label.status=Statut : -label.username=Nom utilisateur : -label.username.mnemonic=O +label.username=N&om utilisateur : label.millimetres=(mm) label.inches=(po) -label.topmargin=haut -label.topmargin.mnemonic=H -label.bottommargin=bas -label.bottommargin.mnemonic=B -label.leftmargin=gauche -label.leftmargin.mnemonic=G -label.rightmargin=droite -label.rightmargin.mnemonic=D +label.topmargin=&haut +label.bottommargin=&bas +label.leftmargin=&gauche +label.rightmargin=&droite # -radiobutton.color=Couleur -radiobutton.color.mnemonic=C -radiobutton.draftq=Brouillon -radiobutton.draftq.mnemonic=L -radiobutton.duplex=Duplex -radiobutton.duplex.mnemonic=D -radiobutton.highq=Max. -radiobutton.highq.mnemonic=X -radiobutton.landscape=Paysage -radiobutton.landscape.mnemonic=Y -radiobutton.monochrome=Monochrome -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=N -radiobutton.oneside=Un c\u00F4t\u00E9 -radiobutton.oneside.mnemonic=U -radiobutton.portrait=Portrait -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=Tout -radiobutton.rangeall.mnemonic=T -radiobutton.rangepages=Pages -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=Paysage invers\u00E9 -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=Portrait invers\u00E9 -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=T\u00EAte-b\u00EAche -radiobutton.tumble.mnemonic=T +radiobutton.color=&Couleur +radiobutton.draftq=Broui&llon +radiobutton.duplex=&Duplex +radiobutton.highq=Ma&x. +radiobutton.landscape=Pa&ysage +radiobutton.monochrome=&Monochrome +radiobutton.normalq=&Normal +radiobutton.oneside=&Un c\u00F4t\u00E9 +radiobutton.portrait=&Portrait +radiobutton.rangeall=&Tout +radiobutton.rangepages=Pag&es +radiobutton.revlandscape=Paysage i&nvers\u00E9 +radiobutton.revportrait=Portra&it invers\u00E9 +radiobutton.tumble=&T\u00EAte-b\u00EAche # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Apparence -tab.appearance.vkMnemonic=65 -tab.general=G\u00E9n\u00E9ral -tab.general.vkMnemonic=71 -tab.pagesetup=Mise en page -tab.pagesetup.vkMnemonic=83 +tab.appearance=&Apparence +tab.general=&G\u00E9n\u00E9ral +tab.pagesetup=Mi&se en page # error.pagerange=Plage de pages non valide. Sp\u00E9cifiez les valeurs de nouveau (ex. : 1-3,5,7-10) error.destination=Nom de fichier non valide ; recommencez diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_it.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_it.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_it.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Annulla button.ok=OK button.print=Stampa -button.properties=Propriet\u00E0... -button.properties.mnemonic=R +button.properties=P&ropriet\u00E0... # -checkbox.collate=Fascicola -checkbox.collate.mnemonic=L -checkbox.jobsheets=Pagina banner -checkbox.jobsheets.mnemonic=P -checkbox.printtofile=Stampa su file -checkbox.printtofile.mnemonic=F +checkbox.collate=Fascico&la +checkbox.jobsheets=&Pagina banner +checkbox.printtofile=Stampa su &file # dialog.printtitle=Stampa dialog.pstitle=Imposta pagina @@ -33,70 +29,42 @@ dialog.writeerror=Impossibile scrivere nel file: # label.info=Informazioni: -label.jobname=Nome job: -label.jobname.mnemonic=J -label.numcopies=Numero di copie: -label.numcopies.mnemonic=O -label.priority=Priorit\u00E0: -label.priority.mnemonic=I -label.psname=Nome: -label.psname.mnemonic=N +label.jobname=Nome &job: +label.numcopies=Numer&o di copie: +label.priority=Pr&iorit\u00E0: +label.psname=&Nome: label.pstype=Tipo: label.rangeto=A -label.size=Dimensioni: -label.size.mnemonic=M -label.source=Origine: -label.source.mnemonic=R +label.size=Di&mensioni: +label.source=O&rigine: label.status=Stato: -label.username=Nome utente: -label.username.mnemonic=U +label.username=Nome &utente: label.millimetres=(mm) label.inches=(poll.) -label.topmargin=superiore -label.topmargin.mnemonic=P -label.bottommargin=inferiore -label.bottommargin.mnemonic=F -label.leftmargin=sinistro -label.leftmargin.mnemonic=T -label.rightmargin=destro -label.rightmargin.mnemonic=D +label.topmargin=su&periore +label.bottommargin=in&feriore +label.leftmargin=sinis&tro +label.rightmargin=&destro # -radiobutton.color=Colore -radiobutton.color.mnemonic=C -radiobutton.draftq=Bozza -radiobutton.draftq.mnemonic=B -radiobutton.duplex=Fronte retro -radiobutton.duplex.mnemonic=R -radiobutton.highq=Alta -radiobutton.highq.mnemonic=L -radiobutton.landscape=Orizzontale -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=Monocromatico -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normale -radiobutton.normalq.mnemonic=N -radiobutton.oneside=Un lato -radiobutton.oneside.mnemonic=O -radiobutton.portrait=Verticale -radiobutton.portrait.mnemonic=V -radiobutton.rangeall=Tutto -radiobutton.rangeall.mnemonic=U -radiobutton.rangepages=Pagine -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=Orizzontale capovolto -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=Verticale capovolto -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=Lato corto -radiobutton.tumble.mnemonic=T +radiobutton.color=&Colore +radiobutton.draftq=&Bozza +radiobutton.duplex=F&ronte retro +radiobutton.highq=A<a +radiobutton.landscape=Orizzonta&le +radiobutton.monochrome=&Monocromatico +radiobutton.normalq=&Normale +radiobutton.oneside=Un lat&o +radiobutton.portrait=&Verticale +radiobutton.rangeall=T&utto +radiobutton.rangepages=Pagin&e +radiobutton.revlandscape=Orizzo&ntale capovolto +radiobutton.revportrait=Vert&icale capovolto +radiobutton.tumble=La&to corto # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Aspetto -tab.appearance.vkMnemonic=65 -tab.general=Generale -tab.general.vkMnemonic=71 -tab.pagesetup=Imposta pagina -tab.pagesetup.vkMnemonic=83 +tab.appearance=&Aspetto +tab.general=&Generale +tab.pagesetup=Impo&sta pagina # error.pagerange=Intervallo pagine non valido; immettere nuovamente i valori (ad es. 1-3,5,7-10) error.destination=Nome file non valido; riprovare diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_ja.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_ja.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_ja.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=\u53D6\u6D88 button.ok=OK button.print=\u5370\u5237 -button.properties=\u30D7\u30ED\u30D1\u30C6\u30A3(R)... -button.properties.mnemonic=R +button.properties=\u30D7\u30ED\u30D1\u30C6\u30A3(&R)... # -checkbox.collate=\u4E01\u5408\u3044(C) -checkbox.collate.mnemonic=C -checkbox.jobsheets=\u30D0\u30CA\u30FC\u30FB\u30DA\u30FC\u30B8(B) -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B(F) -checkbox.printtofile.mnemonic=F +checkbox.collate=\u4E01\u5408\u3044(&C) +checkbox.jobsheets=\u30D0\u30CA\u30FC\u30FB\u30DA\u30FC\u30B8(&B) +checkbox.printtofile=\u30D5\u30A1\u30A4\u30EB\u306B\u51FA\u529B(&F) # dialog.printtitle=\u5370\u5237 dialog.pstitle=\u30DA\u30FC\u30B8\u8A2D\u5B9A @@ -33,70 +29,42 @@ dialog.writeerror=\u30D5\u30A1\u30A4\u30EB\u306B\u66F8\u304D\u8FBC\u3081\u307E\u305B\u3093: # label.info=\u60C5\u5831: -label.jobname=\u30B8\u30E7\u30D6\u540D(J): -label.jobname.mnemonic=J -label.numcopies=\u5370\u5237\u90E8\u6570(O): -label.numcopies.mnemonic=O -label.priority=\u512A\u5148\u5EA6(R): -label.priority.mnemonic=R -label.psname=\u540D\u524D(N): -label.psname.mnemonic=N +label.jobname=\u30B8\u30E7\u30D6\u540D(&J): +label.numcopies=\u5370\u5237\u90E8\u6570(&O): +label.priority=\u512A\u5148\u5EA6(&R): +label.psname=\u540D\u524D(&N): label.pstype=\u30BF\u30A4\u30D7: label.rangeto=\u5370\u5237\u7BC4\u56F2 -label.size=\u30B5\u30A4\u30BA(Z): -label.size.mnemonic=Z -label.source=\u30BD\u30FC\u30B9(C): -label.source.mnemonic=C +label.size=\u30B5\u30A4\u30BA(&Z): +label.source=\u30BD\u30FC\u30B9(&C): label.status=\u72B6\u614B: -label.username=\u30E6\u30FC\u30B6\u30FC\u540D(U): -label.username.mnemonic=U +label.username=\u30E6\u30FC\u30B6\u30FC\u540D(&U): label.millimetres=(mm) label.inches=(in) -label.topmargin=\u4E0A(T) -label.topmargin.mnemonic=T -label.bottommargin=\u4E0B(B) -label.bottommargin.mnemonic=B -label.leftmargin=\u5DE6(F) -label.leftmargin.mnemonic=F -label.rightmargin=\u53F3(R) -label.rightmargin.mnemonic=R +label.topmargin=\u4E0A(&T) +label.bottommargin=\u4E0B(&B) +label.leftmargin=\u5DE6(&F) +label.rightmargin=\u53F3(&R) # -radiobutton.color=\u30AB\u30E9\u30FC(C) -radiobutton.color.mnemonic=C -radiobutton.draftq=\u30C9\u30E9\u30D5\u30C8(F) -radiobutton.draftq.mnemonic=F -radiobutton.duplex=\u4E21\u9762(D) -radiobutton.duplex.mnemonic=D -radiobutton.highq=\u9AD8(H) -radiobutton.highq.mnemonic=H -radiobutton.landscape=\u6A2A(L) -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=\u30E2\u30CE\u30AF\u30ED(M) -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=\u6A19\u6E96(N) -radiobutton.normalq.mnemonic=N -radiobutton.oneside=\u7247\u9762(O) -radiobutton.oneside.mnemonic=O -radiobutton.portrait=\u7E26(P) -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=\u3059\u3079\u3066(L) -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=\u30DA\u30FC\u30B8(E) -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=\u30E9\u30F3\u30C9\u30B9\u30B1\u30FC\u30D7(\u53CD\u8EE2)(N) -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=\u30DD\u30FC\u30C8\u30EC\u30A4\u30C8(\u53CD\u8EE2)(I) -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=\u53CD\u8EE2(T) -radiobutton.tumble.mnemonic=T +radiobutton.color=\u30AB\u30E9\u30FC(&C) +radiobutton.draftq=\u30C9\u30E9\u30D5\u30C8(&F) +radiobutton.duplex=\u4E21\u9762(&D) +radiobutton.highq=\u9AD8(&H) +radiobutton.landscape=\u6A2A(&L) +radiobutton.monochrome=\u30E2\u30CE\u30AF\u30ED(&M) +radiobutton.normalq=\u6A19\u6E96(&N) +radiobutton.oneside=\u7247\u9762(&O) +radiobutton.portrait=\u7E26(&P) +radiobutton.rangeall=\u3059\u3079\u3066(&L) +radiobutton.rangepages=\u30DA\u30FC\u30B8(&E) +radiobutton.revlandscape=\u30E9\u30F3\u30C9\u30B9\u30B1\u30FC\u30D7(\u53CD\u8EE2)(&N) +radiobutton.revportrait=\u30DD\u30FC\u30C8\u30EC\u30A4\u30C8(\u53CD\u8EE2)(&I) +radiobutton.tumble=\u53CD\u8EE2(&T) # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=\u5916\u89B3(A) -tab.appearance.vkMnemonic=65 -tab.general=\u4E00\u822C(G) -tab.general.vkMnemonic=71 -tab.pagesetup=\u30DA\u30FC\u30B8\u8A2D\u5B9A(S) -tab.pagesetup.vkMnemonic=83 +tab.appearance=\u5916\u89B3(&A) +tab.general=\u4E00\u822C(&G) +tab.pagesetup=\u30DA\u30FC\u30B8\u8A2D\u5B9A(&S) # error.pagerange=\u7121\u52B9\u306A\u30DA\u30FC\u30B8\u7BC4\u56F2\u3002\u5024\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044(\u4F8B\u30011-3,5,7-10) error.destination=\u7121\u52B9\u306A\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_ko.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_ko.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_ko.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=\uCDE8\uC18C button.ok=\uD655\uC778 button.print=\uC778\uC1C4 -button.properties=\uC18D\uC131(R)... -button.properties.mnemonic=R +button.properties=\uC18D\uC131(&R)... # -checkbox.collate=\uD55C \uBD80\uC529 \uC778\uC1C4(C) -checkbox.collate.mnemonic=C -checkbox.jobsheets=\uBC30\uB108 \uD398\uC774\uC9C0(B) -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=\uD30C\uC77C\uB85C \uC778\uC1C4(F) -checkbox.printtofile.mnemonic=F +checkbox.collate=\uD55C \uBD80\uC529 \uC778\uC1C4(&C) +checkbox.jobsheets=\uBC30\uB108 \uD398\uC774\uC9C0(&B) +checkbox.printtofile=\uD30C\uC77C\uB85C \uC778\uC1C4(&F) # dialog.printtitle=\uC778\uC1C4 dialog.pstitle=\uD398\uC774\uC9C0 \uC124\uC815 @@ -33,70 +29,42 @@ dialog.writeerror=\uD30C\uC77C\uC5D0 \uC4F8 \uC218 \uC5C6\uC74C: # label.info=\uC815\uBCF4: -label.jobname=\uC791\uC5C5 \uC774\uB984(J): -label.jobname.mnemonic=J -label.numcopies=\uB9E4\uC218(O): -label.numcopies.mnemonic=O -label.priority=\uC6B0\uC120\uC21C\uC704(R): -label.priority.mnemonic=R -label.psname=\uC774\uB984(N): -label.psname.mnemonic=N +label.jobname=\uC791\uC5C5 \uC774\uB984(&J): +label.numcopies=\uB9E4\uC218(&O): +label.priority=\uC6B0\uC120\uC21C\uC704(&R): +label.psname=\uC774\uB984(&N): label.pstype=\uC720\uD615: label.rangeto=\uC885\uB8CC -label.size=\uD06C\uAE30(Z): -label.size.mnemonic=Z -label.source=\uC18C\uC2A4(C): -label.source.mnemonic=C +label.size=\uD06C\uAE30(&Z): +label.source=\uC18C\uC2A4(&C): label.status=\uC0C1\uD0DC: -label.username=\uC0AC\uC6A9\uC790 \uC774\uB984(U): -label.username.mnemonic=U +label.username=\uC0AC\uC6A9\uC790 \uC774\uB984(&U): label.millimetres=(mm) label.inches=(\uC778\uCE58) -label.topmargin=\uC704\uCABD(T) -label.topmargin.mnemonic=T -label.bottommargin=\uC544\uB798\uCABD(B) -label.bottommargin.mnemonic=B -label.leftmargin=\uC67C\uCABD(F) -label.leftmargin.mnemonic=F -label.rightmargin=\uC624\uB978\uCABD(R) -label.rightmargin.mnemonic=R +label.topmargin=\uC704\uCABD(&T) +label.bottommargin=\uC544\uB798\uCABD(&B) +label.leftmargin=\uC67C\uCABD(&F) +label.rightmargin=\uC624\uB978\uCABD(&R) # -radiobutton.color=\uC0C9\uC0C1(C) -radiobutton.color.mnemonic=C -radiobutton.draftq=\uCD08\uC548(F) -radiobutton.draftq.mnemonic=F -radiobutton.duplex=\uC591\uBA74(D) -radiobutton.duplex.mnemonic=D -radiobutton.highq=\uB192\uC74C(H) -radiobutton.highq.mnemonic=H -radiobutton.landscape=\uAC00\uB85C(L) -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=\uB2E8\uC0C9(M) -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=\uBCF4\uD1B5(N) -radiobutton.normalq.mnemonic=N -radiobutton.oneside=\uB2E8\uBA74(O) -radiobutton.oneside.mnemonic=O -radiobutton.portrait=\uC138\uB85C(P) -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=\uC804\uCCB4(L) -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=\uD398\uC774\uC9C0(E) -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=\uAC00\uB85C \uBC18\uC804(N) -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=\uC138\uB85C \uBC18\uC804(I) -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=\uD68C\uC804\uC2DD(T) -radiobutton.tumble.mnemonic=T +radiobutton.color=\uC0C9\uC0C1(&C) +radiobutton.draftq=\uCD08\uC548(&F) +radiobutton.duplex=\uC591\uBA74(&D) +radiobutton.highq=\uB192\uC74C(&H) +radiobutton.landscape=\uAC00\uB85C(&L) +radiobutton.monochrome=\uB2E8\uC0C9(&M) +radiobutton.normalq=\uBCF4\uD1B5(&N) +radiobutton.oneside=\uB2E8\uBA74(&O) +radiobutton.portrait=\uC138\uB85C(&P) +radiobutton.rangeall=\uC804\uCCB4(&L) +radiobutton.rangepages=\uD398\uC774\uC9C0(&E) +radiobutton.revlandscape=\uAC00\uB85C \uBC18\uC804(&N) +radiobutton.revportrait=\uC138\uB85C \uBC18\uC804(&I) +radiobutton.tumble=\uD68C\uC804\uC2DD(&T) # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=\uBAA8\uC591(A) -tab.appearance.vkMnemonic=65 -tab.general=\uC77C\uBC18 \uC0AC\uD56D(G) -tab.general.vkMnemonic=71 -tab.pagesetup=\uD398\uC774\uC9C0 \uC124\uC815(S) -tab.pagesetup.vkMnemonic=83 +tab.appearance=\uBAA8\uC591(&A) +tab.general=\uC77C\uBC18 \uC0AC\uD56D(&G) +tab.pagesetup=\uD398\uC774\uC9C0 \uC124\uC815(&S) # error.pagerange=\uBD80\uC801\uD569\uD55C \uD398\uC774\uC9C0 \uBC94\uC704: \uAC12\uC744 \uB2E4\uC2DC \uC785\uB825\uD558\uC2ED\uC2DC\uC624(\uC608: 1-3,5,7-10). error.destination=\uBD80\uC801\uD569\uD55C \uD30C\uC77C \uC774\uB984: \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC2ED\uC2DC\uC624. diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_pt_BR.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_pt_BR.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_pt_BR.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Cancelar button.ok=OK button.print=Imprimir -button.properties=Propriedades... -button.properties.mnemonic=D +button.properties=Proprie&dades... # -checkbox.collate=Agrupar -checkbox.collate.mnemonic=R -checkbox.jobsheets=P\u00E1gina com Banner -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=Imprimir em Arquivo -checkbox.printtofile.mnemonic=I +checkbox.collate=Ag&rupar +checkbox.jobsheets=P\u00E1gina com &Banner +checkbox.printtofile=&Imprimir em Arquivo # dialog.printtitle=Imprimir dialog.pstitle=Configura\u00E7\u00E3o da P\u00E1gina @@ -33,70 +29,42 @@ dialog.writeerror=N\u00E3o \u00E9 poss\u00EDvel gravar no arquivo: # label.info=Informa\u00E7\u00F5es: -label.jobname=Nome do Job: -label.jobname.mnemonic=J -label.numcopies=N\u00FAmero de c\u00F3pias: -label.numcopies.mnemonic=O -label.priority=Prioridade: -label.priority.mnemonic=P -label.psname=Nome: -label.psname.mnemonic=N +label.jobname=Nome do &Job: +label.numcopies=N\u00FAmer&o de c\u00F3pias: +label.priority=&Prioridade: +label.psname=&Nome: label.pstype=Tipo: label.rangeto=At\u00E9 -label.size=Tamanho: -label.size.mnemonic=M -label.source=Origem: -label.source.mnemonic=O +label.size=Ta&manho: +label.source=&Origem: label.status=Status: -label.username=Nome do Usu\u00E1rio: -label.username.mnemonic=U +label.username=Nome do &Usu\u00E1rio: label.millimetres=(mm) label.inches=(pol) -label.topmargin=superior -label.topmargin.mnemonic=S -label.bottommargin=inferior -label.bottommargin.mnemonic=I -label.leftmargin=esquerda: -label.leftmargin.mnemonic=Q -label.rightmargin=direita -label.rightmargin.mnemonic=D +label.topmargin=&superior +label.bottommargin=&inferior +label.leftmargin=es&querda: +label.rightmargin=&direita # -radiobutton.color=Cor -radiobutton.color.mnemonic=O -radiobutton.draftq=Rascunho -radiobutton.draftq.mnemonic=R -radiobutton.duplex=Duplex -radiobutton.duplex.mnemonic=D -radiobutton.highq=Alta -radiobutton.highq.mnemonic=T -radiobutton.landscape=Paisagem -radiobutton.landscape.mnemonic=P -radiobutton.monochrome=Monocrom\u00E1tico -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=N -radiobutton.oneside=Um Lado -radiobutton.oneside.mnemonic=L -radiobutton.portrait=Retrato -radiobutton.portrait.mnemonic=R -radiobutton.rangeall=Tudo -radiobutton.rangeall.mnemonic=U -radiobutton.rangepages=P\u00E1ginas -radiobutton.rangepages.mnemonic=P -radiobutton.revlandscape=Paisagem Invertida -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=Retrato Invertido -radiobutton.revportrait.mnemonic=E -radiobutton.tumble=Virar -radiobutton.tumble.mnemonic=V +radiobutton.color=C&or +radiobutton.draftq=&Rascunho +radiobutton.duplex=&Duplex +radiobutton.highq=Al&ta +radiobutton.landscape=&Paisagem +radiobutton.monochrome=&Monocrom\u00E1tico +radiobutton.normalq=&Normal +radiobutton.oneside=Um &Lado +radiobutton.portrait=&Retrato +radiobutton.rangeall=T&udo +radiobutton.rangepages=&P\u00E1ginas +radiobutton.revlandscape=Paisagem I&nvertida +radiobutton.revportrait=R&etrato Invertido +radiobutton.tumble=&Virar # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Apar\u00EAncia -tab.appearance.vkMnemonic=65 -tab.general=Geral -tab.general.vkMnemonic=71 -tab.pagesetup=Configura\u00E7\u00E3o de P\u00E1gina -tab.pagesetup.vkMnemonic=67 +tab.appearance=&Apar\u00EAncia +tab.general=&Geral +tab.pagesetup=&Configura\u00E7\u00E3o de P\u00E1gina # error.pagerange=Faixa de p\u00E1ginas inv\u00E1lida; insira novamente os valores (por exemplo, 1-3,5,7-10) error.destination=Nome de arquivo inv\u00E1lido; tente novamente diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_sv.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_sv.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_sv.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=Avbryt button.ok=OK button.print=Skriv ut -button.properties=Egenskaper... -button.properties.mnemonic=R +button.properties=Egenskape&r... # -checkbox.collate=Sortera -checkbox.collate.mnemonic=T -checkbox.jobsheets=F\u00F6rs\u00E4ttsblad -checkbox.jobsheets.mnemonic=R -checkbox.printtofile=Skriv ut till fil -checkbox.printtofile.mnemonic=K +checkbox.collate=Sor&tera +checkbox.jobsheets=F\u00F6&rs\u00E4ttsblad +checkbox.printtofile=S&kriv ut till fil # dialog.printtitle=Skriv ut dialog.pstitle=Utskriftsformat @@ -33,70 +29,42 @@ dialog.writeerror=Kan inte skriva till filen: # label.info=Information: -label.jobname=Utskrift: -label.jobname.mnemonic=U -label.numcopies=Antal exemplar: -label.numcopies.mnemonic=E -label.priority=Prioritet: -label.priority.mnemonic=R -label.psname=Namn: -label.psname.mnemonic=N +label.jobname=&Utskrift: +label.numcopies=Antal &exemplar: +label.priority=P&rioritet: +label.psname=&Namn: label.pstype=Typ: label.rangeto=Till -label.size=Storlek: -label.size.mnemonic=O -label.source=K\u00E4lla: -label.source.mnemonic=K +label.size=St&orlek: +label.source=&K\u00E4lla: label.status=Status: -label.username=Anv\u00E4ndarnamn: -label.username.mnemonic=N +label.username=A&nv\u00E4ndarnamn: label.millimetres=(mm) label.inches=(tum) -label.topmargin=\u00F6verkant -label.topmargin.mnemonic=R -label.bottommargin=nederkant -label.bottommargin.mnemonic=N -label.leftmargin=v\u00E4nster -label.leftmargin.mnemonic=V -label.rightmargin=h\u00F6ger -label.rightmargin.mnemonic=H +label.topmargin=\u00F6ve&rkant +label.bottommargin=&nederkant +label.leftmargin=&v\u00E4nster +label.rightmargin=&h\u00F6ger # -radiobutton.color=F\u00E4rg -radiobutton.color.mnemonic=G -radiobutton.draftq=Utkast -radiobutton.draftq.mnemonic=K -radiobutton.duplex=Dubbelsidig -radiobutton.duplex.mnemonic=D -radiobutton.highq=H\u00F6g -radiobutton.highq.mnemonic=H -radiobutton.landscape=Liggande -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=Monokrom -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=Normal -radiobutton.normalq.mnemonic=O -radiobutton.oneside=Ensidig -radiobutton.oneside.mnemonic=E -radiobutton.portrait=St\u00E5ende -radiobutton.portrait.mnemonic=D -radiobutton.rangeall=Alla -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=Sidor -radiobutton.rangepages.mnemonic=D -radiobutton.revlandscape=Omv\u00E4nt liggande -radiobutton.revlandscape.mnemonic=G -radiobutton.revportrait=Omv\u00E4nt st\u00E5ende -radiobutton.revportrait.mnemonic=M -radiobutton.tumble=V\u00E4nd -radiobutton.tumble.mnemonic=V +radiobutton.color=F\u00E4r&g +radiobutton.draftq=Ut&kast +radiobutton.duplex=&Dubbelsidig +radiobutton.highq=&H\u00F6g +radiobutton.landscape=&Liggande +radiobutton.monochrome=&Monokrom +radiobutton.normalq=N&ormal +radiobutton.oneside=&Ensidig +radiobutton.portrait=St\u00E5en&de +radiobutton.rangeall=A&lla +radiobutton.rangepages=Si&dor +radiobutton.revlandscape=Omv\u00E4nt li&ggande +radiobutton.revportrait=O&mv\u00E4nt st\u00E5ende +radiobutton.tumble=&V\u00E4nd # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=Format -tab.appearance.vkMnemonic=70 -tab.general=Allm\u00E4nt -tab.general.vkMnemonic=65 -tab.pagesetup=Utskriftsformat -tab.pagesetup.vkMnemonic=83 +tab.appearance=&Format +tab.general=&Allm\u00E4nt +tab.pagesetup=Ut&skriftsformat # error.pagerange=Ogiltigt sidintervall. Skriv in v\u00E4rdena igen (t ex 1-3,5,7-10) error.destination=Ogiltigt filnamn. F\u00F6rs\u00F6k igen. diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_zh_CN.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_zh_CN.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_zh_CN.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=\u53D6\u6D88 button.ok=\u786E\u5B9A button.print=\u6253\u5370 -button.properties=\u5C5E\u6027(R)... -button.properties.mnemonic=R +button.properties=\u5C5E\u6027(&R)... # -checkbox.collate=\u9010\u4EFD\u6253\u5370(C) -checkbox.collate.mnemonic=C -checkbox.jobsheets=\u6807\u5E1C\u9875(B) -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=\u6253\u5370\u5230\u6587\u4EF6(F) -checkbox.printtofile.mnemonic=F +checkbox.collate=\u9010\u4EFD\u6253\u5370(&C) +checkbox.jobsheets=\u6807\u5E1C\u9875(&B) +checkbox.printtofile=\u6253\u5370\u5230\u6587\u4EF6(&F) # dialog.printtitle=\u6253\u5370 dialog.pstitle=\u9875\u9762\u8BBE\u7F6E @@ -33,70 +29,42 @@ dialog.writeerror=\u65E0\u6CD5\u5199\u5165\u6587\u4EF6: # label.info=\u4FE1\u606F: -label.jobname=\u4F5C\u4E1A\u540D(J): -label.jobname.mnemonic=J -label.numcopies=\u6253\u5370\u4EFD\u6570(O): -label.numcopies.mnemonic=O -label.priority=\u4F18\u5148\u7EA7(R): -label.priority.mnemonic=R -label.psname=\u540D\u79F0(N): -label.psname.mnemonic=N +label.jobname=\u4F5C\u4E1A\u540D(&J): +label.numcopies=\u6253\u5370\u4EFD\u6570(&O): +label.priority=\u4F18\u5148\u7EA7(&R): +label.psname=\u540D\u79F0(&N): label.pstype=\u7C7B\u578B: label.rangeto=\u81F3 -label.size=\u5927\u5C0F(Z): -label.size.mnemonic=Z -label.source=\u6765\u6E90(C): -label.source.mnemonic=C +label.size=\u5927\u5C0F(&Z): +label.source=\u6765\u6E90(&C): label.status=\u72B6\u6001: -label.username=\u7528\u6237\u540D(U): -label.username.mnemonic=U +label.username=\u7528\u6237\u540D(&U): label.millimetres=(\u6BEB\u7C73) label.inches=(\u82F1\u5BF8) -label.topmargin=\u4E0A\u8FB9\u8DDD(T) -label.topmargin.mnemonic=T -label.bottommargin=\u4E0B\u8FB9\u8DDD(B) -label.bottommargin.mnemonic=B -label.leftmargin=\u5DE6\u8FB9\u8DDD(F) -label.leftmargin.mnemonic=F -label.rightmargin=\u53F3\u8FB9\u8DDD(R) -label.rightmargin.mnemonic=R +label.topmargin=\u4E0A\u8FB9\u8DDD(&T) +label.bottommargin=\u4E0B\u8FB9\u8DDD(&B) +label.leftmargin=\u5DE6\u8FB9\u8DDD(&F) +label.rightmargin=\u53F3\u8FB9\u8DDD(&R) # -radiobutton.color=\u989C\u8272(C) -radiobutton.color.mnemonic=C -radiobutton.draftq=\u8349\u56FE(F) -radiobutton.draftq.mnemonic=F -radiobutton.duplex=\u53CC\u9762\u6253\u5370(D) -radiobutton.duplex.mnemonic=D -radiobutton.highq=\u9AD8(H) -radiobutton.highq.mnemonic=H -radiobutton.landscape=\u6A2A\u5411(L) -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=\u5355\u8272(M) -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=\u6B63\u5E38(N) -radiobutton.normalq.mnemonic=N -radiobutton.oneside=\u5355\u9762(O) -radiobutton.oneside.mnemonic=O -radiobutton.portrait=\u7EB5\u5411(P) -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=\u5168\u90E8(L) -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=\u9875\u7801\u8303\u56F4(E) -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=\u6A2A\u5411\u53CD\u9762\u6253\u5370(N) -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=\u7EB5\u5411\u53CD\u9762\u6253\u5370(I) -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=\u7FFB\u8F6C(T) -radiobutton.tumble.mnemonic=T +radiobutton.color=\u989C\u8272(&C) +radiobutton.draftq=\u8349\u56FE(&F) +radiobutton.duplex=\u53CC\u9762\u6253\u5370(&D) +radiobutton.highq=\u9AD8(&H) +radiobutton.landscape=\u6A2A\u5411(&L) +radiobutton.monochrome=\u5355\u8272(&M) +radiobutton.normalq=\u6B63\u5E38(&N) +radiobutton.oneside=\u5355\u9762(&O) +radiobutton.portrait=\u7EB5\u5411(&P) +radiobutton.rangeall=\u5168\u90E8(&L) +radiobutton.rangepages=\u9875\u7801\u8303\u56F4(&E) +radiobutton.revlandscape=\u6A2A\u5411\u53CD\u9762\u6253\u5370(&N) +radiobutton.revportrait=\u7EB5\u5411\u53CD\u9762\u6253\u5370(&I) +radiobutton.tumble=\u7FFB\u8F6C(&T) # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=\u5916\u89C2(A) -tab.appearance.vkMnemonic=65 -tab.general=\u4E00\u822C\u4FE1\u606F(G) -tab.general.vkMnemonic=71 -tab.pagesetup=\u9875\u9762\u8BBE\u7F6E(S) -tab.pagesetup.vkMnemonic=83 +tab.appearance=\u5916\u89C2(&A) +tab.general=\u4E00\u822C\u4FE1\u606F(&G) +tab.pagesetup=\u9875\u9762\u8BBE\u7F6E(&S) # error.pagerange=\u65E0\u6548\u7684\u9875\u9762\u8303\u56F4; \u8BF7\u91CD\u65B0\u8F93\u5165\u6570\u503C (\u4F8B\u5982 1-3,5,7-10) error.destination=\u65E0\u6548\u7684\u6587\u4EF6\u540D; \u8BF7\u91CD\u8BD5 diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/print/resources/serviceui_zh_TW.properties --- a/jdk/src/share/classes/sun/print/resources/serviceui_zh_TW.properties Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/print/resources/serviceui_zh_TW.properties Wed May 09 13:13:41 2012 -0700 @@ -14,15 +14,11 @@ button.cancel=\u53D6\u6D88 button.ok=\u78BA\u5B9A button.print=\u5217\u5370 -button.properties=\u7279\u6027(R)... -button.properties.mnemonic=R +button.properties=\u7279\u6027(&R)... # -checkbox.collate=\u7406\u5E8F(C) -checkbox.collate.mnemonic=C -checkbox.jobsheets=\u6A19\u984C\u9801(B) -checkbox.jobsheets.mnemonic=B -checkbox.printtofile=\u5217\u5370\u81F3\u6A94\u6848(F) -checkbox.printtofile.mnemonic=F +checkbox.collate=\u7406\u5E8F(&C) +checkbox.jobsheets=\u6A19\u984C\u9801(&B) +checkbox.printtofile=\u5217\u5370\u81F3\u6A94\u6848(&F) # dialog.printtitle=\u5217\u5370 dialog.pstitle=\u9801\u9762\u8A2D\u5B9A @@ -33,70 +29,42 @@ dialog.writeerror=\u7121\u6CD5\u5BEB\u5165\u81F3\u6A94\u6848: # label.info=\u8CC7\u8A0A: -label.jobname=\u5DE5\u4F5C\u540D\u7A31(J): -label.jobname.mnemonic=J -label.numcopies=\u5217\u5370\u4EFD\u6578(O): -label.numcopies.mnemonic=O -label.priority=\u512A\u5148\u6B0A(R): -label.priority.mnemonic=R -label.psname=\u540D\u7A31(N): -label.psname.mnemonic=N +label.jobname=\u5DE5\u4F5C\u540D\u7A31(&J): +label.numcopies=\u5217\u5370\u4EFD\u6578(&O): +label.priority=\u512A\u5148\u6B0A(&R): +label.psname=\u540D\u7A31(&N): label.pstype=\u985E\u578B: label.rangeto=\u81F3 -label.size=\u5927\u5C0F(Z): -label.size.mnemonic=Z -label.source=\u4F86\u6E90(C): -label.source.mnemonic=C +label.size=\u5927\u5C0F(&Z): +label.source=\u4F86\u6E90(&C): label.status=\u72C0\u614B: -label.username=\u4F7F\u7528\u8005\u540D\u7A31(U): -label.username.mnemonic=U +label.username=\u4F7F\u7528\u8005\u540D\u7A31(&U): label.millimetres=(mm) label.inches=(in) -label.topmargin=\u9802\u7AEF\u908A\u8DDD(T) -label.topmargin.mnemonic=T -label.bottommargin=\u5E95\u90E8\u908A\u8DDD(B) -label.bottommargin.mnemonic=B -label.leftmargin=\u5DE6\u908A\u8DDD(F) -label.leftmargin.mnemonic=F -label.rightmargin=\u53F3\u908A\u8DDD(R) -label.rightmargin.mnemonic=R +label.topmargin=\u9802\u7AEF\u908A\u8DDD(&T) +label.bottommargin=\u5E95\u90E8\u908A\u8DDD(&B) +label.leftmargin=\u5DE6\u908A\u8DDD(&F) +label.rightmargin=\u53F3\u908A\u8DDD(&R) # -radiobutton.color=\u984F\u8272(C) -radiobutton.color.mnemonic=C -radiobutton.draftq=\u8349\u7A3F(F) -radiobutton.draftq.mnemonic=F -radiobutton.duplex=\u96D9\u9762\u5217\u5370(D) -radiobutton.duplex.mnemonic=D -radiobutton.highq=\u9AD8(H) -radiobutton.highq.mnemonic=H -radiobutton.landscape=\u6A6B\u5411(L) -radiobutton.landscape.mnemonic=L -radiobutton.monochrome=\u55AE\u8272(M) -radiobutton.monochrome.mnemonic=M -radiobutton.normalq=\u6B63\u5E38(N) -radiobutton.normalq.mnemonic=N -radiobutton.oneside=\u55AE\u9762(O) -radiobutton.oneside.mnemonic=O -radiobutton.portrait=\u76F4\u5411(P) -radiobutton.portrait.mnemonic=P -radiobutton.rangeall=\u5168\u90E8(L) -radiobutton.rangeall.mnemonic=L -radiobutton.rangepages=\u9801\u9762(E) -radiobutton.rangepages.mnemonic=E -radiobutton.revlandscape=\u53CD\u5411\u6A6B\u5370(N) -radiobutton.revlandscape.mnemonic=N -radiobutton.revportrait=\u53CD\u5411\u76F4\u5370(I) -radiobutton.revportrait.mnemonic=I -radiobutton.tumble=\u7FFB\u8F49(T) -radiobutton.tumble.mnemonic=T +radiobutton.color=\u984F\u8272(&C) +radiobutton.draftq=\u8349\u7A3F(&F) +radiobutton.duplex=\u96D9\u9762\u5217\u5370(&D) +radiobutton.highq=\u9AD8(&H) +radiobutton.landscape=\u6A6B\u5411(&L) +radiobutton.monochrome=\u55AE\u8272(&M) +radiobutton.normalq=\u6B63\u5E38(&N) +radiobutton.oneside=\u55AE\u9762(&O) +radiobutton.portrait=\u76F4\u5411(&P) +radiobutton.rangeall=\u5168\u90E8(&L) +radiobutton.rangepages=\u9801\u9762(&E) +radiobutton.revlandscape=\u53CD\u5411\u6A6B\u5370(&N) +radiobutton.revportrait=\u53CD\u5411\u76F4\u5370(&I) +radiobutton.tumble=\u7FFB\u8F49(&T) # The vkMnemonics correspond with the constants defined in KeyEvent, eg # 65 = KeyEvent.VK_A -tab.appearance=\u5916\u89C0(A) -tab.appearance.vkMnemonic=65 -tab.general=\u4E00\u822C(G) -tab.general.vkMnemonic=71 -tab.pagesetup=\u9801\u9762\u8A2D\u5B9A(S) -tab.pagesetup.vkMnemonic=83 +tab.appearance=\u5916\u89C0(&A) +tab.general=\u4E00\u822C(&G) +tab.pagesetup=\u9801\u9762\u8A2D\u5B9A(&S) # error.pagerange=\u7121\u6548\u7684\u9801\u9762\u7BC4\u570D; \u8ACB\u91CD\u65B0\u8F38\u5165\u6578\u503C (\u4F8B\u5982 1-3,5,7-10) error.destination=\u7121\u6548\u7684\u6A94\u540D; \u8ACB\u518D\u8A66\u4E00\u6B21 diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/action/LoadLibraryAction.java --- a/jdk/src/share/classes/sun/security/action/LoadLibraryAction.java Wed May 09 13:07:57 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.action; - -/** - * A convenience class for loading a system library as a privileged action. - * - *

An instance of this class can be used as the argument of - * AccessController.doPrivileged. - * - *

The following code attempts to load the system library named - * "lib" as a privileged action:

- * - *

- * java.security.AccessController.doPrivileged(new LoadLibraryAction("lib"));
- * 
- * - * @author Roland Schemers - * @see java.security.PrivilegedAction - * @see java.security.AccessController - * @since 1.2 - */ - -public class LoadLibraryAction implements java.security.PrivilegedAction { - private String theLib; - - /** - * Constructor that takes the name of the system library that needs to be - * loaded. - * - *

The manner in which a library name is mapped to the - * actual system library is system dependent. - * - * @param theLib the name of the library. - */ - public LoadLibraryAction(String theLib) { - this.theLib = theLib; - } - - /** - * Loads the system library whose name was specified in the constructor. - */ - public Void run() { - System.loadLibrary(theLib); - return null; - } -} diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java --- a/jdk/src/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -90,7 +90,7 @@ "libgssapi_krb5.so", "libgssapi_krb5.so.2", }; - } else if (osname.startsWith("Mac OS X")) { + } else if (osname.contains("OS X")) { gssLibs = new String[]{ "/usr/lib/sasl2/libgssapiv2.2.so", }; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/krb5/Config.java --- a/jdk/src/share/classes/sun/security/krb5/Config.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/krb5/Config.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, 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 @@ -737,7 +737,7 @@ } } else if (osname.startsWith("SunOS")) { name = "/etc/krb5/krb5.conf"; - } else if (osname.startsWith("Mac")) { + } else if (osname.contains("OS X")) { if (isMacosLionOrBetter()) return ""; name = findMacosConfigFile(); } else { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/krb5/Credentials.java --- a/jdk/src/share/classes/sun/security/krb5/Credentials.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -289,7 +289,7 @@ String os = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("os.name")); if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS") || - os.toUpperCase(Locale.ENGLISH).startsWith("MAC")) { + os.toUpperCase(Locale.ENGLISH).contains("OS X")) { Credentials creds = acquireDefaultCreds(); if (creds == null) { if (DEBUG) { @@ -478,7 +478,7 @@ java.security.AccessController.doPrivileged( new java.security.PrivilegedAction () { public Void run() { - if (System.getProperty("os.name").startsWith("Mac")) { + if (System.getProperty("os.name").contains("OS X")) { System.loadLibrary("osxkrb5"); } else { System.loadLibrary("w2k_lsa_auth"); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java --- a/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java Wed May 09 13:13:41 2012 -0700 @@ -36,7 +36,13 @@ private static native Hashtable getKerberosConfig(); static { - java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("osx")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("osx"); + return null; + } + }); installNotificationCallback(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java --- a/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/provider/ByteArrayAccess.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -95,7 +95,8 @@ private static boolean unaligned() { String arch = java.security.AccessController.doPrivileged (new sun.security.action.GetPropertyAction("os.arch", "")); - return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64"); + return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64") + || arch.equals("x86_64"); } /** diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/smartcardio/PCSC.java --- a/jdk/src/share/classes/sun/security/smartcardio/PCSC.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/smartcardio/PCSC.java Wed May 09 13:13:41 2012 -0700 @@ -27,8 +27,6 @@ import java.security.AccessController; -import sun.security.action.LoadLibraryAction; - /** * Access to native PC/SC functions and definition of PC/SC constants. * Initialization and platform specific PC/SC constants are handled in diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java --- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Wed May 09 13:13:41 2012 -0700 @@ -59,10 +59,10 @@ public final static String PROPERTY_TLS_DISABLED_ALGS = "jdk.tls.disabledAlgorithms"; - private static Map disabledAlgorithmsMap = - Collections.synchronizedMap(new HashMap()); - private static Map keySizeConstraintsMap = - Collections.synchronizedMap(new HashMap()); + private final static Map disabledAlgorithmsMap = + new HashMap<>(); + private final static Map keySizeConstraintsMap = + new HashMap<>(); private String[] disabledAlgorithms; private KeySizeConstraints keySizeConstraints; @@ -74,6 +74,8 @@ * algorithm constraints */ public DisabledAlgorithmConstraints(String propertyName) { + // Both disabledAlgorithmsMap and keySizeConstraintsMap are + // synchronized with the lock of disabledAlgorithmsMap. synchronized (disabledAlgorithmsMap) { if(!disabledAlgorithmsMap.containsKey(propertyName)) { loadDisabledAlgorithmsMap(propertyName); diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/tracing/dtrace/JVM.java --- a/jdk/src/share/classes/sun/tracing/dtrace/JVM.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/tracing/dtrace/JVM.java Wed May 09 13:13:41 2012 -0700 @@ -35,8 +35,13 @@ class JVM { static { - java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("jsdt")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("jsdt"); + return null; + } + }); } static long activate(String moduleName, DTraceProvider[] providers) { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/classes/sun/util/logging/PlatformLogger.java --- a/jdk/src/share/classes/sun/util/logging/PlatformLogger.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/classes/sun/util/logging/PlatformLogger.java Wed May 09 13:13:41 2012 -0700 @@ -516,6 +516,9 @@ } void doLog(int level, String msg, Object... params) { + if (!isLoggable(level)) { + return; + } // only pass String objects to the j.u.l.Logger which may // be created by untrusted code int len = (params != null) ? params.length : 0; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -188,9 +188,13 @@ entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) { CHECK_0; assert(ix_->ixTag == ixTag - || (ixTag == CONSTANT_Literal - && ix_->ixTag >= CONSTANT_Integer - && ix_->ixTag <= CONSTANT_String)); + || ((ixTag == CONSTANT_All || + ixTag == CONSTANT_LoadableValue || + ixTag == CONSTANT_AnyMember) + || (ixTag == CONSTANT_FieldSpecific && + ix_->ixTag >= CONSTANT_Integer && + ix_->ixTag <= CONSTANT_String)) + ); int n = vs[0].getInt() - nullOK; // Note: band-local nullOK means null encodes as 0. // But nullOKwithCaller means caller is willing to tolerate a null. @@ -270,22 +274,15 @@ #define NO_INDEX 0 struct band_init { -#ifndef PRODUCT int bn; const char* name; -#endif int defc; int index; }; -#ifdef PRODUCT -#define BAND_INIT(name, cspec, ix) \ - { cspec, ix } -#else #define BAND_INIT(name, cspec, ix) \ { e_##name, #name, /*debug only*/ \ cspec, ix } -#endif const band_init all_band_inits[] = { //BAND_INIT(archive_magic, BYTE1_spec, 0), @@ -314,6 +311,14 @@ BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)), BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(cp_MethodHandle_refkind, DELTA5_spec, 0), + BAND_INIT(cp_MethodHandle_member, UDELTA5_spec, INDEX(CONSTANT_AnyMember)), + BAND_INIT(cp_MethodType, UDELTA5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(cp_BootstrapMethod_ref, DELTA5_spec, INDEX(CONSTANT_MethodHandle)), + BAND_INIT(cp_BootstrapMethod_arg_count, UDELTA5_spec, 0), + BAND_INIT(cp_BootstrapMethod_arg, DELTA5_spec, INDEX(CONSTANT_LoadableValue)), + BAND_INIT(cp_InvokeDynamic_spec, DELTA5_spec, INDEX(CONSTANT_BootstrapMethod)), + BAND_INIT(cp_InvokeDynamic_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), BAND_INIT(attr_definition_headers, BYTE1_spec, 0), BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), @@ -333,7 +338,7 @@ BAND_INIT(field_attr_count, UNSIGNED5_spec, 0), BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0), BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0), - BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)), + BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_FieldSpecific)), BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1), @@ -415,10 +420,12 @@ BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)), BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)), BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)), + BAND_INIT(bc_loadablevalueref, DELTA5_spec, INDEX(CONSTANT_LoadableValue)), BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)), BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)), BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)), + BAND_INIT(bc_indyref, DELTA5_spec, INDEX(CONSTANT_InvokeDynamic)), BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), @@ -471,7 +478,7 @@ for (int i = 0; i < BAND_LIMIT; i++) { band* scan = &tmp_all_bands[i]; uint tag = scan->ixTag; // Cf. #define INDEX(tag) above - if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0) { + if (tag != 0 && tag != CONSTANT_FieldSpecific && (tag & SUBINDEX_BIT) == 0) { scan->setIndex(u->cp.getIndex(tag)); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/bands.h --- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,7 @@ struct unpacker; struct band { -#ifndef PRODUCT const char* name; -#endif int bn; // band_number of this band coding* defc; // default coding method cpindex* ix; // CP entry mapping, if CPRefBand @@ -162,6 +160,14 @@ e_cp_Method_desc, e_cp_Imethod_class, e_cp_Imethod_desc, + e_cp_MethodHandle_refkind, + e_cp_MethodHandle_member, + e_cp_MethodType, + e_cp_BootstrapMethod_ref, + e_cp_BootstrapMethod_arg_count, + e_cp_BootstrapMethod_arg, + e_cp_InvokeDynamic_spec, + e_cp_InvokeDynamic_desc, // bands which define transmission of attributes e_attr_definition_headers, @@ -284,11 +290,13 @@ e_bc_longref, e_bc_doubleref, e_bc_stringref, + e_bc_loadablevalueref, e_bc_classref, e_bc_fieldref, e_bc_methodref, e_bc_imethodref, + e_bc_indyref, // _self_linker_op family e_bc_thisfield, @@ -343,6 +351,14 @@ #define cp_Method_desc all_bands[e_cp_Method_desc] #define cp_Imethod_class all_bands[e_cp_Imethod_class] #define cp_Imethod_desc all_bands[e_cp_Imethod_desc] +#define cp_MethodHandle_refkind all_bands[e_cp_MethodHandle_refkind] +#define cp_MethodHandle_member all_bands[e_cp_MethodHandle_member] +#define cp_MethodType all_bands[e_cp_MethodType] +#define cp_BootstrapMethod_ref all_bands[e_cp_BootstrapMethod_ref] +#define cp_BootstrapMethod_arg_count all_bands[e_cp_BootstrapMethod_arg_count] +#define cp_BootstrapMethod_arg all_bands[e_cp_BootstrapMethod_arg] +#define cp_InvokeDynamic_spec all_bands[e_cp_InvokeDynamic_spec] +#define cp_InvokeDynamic_desc all_bands[e_cp_InvokeDynamic_desc] #define attr_definition_headers all_bands[e_attr_definition_headers] #define attr_definition_name all_bands[e_attr_definition_name] #define attr_definition_layout all_bands[e_attr_definition_layout] @@ -437,10 +453,12 @@ #define bc_longref all_bands[e_bc_longref] #define bc_doubleref all_bands[e_bc_doubleref] #define bc_stringref all_bands[e_bc_stringref] +#define bc_loadablevalueref all_bands[e_bc_loadablevalueref] #define bc_classref all_bands[e_bc_classref] #define bc_fieldref all_bands[e_bc_fieldref] #define bc_methodref all_bands[e_bc_methodref] #define bc_imethodref all_bands[e_bc_imethodref] +#define bc_indyref all_bands[e_bc_indyref] #define bc_thisfield all_bands[e_bc_thisfield] #define bc_superfield all_bands[e_bc_superfield] #define bc_thismethod all_bands[e_bc_thismethod] diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/constants.h --- a/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/constants.h Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -49,61 +49,82 @@ #define JAVA6_PACKAGE_MAJOR_VERSION 160 #define JAVA6_PACKAGE_MINOR_VERSION 1 +#define JAVA7_PACKAGE_MAJOR_VERSION 170 +#define JAVA7_PACKAGE_MINOR_VERSION 1 // magic number for gzip streams (for processing pack200-gzip data) #define GZIP_MAGIC 0x1F8B0800 #define GZIP_MAGIC_MASK 0xFFFFFF00 // last byte is variable "flg" field enum { - CONSTANT_None, - CONSTANT_Utf8, - CONSTANT_unused2, /* unused, was Unicode */ - CONSTANT_Integer, - CONSTANT_Float, - CONSTANT_Long, - CONSTANT_Double, - CONSTANT_Class, - CONSTANT_String, - CONSTANT_Fieldref, - CONSTANT_Methodref, - CONSTANT_InterfaceMethodref, - CONSTANT_NameandType, + CONSTANT_None = 0, + CONSTANT_Utf8 = 1, + CONSTANT_unused = 2, /* unused, was Unicode */ + CONSTANT_Integer = 3, + CONSTANT_Float = 4, + CONSTANT_Long = 5, + CONSTANT_Double = 6, + CONSTANT_Class = 7, + CONSTANT_String = 8, + CONSTANT_Fieldref = 9, + CONSTANT_Methodref = 10, + CONSTANT_InterfaceMethodref = 11, + CONSTANT_NameandType = 12, + CONSTANT_unused13 = 13, + CONSTANT_unused14 = 14, + CONSTANT_MethodHandle = 15, + CONSTANT_MethodType = 16, + CONSTANT_unused17 = 17, + CONSTANT_InvokeDynamic = 18, + CONSTANT_Limit = 19, + CONSTANT_Signature = CONSTANT_unused13, + CONSTANT_BootstrapMethod = CONSTANT_unused17, // used only for InvokeDynamic + CONSTANT_All = 50, // combined global map + CONSTANT_LoadableValue = 51, // used for 'KL' and qldc operands + CONSTANT_AnyMember = 52, // union of refs to field or (interface) method + CONSTANT_FieldSpecific = 53, // used only for 'KQ' ConstantValue attrs + CONSTANT_GroupFirst = CONSTANT_All, // start group marker + CONSTANT_GroupLimit = 54, // end group marker - CONSTANT_Signature = 13, - CONSTANT_All = 14, - CONSTANT_Limit = 15, - CONSTANT_NONE = 0, - - CONSTANT_Literal = 20, //pseudo-tag for debugging - CONSTANT_Member = 21, //pseudo-tag for debugging + // CONSTANT_MethodHandle reference kinds + REF_getField = 1, + REF_getStatic = 2, + REF_putField = 3, + REF_putStatic = 4, + REF_invokeVirtual = 5, + REF_invokeStatic = 6, + REF_invokeSpecial = 7, + REF_newInvokeSpecial = 8, + REF_invokeInterface = 9, SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag ACC_STATIC = 0x0008, ACC_IC_LONG_FORM = (1<<16), //for ic_flags - CLASS_ATTR_SourceFile = 17, - CLASS_ATTR_EnclosingMethod = 18, - CLASS_ATTR_InnerClasses = 23, - CLASS_ATTR_ClassFile_version = 24, - FIELD_ATTR_ConstantValue = 17, - METHOD_ATTR_Code = 17, - METHOD_ATTR_Exceptions = 18, - METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23, + CLASS_ATTR_SourceFile = 17, + CLASS_ATTR_EnclosingMethod = 18, + CLASS_ATTR_InnerClasses = 23, + CLASS_ATTR_ClassFile_version = 24, + CLASS_ATTR_BootstrapMethods = 25, + FIELD_ATTR_ConstantValue = 17, + METHOD_ATTR_Code = 17, + METHOD_ATTR_Exceptions = 18, + METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23, METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24, - METHOD_ATTR_AnnotationDefault = 25, - CODE_ATTR_StackMapTable = 0, - CODE_ATTR_LineNumberTable = 1, - CODE_ATTR_LocalVariableTable = 2, + METHOD_ATTR_AnnotationDefault = 25, + CODE_ATTR_StackMapTable = 0, + CODE_ATTR_LineNumberTable = 1, + CODE_ATTR_LocalVariableTable = 2, CODE_ATTR_LocalVariableTypeTable = 3, //X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined - X_ATTR_Signature = 19, - X_ATTR_Deprecated = 20, - X_ATTR_RuntimeVisibleAnnotations = 21, + X_ATTR_Signature = 19, + X_ATTR_Deprecated = 20, + X_ATTR_RuntimeVisibleAnnotations = 21, X_ATTR_RuntimeInvisibleAnnotations = 22, - X_ATTR_OVERFLOW = 16, - X_ATTR_LIMIT_NO_FLAGS_HI = 32, - X_ATTR_LIMIT_FLAGS_HI = 63, + X_ATTR_OVERFLOW = 16, + X_ATTR_LIMIT_NO_FLAGS_HI = 32, + X_ATTR_LIMIT_FLAGS_HI = 63, #define O_ATTR_DO(F) \ F(X_ATTR_OVERFLOW,01) \ @@ -121,6 +142,7 @@ F(CLASS_ATTR_InnerClasses,InnerClasses) \ F(CLASS_ATTR_EnclosingMethod,EnclosingMethod) \ F(CLASS_ATTR_ClassFile_version,02) \ + F(CLASS_ATTR_BootstrapMethods,BootstrapMethods) \ /*(end)*/ #define FIELD_ATTR_DO(F) \ F(FIELD_ATTR_ConstantValue,ConstantValue) \ @@ -175,7 +197,7 @@ AO_HAVE_SPECIAL_FORMATS = 1<<0, AO_HAVE_CP_NUMBERS = 1<<1, AO_HAVE_ALL_CODE_FLAGS = 1<<2, - AO_3_UNUSED_MBZ = 1<<3, + AO_HAVE_CP_EXTRAS = 1<<3, AO_HAVE_FILE_HEADERS = 1<<4, AO_DEFLATE_HINT = 1<<5, AO_HAVE_FILE_MODTIME = 1<<6, @@ -185,11 +207,13 @@ AO_HAVE_FIELD_FLAGS_HI = 1<<10, AO_HAVE_METHOD_FLAGS_HI = 1<<11, AO_HAVE_CODE_FLAGS_HI = 1<<12, + AO_UNUSED_MBZ = (-1)<<13, // options bits reserved for future use. + #define ARCHIVE_BIT_DO(F) \ F(AO_HAVE_SPECIAL_FORMATS) \ F(AO_HAVE_CP_NUMBERS) \ F(AO_HAVE_ALL_CODE_FLAGS) \ - /*F(AO_3_UNUSED_MBZ)*/ \ + F(AO_HAVE_CP_EXTRAS) \ F(AO_HAVE_FILE_HEADERS) \ F(AO_DEFLATE_HINT) \ F(AO_HAVE_FILE_MODTIME) \ @@ -215,14 +239,14 @@ NO_MODTIME = 0, // null modtime value // meta-coding - _meta_default = 0, + _meta_default = 0, _meta_canon_min = 1, _meta_canon_max = 115, - _meta_arb = 116, - _meta_run = 117, - _meta_pop = 141, - _meta_limit = 189, - _meta_error = 255, + _meta_arb = 116, + _meta_run = 117, + _meta_pop = 141, + _meta_limit = 189, + _meta_error = 255, _xxx_1_end }; @@ -416,7 +440,7 @@ bc_invokespecial = 183, // 0xb7 bc_invokestatic = 184, // 0xb8 bc_invokeinterface = 185, // 0xb9 - bc_xxxunusedxxx = 186, // 0xba + bc_invokedynamic = 186, // 0xba bc_new = 187, // 0xbb bc_newarray = 188, // 0xbc bc_anewarray = 189, // 0xbd @@ -455,17 +479,19 @@ _invokeinit_limit = _invokeinit_op+3, _xldc_op = _invokeinit_limit, - bc_aldc = bc_ldc, + bc_sldc = bc_ldc, // previously named bc_aldc bc_cldc = _xldc_op+0, bc_ildc = _xldc_op+1, bc_fldc = _xldc_op+2, - bc_aldc_w = bc_ldc_w, + bc_sldc_w = bc_ldc_w, // previously named bc_aldc_w bc_cldc_w = _xldc_op+3, bc_ildc_w = _xldc_op+4, bc_fldc_w = _xldc_op+5, bc_lldc2_w = bc_ldc2_w, bc_dldc2_w = _xldc_op+6, - _xldc_limit = _xldc_op+7, - + // anything other primitive, string, or class must be handled with qldc: + bc_qldc = _xldc_op+7, + bc_qldc_w = _xldc_op+8, + _xldc_limit = _xldc_op+9, _xxx_3_end }; diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/defines.h --- a/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/defines.h Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -109,7 +109,8 @@ #define dup2(a,b) _dup2(a,b) #define strcasecmp(s1, s2) _stricmp(s1,s2) #define tempname _tempname -#define sleep Sleep +#define sleep Sleep +#define snprintf _snprintf #else typedef signed char byte; #ifdef _LP64 diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -81,7 +81,12 @@ CONSTANT_NameandType, CONSTANT_Fieldref, CONSTANT_Methodref, - CONSTANT_InterfaceMethodref + CONSTANT_InterfaceMethodref, + // constants defined as of JDK 7 + CONSTANT_MethodHandle, + CONSTANT_MethodType, + CONSTANT_BootstrapMethod, + CONSTANT_InvokeDynamic }; #define N_TAGS_IN_ORDER (sizeof TAGS_IN_ORDER) @@ -101,6 +106,11 @@ "InterfaceMethodref", "NameandType", "*Signature", + "unused14", + "MethodHandle", + "MethodType", + "*BootstrapMethod", + "InvokeDynamic", 0 }; @@ -114,9 +124,13 @@ #endif - -// REQUESTED must be -2 for u2 and REQUESTED_LDC must be -1 for u1 -enum { NOT_REQUESTED = 0, REQUESTED = -2, REQUESTED_LDC = -1 }; +// Note that REQUESTED_LDC comes first, then the normal REQUESTED, +// in the regular constant pool. +enum { REQUESTED_NONE = -1, + // The codes below REQUESTED_NONE are in constant pool output order, + // for the sake of outputEntry_cmp: + REQUESTED_LDC = -99, REQUESTED +}; #define NO_INORD ((uint)-1) @@ -146,7 +160,7 @@ void requestOutputIndex(cpool& cp, int req = REQUESTED); int getOutputIndex() { - assert(outputIndex > NOT_REQUESTED); + assert(outputIndex > REQUESTED_NONE); return outputIndex; } @@ -167,12 +181,12 @@ } entry* memberClass() { - assert(tagMatches(CONSTANT_Member)); + assert(tagMatches(CONSTANT_AnyMember)); return ref(0); } entry* memberDescr() { - assert(tagMatches(CONSTANT_Member)); + assert(tagMatches(CONSTANT_AnyMember)); return ref(1); } @@ -199,9 +213,9 @@ return (tag2 == tag) || (tag2 == CONSTANT_Utf8 && tag == CONSTANT_Signature) #ifndef PRODUCT - || (tag2 == CONSTANT_Literal + || (tag2 == CONSTANT_FieldSpecific && tag >= CONSTANT_Integer && tag <= CONSTANT_String && tag != CONSTANT_Class) - || (tag2 == CONSTANT_Member + || (tag2 == CONSTANT_AnyMember && tag >= CONSTANT_Fieldref && tag <= CONSTANT_InterfaceMethodref) #endif ; @@ -309,6 +323,7 @@ code_fixup_offset.free(); code_fixup_source.free(); requested_ics.free(); + cp.requested_bsms.free(); cur_classfile_head.free(); cur_classfile_tail.free(); for (i = 0; i < ATTR_CONTEXT_LIMIT; i++) @@ -448,12 +463,12 @@ int unpacker::putref_index(entry* e, int size) { if (e == null) return 0; - else if (e->outputIndex > NOT_REQUESTED) + else if (e->outputIndex > REQUESTED_NONE) return e->outputIndex; else if (e->tag == CONSTANT_Signature) return putref_index(e->ref(0), size); else { - e->requestOutputIndex(cp, -size); + e->requestOutputIndex(cp, (size == 1 ? REQUESTED_LDC : REQUESTED)); // Later on we'll fix the bits. class_fixup_type.addByte(size); class_fixup_offset.add((int)wpoffset()); @@ -515,28 +530,33 @@ b.copyFrom(ptr, len); } +bool testBit(int archive_options, int bitMask) { + return (archive_options & bitMask) != 0; +} + // Read up through band_headers. // Do the archive_size dance to set the size of the input mega-buffer. void unpacker::read_file_header() { // Read file header to determine file type and total size. enum { MAGIC_BYTES = 4, - AH_LENGTH_0 = 3, //minver, majver, options are outside of archive_size + AH_LENGTH_0 = 3, // archive_header_0 = {minver, majver, options} + AH_LENGTH_MIN = 15, // observed in spec {header_0[3], cp_counts[8], class_counts[4]} AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes - AH_LENGTH = 26, //maximum archive header length (w/ all fields) + AH_LENGTH = 30, //maximum archive header length (w/ all fields) // Length contributions from optional header fields: - AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files - AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN - AH_CP_NUMBER_LEN = 4, // int/float/long/double - AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers - AH_LENGTH_MIN = AH_LENGTH - -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN), - ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN), + AH_LENGTH_S = 2, // archive_header_S = optional {size_hi, size_lo} + AH_ARCHIVE_SIZE_HI = 0, // offset in archive_header_S + AH_ARCHIVE_SIZE_LO = 1, // offset in archive_header_S + AH_FILE_HEADER_LEN = 5, // file_counts = {{size_hi, size_lo), next, modtile, files} + AH_SPECIAL_FORMAT_LEN = 2, // special_count = {layouts, band_headers} + AH_CP_NUMBER_LEN = 4, // cp_number_counts = {int, float, long, double} + AH_CP_EXTRA_LEN = 4, // cp_attr_counts = {MH, MT, InDy, BSM} + ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S, FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN }; assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic - assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size // An absolute minimum null archive is magic[4], {minver,majver,options}[3], // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes. // (Note that archive_size is optional; it may be 0..10 bytes in length.) @@ -622,23 +642,32 @@ // Read the first 3 values from the header. value_stream hdr; int hdrVals = 0; - int hdrValsSkipped = 0; // debug only + int hdrValsSkipped = 0; // for assert hdr.init(rp, rplimit, UNSIGNED5_spec); minver = hdr.getInt(); majver = hdr.getInt(); hdrVals += 2; - if (magic != (int)JAVA_PACKAGE_MAGIC || - (majver != JAVA5_PACKAGE_MAJOR_VERSION && - majver != JAVA6_PACKAGE_MAJOR_VERSION) || - (minver != JAVA5_PACKAGE_MINOR_VERSION && - minver != JAVA6_PACKAGE_MINOR_VERSION)) { + int majmin[3][2] = { + {JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION}, + {JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION}, + {JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION} + }; + int majminfound = false; + for (int i = 0 ; i < 3 ; i++) { + if (majver == majmin[i][0] && minver == majmin[i][1]) { + majminfound = true; + break; + } + } + if (majminfound == null) { char message[200]; sprintf(message, "@" ERROR_FORMAT ": magic/ver = " - "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d\n", + "%08X/%d.%d should be %08X/%d.%d OR %08X/%d.%d OR %08X/%d.%d\n", magic, majver, minver, JAVA_PACKAGE_MAGIC, JAVA5_PACKAGE_MAJOR_VERSION, JAVA5_PACKAGE_MINOR_VERSION, - JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION); + JAVA_PACKAGE_MAGIC, JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION, + JAVA_PACKAGE_MAGIC, JAVA7_PACKAGE_MAJOR_VERSION, JAVA7_PACKAGE_MINOR_VERSION); abort(message); } CHECK; @@ -646,18 +675,26 @@ archive_options = hdr.getInt(); hdrVals += 1; assert(hdrVals == AH_LENGTH_0); // first three fields only - -#define ORBIT(bit) |(bit) - int OPTION_LIMIT = (0 ARCHIVE_BIT_DO(ORBIT)); -#undef ORBIT - if ((archive_options & ~OPTION_LIMIT) != 0) { - fprintf(errstrm, "Warning: Illegal archive options 0x%x\n", - archive_options); - abort("illegal archive options"); + bool haveSizeHi = testBit(archive_options, AO_HAVE_FILE_SIZE_HI); + bool haveModTime = testBit(archive_options, AO_HAVE_FILE_MODTIME); + bool haveFileOpt = testBit(archive_options, AO_HAVE_FILE_OPTIONS); + + bool haveSpecial = testBit(archive_options, AO_HAVE_SPECIAL_FORMATS); + bool haveFiles = testBit(archive_options, AO_HAVE_FILE_HEADERS); + bool haveNumbers = testBit(archive_options, AO_HAVE_CP_NUMBERS); + bool haveCPExtra = testBit(archive_options, AO_HAVE_CP_EXTRAS); + + if (majver < JAVA7_PACKAGE_MAJOR_VERSION) { + if (haveCPExtra) { + abort("Format bits for Java 7 must be zero in previous releases"); + return; + } + } + if (testBit(archive_options, AO_UNUSED_MBZ)) { + abort("High archive option bits are reserved and must be zero"); return; } - - if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) { + if (haveFiles) { uint hi = hdr.getInt(); uint lo = hdr.getInt(); julong x = band::makeLong(hi, lo); @@ -738,13 +775,23 @@ return; } - // read the rest of the header fields - ensure_input((AH_LENGTH-AH_LENGTH_0) * B_MAX); + // read the rest of the header fields int assertSkipped = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; + int remainingHeaders = AH_LENGTH_MIN - AH_LENGTH_0 - AH_LENGTH_S; + if (haveSpecial) + remainingHeaders += AH_SPECIAL_FORMAT_LEN; + if (haveFiles) + remainingHeaders += AH_FILE_HEADER_LEN; + if (haveNumbers) + remainingHeaders += AH_CP_NUMBER_LEN; + if (haveCPExtra) + remainingHeaders += AH_CP_EXTRA_LEN; + + ensure_input(remainingHeaders * B_MAX); CHECK; hdr.rp = rp; hdr.rplimit = rplimit; - if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) { + if (haveFiles) { archive_next_count = hdr.getInt(); CHECK_COUNT(archive_next_count); archive_modtime = hdr.getInt(); @@ -755,7 +802,7 @@ hdrValsSkipped += 3; } - if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) { + if (haveSpecial) { band_headers_size = hdr.getInt(); CHECK_COUNT(band_headers_size); attr_definition_count = hdr.getInt(); @@ -767,7 +814,7 @@ int cp_counts[N_TAGS_IN_ORDER]; for (int k = 0; k < (int)N_TAGS_IN_ORDER; k++) { - if (!(archive_options & AO_HAVE_CP_NUMBERS)) { + if (!haveNumbers) { switch (TAGS_IN_ORDER[k]) { case CONSTANT_Integer: case CONSTANT_Float: @@ -778,6 +825,17 @@ continue; } } + if (!haveCPExtra) { + switch(TAGS_IN_ORDER[k]) { + case CONSTANT_MethodHandle: + case CONSTANT_MethodType: + case CONSTANT_InvokeDynamic: + case CONSTANT_BootstrapMethod: + cp_counts[k] = 0; + hdrValsSkipped += 1; + continue; + } + } cp_counts[k] = hdr.getInt(); CHECK_COUNT(cp_counts[k]); hdrVals += 1; @@ -791,36 +849,26 @@ CHECK_COUNT(class_count); hdrVals += 4; - // done with archive_header + // done with archive_header, time to reconcile to ensure + // we have read everything correctly hdrVals += hdrValsSkipped; assert(hdrVals == AH_LENGTH); -#ifndef PRODUCT - int assertSkipped = AH_LENGTH - AH_LENGTH_MIN; - if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) - assertSkipped -= AH_FILE_HEADER_LEN; - if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) - assertSkipped -= AH_SPECIAL_FORMAT_LEN; - if ((archive_options & AO_HAVE_CP_NUMBERS) != 0) - assertSkipped -= AH_CP_NUMBER_LEN; - assert(hdrValsSkipped == assertSkipped); -#endif //PRODUCT - rp = hdr.rp; if (rp > rplimit) abort("EOF reading archive header"); // Now size the CP. #ifndef PRODUCT - bool x = (N_TAGS_IN_ORDER == cpool::NUM_COUNTS); - assert(x); + // bool x = (N_TAGS_IN_ORDER == CONSTANT_Limit); + // assert(x); #endif //PRODUCT cp.init(this, cp_counts); CHECK; default_file_modtime = archive_modtime; - if (default_file_modtime == 0 && !(archive_options & AO_HAVE_FILE_MODTIME)) + if (default_file_modtime == 0 && haveModTime) default_file_modtime = DEFAULT_ARCHIVE_MODTIME; // taken from driver - if ((archive_options & AO_DEFLATE_HINT) != 0) + if (testBit(archive_options, AO_DEFLATE_HINT)) default_file_options |= FO_DEFLATE_HINT; // meta-bytes, if any, immediately follow archive header @@ -876,7 +924,7 @@ // Cf. PackageReader.readConstantPoolCounts -void cpool::init(unpacker* u_, int counts[NUM_COUNTS]) { +void cpool::init(unpacker* u_, int counts[CONSTANT_Limit]) { this->u = u_; // Fill-pointer for CP. @@ -924,13 +972,16 @@ first_extra_entry = &entries[nentries]; // Initialize the standard indexes. - tag_count[CONSTANT_All] = nentries; - tag_base[ CONSTANT_All] = 0; for (int tag = 0; tag < CONSTANT_Limit; tag++) { entry* cpMap = &entries[tag_base[tag]]; tag_index[tag].init(tag_count[tag], cpMap, tag); } + // Initialize *all* our entries once + for (int i = 0 ; i < maxentries ; i++) + entries[i].outputIndex = REQUESTED_NONE; + + initGroupIndexes(); // Initialize hashTab to a generous power-of-two size. uint pow2 = 1; uint target = maxentries + maxentries/2; // 60% full @@ -1281,6 +1332,70 @@ //cp_Signature_classes.done(); } +maybe_inline +void unpacker::checkLegacy(const char* name) { + if (u->majver < JAVA7_PACKAGE_MAJOR_VERSION) { + char message[100]; + snprintf(message, 99, "unexpected band %s\n", name); + abort(message); + } +} + +maybe_inline +void unpacker::read_method_handle(entry* cpMap, int len) { + if (len > 0) { + checkLegacy(cp_MethodHandle_refkind.name); + } + cp_MethodHandle_refkind.readData(len); + cp_MethodHandle_member.setIndexByTag(CONSTANT_AnyMember); + cp_MethodHandle_member.readData(len); + for (int i = 0 ; i < len ; i++) { + entry& e = cpMap[i]; + e.value.i = cp_MethodHandle_refkind.getInt(); + e.refs = U_NEW(entry*, e.nrefs = 1); + e.refs[0] = cp_MethodHandle_member.getRef(); + CHECK; + } +} + +maybe_inline +void unpacker::read_method_type(entry* cpMap, int len) { + if (len > 0) { + checkLegacy(cp_MethodType.name); + } + cp_MethodType.setIndexByTag(CONSTANT_Signature); + cp_MethodType.readData(len); + for (int i = 0 ; i < len ; i++) { + entry& e = cpMap[i]; + e.refs = U_NEW(entry*, e.nrefs = 1); + e.refs[0] = cp_MethodType.getRef(); + } +} + +maybe_inline +void unpacker::read_bootstrap_methods(entry* cpMap, int len) { + if (len > 0) { + checkLegacy(cp_BootstrapMethod_ref.name); + } + cp_BootstrapMethod_ref.setIndexByTag(CONSTANT_MethodHandle); + cp_BootstrapMethod_ref.readData(len); + + cp_BootstrapMethod_arg_count.readData(len); + int totalArgCount = cp_BootstrapMethod_arg_count.getIntTotal(); + cp_BootstrapMethod_arg.setIndexByTag(CONSTANT_LoadableValue); + cp_BootstrapMethod_arg.readData(totalArgCount); + for (int i = 0; i < len; i++) { + entry& e = cpMap[i]; + int argc = cp_BootstrapMethod_arg_count.getInt(); + e.value.i = argc; + e.refs = U_NEW(entry*, e.nrefs = argc + 1); + e.refs[0] = cp_BootstrapMethod_ref.getRef(); + for (int j = 1 ; j < e.nrefs ; j++) { + e.refs[j] = cp_BootstrapMethod_arg.getRef(); + CHECK; + } + } +} // Cf. PackageReader.readConstantPool void unpacker::read_cp() { byte* rp0 = rp; @@ -1298,6 +1413,14 @@ cpMap[i].tag = tag; cpMap[i].inord = i; } + // Initialize the tag's CP index right away, since it might be needed + // in the next pass to initialize the CP for another tag. +#ifndef PRODUCT + cpindex* ix = &cp.tag_index[tag]; + assert(ix->ixTag == tag); + assert((int)ix->len == len); + assert(ix->base1 == cpMap); +#endif switch (tag) { case CONSTANT_Utf8: @@ -1344,19 +1467,27 @@ CONSTANT_Class, CONSTANT_NameandType, cpMap, len); break; + case CONSTANT_MethodHandle: + // consumes cp_MethodHandle_refkind and cp_MethodHandle_member + read_method_handle(cpMap, len); + break; + case CONSTANT_MethodType: + // consumes cp_MethodType + read_method_type(cpMap, len); + break; + case CONSTANT_InvokeDynamic: + read_double_refs(cp_InvokeDynamic_spec, CONSTANT_BootstrapMethod, + CONSTANT_NameandType, + cpMap, len); + break; + case CONSTANT_BootstrapMethod: + // consumes cp_BootstrapMethod_ref, cp_BootstrapMethod_arg_count and cp_BootstrapMethod_arg + read_bootstrap_methods(cpMap, len); + break; default: assert(false); break; } - - // Initialize the tag's CP index right away, since it might be needed - // in the next pass to initialize the CP for another tag. -#ifndef PRODUCT - cpindex* ix = &cp.tag_index[tag]; - assert(ix->ixTag == tag); - assert((int)ix->len == len); - assert(ix->base1 == cpMap); -#endif CHECK; } @@ -1791,7 +1922,12 @@ case 'F': ixTag = CONSTANT_Float; break; case 'D': ixTag = CONSTANT_Double; break; case 'S': ixTag = CONSTANT_String; break; - case 'Q': ixTag = CONSTANT_Literal; break; + case 'Q': ixTag = CONSTANT_FieldSpecific; break; + + // new in 1.7 + case 'M': ixTag = CONSTANT_MethodHandle; break; + case 'T': ixTag = CONSTANT_MethodType; break; + case 'L': ixTag = CONSTANT_LoadableValue; break; } } else { switch (*lp++) { @@ -1803,6 +1939,11 @@ case 'I': ixTag = CONSTANT_InterfaceMethodref; break; case 'U': ixTag = CONSTANT_Utf8; break; //utf8_ref case 'Q': ixTag = CONSTANT_All; break; //untyped_ref + + // new in 1.7 + case 'Y': ixTag = CONSTANT_InvokeDynamic; break; + case 'B': ixTag = CONSTANT_BootstrapMethod; break; + case 'N': ixTag = CONSTANT_AnyMember; break; } } if (ixTag == CONSTANT_None) { @@ -1873,13 +2014,13 @@ // Decide whether bands for the optional high flag words are present. attr_defs[ATTR_CONTEXT_CLASS] - .setHaveLongFlags((archive_options & AO_HAVE_CLASS_FLAGS_HI) != 0); + .setHaveLongFlags(testBit(archive_options, AO_HAVE_CLASS_FLAGS_HI)); attr_defs[ATTR_CONTEXT_FIELD] - .setHaveLongFlags((archive_options & AO_HAVE_FIELD_FLAGS_HI) != 0); + .setHaveLongFlags(testBit(archive_options, AO_HAVE_FIELD_FLAGS_HI)); attr_defs[ATTR_CONTEXT_METHOD] - .setHaveLongFlags((archive_options & AO_HAVE_METHOD_FLAGS_HI) != 0); + .setHaveLongFlags(testBit(archive_options, AO_HAVE_METHOD_FLAGS_HI)); attr_defs[ATTR_CONTEXT_CODE] - .setHaveLongFlags((archive_options & AO_HAVE_CODE_FLAGS_HI) != 0); + .setHaveLongFlags(testBit(archive_options, AO_HAVE_CODE_FLAGS_HI)); // Set up built-in attrs. // (The simple ones are hard-coded. The metadata layouts are not.) @@ -2579,7 +2720,7 @@ // It has data, so unparse an element. if (b.ixTag != CONSTANT_None) { assert(le_kind == EK_REF); - if (b.ixTag == CONSTANT_Literal) + if (b.ixTag == CONSTANT_FieldSpecific) e = b.getRefUsing(cp.getKQIndex()); else e = b.getRefN(); @@ -2653,13 +2794,13 @@ void unpacker::read_files() { file_name.readData(file_count); - if ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0) + if (testBit(archive_options, AO_HAVE_FILE_SIZE_HI)) file_size_hi.readData(file_count); file_size_lo.readData(file_count); - if ((archive_options & AO_HAVE_FILE_MODTIME) != 0) + if (testBit(archive_options, AO_HAVE_FILE_MODTIME)) file_modtime.readData(file_count); int allFiles = file_count + class_count; - if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0) { + if (testBit(archive_options, AO_HAVE_FILE_OPTIONS)) { file_options.readData(file_count); // FO_IS_CLASS_STUB might be set, causing overlap between classes and files for (int i = 0; i < file_count; i++) { @@ -2703,7 +2844,7 @@ max_stack = sc % mod; max_na_locals = sc / mod; // caller must add static, siglen handler_count = nh; - if ((archive_options & AO_HAVE_ALL_CODE_FLAGS) != 0) + if (testBit(archive_options, AO_HAVE_ALL_CODE_FLAGS)) cflags = -1; else cflags = 0; // this one has no attributes @@ -2777,12 +2918,14 @@ return &bc_longref; case bc_dldc2_w: return &bc_doubleref; - case bc_aldc: - case bc_aldc_w: + case bc_sldc: + case bc_sldc_w: return &bc_stringref; case bc_cldc: case bc_cldc_w: return &bc_classref; + case bc_qldc: case bc_qldc_w: + return &bc_loadablevalueref; case bc_getstatic: case bc_putstatic: @@ -2796,6 +2939,8 @@ return &bc_methodref; case bc_invokeinterface: return &bc_imethodref; + case bc_invokedynamic: + return &bc_indyref; case bc_new: case bc_anewarray: @@ -3131,6 +3276,71 @@ } } +bool isLoadableValue(int tag) { + switch(tag) { + case CONSTANT_Integer: + case CONSTANT_Float: + case CONSTANT_Long: + case CONSTANT_Double: + case CONSTANT_String: + case CONSTANT_Class: + case CONSTANT_MethodHandle: + case CONSTANT_MethodType: + return true; + default: + return false; + } +} +/* + * this method can be used to size an array using null as the parameter, + * thereafter can be reused to initialize the array using a valid pointer + * as a parameter. + */ +int cpool::initLoadableValues(entry** loadable_entries) { + int loadable_count = 0; + for (int i = 0; i < (int)N_TAGS_IN_ORDER; i++) { + int tag = TAGS_IN_ORDER[i]; + if (!isLoadableValue(tag)) + continue; + if (loadable_entries != NULL) { + for (int n = 0 ; n < tag_count[tag] ; n++) { + loadable_entries[loadable_count + n] = &entries[tag_base[tag] + n]; + } + } + loadable_count += tag_count[tag]; + } + return loadable_count; +} + +// Initialize various views into the constant pool. +void cpool::initGroupIndexes() { + // Initialize All + int all_count = 0; + for (int tag = CONSTANT_None ; tag < CONSTANT_Limit ; tag++) { + all_count += tag_count[tag]; + } + entry* all_entries = &entries[tag_base[CONSTANT_None]]; + tag_group_count[CONSTANT_All - CONSTANT_All] = all_count; + tag_group_index[CONSTANT_All - CONSTANT_All].init(all_count, all_entries, CONSTANT_All); + + // Initialize LoadableValues + int loadable_count = initLoadableValues(NULL); + entry** loadable_entries = U_NEW(entry*, loadable_count); + initLoadableValues(loadable_entries); + tag_group_count[CONSTANT_LoadableValue - CONSTANT_All] = loadable_count; + tag_group_index[CONSTANT_LoadableValue - CONSTANT_All].init(loadable_count, + loadable_entries, CONSTANT_LoadableValue); + +// Initialize AnyMembers + int any_count = tag_count[CONSTANT_Fieldref] + + tag_count[CONSTANT_Methodref] + + tag_count[CONSTANT_InterfaceMethodref]; + entry *any_entries = &entries[tag_base[CONSTANT_Fieldref]]; + tag_group_count[CONSTANT_AnyMember - CONSTANT_All] = any_count; + tag_group_index[CONSTANT_AnyMember - CONSTANT_All].init(any_count, + any_entries, CONSTANT_AnyMember); +} + void cpool::initMemberIndexes() { // This function does NOT refer to any class schema. // It is totally internal to the cpool. @@ -3238,13 +3448,13 @@ } void entry::requestOutputIndex(cpool& cp, int req) { - assert(outputIndex <= NOT_REQUESTED); // must not have assigned indexes yet + assert(outputIndex <= REQUESTED_NONE); // must not have assigned indexes yet if (tag == CONSTANT_Signature) { ref(0)->requestOutputIndex(cp, req); return; } assert(req == REQUESTED || req == REQUESTED_LDC); - if (outputIndex != NOT_REQUESTED) { + if (outputIndex != REQUESTED_NONE) { if (req == REQUESTED_LDC) outputIndex = req; // this kind has precedence return; @@ -3252,31 +3462,52 @@ outputIndex = req; //assert(!cp.outputEntries.contains(this)); assert(tag != CONSTANT_Signature); - cp.outputEntries.add(this); + // The BSMs are jetisoned to a side table, however all references + // that the BSMs refer to, need to be considered. + if (tag == CONSTANT_BootstrapMethod) { + // this is a a pseudo-op entry; an attribute will be generated later on + cp.requested_bsms.add(this); + } else { + // all other tag types go into real output file CP: + cp.outputEntries.add(this); + } for (int j = 0; j < nrefs; j++) { ref(j)->requestOutputIndex(cp); } } void cpool::resetOutputIndexes() { - int i; - int noes = outputEntries.length(); + /* + * reset those few entries that are being used in the current class + * (Caution since this method is called after every class written, a loop + * over every global constant pool entry would be a quadratic cost.) + */ + + int noes = outputEntries.length(); entry** oes = (entry**) outputEntries.base(); - for (i = 0; i < noes; i++) { + for (int i = 0 ; i < noes ; i++) { entry& e = *oes[i]; - e.outputIndex = NOT_REQUESTED; + e.outputIndex = REQUESTED_NONE; + } + + // do the same for bsms and reset them if required + int nbsms = requested_bsms.length(); + entry** boes = (entry**) requested_bsms.base(); + for (int i = 0 ; i < nbsms ; i++) { + entry& e = *boes[i]; + e.outputIndex = REQUESTED_NONE; } outputIndexLimit = 0; outputEntries.empty(); #ifndef PRODUCT - // they must all be clear now - for (i = 0; i < (int)nentries; i++) - assert(entries[i].outputIndex == NOT_REQUESTED); + // ensure things are cleared out + for (int i = 0; i < (int)maxentries; i++) + assert(entries[i].outputIndex == REQUESTED_NONE); #endif } static const byte TAG_ORDER[CONSTANT_Limit] = { - 0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8 + 0, 1, 0, 2, 3, 4, 5, 7, 6, 10, 11, 12, 9, 8, 0, 13, 14, 15, 16 }; extern "C" @@ -3323,10 +3554,18 @@ if (nentries > 100) checkStep = nentries / 100; for (i = (int)(checkStart++ % checkStep); i < (int)nentries; i += checkStep) { entry& e = entries[i]; - if (e.outputIndex != NOT_REQUESTED) { - assert(outputEntries.contains(&e)); + if (e.tag == CONSTANT_BootstrapMethod) { + if (e.outputIndex != REQUESTED_NONE) { + assert(requested_bsms.contains(&e)); + } else { + assert(!requested_bsms.contains(&e)); + } } else { - assert(!outputEntries.contains(&e)); + if (e.outputIndex != REQUESTED_NONE) { + assert(outputEntries.contains(&e)); + } else { + assert(!outputEntries.contains(&e)); + } } } @@ -3348,7 +3587,7 @@ int nextIndex = 1; // always skip index #0 in output cpool for (i = 0; i < noes; i++) { entry& e = *oes[i]; - assert(e.outputIndex == REQUESTED || e.outputIndex == REQUESTED_LDC); + assert(e.outputIndex >= REQUESTED_LDC); e.outputIndex = nextIndex++; if (e.isDoubleWord()) nextIndex++; // do not use the next index } @@ -3396,7 +3635,7 @@ default: if (nrefs == 0) { buf = getbuf(20); - sprintf((char*)buf.ptr, "", tag); + sprintf((char*)buf.ptr, TAG_NAME[tag]); } else if (nrefs == 1) { return refs[0]->string(); } else { @@ -3674,6 +3913,7 @@ class_fixup_offset.empty(); class_fixup_ref.empty(); requested_ics.empty(); + cp.requested_bsms.empty(); } cpindex* cpool::getKQIndex() { @@ -3931,13 +4171,15 @@ case bc_ildc: case bc_cldc: case bc_fldc: - case bc_aldc: + case bc_sldc: + case bc_qldc: origBC = bc_ldc; break; case bc_ildc_w: case bc_cldc_w: case bc_fldc_w: - case bc_aldc_w: + case bc_sldc_w: + case bc_qldc_w: origBC = bc_ldc_w; break; case bc_lldc2_w: @@ -3962,6 +4204,10 @@ int argSize = ref->memberDescr()->descrType()->typeSize(); putu1_fast(1 + argSize); putu1_fast(0); + } else if (origBC == bc_invokedynamic) { + // pad the next two byte + putu1_fast(0); + putu1_fast(0); } continue; } @@ -4353,49 +4599,12 @@ return (p1 > p2)? 1: (p1 < p2)? -1: 0; } -void unpacker::write_classfile_tail() { - cur_classfile_tail.empty(); - set_output(&cur_classfile_tail); - - int i, num; - - attr_definitions& ad = attr_defs[ATTR_CONTEXT_CLASS]; - - bool haveLongFlags = ad.haveLongFlags(); - julong kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags); - julong indexMask = ad.flagIndexMask(); - - cur_class = class_this.getRef(); - cur_super = class_super.getRef(); - - CHECK; - - if (cur_super == cur_class) cur_super = null; - // special representation for java/lang/Object - - putu2((ushort)(kflags & ~indexMask)); - putref(cur_class); - putref(cur_super); - - putu2(num = class_interface_count.getInt()); - for (i = 0; i < num; i++) { - putref(class_interface.getRef()); - } - - write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); - write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD); - CHECK; - - cur_class_has_local_ics = false; // may be set true by write_attrs - - - int naOffset = (int)wpoffset(); - int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask)); - - - // at the very last, choose which inner classes (if any) pertain to k: +/* + * writes the InnerClass attributes and returns the updated attribute + */ +int unpacker::write_ics(int naOffset, int na) { #ifdef ASSERT - for (i = 0; i < ic_count; i++) { + for (int i = 0; i < ic_count; i++) { assert(!ics[i].requested); } #endif @@ -4416,7 +4625,7 @@ // include it and all its outers. int noes = cp.outputEntries.length(); entry** oes = (entry**) cp.outputEntries.base(); - for (i = 0; i < noes; i++) { + for (int i = 0; i < noes; i++) { entry& e = *oes[i]; if (e.tag != CONSTANT_Class) continue; // wrong sort for (inner_class* ic = cp.getIC(&e); @@ -4442,10 +4651,10 @@ // Note: extra_ics will be freed up by next call to get_next_file(). } } - for (i = 0; i < num_extra_ics; i++) { + for (int i = 0; i < num_extra_ics; i++) { inner_class& extra_ic = extra_ics[i]; extra_ic.inner = class_InnerClasses_RC.getRef(); - CHECK; + CHECK_0; // Find the corresponding equivalent global IC: inner_class* global_ic = cp.getIC(extra_ic.inner); int flags = class_InnerClasses_F.getInt(); @@ -4493,7 +4702,7 @@ putu2(local_ics); PTRLIST_QSORT(requested_ics, raw_address_cmp); int num_global_ics = requested_ics.length(); - for (i = -num_global_ics; i < num_extra_ics; i++) { + for (int i = -num_global_ics; i < num_extra_ics; i++) { inner_class* ic; if (i < 0) ic = (inner_class*) requested_ics.get(num_global_ics+i); @@ -4512,17 +4721,99 @@ } // Tidy up global 'requested' bits: - for (i = requested_ics.length(); --i >= 0; ) { + for (int i = requested_ics.length(); --i >= 0; ) { inner_class* ic = (inner_class*) requested_ics.get(i); ic->requested = false; } requested_ics.empty(); - + return na; +} + +/* + * Writes the BootstrapMethods attribute and returns the updated attribute count + */ +int unpacker::write_bsms(int naOffset, int na) { + cur_class_local_bsm_count = cp.requested_bsms.length(); + if (cur_class_local_bsm_count > 0) { + int noes = cp.outputEntries.length(); + entry** oes = (entry**) cp.outputEntries.base(); + PTRLIST_QSORT(cp.requested_bsms, outputEntry_cmp); + // append the BootstrapMethods attribute (after the InnerClasses attr): + putref(cp.sym[cpool::s_BootstrapMethods]); + int sizeOffset = (int)wpoffset(); + byte* sizewp = wp; + putu4(-99); // attr size will be patched + putu2(cur_class_local_bsm_count); + int written_bsms = 0; + for (int i = 0 ; i < cur_class_local_bsm_count ; i++) { + entry* e = (entry*)cp.requested_bsms.get(i); + assert(e->outputIndex != REQUESTED_NONE); + // output index is the index within the array + e->outputIndex = i; + putref(e->refs[0]); // bsm + putu2(e->nrefs-1); // number of args after bsm + for (int j = 1; j < e->nrefs; j++) { + putref(e->refs[j]); + } + written_bsms += 1; + } + assert(written_bsms == cur_class_local_bsm_count); // else insane + putu4_at(sizewp, (int)(wp - (sizewp+4))); // size of code attr + putu2_at(wp_at(naOffset), ++na); // increment class attr count + } + return na; +} + +void unpacker::write_classfile_tail() { + + cur_classfile_tail.empty(); + set_output(&cur_classfile_tail); + + int i, num; + + attr_definitions& ad = attr_defs[ATTR_CONTEXT_CLASS]; + + bool haveLongFlags = ad.haveLongFlags(); + julong kflags = class_flags_hi.getLong(class_flags_lo, haveLongFlags); + julong indexMask = ad.flagIndexMask(); + + cur_class = class_this.getRef(); + cur_super = class_super.getRef(); CHECK; + + if (cur_super == cur_class) cur_super = null; + // special representation for java/lang/Object + + putu2((ushort)(kflags & ~indexMask)); + putref(cur_class); + putref(cur_super); + + putu2(num = class_interface_count.getInt()); + for (i = 0; i < num; i++) { + putref(class_interface.getRef()); + } + + write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD); + write_members(class_method_count.getInt(), ATTR_CONTEXT_METHOD); + CHECK; + + cur_class_has_local_ics = false; // may be set true by write_attrs + + int naOffset = (int)wpoffset(); // note the attr count location + int na = write_attrs(ATTR_CONTEXT_CLASS, (kflags & indexMask)); + CHECK; + + na = write_bsms(naOffset, na); + CHECK; + + // choose which inner classes (if any) pertain to k: + na = write_ics(naOffset, na); + CHECK; + close_output(); + cp.computeOutputIndexes(); // rewrite CP references in the tail - cp.computeOutputIndexes(); int nextref = 0; for (i = 0; i < (int)class_fixup_type.size(); i++) { int type = class_fixup_type.getByte(i); @@ -4579,9 +4870,18 @@ case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_NameandType: + case CONSTANT_InvokeDynamic: putu2(e.refs[0]->getOutputIndex()); putu2(e.refs[1]->getOutputIndex()); break; + case CONSTANT_MethodHandle: + putu1(e.value.i); + putu2(e.refs[0]->getOutputIndex()); + break; + case CONSTANT_MethodType: + putu2(e.refs[0]->getOutputIndex()); + break; + case CONSTANT_BootstrapMethod: // should not happen default: abort(ERROR_INTERNAL); } @@ -4620,11 +4920,11 @@ entry* e = file_name.getRef(); CHECK_0; cur_file.name = e->utf8String(); - bool haveLongSize = ((archive_options & AO_HAVE_FILE_SIZE_HI) != 0); + bool haveLongSize = (testBit(archive_options, AO_HAVE_FILE_SIZE_HI)); cur_file.size = file_size_hi.getLong(file_size_lo, haveLongSize); - if ((archive_options & AO_HAVE_FILE_MODTIME) != 0) + if (testBit(archive_options, AO_HAVE_FILE_MODTIME)) cur_file.modtime += file_modtime.getInt(); //relative to archive modtime - if ((archive_options & AO_HAVE_FILE_OPTIONS) != 0) + if (testBit(archive_options, AO_HAVE_FILE_OPTIONS)) cur_file.options |= file_options.getInt() & ~suppress_file_options; } else if (classes_written < class_count) { // there is a class for a missing file record diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.h Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -22,9 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - - - // Global Structures struct jar; struct gunzip; @@ -70,6 +67,9 @@ cpindex tag_index[CONSTANT_Limit]; ptrlist tag_extras[CONSTANT_Limit]; + int tag_group_count[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; + cpindex tag_group_index[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; + cpindex* member_indexes; // indexed by 2*CONSTANT_Class.inord cpindex* getFieldIndex(entry* classRef); cpindex* getMethodIndex(entry* classRef); @@ -82,6 +82,7 @@ int outputIndexLimit; // index limit after renumbering ptrlist outputEntries; // list of entry* needing output idx assigned + ptrlist requested_bsms; // which bsms need output? entry** hashTab; uint hashTabLength; @@ -100,24 +101,36 @@ entry* sym[s_LIMIT]; // read counts from hdr, allocate main arrays - enum { NUM_COUNTS = 12 }; - void init(unpacker* u, int counts[NUM_COUNTS]); + void init(unpacker* u, int counts[CONSTANT_Limit]); // pointer to outer unpacker, for error checks etc. unpacker* u; int getCount(byte tag) { - assert((uint)tag < CONSTANT_Limit); - return tag_count[tag]; + if ((uint)tag >= CONSTANT_GroupFirst) { + assert((uint)tag < CONSTANT_GroupLimit); + return tag_group_count[(uint)tag - CONSTANT_GroupFirst]; + } else { + assert((uint)tag < CONSTANT_Limit); + return tag_count[(uint)tag]; + } } cpindex* getIndex(byte tag) { - assert((uint)tag < CONSTANT_Limit); - return &tag_index[tag]; + if ((uint)tag >= CONSTANT_GroupFirst) { + assert((uint)tag < CONSTANT_GroupLimit); + return &tag_group_index[(uint)tag - CONSTANT_GroupFirst]; + } else { + assert((uint)tag < CONSTANT_Limit); + return &tag_index[(uint)tag]; + } } + cpindex* getKQIndex(); // uses cur_descr void expandSignatures(); + void initGroupIndexes(); void initMemberIndexes(); + int initLoadableValues(entry** loadable_entries); void computeOutputOrder(); void computeOutputIndexes(); @@ -234,6 +247,7 @@ int cur_descr_flags; // flags corresponding to cur_descr int cur_class_minver, cur_class_majver; bool cur_class_has_local_ics; + int cur_class_local_bsm_count; fillbytes cur_classfile_head; fillbytes cur_classfile_tail; int files_written; // also tells which file we're working on @@ -412,7 +426,7 @@ void abort(const char* s = null); bool aborting() { return abort_message != null; } static unpacker* current(); // find current instance - + void checkLegacy(const char* name); // Output management void set_output(fillbytes* which) { assert(wp == null); @@ -464,6 +478,8 @@ void write_bc_ops(); void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD int write_attrs(int attrc, julong indexBits); + int write_ics(int naOffset, int na); + int write_bsms(int naOffset, int na); // The readers void read_bands(); @@ -484,6 +500,9 @@ void read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len); void read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry* cpMap, int len); void read_signature_values(entry* cpMap, int len); + void read_method_handle(entry* cpMap, int len); + void read_method_type(entry* cpMap, int len); + void read_bootstrap_methods(entry* cpMap, int len); }; inline void cpool::abort(const char* msg) { u->abort(msg); } diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/java/util/zip/ZipFile.c --- a/jdk/src/share/native/java/util/zip/ZipFile.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/java/util/zip/ZipFile.c Wed May 09 13:13:41 2012 -0700 @@ -117,6 +117,7 @@ result = ptr_to_jlong(zip); } else if (msg != 0) { ThrowZipException(env, msg); + free(msg); } else if (errno == ENOMEM) { JNU_ThrowOutOfMemoryError(env, 0); } else { diff -r 070b00370cae -r 5904985dac0a jdk/src/share/native/java/util/zip/zip_util.c --- a/jdk/src/share/native/java/util/zip/zip_util.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/share/native/java/util/zip/zip_util.c Wed May 09 13:13:41 2012 -0700 @@ -726,7 +726,7 @@ * Opens a zip file with the specified mode. Returns the jzfile object * or NULL if an error occurred. If a zip error occurred then *pmsg will * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be - * set to NULL. + * set to NULL. Caller is responsible to free the error message. */ jzfile * ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified) @@ -751,12 +751,12 @@ * Returns the jzfile corresponding to the given file name from the cache of * zip files, or NULL if the file is not in the cache. If the name is longer * than PATH_MAX or a zip error occurred then *pmsg will be set to the error - * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. + * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller + * is responsible to free the error message. */ jzfile * ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified) { - static char errbuf[256]; char buf[PATH_MAX]; jzfile *zip; @@ -771,7 +771,7 @@ if (strlen(name) >= PATH_MAX) { if (pmsg) { - *pmsg = "zip file name too long"; + *pmsg = strdup("zip file name too long"); } return NULL; } @@ -796,7 +796,8 @@ * Reads data from the given file descriptor to create a jzfile, puts the * jzfile in a cache, and returns that jzfile. Returns NULL in case of error. * If a zip error occurs, then *pmsg will be set to the error message text if - * pmsg != 0. Otherwise, *pmsg will be set to NULL. + * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to + * free the error message. */ jzfile * @@ -809,7 +810,7 @@ ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, jboolean usemmap) { - static char errbuf[256]; + char errbuf[256]; jlong len; jzfile *zip; @@ -825,7 +826,7 @@ if (zfd == -1) { if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0) - *pmsg = errbuf; + *pmsg = strdup(errbuf); freeZip(zip); return NULL; } @@ -834,11 +835,11 @@ if (len <= 0) { if (len == 0) { /* zip file is empty */ if (pmsg) { - *pmsg = "zip file is empty"; + *pmsg = strdup("zip file is empty"); } } else { /* error */ if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0) - *pmsg = errbuf; + *pmsg = strdup(errbuf); } ZFILE_Close(zfd); freeZip(zip); @@ -850,7 +851,8 @@ /* An error occurred while trying to read the zip file */ if (pmsg != 0) { /* Set the zip error message */ - *pmsg = zip->msg; + if (zip->msg != NULL) + *pmsg = strdup(zip->msg); } freeZip(zip); return NULL; @@ -867,12 +869,17 @@ * Opens a zip file for reading. Returns the jzfile object or NULL * if an error occurred. If a zip error occurred then *msg will be * set to the error message text if msg != 0. Otherwise, *msg will be - * set to NULL. + * set to NULL. Caller doesn't need to free the error message. */ jzfile * JNICALL ZIP_Open(const char *name, char **pmsg) { - return ZIP_Open_Generic(name, pmsg, O_RDONLY, 0); + jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0); + if (file == NULL && pmsg != NULL && *pmsg != NULL) { + free(*pmsg); + *pmsg = "Zip file open error"; + } + return file; } /* diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/awt/X11/XTextAreaPeer.java --- a/jdk/src/solaris/classes/sun/awt/X11/XTextAreaPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11/XTextAreaPeer.java Wed May 09 13:13:41 2012 -0700 @@ -657,10 +657,13 @@ } - // TODO : fix this duplicate code - class XAWTCaret extends DefaultCaret { + static class XAWTCaret extends DefaultCaret { public void focusGained(FocusEvent e) { super.focusGained(e); + if (getComponent().isEnabled()){ + // Make sure the cursor is visible in case of non-editable TextArea + super.setVisible(true); + } getComponent().repaint(); } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java --- a/jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11/XTextFieldPeer.java Wed May 09 13:13:41 2012 -0700 @@ -578,31 +578,7 @@ } protected Caret createCaret() { - return new XAWTCaret(); - } - } - - class XAWTCaret extends DefaultCaret { - public void focusGained(FocusEvent e) { - super.focusGained(e); - getComponent().repaint(); - } - - public void focusLost(FocusEvent e) { - super.focusLost(e); - getComponent().repaint(); - } - - // Fix for 5100950: textarea.getSelectedText() returns the de-selected text, on XToolkit - // Restoring Motif behaviour - // If the text is unhighlighted then we should sets the selection range to zero - public void setSelectionVisible(boolean vis) { - if (vis){ - super.setSelectionVisible(vis); - }else{ - // In order to de-select the selection - setDot(getDot()); - } + return new XTextAreaPeer.XAWTCaret(); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/management/FileSystemImpl.java --- a/jdk/src/solaris/classes/sun/management/FileSystemImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/management/FileSystemImpl.java Wed May 09 13:13:41 2012 -0700 @@ -48,7 +48,12 @@ // Initialization static { - java.security.AccessController - .doPrivileged(new sun.security.action.LoadLibraryAction("management")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java --- a/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/net/dns/ResolverConfigurationImpl.java Wed May 09 13:13:41 2012 -0700 @@ -251,7 +251,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java --- a/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -50,7 +50,7 @@ return new SolarisAsynchronousChannelProvider(); if (osname.equals("Linux")) return new LinuxAsynchronousChannelProvider(); - if (osname.startsWith("Mac OS")) + if (osname.contains("OS X")) return new BsdAsynchronousChannelProvider(); throw new InternalError("platform not recognized"); } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Wed May 09 13:13:41 2012 -0700 @@ -1100,7 +1100,12 @@ static { Util.load(); /* loads nio & net native libraries */ java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("sctp")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("sctp"); + return null; + } + }); initIDs(); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Wed May 09 13:13:41 2012 -0700 @@ -989,6 +989,11 @@ static { Util.load(); /* loads nio & net native libraries */ java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("sctp")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("sctp"); + return null; + } + }); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java --- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java Wed May 09 13:13:41 2012 -0700 @@ -428,7 +428,12 @@ static { Util.load(); // loads nio & net native libraries java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("sctp")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("sctp"); + return null; + } + }); initIDs(); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java --- a/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -68,7 +68,7 @@ return createProvider("sun.nio.fs.SolarisFileSystemProvider"); if (osname.equals("Linux")) return createProvider("sun.nio.fs.LinuxFileSystemProvider"); - if (osname.equals("Darwin") || osname.startsWith("Mac OS X")) + if (osname.equals("Darwin") || osname.contains("OS X")) return createProvider("sun.nio.fs.BsdFileSystemProvider"); throw new AssertionError("Platform not recognized"); } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java Wed May 09 13:13:41 2012 -0700 @@ -314,7 +314,7 @@ fileKey2WatchKey.put(fileKey, watchKey); // register all entries in directory - registerChildren(dir, watchKey, false); + registerChildren(dir, watchKey, false, false); return watchKey; } @@ -486,7 +486,8 @@ void processDirectoryEvents(SolarisWatchKey key, int mask) { if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) { registerChildren(key.getDirectory(), key, - key.events().contains(StandardWatchEventKinds.ENTRY_CREATE)); + key.events().contains(StandardWatchEventKinds.ENTRY_CREATE), + key.events().contains(StandardWatchEventKinds.ENTRY_DELETE)); } } @@ -535,14 +536,16 @@ /** * Registers all entries in the given directory * - * The {@code sendEvents} parameter indicates if ENTRY_CREATE events - * should be queued when new entries are found. When initially - * registering a directory then will always be false. When re-scanning - * a directory then it depends on if the event is enabled or not. + * The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters + * indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued + * when new entries are found. When initially registering a directory + * they will always be false. When re-scanning a directory then it + * depends on if the events are enabled or not. */ void registerChildren(UnixPath dir, SolarisWatchKey parent, - boolean sendEvents) + boolean sendCreateEvents, + boolean sendDeleteEvents) { // if the ENTRY_MODIFY event is not enabled then we don't need // modification events for entries in the directory @@ -550,14 +553,7 @@ if (parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY)) events |= (FILE_MODIFIED | FILE_ATTRIB); - DirectoryStream stream = null; - try { - stream = Files.newDirectoryStream(dir); - } catch (IOException x) { - // nothing we can do - return; - } - try { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { for (Path entry: stream) { Path name = entry.getFileName(); @@ -565,32 +561,34 @@ if (parent.getChild(name) != null) continue; - // send ENTRY_CREATE if enabled - if (sendEvents) { - parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name); - } - - // register it + // attempt to register entry long object = 0L; + int errno = 0; try { object = registerImpl((UnixPath)entry, events); } catch (UnixException x) { - // can't register so ignore for now. - continue; + errno = x.errno(); } - // create node - EntryNode node = new EntryNode(object, entry.getFileName(), parent); - // tell the parent about it - parent.addChild(entry.getFileName(), node); - object2Node.put(object, node); + boolean registered = (object != 0L); + boolean deleted = (errno == ENOENT); + + if (registered) { + // create node + EntryNode node = new EntryNode(object, entry.getFileName(), parent); + // tell the parent about it + parent.addChild(entry.getFileName(), node); + object2Node.put(object, node); + } + + if (sendCreateEvents && (registered || deleted)) + parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name); + if (sendDeleteEvents && deleted) + parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name); + } - } catch (ConcurrentModificationException x) { - // error during iteration which we ignore for now - } finally { - try { - stream.close(); - } catch (IOException x) { } + } catch (DirectoryIteratorException | IOException x) { + // nothing we can do } } diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/print/CUPSPrinter.java --- a/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Wed May 09 13:13:41 2012 -0700 @@ -77,7 +77,12 @@ static { // load awt library to access native code java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); libFound = initIDs(); if (libFound) { cupsServer = getCupsServer(); diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java --- a/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Wed May 09 13:13:41 2012 -0700 @@ -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 @@ -120,7 +120,7 @@ static boolean isBSD() { return (osname.equals("Linux") || - osname.startsWith("Mac OS X")); + osname.contains("OS X")); } static final int UNINITIALIZED = -1; diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c --- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Wed May 09 13:13:41 2012 -0700 @@ -84,6 +84,7 @@ #endif extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him); +extern int getDefaultScopeID(JNIEnv *env); /* * Returns a java.lang.Integer based on 'i' @@ -2418,7 +2419,11 @@ } } #endif - +#ifdef MACOSX + if (family == AF_INET6 && index == 0) { + index = getDefaultScopeID(env); + } +#endif mname6.ipv6mr_interface = index; } else { jint idx = (*env)->GetIntField(env, niObj, ni_indexID); diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/native/java/net/net_util_md.c --- a/jdk/src/solaris/native/java/net/net_util_md.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/native/java/net/net_util_md.c Wed May 09 13:13:41 2012 -0700 @@ -109,6 +109,24 @@ #endif } +int getDefaultScopeID(JNIEnv *env) { + static jclass ni_class = NULL; + static jfieldID ni_defaultIndexID; + if (ni_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL(c); + c = (*env)->NewGlobalRef(env, c); + CHECK_NULL(c); + ni_defaultIndexID = (*env)->GetStaticFieldID(env, c, + "defaultIndex", "I"); + ni_class = c; + } + int defaultIndex = 0; + defaultIndex = (*env)->GetStaticIntField(env, ni_class, + ni_defaultIndexID); + return defaultIndex; +} + #ifdef __solaris__ static int init_tcp_max_buf, init_udp_max_buf; static int tcp_max_buf; diff -r 070b00370cae -r 5904985dac0a jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c --- a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Wed May 09 13:13:41 2012 -0700 @@ -77,7 +77,7 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this, - jobject fdo) + jobject fdo, jboolean isIPv6) { jint fd = fdval(env, fdo); int rv; @@ -94,7 +94,7 @@ memset(&sa, 0, sizeof(sa)); #ifdef AF_INET6 - if (ipv6_available()) { + if (isIPv6) { struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&sa; #if defined(_ALLBSD_SOURCE) him6->sin6_family = AF_INET6; diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java --- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed May 09 13:13:41 2012 -0700 @@ -37,8 +37,6 @@ import java.util.List; import java.util.concurrent.*; -import sun.security.action.LoadLibraryAction; - import static sun.awt.shell.Win32ShellFolder2.*; import sun.awt.OSInfo; @@ -56,7 +54,13 @@ static { // Load library here - AccessController.doPrivileged(new LoadLibraryAction("awt")); + AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } public ShellFolder createShellFolder(File file) throws FileNotFoundException { diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/awt/windows/WToolkit.java --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed May 09 13:13:41 2012 -0700 @@ -94,7 +94,12 @@ public static void loadLibraries() { if (!loaded) { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); loaded = true; } } diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/management/FileSystemImpl.java --- a/jdk/src/windows/classes/sun/management/FileSystemImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/management/FileSystemImpl.java Wed May 09 13:13:41 2012 -0700 @@ -56,8 +56,13 @@ // Initialization static { - java.security.AccessController - .doPrivileged(new sun.security.action.LoadLibraryAction("management")); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); init0(); } } diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java --- a/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/net/dns/ResolverConfigurationImpl.java Wed May 09 13:13:41 2012 -0700 @@ -161,7 +161,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + return null; + } + }); init0(); // start the address listener thread diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/print/Win32PrintServiceLookup.java --- a/jdk/src/windows/classes/sun/print/Win32PrintServiceLookup.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/print/Win32PrintServiceLookup.java Wed May 09 13:13:41 2012 -0700 @@ -56,7 +56,12 @@ static { java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("awt")); + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("awt"); + return null; + } + }); } /* The singleton win32 print lookup service. diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/classes/sun/security/smartcardio/PlatformPCSC.java --- a/jdk/src/windows/classes/sun/security/smartcardio/PlatformPCSC.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/classes/sun/security/smartcardio/PlatformPCSC.java Wed May 09 13:13:41 2012 -0700 @@ -26,8 +26,7 @@ package sun.security.smartcardio; import java.security.AccessController; - -import sun.security.action.LoadLibraryAction; +import java.security.PrivilegedAction; // Platform specific code and constants class PlatformPCSC { @@ -44,7 +43,12 @@ private static Throwable loadLibrary() { try { - AccessController.doPrivileged(new LoadLibraryAction("j2pcsc")); + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("j2pcsc"); + return null; + } + }); return null; } catch (Throwable e) { return e; diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/native/java/net/NetworkInterface.c --- a/jdk/src/windows/native/java/net/NetworkInterface.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/native/java/net/NetworkInterface.c Wed May 09 13:13:41 2012 -0700 @@ -178,7 +178,7 @@ int count; netif *netifP; DWORD i; - int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, net=0; + int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0; /* * Ask the IP Helper library to enumerate the adapters @@ -218,15 +218,15 @@ */ switch (ifrowP->dwType) { case MIB_IF_TYPE_ETHERNET: - sprintf(dev_name, "eth%d", eth++); + _snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++); break; case MIB_IF_TYPE_TOKENRING: - sprintf(dev_name, "tr%d", tr++); + _snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++); break; case MIB_IF_TYPE_FDDI: - sprintf(dev_name, "fddi%d", fddi++); + _snprintf_s(dev_name, 8, _TRUNCATE, "fddi%d", fddi++); break; case MIB_IF_TYPE_LOOPBACK: @@ -234,20 +234,24 @@ if (lo > 0) { continue; } - strcpy(dev_name, "lo"); + strncpy_s(dev_name, 8, "lo", _TRUNCATE); lo++; break; case MIB_IF_TYPE_PPP: - sprintf(dev_name, "ppp%d", ppp++); + _snprintf_s(dev_name, 8, _TRUNCATE, "ppp%d", ppp++); break; case MIB_IF_TYPE_SLIP: - sprintf(dev_name, "sl%d", sl++); + _snprintf_s(dev_name, 8, _TRUNCATE, "sl%d", sl++); + break; + + case IF_TYPE_IEEE80211: + _snprintf_s(dev_name, 8, _TRUNCATE, "wlan%d", wlan++); break; default: - sprintf(dev_name, "net%d", net++); + _snprintf_s(dev_name, 8, _TRUNCATE, "net%d", net++); } /* @@ -382,6 +386,7 @@ case MIB_IF_TYPE_TOKENRING: case MIB_IF_TYPE_FDDI: case MIB_IF_TYPE_LOOPBACK: + case IF_TYPE_IEEE80211: /** * Contrary to what it seems to indicate, dwBCastAddr doesn't * contain the broadcast address but 0 or 1 depending on whether @@ -928,6 +933,7 @@ case MIB_IF_TYPE_ETHERNET: case MIB_IF_TYPE_TOKENRING: case MIB_IF_TYPE_FDDI: + case IF_TYPE_IEEE80211: len = ifRowP->dwPhysAddrLen; ret = (*env)->NewByteArray(env, len); if (!IS_NULL(ret)) { diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/native/java/net/NetworkInterface.h --- a/jdk/src/windows/native/java/net/NetworkInterface.h Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/native/java/net/NetworkInterface.h Wed May 09 13:13:41 2012 -0700 @@ -89,4 +89,9 @@ int enumInterfaces(JNIEnv *env, netif **netifPP); +// Windows Visa (and later) only..... +#ifndef IF_TYPE_IEEE80211 +#define IF_TYPE_IEEE80211 71 #endif + +#endif diff -r 070b00370cae -r 5904985dac0a jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c --- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Wed May 09 13:07:57 2012 -0700 +++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Wed May 09 13:13:41 2012 -0700 @@ -108,7 +108,7 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this, - jobject fdo) + jobject fdo, jboolean isIPv6) { jint fd = fdval(env, fdo); int rv = 0; diff -r 070b00370cae -r 5904985dac0a jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/ProblemList.txt Wed May 09 13:13:41 2012 -0700 @@ -286,13 +286,13 @@ # Failing on Solaris i586, 3/9/2010, not a -samevm issue (jdk_security3) sun/security/pkcs11/Secmod/AddPrivateKey.java solaris-i586 -sun/security/pkcs11/ec/ReadCertificates.java solaris-i586 -sun/security/pkcs11/ec/ReadPKCS12.java solaris-i586 +sun/security/pkcs11/ec/ReadCertificates.java generic-all +sun/security/pkcs11/ec/ReadPKCS12.java generic-all sun/security/pkcs11/ec/TestCurves.java solaris-i586 sun/security/pkcs11/ec/TestECDSA.java solaris-i586 #sun/security/pkcs11/ec/TestECGenSpec.java solaris-i586 #sun/security/pkcs11/ec/TestKeyFactory.java solaris-i586 -sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java solaris-i586 +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java generic-all # Fails on Fedora 9/Ubuntu 10.04 64bit, PKCS11Exception: CKR_DEVICE_ERROR sun/security/pkcs11/KeyAgreement/TestDH.java generic-all diff -r 070b00370cae -r 5904985dac0a jdk/test/com/sun/crypto/provider/Mac/MacClone.java --- a/jdk/test/com/sun/crypto/provider/Mac/MacClone.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/com/sun/crypto/provider/Mac/MacClone.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 0000000 + * @bug 7087021 * @summary MacClone * @author Jan Luehe */ @@ -56,7 +56,7 @@ KeyGenerator kgen = KeyGenerator.getInstance("DES"); SecretKey skey = kgen.generateKey(); - mac = Mac.getInstance("HmacSHA1"); + mac = Mac.getInstance("HmacSHA1", "SunJCE"); mac.init(skey); macClone = (Mac)mac.clone(); System.out.println(macClone.getProvider().toString()); diff -r 070b00370cae -r 5904985dac0a jdk/test/demo/jvmti/DemoRun.java --- a/jdk/test/demo/jvmti/DemoRun.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/demo/jvmti/DemoRun.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -124,7 +124,7 @@ String os_name = System.getProperty("os.name"); String libprefix = os_name.contains("Windows")?"":"lib"; String libsuffix = os_name.contains("Windows")?".dll": - os_name.startsWith("Mac OS")?".dylib":".so"; + os_name.contains("OS X")?".dylib":".so"; boolean d64 = ( os_name.contains("Solaris") || os_name.contains("SunOS") ) && ( os_arch.equals("sparcv9") || diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.html Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,50 @@ + + + + + FrameStateTest + + + +

FrameStateTest
Bug ID: 4157271

+

This test checks that when setState(Frame.ICONIFIED) is called before + setVisible(true) the Frame is shown in the proper iconified state. + The problem was that it did not honor the initial iconic state, but + instead was shown in the NORMAL state.

+

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

+ + + + diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Frame/FrameStateTest/FrameStateTest.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 4157271 + @summary Checks that when a Frame is created it honors the state it + was set to. The bug was that if setState(Frame.ICONIFIED) was + called before setVisible(true) the Frame would be shown in NORMAL + state instead of ICONIFIED. + @author JTG East Team: area=awt.Frame + @run applet/manual=yesno FrameStateTest.html +*/ + +/** + * FrameStateTest.java + * + * summary: Checks that when setState(Frame.ICONIFIED) is called before + * setVisible(true) the Frame is shown in the proper iconified state. + * The problem was that it did not honor the initial iconic state, but + * instead was shown in the NORMAL state. + */ + +import java.awt.event.*; +import java.awt.*; +import java.lang.*; +import java.applet.Applet; + + +public class FrameStateTest extends Applet implements ActionListener, ItemListener{ + + Button btnCreate = new Button("Create Frame"); + Button btnDispose = new Button("Dispose Frame"); + CheckboxGroup cbgState = new CheckboxGroup(); + CheckboxGroup cbgResize = new CheckboxGroup(); + Checkbox cbIconState = new Checkbox("Frame state ICONIFIED",cbgState,false); + Checkbox cbNormState = new Checkbox("Frame state NORMAL",cbgState,true); + Checkbox cbNonResize = new Checkbox("Frame Nonresizable",cbgResize,false); + Checkbox cbResize = new Checkbox("Frame Resizable",cbgResize,true); + int iState = 0; + boolean bResize = true; + CreateFrame icontst; + + public void init() { + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + "Steps to try to reproduce this problem:", + "When this test is run an Applet Viewer window will display. In the", + "Applet Viewer window select the different options for the Frame (i.e.", + "{Normal, Non-resizalbe}, {Normal, Resizable}, {Iconified, Resizable},", + "{Iconified, Non-resizalbe}). After chosing the Frame's state click the", + "Create Frame button. After the Frame (Frame State Test (Window2)) comes", + "up make sure the proper behavior occurred (Frame shown in proper state).", + "Click the Dispose button to close the Frame. Do the above steps for all", + "the different Frame state combinations available. If you observe the", + "proper behavior the test has passed, Press the Pass button. Otherwise", + "the test has failed, Press the Fail button.", + "Note: In Frame State Test (Window2) you can also chose the different", + "buttons to see different Frame behavior. An example of a problem that", + "has been seen, With the Frame nonresizable you can not iconify the Frame." + }; + Sysout.createDialogWithInstructions( instructions ); + + btnDispose.setEnabled(false); + add(btnCreate, BorderLayout.NORTH); + add(btnDispose, BorderLayout.SOUTH); + + Panel p = new Panel(new GridLayout(0,1)); + p.add(cbIconState); + p.add(cbResize); + add(p, BorderLayout.WEST); + + p = new Panel(new GridLayout(0,1)); + p.add(cbNormState); + p.add(cbNonResize); + add(p, BorderLayout.EAST); + + // Add Listeners + btnDispose.addActionListener(this); + btnCreate.addActionListener(this); + cbNormState.addItemListener(this); + cbResize.addItemListener(this); + cbIconState.addItemListener(this); + cbNonResize.addItemListener(this); + + resize(600, 200); + + }//End init() + + public void actionPerformed(ActionEvent evt) { + + + if (evt.getSource() == btnCreate) { + btnCreate.setEnabled(false); + btnDispose.setEnabled(true); + icontst = new CreateFrame(iState, bResize); + icontst.show(); + } else if (evt.getSource() == btnDispose) { + btnCreate.setEnabled(true); + btnDispose.setEnabled(false); + icontst.dispose(); + } + } + + public void itemStateChanged(ItemEvent evt) { + + if (cbNormState.getState()) iState = 0; + if (cbIconState.getState()) iState = 1; + if (cbResize.getState()) bResize = true; + if (cbNonResize.getState()) bResize = false; + + } + +}// class FrameStateTest + + +class CreateFrame extends Frame implements ActionListener , WindowListener { + + static int e=0; + static int u=0; + static int p=0; + static int i=0; + static int v=0; + + Button b1, b2, b3, b4, b5, b6, b7; + boolean resizable = true; + boolean iconic = false; + String name = "Frame State Test"; + + CreateFrame (int iFrameState, boolean bFrameResizable) { + + setTitle("Frame State Test (Window 2)"); + + if (iFrameState == 1) { + iconic = true; + } + + if (!(bFrameResizable)) { + resizable = false; + } + + System.out.println("CREATING FRAME - Initially "+ + ((iconic) ? "ICONIFIED" : "NORMAL (NON-ICONIFIED)") + " and " + + ((resizable) ? "RESIZABLE" : "NON-RESIZABLE") ); + + Sysout.println("CREATING FRAME - Initially "+ + ((iconic) ? "ICONIFIED" : "NORMAL (NON-ICONIFIED)") + " and " + + ((resizable) ? "RESIZABLE" : "NON-RESIZABLE") ); + + setLayout(new FlowLayout() ); + b1 = new Button("resizable"); + add(b1); + b2 = new Button("resize"); + add(b2); + b3 = new Button("iconify"); + add(b3); + b4 = new Button("iconify and restore"); + add(b4); + b5 = new Button("hide and show"); + add(b5); + b6 = new Button("hide, iconify and show"); + add(b6); + b7 = new Button("hide, iconify, show, and restore"); + add(b7); + b1.addActionListener(this); + b2.addActionListener(this); + b3.addActionListener(this); + b4.addActionListener(this); + b5.addActionListener(this); + b6.addActionListener(this); + b7.addActionListener(this); + addWindowListener(this); + + setBounds(100,2,200, 200); + setState(iconic ? Frame.ICONIFIED: Frame.NORMAL); + setResizable(resizable); + pack(); + setVisible(true); + + } + + public void actionPerformed ( ActionEvent e ) + { + if ( e.getSource() == b2 ) { + Rectangle r = this.getBounds(); + r.width += 10; + System.out.println(" - button pressed - setting bounds on Frame to: "+r); + setBounds(r); + validate(); + } else if ( e.getSource() == b1 ) { + resizable = !resizable; + System.out.println(" - button pressed - setting Resizable to: "+resizable); + ((Frame)(b1.getParent())).setResizable(resizable); + } else if ( e.getSource() == b3 ) { + System.out.println(" - button pressed - setting Iconic: "); + dolog(); + ((Frame)(b1.getParent())).setState(Frame.ICONIFIED); + dolog(); + } else if ( e.getSource() == b4 ) { + System.out.println(" - button pressed - setting Iconic: "); + dolog(); + ((Frame)(b1.getParent())).setState(Frame.ICONIFIED); + dolog(); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - now restoring: "); + ((Frame)(b1.getParent())).setState(Frame.NORMAL); + dolog(); + } else if ( e.getSource() == b5 ) { + System.out.println(" - button pressed - hiding : "); + dolog(); + ((Frame)(b1.getParent())).setVisible(false); + dolog(); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - now reshowing: "); + ((Frame)(b1.getParent())).setVisible(true); + dolog(); + } else if ( e.getSource() == b6 ) { + System.out.println(" - button pressed - hiding : "); + dolog(); + ((Frame)(b1.getParent())).setVisible(false); + dolog(); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - setting Iconic: "); + dolog(); + ((Frame)(b1.getParent())).setState(Frame.ICONIFIED); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - now reshowing: "); + ((Frame)(b1.getParent())).setVisible(true); + dolog(); + } else if ( e.getSource() == b7 ) { + System.out.println(" - button pressed - hiding : "); + dolog(); + ((Frame)(b1.getParent())).setVisible(false); + dolog(); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - setting Iconic: "); + dolog(); + ((Frame)(b1.getParent())).setState(Frame.ICONIFIED); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - now reshowing: "); + ((Frame)(b1.getParent())).setVisible(true); + dolog(); + try { + Thread.sleep(1000); + } catch (Exception ex) {}; + System.out.println(" - now restoring: "); + ((Frame)(b1.getParent())).setState(Frame.NORMAL); + dolog(); + } + } + + public void windowActivated(WindowEvent e) { + System.out.println(name + " Activated"); + dolog(); + } + public void windowClosed(WindowEvent e) { + System.out.println(name + " Closed"); + dolog(); + } + public void windowClosing(WindowEvent e) { + ((Window)(e.getSource())).dispose(); + System.out.println(name + " Closing"); + dolog(); + } + public void windowDeactivated(WindowEvent e) { + System.out.println(name + " Deactivated"); + dolog(); + } + public void windowDeiconified(WindowEvent e) { + System.out.println(name + " Deiconified"); + dolog(); + } + public void windowIconified(WindowEvent e) { + System.out.println(name + " Iconified"); + dolog(); + } + public void windowOpened(WindowEvent e) { + System.out.println(name + " Opened"); + dolog(); + } + + public void dolog() { + System.out.println(" getState returns: "+getState()); + } +} + +// }// class FrameStateTest + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + + }// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + int scrollNone = TextArea.SCROLLBARS_NONE; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 10, maxStringLength, scrollBoth ); + add("South", messageText); + + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + + + }// TestDialog class diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7154048 + * @summary Window created under a mouse does not receive mouse enter event. + * Mouse Entered/Exited events should be generated during dragging the window + * out of the frame and to the frame. + * @library ../../regtesthelpers + * @build Util + * @author alexandr.scherbatiy area=awt.event + * @run main DragWindowOutOfFrameTest + */ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import java.util.concurrent.*; +import sun.awt.SunToolkit; + +import test.java.awt.regtesthelpers.Util; + +public class DragWindowOutOfFrameTest { + + private static volatile int dragWindowMouseEnteredCount = 0; + private static volatile int dragWindowMouseExitedCount = 0; + private static volatile int dragWindowMouseReleasedCount = 0; + private static volatile int buttonMouseEnteredCount = 0; + private static volatile int buttonMouseExitedCount = 0; + private static volatile int labelMouseEnteredCount = 0; + private static volatile int labelMouseExitedCount = 0; + private static volatile int labelMouseReleasedCount = 0; + private static MyDragWindow dragWindow; + private static JLabel label; + private static JButton button; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point pointToClick = Util.invokeOnEDT(new Callable() { + + @Override + public Point call() throws Exception { + return getCenterPoint(label); + } + }); + + + robot.mouseMove(pointToClick.x, pointToClick.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (dragWindowMouseEnteredCount != 1 && dragWindowMouseExitedCount != 0) { + throw new RuntimeException( + "Wrong number mouse Entered/Exited events on Drag Window!"); + } + + Point pointToDrag = Util.invokeOnEDT(new Callable() { + + @Override + public Point call() throws Exception { + label.addMouseListener(new LabelMouseListener()); + button.addMouseListener(new ButtonMouseListener()); + return getCenterPoint(button); + } + }); + + robot.mouseMove(450, pointToClick.y); + toolkit.realSync(); + + if (labelMouseEnteredCount != 0 && labelMouseExitedCount != 1) { + throw new RuntimeException( + "Wrong number Mouse Entered/Exited events on label!"); + } + + robot.mouseMove(450, pointToDrag.y); + toolkit.realSync(); + + if (labelMouseEnteredCount != 0 && labelMouseExitedCount != 1) { + throw new RuntimeException( + "Wrong number Mouse Entered/Exited events on label!"); + } + + if (buttonMouseEnteredCount != 0 && buttonMouseExitedCount != 0) { + throw new RuntimeException( + "Wrong number Mouse Entered/Exited events on button!"); + } + + robot.mouseMove(pointToDrag.y, pointToDrag.y); + toolkit.realSync(); + + if (buttonMouseEnteredCount != 1 && buttonMouseExitedCount != 0) { + throw new RuntimeException( + "Wrong number Mouse Entered/Exited events on button!"); + } + + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (labelMouseReleasedCount != 1) { + throw new RuntimeException("No MouseReleased event on label!"); + } + } + + private static Point getCenterPoint(Component comp) { + Point p = comp.getLocationOnScreen(); + Rectangle rect = comp.getBounds(); + return new Point(p.x + rect.width / 2, p.y + rect.height / 2); + } + + private static void createAndShowGUI() { + + JFrame frame = new JFrame("Main Frame"); + frame.setLocation(100, 100); + frame.setSize(300, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + label = new JLabel("Label"); + + DragWindowCreationMouseListener listener = new DragWindowCreationMouseListener(frame); + label.addMouseListener(listener); + label.addMouseMotionListener(listener); + + button = new JButton("Button"); + Panel panel = new Panel(new BorderLayout()); + + panel.add(label, BorderLayout.NORTH); + panel.add(button, BorderLayout.CENTER); + + frame.getContentPane().add(panel); + frame.setVisible(true); + + } + + private static Point getAbsoluteLocation(MouseEvent e) { + return new Point(e.getXOnScreen(), e.getYOnScreen()); + } + + static class MyDragWindow extends Window { + + public MyDragWindow(Window parent, Point location) { + super(parent); + setSize(500, 300); + setVisible(true); + JPanel panel = new JPanel(); + add(panel); + setLocation(location.x - 250, location.y - 150); + addMouseListener(new DragWindowMouseListener()); + } + + void dragTo(Point point) { + setLocation(point.x - 250, point.y - 150); + } + } + + static class DragWindowCreationMouseListener extends MouseAdapter { + + Point origin; + Window parent; + + public DragWindowCreationMouseListener(Window parent) { + this.parent = parent; + } + + @Override + public void mousePressed(MouseEvent e) { + if (dragWindow == null) { + dragWindow = new MyDragWindow(parent, getAbsoluteLocation(e)); + } else { + dragWindow.setVisible(true); + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + labelMouseReleasedCount++; + if (dragWindow != null) { + dragWindow.setVisible(false); + } + } + + public void mouseDragged(MouseEvent e) { + if (dragWindow != null) { + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + } + + static class DragWindowMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + dragWindowMouseEnteredCount++; + } + + @Override + public void mouseExited(MouseEvent e) { + dragWindowMouseExitedCount++; + } + + @Override + public void mouseReleased(MouseEvent e) { + dragWindowMouseReleasedCount++; + } + } + + static class LabelMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + labelMouseEnteredCount++; + } + + @Override + public void mouseExited(MouseEvent e) { + labelMouseExitedCount++; + } + } + + static class ButtonMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + buttonMouseEnteredCount++; + } + + @Override + public void mouseExited(MouseEvent e) { + buttonMouseExitedCount++; + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Mouse/EnterExitEvents/DragWindowTest.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7154048 + * @summary Window created under a mouse does not receive mouse enter event. + * Mouse Entered/Exited events are wrongly generated during dragging the window + * from one component to another + * @library ../../regtesthelpers + * @build Util + * @author alexandr.scherbatiy area=awt.event + * @run main DragWindowTest + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import java.util.concurrent.*; +import sun.awt.SunToolkit; + +import test.java.awt.regtesthelpers.Util; + +public class DragWindowTest { + + private static volatile int dragWindowMouseEnteredCount = 0; + private static volatile int dragWindowMouseReleasedCount = 0; + private static volatile int buttonMouseEnteredCount = 0; + private static volatile int labelMouseReleasedCount = 0; + private static MyDragWindow dragWindow; + private static JLabel label; + private static JButton button; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point pointToClick = Util.invokeOnEDT(new Callable() { + + @Override + public Point call() throws Exception { + return getCenterPoint(label); + } + }); + + + robot.mouseMove(pointToClick.x, pointToClick.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (dragWindowMouseEnteredCount != 1) { + throw new RuntimeException("No MouseEntered event on Drag Window!"); + } + + Point pointToDrag = Util.invokeOnEDT(new Callable() { + + @Override + public Point call() throws Exception { + button.addMouseListener(new ButtonMouseListener()); + return getCenterPoint(button); + } + }); + + robot.mouseMove(pointToDrag.x, pointToDrag.y); + toolkit.realSync(); + + if (buttonMouseEnteredCount != 0) { + throw new RuntimeException("Extra MouseEntered event on button!"); + } + + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + if (labelMouseReleasedCount != 1) { + throw new RuntimeException("No MouseReleased event on label!"); + } + + } + + private static Point getCenterPoint(Component comp) { + Point p = comp.getLocationOnScreen(); + Rectangle rect = comp.getBounds(); + return new Point(p.x + rect.width / 2, p.y + rect.height / 2); + } + + private static void createAndShowGUI() { + + JFrame frame = new JFrame("Main Frame"); + frame.setSize(300, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + label = new JLabel("Label"); + + LabelMouseListener listener = new LabelMouseListener(frame); + label.addMouseListener(listener); + label.addMouseMotionListener(listener); + + button = new JButton("Button"); + Panel panel = new Panel(new BorderLayout()); + + panel.add(label, BorderLayout.NORTH); + panel.add(button, BorderLayout.CENTER); + + frame.getContentPane().add(panel); + frame.setVisible(true); + + } + + private static Point getAbsoluteLocation(MouseEvent e) { + return new Point(e.getXOnScreen(), e.getYOnScreen()); + } + + static class MyDragWindow extends Window { + + static int d = 30; + + public MyDragWindow(Window parent, Point location) { + super(parent); + setSize(150, 150); + setVisible(true); + JPanel panel = new JPanel(); + add(panel); + setLocation(location.x - d, location.y - d); + addMouseListener(new DragWindowMouseListener()); + } + + void dragTo(Point point) { + setLocation(point.x - d, point.y - d); + } + } + + static class LabelMouseListener extends MouseAdapter { + + Point origin; + Window parent; + + public LabelMouseListener(Window parent) { + this.parent = parent; + } + + @Override + public void mousePressed(MouseEvent e) { + if (dragWindow == null) { + dragWindow = new MyDragWindow(parent, getAbsoluteLocation(e)); + } else { + dragWindow.setVisible(true); + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + labelMouseReleasedCount++; + if (dragWindow != null) { + dragWindow.setVisible(false); + } + } + + public void mouseDragged(MouseEvent e) { + if (dragWindow != null) { + dragWindow.dragTo(getAbsoluteLocation(e)); + } + } + } + + static class DragWindowMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + dragWindowMouseEnteredCount++; + } + + @Override + public void mouseReleased(MouseEvent e) { + dragWindowMouseReleasedCount++; + } + } + + static class ButtonMouseListener extends MouseAdapter { + + @Override + public void mouseEntered(MouseEvent e) { + buttonMouseEnteredCount++; + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7154048 + * @summary Programmatically resized window does not receive mouse entered/exited events + * @author alexandr.scherbatiy area=awt.event + * @run main ResizingFrameTest + */ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import sun.awt.SunToolkit; + +public class ResizingFrameTest { + + private static volatile int mouseEnteredCount = 0; + private static volatile int mouseExitedCount = 0; + private static JFrame frame; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.mouseMove(100, 100); + + // create a frame under the mouse cursor + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + createAndShowGUI(); + } + }); + + + toolkit.realSync(); + + if (mouseEnteredCount != 1 || mouseExitedCount != 0) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // iconify frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(Frame.ICONIFIED); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 1 || mouseExitedCount != 1) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // deiconify frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(Frame.NORMAL); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 2 || mouseExitedCount != 1) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // move the mouse out of the frame + robot.mouseMove(500, 500); + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 2 || mouseExitedCount != 2) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // maximize the frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 3 || mouseExitedCount != 2) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + + // demaximize the frame + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setExtendedState(Frame.NORMAL); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 3 || mouseExitedCount != 3) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + + } + + // move the frame under the mouse + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setLocation(400, 400); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 4 || mouseExitedCount != 3) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // move the frame out of the mouse + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setLocation(100, 100); + } + }); + + toolkit.realSync(); + robot.delay(400); + + if (mouseEnteredCount != 4 || mouseExitedCount != 4) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // enlarge the frame bounds + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setBounds(100, 100, 800, 800); + } + }); + + toolkit.realSync(); + robot.delay(200); + + if (mouseEnteredCount != 5 || mouseExitedCount != 4) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + + // make the frame bounds smaller + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + frame.setBounds(100, 100, 200, 300); + } + }); + + toolkit.realSync(); + robot.delay(400); + + + if (mouseEnteredCount != 5 || mouseExitedCount != 5) { + throw new RuntimeException("No Mouse Entered/Exited events!"); + } + } + + private static void createAndShowGUI() { + + frame = new JFrame("Main Frame"); + frame.setSize(300, 200); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.addMouseListener(new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent e) { + mouseEnteredCount++; + } + + @Override + public void mouseExited(MouseEvent e) { + mouseExitedCount++; + } + }); + + frame.setVisible(true); + } +} \ No newline at end of file diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + + +/* @test + * @bug 7129742 + * @summary Focus in non-editable TextArea is not shown on Linux. + * @author Sean Chou + */ + +import java.awt.FlowLayout; +import java.awt.TextArea; +import java.awt.Toolkit; +import java.lang.reflect.Field; + +import javax.swing.JFrame; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.text.DefaultCaret; + +import sun.awt.SunToolkit; + +public class bug7129742 { + + public static DefaultCaret caret = null; + public static JFrame frame = null; + public static boolean fastreturn = false; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame("Test"); + TextArea textArea = new TextArea("Non-editable textArea"); + textArea.setEditable(false); + frame.setLayout(new FlowLayout()); + frame.add(textArea); + frame.pack(); + frame.setVisible(true); + + try { + Class XTextAreaPeerClzz = textArea.getPeer().getClass(); + System.out.println(XTextAreaPeerClzz.getName()); + if (!XTextAreaPeerClzz.getName().equals("sun.awt.X11.XTextAreaPeer")) { + fastreturn = true; + return; + } + + Field jtextField = XTextAreaPeerClzz.getDeclaredField("jtext"); + jtextField.setAccessible(true); + JTextArea jtext = (JTextArea)jtextField.get(textArea.getPeer()); + caret = (DefaultCaret) jtext.getCaret(); + + textArea.requestFocusInWindow(); + } catch (NoSuchFieldException | SecurityException + | IllegalArgumentException | IllegalAccessException e) { + /* These exceptions mean the implementation of XTextAreaPeer is + * changed, this testcase is not valid any more, fix it or remove. + */ + frame.dispose(); + throw new RuntimeException("This testcase is not valid any more!"); + } + } + }); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try{ + if (fastreturn) { + return; + } + boolean passed = caret.isActive(); + System.out.println("is caret visible : " + passed); + + if (!passed) { + throw new RuntimeException("The test for bug 71297422 failed"); + } + } finally { + frame.dispose(); + } + } + }); + } + +} diff -r 070b00370cae -r 5904985dac0a jdk/test/java/awt/regtesthelpers/Util.java --- a/jdk/test/java/awt/regtesthelpers/Util.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/awt/regtesthelpers/Util.java Wed May 09 13:13:41 2012 -0700 @@ -600,4 +600,34 @@ time, printEvent); } + + + /** + * Invokes the task on the EDT thread. + * + * @return result of the task + */ + public static T invokeOnEDT(final java.util.concurrent.Callable task) throws Exception { + final java.util.List result = new java.util.ArrayList(1); + final Exception[] exception = new Exception[1]; + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + result.add(task.call()); + } catch (Exception e) { + exception[0] = e; + } + } + }); + + if (exception[0] != null) { + throw exception[0]; + } + + return result.get(0); + } + } diff -r 070b00370cae -r 5904985dac0a jdk/test/java/io/File/GetXSpace.java --- a/jdk/test/java/io/File/GetXSpace.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/io/File/GetXSpace.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -51,7 +51,7 @@ private static final String dfFormat; static { if (name.equals("SunOS") || name.equals("Linux") - || name.startsWith("Mac OS")) { + || name.contains("OS X")) { // FileSystem Total Used Available Use% MountedOn dfFormat = "([^\\s]+)\\s+(\\d+)\\s+\\d+\\s+(\\d+)\\s+\\d+%\\s+([^\\s]+)"; } else if (name.startsWith("Windows")) { diff -r 070b00370cae -r 5904985dac0a jdk/test/java/lang/ProcessBuilder/Basic.java --- a/jdk/test/java/lang/ProcessBuilder/Basic.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Wed May 09 13:13:41 2012 -0700 @@ -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 @@ -597,7 +597,7 @@ static class MacOSX { public static boolean is() { return is; } private static final String osName = System.getProperty("os.name"); - private static final boolean is = osName.startsWith("Mac OS"); + private static final boolean is = osName.contains("OS X"); } static class True { diff -r 070b00370cae -r 5904985dac0a jdk/test/java/lang/ProcessBuilder/Zombies.java --- a/jdk/test/java/lang/ProcessBuilder/Zombies.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/lang/ProcessBuilder/Zombies.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -34,7 +34,7 @@ static final String os = System.getProperty("os.name"); - static final String TrueCommand = os.startsWith("Mac OS")? + static final String TrueCommand = os.contains("OS X")? "/usr/bin/true" : "/bin/true"; public static void main(String[] args) throws Throwable { diff -r 070b00370cae -r 5904985dac0a jdk/test/java/lang/invoke/InvokeGenericTest.java --- a/jdk/test/java/lang/invoke/InvokeGenericTest.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -76,7 +76,7 @@ String name = properties.getProperty("java.vm.name"); String arch = properties.getProperty("os.arch"); if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") || - arch.equals("sparc") || arch.equals("sparcv9")) && + arch.equals("x86_64") || arch.equals("sparc") || arch.equals("sparcv9")) && (name.contains("Client") || name.contains("Server")) ) { platformOK = true; diff -r 070b00370cae -r 5904985dac0a jdk/test/java/lang/management/OperatingSystemMXBean/GetSystemLoadAverage.java --- a/jdk/test/java/lang/management/OperatingSystemMXBean/GetSystemLoadAverage.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/lang/management/OperatingSystemMXBean/GetSystemLoadAverage.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -80,7 +80,7 @@ } private static String LOAD_AVERAGE_TEXT - = System.getProperty("os.name").startsWith("Mac OS") + = System.getProperty("os.name").contains("OS X") ? "load averages:" : "load average:"; @@ -99,7 +99,7 @@ System.out.println("Load average returned from uptime = " + output); System.out.println("getSystemLoadAverage() returned " + loadavg); - String[] lavg = System.getProperty("os.name").startsWith("Mac OS") + String[] lavg = System.getProperty("os.name").contains("OS X") ? output.split(" ") : output.split(","); double expected = Double.parseDouble(lavg[0]); diff -r 070b00370cae -r 5904985dac0a jdk/test/java/nio/channels/DatagramChannel/Disconnect.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/channels/DatagramChannel/Disconnect.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7132924 + * @summary Test DatagramChannel.disconnect when DatagramChannel is connected to an IPv4 socket + * @run main Disconnect + * @run main/othervm -Djava.net.preferIPv4Stack=true Disconnect + */ + +import java.net.*; +import java.nio.*; +import java.nio.channels.*; +import java.io.IOException; + +public class Disconnect { + public static void main(String[] args) throws IOException { + // test with default protocol family + try (DatagramChannel dc = DatagramChannel.open()) { + test(dc); + test(dc); + } + + // test with IPv4 only + try (DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)) { + test(dc); + test(dc); + } + } + + /** + * Connect DatagramChannel to a server, write a datagram and disconnect. Invoke + * a second or subsequent time with the same DatagramChannel instance to check + * that disconnect works as expected. + */ + static void test(DatagramChannel dc) throws IOException { + try (DatagramChannel server = DatagramChannel.open()) { + server.bind(new InetSocketAddress(0)); + + InetAddress lh = InetAddress.getLocalHost(); + dc.connect(new InetSocketAddress(lh, server.socket().getLocalPort())); + + dc.write(ByteBuffer.wrap("hello".getBytes())); + + ByteBuffer bb = ByteBuffer.allocate(100); + server.receive(bb); + + dc.disconnect(); + + try { + dc.write(ByteBuffer.wrap("another message".getBytes())); + throw new RuntimeException("write should fail, not connected"); + } catch (NotYetConnectedException expected) { + } + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/java/nio/channels/FileChannel/Size.java --- a/jdk/test/java/nio/channels/FileChannel/Size.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/nio/channels/FileChannel/Size.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -69,7 +69,7 @@ // Windows and Linux can't handle the really large file sizes for a truncate // or a positional write required by the test for 4563125 String osName = System.getProperty("os.name"); - if (osName.startsWith("SunOS") || osName.startsWith("Mac OS")) { + if (osName.startsWith("SunOS") || osName.contains("OS X")) { blah = File.createTempFile("blah", null); long testSize = ((long)Integer.MAX_VALUE) * 2; initTestFile(blah, 10); diff -r 070b00370cae -r 5904985dac0a jdk/test/java/nio/channels/FileChannel/Transfer.java --- a/jdk/test/java/nio/channels/FileChannel/Transfer.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -228,7 +228,7 @@ // Windows and Linux can't handle the really large file sizes for a // truncate or a positional write required by the test for 4563125 String osName = System.getProperty("os.name"); - if (!(osName.startsWith("SunOS") || osName.startsWith("Mac OS"))) + if (!(osName.startsWith("SunOS") || osName.contains("OS X"))) return; File source = File.createTempFile("blah", null); source.deleteOnExit(); diff -r 070b00370cae -r 5904985dac0a jdk/test/java/nio/file/FileSystem/Basic.java --- a/jdk/test/java/nio/file/FileSystem/Basic.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/java/nio/file/FileSystem/Basic.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -76,7 +76,7 @@ checkSupported(fs, "posix", "unix", "owner", "acl", "user"); if (os.equals("Linux")) checkSupported(fs, "posix", "unix", "owner", "dos", "user"); - if (os.startsWith("Mac OS")) + if (os.contains("OS X")) checkSupported(fs, "posix", "unix", "owner"); if (os.equals("Windows")) checkSupported(fs, "owner", "dos", "acl", "user"); diff -r 070b00370cae -r 5904985dac0a jdk/test/java/nio/file/WatchService/MayFlies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/nio/file/WatchService/MayFlies.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7164570 + * @summary Test that CREATE and DELETE events are paired for very + * short lived files + * @library .. + * @run main MayFlies + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKinds.*; +import java.util.*; +import java.util.concurrent.*; + +public class MayFlies { + + static volatile boolean stopped; + + static volatile boolean failure; + + /** + * Continuously creates short-lived files in a directory until {@code + * stopped} is set to {@code true}. + */ + static class MayFlyHatcher implements Runnable { + static final Random rand = new Random(); + + private final Path dir; + private final String prefix; + + private MayFlyHatcher(Path dir, String prefix) { + this.dir = dir; + this.prefix = prefix; + } + + static void start(Path dir, String prefix) { + MayFlyHatcher hatcher = new MayFlyHatcher(dir, prefix); + new Thread(hatcher).start(); + } + + public void run() { + try { + int n = 0; + while (!stopped) { + Path name = dir.resolve(prefix + (++n)); + Files.createFile(name); + if (rand.nextBoolean()) + Thread.sleep(rand.nextInt(500)); + Files.delete(name); + Thread.sleep(rand.nextInt(100)); + } + System.out.format("%d %ss hatched%n", n, prefix); + } catch (Exception x) { + failure = true; + x.printStackTrace(); + } + } + } + + /** + * Test phases. + */ + static enum Phase { + /** + * Short-lived files are being created + */ + RUNNING, + /** + * Draining the final events + */ + FINISHING, + /** + * No more events or overflow detected + */ + FINISHED + }; + + + public static void main(String[] args) throws Exception { + + // schedules file creation to stop after 10 seconds + ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor(); + pool.schedule( + new Runnable() { public void run() { stopped = true; }}, + 10, TimeUnit.SECONDS); + + Path dir = TestUtil.createTemporaryDirectory(); + + Set entries = new HashSet<>(); + int nCreateEvents = 0; + boolean overflow = false; + + try (WatchService watcher = FileSystems.getDefault().newWatchService()) { + WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); + + // start hatching Mayflies + MayFlyHatcher.start(dir, "clinger"); + MayFlyHatcher.start(dir, "crawler"); + MayFlyHatcher.start(dir, "burrower"); + MayFlyHatcher.start(dir, "swimmer"); + + Phase phase = Phase.RUNNING; + while (phase != Phase.FINISHED) { + // during the running phase then poll for 1 second. + // once the file creation has stopped then move to the finishing + // phase where we do a long poll to ensure that all events have + // been read. + int time = (phase == Phase.RUNNING) ? 1 : 15; + key = watcher.poll(time, TimeUnit.SECONDS); + if (key == null) { + if (phase == Phase.RUNNING && stopped) + phase = Phase.FINISHING; + else if (phase == Phase.FINISHING) + phase = Phase.FINISHED; + } else { + // process events + for (WatchEvent event: key.pollEvents()) { + if (event.kind() == ENTRY_CREATE) { + Path name = (Path)event.context(); + boolean added = entries.add(name); + if (!added) + throw new RuntimeException("Duplicate ENTRY_CREATE event"); + nCreateEvents++; + } else if (event.kind() == ENTRY_DELETE) { + Path name = (Path)event.context(); + boolean removed = entries.remove(name); + if (!removed) + throw new RuntimeException("ENTRY_DELETE event without ENTRY_CREATE event"); + } else if (event.kind() == OVERFLOW) { + overflow = true; + phase = Phase.FINISHED; + } else { + throw new RuntimeException("Unexpected event: " + event.kind()); + } + } + key.reset(); + } + } + + System.out.format("%d ENTRY_CREATE events read%n", nCreateEvents); + + // there should be a DELETE event for each CREATE event and so the + // entries set should be empty. + if (!overflow && !entries.isEmpty()) + throw new RuntimeException("Missed " + entries.size() + " DELETE event(s)"); + + + } finally { + try { + TestUtil.removeAll(dir); + } finally { + pool.shutdown(); + } + } + + if (failure) + throw new RuntimeException("Test failed - see log file for details"); + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/java/util/prefs/RemoveNullKeyCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/prefs/RemoveNullKeyCheck.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7160242 + * @summary Check if NullPointerException is thrown if the key passed + * to remove() is null. + */ + +import java.util.prefs.Preferences; + +public class RemoveNullKeyCheck { + + public static void main(String[] args) throws Exception { + try { + Preferences node = Preferences.userRoot().node("N1"); + node.remove(null); + throw new RuntimeException("Expected NullPointerException " + + "not thrown"); + } catch (NullPointerException npe) { + System.out.println("NullPointerException thrown"); + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/javax/swing/JComponent/7154030/bug7154030.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JComponent/7154030/bug7154030.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import sun.awt.SunToolkit; + +import java.awt.AWTException; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; + +/* @test 1.1 2012/04/12 + * @bug 7154030 + * @summary Swing components fail to hide after calling hide() + * @author Jonathan Lu + * @library ../../regtesthelpers/ + * @build Util + * @run main bug7154030 + */ + +public class bug7154030 { + + private static JButton button = null; + + public static void main(String[] args) throws Exception { + BufferedImage imageInit = null; + + BufferedImage imageShow = null; + + BufferedImage imageHide = null; + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + Robot robot = new Robot(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + JDesktopPane desktop = new JDesktopPane(); + button = new JButton("button"); + JFrame frame = new JFrame(); + + button.setSize(200, 200); + button.setLocation(100, 100); + button.setForeground(Color.RED); + button.setBackground(Color.RED); + button.setOpaque(true); + button.setVisible(false); + desktop.add(button); + + frame.setContentPane(desktop); + frame.setSize(300, 300); + frame.setLocation(0, 0); + frame.setVisible(true); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + } + }); + + toolkit.realSync(); + imageInit = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + button.show(); + } + }); + + toolkit.realSync(); + imageShow = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + if (Util.compareBufferedImages(imageInit, imageShow)) { + throw new Exception("Failed to show opaque button"); + } + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + button.hide(); + } + }); + + toolkit.realSync(); + imageHide = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + + if (!Util.compareBufferedImages(imageInit, imageHide)) { + throw new Exception("Failed to hide opaque button"); + } + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + button.setOpaque(false); + button.setBackground(new Color(128, 128, 0)); + button.setVisible(false); + } + }); + + toolkit.realSync(); + imageInit = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + button.show(); + } + }); + + toolkit.realSync(); + imageShow = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + button.hide(); + } + }); + + if (Util.compareBufferedImages(imageInit, imageShow)) { + throw new Exception("Failed to show non-opaque button"); + } + + toolkit.realSync(); + imageHide = robot.createScreenCapture(new Rectangle(0, 0, 300, 300)); + + if (!Util.compareBufferedImages(imageInit, imageHide)) { + throw new Exception("Failed to hide non-opaque button"); + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/javax/swing/JTable/7055065/bug7055065.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTable/7055065/bug7055065.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +/* @test 1.1 2012/04/19 + * @bug 7055065 + * @summary NullPointerException when sorting JTable with empty cell + * @author Jonathan Lu + * @library ../../regtesthelpers/ + * @build Util + * @run main bug7055065 + */ + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; +import sun.awt.SunToolkit; +import java.util.concurrent.Callable; + +public class bug7055065 { + + private static JTable table; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + createAndShowUI(); + } + }); + + toolkit.realSync(); + clickCell(robot, 1, 1); + Util.hitKeys(robot, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_BACK_SPACE, + KeyEvent.VK_BACK_SPACE); + + toolkit.realSync(); + clickColumnHeader(robot, 1); + + toolkit.realSync(); + clickColumnHeader(robot, 1); + } + + private static void clickCell(Robot robot, final int row, final int column) + throws Exception { + Point point = Util.invokeOnEDT(new Callable() { + @Override + public Point call() throws Exception { + Rectangle rect = table.getCellRect(row, column, false); + Point point = new Point(rect.x + rect.width / 2, rect.y + + rect.height / 2); + SwingUtilities.convertPointToScreen(point, table); + return point; + } + }); + + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + + private static void clickColumnHeader(Robot robot, final int column) + throws Exception { + Point point = Util.invokeOnEDT(new Callable() { + @Override + public Point call() throws Exception { + Rectangle rect = table.getCellRect(0, column, false); + int headerHeight = table.getTableHeader().getHeight(); + Point point = new Point(rect.x + rect.width / 2, rect.y + - headerHeight / 2); + SwingUtilities.convertPointToScreen(point, table); + return point; + } + }); + + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + + private static void createAndShowUI() { + JFrame frame = new JFrame("SimpleTableDemo"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JPanel newContentPane = new JPanel(); + newContentPane.setOpaque(true); + frame.setContentPane(newContentPane); + + final String[] columnNames = { "String", "Number" }; + final Object[][] data = { { "aaaa", new Integer(1) }, + { "bbbb", new Integer(3) }, { "cccc", new Integer(2) }, + { "dddd", new Integer(4) }, { "eeee", new Integer(5) } }; + table = new JTable(data, columnNames); + + table.setPreferredScrollableViewportSize(new Dimension(500, 400)); + table.setFillsViewportHeight(true); + + TableModel dataModel = new AbstractTableModel() { + + public int getColumnCount() { + return columnNames.length; + } + + public int getRowCount() { + return data.length; + } + + public Object getValueAt(int row, int col) { + return data[row][col]; + } + + public String getColumnName(int column) { + return columnNames[column]; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + + public boolean isCellEditable(int row, int col) { + return col != 5; + } + + public void setValueAt(Object aValue, int row, int column) { + data[row][column] = aValue; + } + }; + table.setModel(dataModel); + TableRowSorter sorter = new TableRowSorter( + dataModel); + table.setRowSorter(sorter); + + JScrollPane scrollPane = new JScrollPane(table); + newContentPane.add(scrollPane); + + frame.pack(); + frame.setLocation(0, 0); + frame.setVisible(true); + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/javax/swing/JTree/4908142/bug4908142.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTree/4908142/bug4908142.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 4908142 + * @summary JList doesn't handle search function appropriately + * @author Andrey Pikalev + * @library ../../regtesthelpers + * @build Util + * @run main bug4908142 + */ +import javax.swing.*; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.*; +import java.util.concurrent.Callable; +import sun.awt.SunToolkit; + +public class bug4908142 { + + private static JTree tree; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + tree.requestFocus(); + tree.setSelectionRow(0); + } + }); + + toolkit.realSync(); + + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_D); + robot.keyRelease(KeyEvent.VK_D); + toolkit.realSync(); + + + String sel = Util.invokeOnEDT(new Callable() { + + @Override + public String call() throws Exception { + return tree.getLastSelectedPathComponent().toString(); + } + }); + + if (!"aad".equals(sel)) { + throw new Error("The selected index should be \"aad\", but not " + sel); + } + } + + private static void createAndShowGUI() { + JFrame fr = new JFrame("Test"); + fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + String[] data = {"aaa", "aab", "aac", "aad", "ade", "bba"}; + final DefaultMutableTreeNode root = new DefaultMutableTreeNode(data[0]); + for (int i = 1; i < data.length; i++) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(data[i]); + root.add(node); + } + + tree = new JTree(root); + + JScrollPane sp = new JScrollPane(tree); + fr.getContentPane().add(sp); + fr.setSize(200, 200); + fr.setVisible(true); + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/sun/net/www/protocol/jar/B4957695.java --- a/jdk/test/sun/net/www/protocol/jar/B4957695.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/sun/net/www/protocol/jar/B4957695.java Wed May 09 13:13:41 2012 -0700 @@ -62,7 +62,8 @@ readOneRequest(s.getInputStream()); try (OutputStreamWriter ow = new OutputStreamWriter((s.getOutputStream()))) { - FileInputStream fin = new FileInputStream("foo1.jar"); + FileInputStream fin = new FileInputStream(new File( + System.getProperty("test.src", "."), "foo1.jar")); int length = fin.available(); byte[] b = new byte[length-10]; fin.read(b, 0, length-10); diff -r 070b00370cae -r 5904985dac0a jdk/test/sun/nio/ch/SelProvider.java --- a/jdk/test/sun/nio/ch/SelProvider.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/sun/nio/ch/SelProvider.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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,7 +39,7 @@ expected = "sun.nio.ch.DevPollSelectorProvider"; } else if ("Linux".equals(osname)) { expected = "sun.nio.ch.EPollSelectorProvider"; - } else if (osname.startsWith("Mac OS")) { + } else if (osname.contains("OS X")) { expected = "sun.nio.ch.KQueueSelectorProvider"; } else return; diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/launcher/Arrrghs.java --- a/jdk/test/tools/launcher/Arrrghs.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/launcher/Arrrghs.java Wed May 09 13:13:41 2012 -0700 @@ -24,7 +24,7 @@ /** * @test * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 - * 6894719 6968053 + * 6894719 6968053 7151314 * @summary Argument parsing validation. * @compile -XDignore.symbol.file Arrrghs.java * @run main Arrrghs @@ -237,6 +237,13 @@ tr.checkNegative(); tr.isNotZeroOutput(); System.out.println(tr); + + // 7151314, test for non-negative exit value for an incorrectly formed + // command line, '% java -jar -W', note the bogus -W + tr = doExec(javaCmd, "-jar", "-W"); + tr.checkNegative(); + tr.contains("Unrecognized option: -W"); + System.out.println(tr); } /* diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/launcher/EnvironmentVariables.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/launcher/EnvironmentVariables.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * see TestSpecialArgs.java + * bug 7131021 + * summary Checks for environment variables set by the launcher + * author anthony.petrov@oracle.com: area=launcher + */ + +public class EnvironmentVariables { + public static void main(String[] args) { + if (args.length != 2) { + throw new RuntimeException("ERROR: two command line arguments expected"); + } + + String name = args[0]; + String expect = args[1]; + String key = null; + + if (!name.endsWith("*")) { + key = name; + } else { + name = name.split("\\*")[0]; + + for (String s : System.getenv().keySet()) { + if (s.startsWith(name)) { + if (key == null) { + key = s; + } else { + System.err.println("WARNING: more variables match: " + s); + } + } + } + + if (key == null) { + throw new RuntimeException("ERROR: unable to find a match for: " + name); + } + } + + System.err.println("Will check the variable named: '" + key + + "' expecting the value: '" + expect + "'"); + + if (!System.getenv().containsKey(key)) { + throw new RuntimeException("ERROR: the variable '" + key + + "' is not present in the environment"); + } + + if (!expect.equals(System.getenv().get(key))) { + throw new RuntimeException("ERROR: expected: '" + expect + + "', got: '" + System.getenv().get(key) + "'"); + } + for (String x : args) { + System.err.print(x + " "); + } + System.err.println("-----> Passed!"); + } +} + diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/launcher/TestHelper.java --- a/jdk/test/tools/launcher/TestHelper.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/launcher/TestHelper.java Wed May 09 13:13:41 2012 -0700 @@ -21,6 +21,9 @@ * questions. */ +import java.io.StringWriter; +import java.io.PrintWriter; +import java.util.Set; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; @@ -66,7 +69,7 @@ static final boolean isWindows = System.getProperty("os.name", "unknown").startsWith("Windows"); static final boolean isMacOSX = - System.getProperty("os.name", "unknown").startsWith("Mac"); + System.getProperty("os.name", "unknown").contains("OS X"); static final boolean is64Bit = System.getProperty("sun.arch.data.model").equals("64"); static final boolean is32Bit = @@ -87,6 +90,7 @@ static final String EXE_FILE_EXT = ".exe"; static final String JLDEBUG_KEY = "_JAVA_LAUNCHER_DEBUG"; static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC"; + static final String TEST_PREFIX = "###TestError###: "; static int testExitValue = 0; @@ -316,19 +320,28 @@ } static TestResult doExec(String...cmds) { - return doExec(null, cmds); + return doExec(null, null, cmds); } + static TestResult doExec(Map envToSet, String...cmds) { + return doExec(envToSet, null, cmds); + } /* * A method which executes a java cmd and returns the results in a container */ - static TestResult doExec(Map envToSet, String...cmds) { + static TestResult doExec(Map envToSet, + Set envToRemove, String...cmds) { String cmdStr = ""; for (String x : cmds) { cmdStr = cmdStr.concat(x + " "); } ProcessBuilder pb = new ProcessBuilder(cmds); Map env = pb.environment(); + if (envToRemove != null) { + for (String key : envToRemove) { + env.remove(key); + } + } if (envToSet != null) { env.putAll(envToSet); } @@ -376,7 +389,8 @@ * of use methods to check the test results. */ static class TestResult { - StringBuilder status; + PrintWriter status; + StringWriter sw; int exitValue; List testOutput; Map env; @@ -384,27 +398,33 @@ public TestResult(String str, int rv, List oList, Map env, Throwable t) { - status = new StringBuilder("Executed command: " + str + "\n"); + sw = new StringWriter(); + status = new PrintWriter(sw); + status.println("Executed command: " + str + "\n"); exitValue = rv; testOutput = oList; this.env = env; this.t = t; } - void appendStatus(String x) { - status = status.append(" " + x + "\n"); + void appendError(String x) { + status.println(TEST_PREFIX + x); + } + + void indentStatus(String x) { + status.println(" " + x); } void checkNegative() { if (exitValue == 0) { - appendStatus("Error: test must not return 0 exit value"); + appendError("test must not return 0 exit value"); testExitValue++; } } void checkPositive() { if (exitValue != 0) { - appendStatus("Error: test did not return 0 exit value"); + appendError("test did not return 0 exit value"); testExitValue++; } } @@ -415,7 +435,7 @@ boolean isZeroOutput() { if (!testOutput.isEmpty()) { - appendStatus("Error: No message from cmd please"); + appendError("No message from cmd please"); testExitValue++; return false; } @@ -424,7 +444,7 @@ boolean isNotZeroOutput() { if (testOutput.isEmpty()) { - appendStatus("Error: Missing message"); + appendError("Missing message"); testExitValue++; return false; } @@ -433,22 +453,25 @@ @Override public String toString() { - status.append("++++Begin Test Info++++\n"); - status.append("++++Test Environment++++\n"); + status.println("++++Begin Test Info++++"); + status.println("++++Test Environment++++"); for (String x : env.keySet()) { - status.append(x).append("=").append(env.get(x)).append("\n"); + indentStatus(x + "=" + env.get(x)); } - status.append("++++Test Output++++\n"); + status.println("++++Test Output++++"); for (String x : testOutput) { - appendStatus(x); + indentStatus(x); } - status.append("++++Test Stack Trace++++\n"); - status.append(t.toString()); + status.println("++++Test Stack Trace++++"); + status.println(t.toString()); for (StackTraceElement e : t.getStackTrace()) { - status.append(e.toString()); + indentStatus(e.toString()); } - status.append("++++End of Test Info++++\n"); - return status.toString(); + status.println("++++End of Test Info++++"); + status.flush(); + String out = sw.toString(); + status.close(); + return out; } boolean contains(String str) { @@ -457,7 +480,7 @@ return true; } } - appendStatus("Error: string <" + str + "> not found"); + appendError("string <" + str + "> not found"); testExitValue++; return false; } @@ -468,7 +491,7 @@ return true; } } - appendStatus("Error: string <" + stringToMatch + "> not found"); + appendError("string <" + stringToMatch + "> not found"); testExitValue++; return false; } diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/launcher/TestSpecialArgs.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/launcher/TestSpecialArgs.java Wed May 09 13:13:41 2012 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7124089 7131021 + * @summary Checks for MacOSX specific flags are accepted or rejected, and + * MacOSX platforms specific environment is consistent. + * @compile -XDignore.symbol.file TestSpecialArgs.java EnvironmentVariables.java + * @run main TestSpecialArgs + */ +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class TestSpecialArgs extends TestHelper { + + public static void main(String... args) { + final Map envMap = new HashMap<>(); + envMap.put("_JAVA_LAUNCHER_DEBUG", "true"); + + TestResult tr = doExec(envMap, javaCmd, "-XstartOnFirstThread", "-version"); + if (isMacOSX) { + if (!tr.contains("In same thread")) { + System.out.println(tr); + throw new RuntimeException("Error: not running in the same thread ?"); + } + if (!tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Error: arg was rejected ????"); + } + } else { + if (tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Error: argument was accepted ????"); + } + } + + tr = doExec(javaCmd, "-Xdock:/tmp/not-available", "-version"); + if (isMacOSX) { + if (!tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Error: arg was rejected ????"); + } + } else { + if (tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Error: argument was accepted ????"); + } + } + // MacOSX specific tests ensue...... + if (!isMacOSX) + return; + Set envToRemove = new HashSet<>(); + Map map = System.getenv(); + for (String s : map.keySet()) { + if (s.startsWith("JAVA_MAIN_CLASS_") + || s.startsWith("APP_NAME_") + || s.startsWith("APP_ICON_")) { + envToRemove.add(s); + } + } + runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(), + "EnvironmentVariables", "JAVA_MAIN_CLASS_*", + "EnvironmentVariables"); + + runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(), + "-Xdock:name=TestAppName", "EnvironmentVariables", + "APP_NAME_*", "TestAppName"); + + runTest(envToRemove, javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(), + "-Xdock:icon=TestAppIcon", "EnvironmentVariables", + "APP_ICON_*", "TestAppIcon"); + } + + static void runTest(Set envToRemove, String... args) { + TestResult tr = doExec(null, envToRemove, args); + if (!tr.isOK()) { + System.err.println(tr.toString()); + throw new RuntimeException("Test Fails"); + } + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/AttributeTests.java --- a/jdk/test/tools/pack200/AttributeTests.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/AttributeTests.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -27,7 +27,7 @@ import java.util.List; /* * @test - * @bug 6982312 + * @bug 6746111 * @summary tests various classfile format and attribute handling by pack200 * @compile -XDignore.symbol.file Utils.java AttributeTests.java * @run main AttributeTests @@ -36,40 +36,8 @@ public class AttributeTests { public static void main(String... args) throws Exception { - test6982312(); test6746111(); } - /* - * This is an interim test, which ensures pack200 handles JSR-292 related - * classfile changes seamlessly, until all the classfile changes in jdk7 - * and jdk8 are fully supported. At that time this test should be jettisoned, - * along with the associated jar file. - * - * The jar file contains sources and classes noting the classes were - * derived by using the javac from the lambda project, - * see http://openjdk.java.net/projects/lambda/. - * Therefore the classes contained in the jar cannot be compiled, using - * the standard jdk7's javac compiler. - */ - static void test6982312() throws IOException { - String pack200Cmd = Utils.getPack200Cmd(); - File dynJar = new File(".", "dyn.jar"); - Utils.copyFile(new File(Utils.TEST_SRC_DIR, "dyn.jar"), dynJar); - File testJar = new File(".", "test.jar"); - List cmds = new ArrayList(); - cmds.add(pack200Cmd); - cmds.add("--repack"); - cmds.add(testJar.getAbsolutePath()); - cmds.add(dynJar.getAbsolutePath()); - Utils.runExec(cmds); - /* - * compare the repacked jar bit-wise, as all the files - * should be transmitted "as-is". - */ - Utils.doCompareBitWise(dynJar.getAbsoluteFile(), testJar.getAbsoluteFile()); - testJar.delete(); - dynJar.delete(); - } /* * this test checks to see if we get the expected strings for output diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/PackageVersionTest.java --- a/jdk/test/tools/pack200/PackageVersionTest.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/PackageVersionTest.java Wed May 09 13:13:41 2012 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -51,6 +51,9 @@ public final static int JAVA6_PACKAGE_MAJOR_VERSION = 160; public final static int JAVA6_PACKAGE_MINOR_VERSION = 1; + public final static int JAVA7_PACKAGE_MAJOR_VERSION = 170; + public final static int JAVA7_PACKAGE_MINOR_VERSION = 1; + public static void main(String... args) { if (!javaHome.getName().endsWith("jre")) { throw new RuntimeException("Error: requires an SDK to run"); @@ -68,9 +71,8 @@ verifyPack("Test6.class", JAVA6_PACKAGE_MAJOR_VERSION, JAVA6_PACKAGE_MINOR_VERSION); - // TODO: change this to the java7 package version as needed. - verifyPack("Test7.class", JAVA6_PACKAGE_MAJOR_VERSION, - JAVA6_PACKAGE_MINOR_VERSION); + verifyPack("Test7.class", JAVA7_PACKAGE_MAJOR_VERSION, + JAVA7_PACKAGE_MINOR_VERSION); // test for resource file, ie. no class files verifyPack("Test6.java", JAVA5_PACKAGE_MAJOR_VERSION, diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/Utils.java --- a/jdk/test/tools/pack200/Utils.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/Utils.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -129,8 +129,10 @@ init(); List cmds = new ArrayList(); cmds.add(getJavaCmd()); - cmds.add("-jar"); - cmds.add(VerifierJar.getName()); + cmds.add("-cp"); + cmds.add(Utils.locateJar("tools.jar") + + System.getProperty("path.separator") + VerifierJar.getName()); + cmds.add("sun.tools.pack.verify.Main"); cmds.add(reference.getAbsolutePath()); cmds.add(specimen.getAbsolutePath()); cmds.add("-O"); @@ -142,8 +144,10 @@ init(); List cmds = new ArrayList(); cmds.add(getJavaCmd()); - cmds.add("-jar"); - cmds.add(VerifierJar.getName()); + cmds.add("-cp"); + cmds.add(Utils.locateJar("tools.jar") + + System.getProperty("path.separator") + VerifierJar.getName()); + cmds.add("sun.tools.pack.verify.Main"); cmds.add(reference.getName()); cmds.add(specimen.getName()); cmds.add("-O"); diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/dyn.jar Binary file jdk/test/tools/pack200/dyn.jar has changed diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/data/README --- a/jdk/test/tools/pack200/pack200-verifier/data/README Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/pack200-verifier/data/README Wed May 09 13:13:41 2012 -0700 @@ -2,19 +2,19 @@ different sources, some are hand-crafted invalid class files (odds directory), or from random JDK builds. -Generally these files serve to ensure the integrity of the packer and unpacker -by, - 1. maximizing the test coverage. - 2. exercising all the Bands in the pack200 specification. - 2. testing the behavior of the packer with invalid classes. - 3. testing the archive integrity, ordering and description (date, sizes, +Generally these files serve to ensure the integrity of the packer and +unpacker by, + * maximizing the test coverage. + * exercising all the Bands in the pack200 specification. + * testing the behavior of the packer with invalid classes. + * testing the archive integrity, ordering and description (date, sizes, CRC etc.) Build: To rebuild this JAR follow these steps: 1. unzip the golden.jar to some directory lets call it "example" 2. now we can add any directories with files into example. - 2. run the script BUILDME.sh as + 3. run the script BUILDME.sh as % sh BUILDME.sh example Note: the BUILDME.sh is known to work on all Unix platforms as well as Windows @@ -32,7 +32,7 @@ Basic: % pack200 --repack test.jar golden.jar - Advanced: + Advanced: inspection of band contents Create a pack.conf as follows: % cat pack.conf com.sun.java.util.jar.pack.dump.bands=true @@ -41,5 +41,6 @@ --verbose golden.jar.pack golden.jar This command will dump the Bands in a unique directory BD_XXXXXX, - one can inspect the directory to ensure all of the bands are being - generated. Familiarity of the Pack200 specification is suggested. \ No newline at end of file + one can then inspect the directory to ensure all of the bands are being + generated. Familiarity of the Pack200 specification is strongly + suggested. diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/data/golden.jar Binary file jdk/test/tools/pack200/pack200-verifier/data/golden.jar has changed diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/make/build.xml --- a/jdk/test/tools/pack200/pack200-verifier/make/build.xml Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/pack200-verifier/make/build.xml Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ - + @@ -22,7 +22,7 @@ diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Wed May 09 13:07:57 2012 -0700 +++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Wed May 09 13:13:41 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,16 +24,58 @@ */ package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- +import com.sun.tools.classfile.AccessFlags; +import com.sun.tools.classfile.Annotation; +import com.sun.tools.classfile.Annotation.*; +import com.sun.tools.classfile.AnnotationDefault_attribute; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Attributes; +import com.sun.tools.classfile.BootstrapMethods_attribute; +import com.sun.tools.classfile.CharacterRangeTable_attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.CompilationID_attribute; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.*; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ConstantValue_attribute; +import com.sun.tools.classfile.DefaultAttribute; +import com.sun.tools.classfile.Deprecated_attribute; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.EnclosingMethod_attribute; +import com.sun.tools.classfile.Exceptions_attribute; +import com.sun.tools.classfile.Field; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; +import com.sun.tools.classfile.Instruction; +import com.sun.tools.classfile.Instruction.TypeKind; +import com.sun.tools.classfile.LineNumberTable_attribute; +import com.sun.tools.classfile.LocalVariableTable_attribute; +import com.sun.tools.classfile.LocalVariableTypeTable_attribute; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.Opcode; +import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; +import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; +import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; +import com.sun.tools.classfile.Signature_attribute; +import com.sun.tools.classfile.SourceDebugExtension_attribute; +import com.sun.tools.classfile.SourceFile_attribute; +import com.sun.tools.classfile.SourceID_attribute; +import com.sun.tools.classfile.StackMapTable_attribute; +import com.sun.tools.classfile.StackMapTable_attribute.*; +import com.sun.tools.classfile.StackMap_attribute; +import com.sun.tools.classfile.Synthetic_attribute; import java.util.*; -import java.util.jar.*; -import java.lang.reflect.*; import java.io.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import xmlkit.XMLKit.Element; /* - * @author jrose + * @author jrose, ksrini */ -public class ClassReader extends ClassSyntax { +public class ClassReader { private static final CommandLineParser CLP = new CommandLineParser("" + "-source: +> = \n" @@ -41,23 +83,24 @@ + "-encoding: +> = \n" + "-jcov $ \n -nojcov !-jcov \n" + "-verbose $ \n -noverbose !-verbose \n" - + "-pretty $ \n -nopretty !-pretty \n" + "-keepPath $ \n -nokeepPath !-keepPath \n" + "-keepCP $ \n -nokeepCP !-keepCP \n" - + "-keepBytes $ \n -nokeepBytes !-keepBytes \n" - + "-parseBytes $ \n -noparseBytes !-parseBytes \n" - + "-resolveRefs $ \n -noresolveRefs !-resolveRefs \n" + "-keepOrder $ \n -nokeepOrder !-keepOrder \n" - + "-keepSizes $ \n -nokeepSizes !-keepSizes \n" + "-continue $ \n -nocontinue !-continue \n" - + "-attrDef & \n" + "-@ >-@ . \n" + "- +? \n" + "\n"); + + // Protected state for representing the class file. + protected Element cfile; // + protected Element cpool; // + protected Element klass; // + protected List thePool; // stringified flattened Constant Pool + public static void main(String[] ava) throws IOException { - ArrayList av = new ArrayList(Arrays.asList(ava)); - HashMap props = new HashMap(); + ArrayList av = new ArrayList<>(Arrays.asList(ava)); + HashMap props = new HashMap<>(); props.put("-encoding:", "UTF8"); // default props.put("-keepOrder", null); // CLI default props.put("-pretty", "1"); // CLI default @@ -80,7 +123,7 @@ } */ if (av.isEmpty()) { - av.add("doit"); //to enter this loop + av.add(""); //to enter this loop } boolean readList = false; for (String a : av) { @@ -119,7 +162,7 @@ private static void doFile(String a, File source, File dest, ClassReader options, String encoding, - boolean contError) throws IOException { + boolean contError) throws IOException { if (!contError) { doFile(a, source, dest, options, encoding); } else { @@ -127,40 +170,49 @@ doFile(a, source, dest, options, encoding); } catch (Exception ee) { System.out.println("Error processing " + source + ": " + ee); + ee.printStackTrace(); } } } - private static void doJar(String a, File source, File dest, ClassReader options, - String encoding, Boolean contError) throws IOException { + private static void doJar(String a, File source, File dest, + ClassReader options, String encoding, + Boolean contError) throws IOException { try { JarFile jf = new JarFile(source); - for (JarEntry je : Collections.list((Enumeration) jf.entries())) { + for (JarEntry je : Collections.list(jf.entries())) { String name = je.getName(); if (!name.endsWith(".class")) { continue; } - doStream(name, jf.getInputStream(je), dest, options, encoding); + try { + doStream(name, jf.getInputStream(je), dest, options, encoding); + } catch (Exception e) { + if (contError) { + System.out.println("Error processing " + source + ": " + e); + e.printStackTrace(); + continue; + } + } } } catch (IOException ioe) { - if (contError) { - System.out.println("Error processing " + source + ": " + ioe); - } else { - throw ioe; - } + throw ioe; } } private static void doStream(String a, InputStream in, File dest, - ClassReader options, String encoding) throws IOException { + ClassReader options, String encoding) throws IOException { File f = new File(a); ClassReader cr = new ClassReader(options); - Element e = cr.readFrom(in); + Element e; + if (options.verbose) { + System.out.println("Reading " + f); + } + e = cr.readFrom(in); OutputStream out; if (dest == null) { - //System.out.println(e.prettyString()); out = System.out; } else { File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath()); @@ -202,20 +254,8 @@ } - public static BufferedReader makeReader(InputStream in, String encoding) throws IOException { - // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name - if (encoding.equals("8BIT")) { - encoding = EIGHT_BIT_CHAR_ENCODING; - } - if (encoding.equals("UTF8")) { - encoding = UTF8_ENCODING; - } - if (encoding.equals("DEFAULT")) { - encoding = null; - } - if (encoding.equals("-")) { - encoding = null; - } + public static BufferedReader makeReader(InputStream in, + String encoding) throws IOException { Reader inw; in = new BufferedInputStream(in); // add buffering if (encoding == null) { @@ -226,20 +266,8 @@ return new BufferedReader(inw); // add buffering } - public static Writer makeWriter(OutputStream out, String encoding) throws IOException { - // encoding in DEFAULT, '', UTF8, 8BIT, , or any valid encoding name - if (encoding.equals("8BIT")) { - encoding = EIGHT_BIT_CHAR_ENCODING; - } - if (encoding.equals("UTF8")) { - encoding = UTF8_ENCODING; - } - if (encoding.equals("DEFAULT")) { - encoding = null; - } - if (encoding.equals("-")) { - encoding = null; - } + public static Writer makeWriter(OutputStream out, + String encoding) throws IOException { Writer outw; if (encoding == null) { outw = new OutputStreamWriter(out); @@ -252,12 +280,9 @@ public Element result() { return cfile; } + protected InputStream in; protected ByteArrayOutputStream buf = new ByteArrayOutputStream(1024); - protected byte cpTag[]; - protected String cpName[]; - protected String[] callables; // varies - public static final String REF_PREFIX = "#"; // input options public boolean pretty = false; public boolean verbose = false; @@ -270,7 +295,7 @@ public boolean keepSizes = false; public ClassReader() { - super.cfile = new Element("ClassFile"); + cfile = new Element("ClassFile"); } public ClassReader(ClassReader options) { @@ -283,12 +308,7 @@ verbose = options.verbose; keepPath = options.keepPath; keepCP = options.keepCP; - keepBytes = options.keepBytes; - parseBytes = options.parseBytes; - resolveRefs = options.resolveRefs; - keepSizes = options.keepSizes; keepOrder = options.keepOrder; - attrTypes = options.attrTypes; } public void copyOptionsFrom(Map options) { @@ -304,274 +324,177 @@ if (options.containsKey("-keepCP")) { keepCP = (options.get("-keepCP") != null); } - if (options.containsKey("-keepBytes")) { - keepBytes = (options.get("-keepBytes") != null); - } - if (options.containsKey("-parseBytes")) { - parseBytes = (options.get("-parseBytes") != null); - } - if (options.containsKey("-resolveRefs")) { - resolveRefs = (options.get("-resolveRefs") != null); - } - if (options.containsKey("-keepSizes")) { - keepSizes = (options.get("-keepSizes") != null); - } if (options.containsKey("-keepOrder")) { keepOrder = (options.get("-keepOrder") != null); } - if (options.containsKey("-attrDef")) { - addAttrTypes(options.get("-attrDef").split(" ")); - } - if (options.get("-jcov") != null) { - addJcovAttrTypes(); - } } + protected String getCpString(int i) { + return thePool.get(i); + } + public Element readFrom(InputStream in) throws IOException { - this.in = in; - // read the file header - int magic = u4(); - if (magic != 0xCAFEBABE) { - throw new RuntimeException("bad magic number " + Integer.toHexString(magic)); + try { + this.in = in; + ClassFile c = ClassFile.read(in); + // read the file header + if (c.magic != 0xCAFEBABE) { + throw new RuntimeException("bad magic number " + + Integer.toHexString(c.magic)); + } + cfile.setAttr("magic", "" + c.magic); + int minver = c.minor_version; + int majver = c.major_version; + cfile.setAttr("minver", "" + minver); + cfile.setAttr("majver", "" + majver); + readCP(c); + readClass(c); + return result(); + } catch (InvalidDescriptor | ConstantPoolException ex) { + throw new IOException("Fatal error", ex); } - cfile.setAttr("magic", "" + magic); - int minver = u2(); - int majver = u2(); - cfile.setAttr("minver", "" + minver); - cfile.setAttr("majver", "" + majver); - readCP(); - readClass(); - return result(); } public Element readFrom(File file) throws IOException { - InputStream in = null; - try { - in = new FileInputStream(file); - Element e = readFrom(new BufferedInputStream(in)); + try (InputStream strm = new FileInputStream(file)) { + Element e = readFrom(new BufferedInputStream(strm)); if (keepPath) { e.setAttr("path", file.toString()); } return e; - } finally { - if (in != null) { - in.close(); - } } } - private void readClass() throws IOException { + private void readClass(ClassFile c) throws IOException, + ConstantPoolException, + InvalidDescriptor { klass = new Element("Class"); cfile.add(klass); - int flags = u2(); - String thisk = cpRef(); - String superk = cpRef(); + String thisk = c.getName(); + klass.setAttr("name", thisk); - boolean flagsSync = ((flags & Modifier.SYNCHRONIZED) != 0); - flags &= ~Modifier.SYNCHRONIZED; - String flagString = flagString(flags, klass); - if (!flagsSync) { - if (flagString.length() > 0) { - flagString += " "; - } - flagString += "!synchronized"; + + AccessFlags af = new AccessFlags(c.access_flags.flags); + klass.setAttr("flags", flagString(af, klass)); + if (!"java/lang/Object".equals(thisk)) { + klass.setAttr("super", c.getSuperclassName()); + } + for (int i : c.interfaces) { + klass.add(new Element("Interface", "name", getCpString(i))); } - klass.setAttr("flags", flagString); - klass.setAttr("super", superk); - for (int len = u2(), i = 0; i < len; i++) { - String interk = cpRef(); - klass.add(new Element("Interface", "name", interk)); + readFields(c, klass); + readMethods(c, klass); + readAttributesFor(c, c.attributes, klass); + klass.trimToSize(); + } + + private void readFields(ClassFile c, Element klass) throws IOException { + int len = c.fields.length; + Element fields = new Element(len); + for (Field f : c.fields) { + Element field = new Element("Field"); + field.setAttr("name", getCpString(f.name_index)); + field.setAttr("type", getCpString(f.descriptor.index)); + field.setAttr("flags", flagString(f.access_flags.flags, field)); + readAttributesFor(c, f.attributes, field); + + field.trimToSize(); + fields.add(field); } - Element fields = readMembers("Field"); + if (!keepOrder) { + fields.sort(); + } klass.addAll(fields); - Element methods = readMembers("Method"); + } + + + private void readMethods(ClassFile c, Element klass) throws IOException { + int len = c.methods.length; + Element methods = new Element(len); + for (Method m : c.methods) { + Element member = new Element("Method"); + member.setAttr("name", getCpString(m.name_index)); + member.setAttr("type", getCpString(m.descriptor.index)); + member.setAttr("flags", flagString(m.access_flags.flags, member)); + readAttributesFor(c, m.attributes, member); + + member.trimToSize(); + methods.add(member); + } if (!keepOrder) { methods.sort(); } klass.addAll(methods); - readAttributesFor(klass); - klass.trimToSize(); - if (keepSizes) { - attachTo(cfile, formatAttrSizes()); - } - if (paddingSize != 0) { - cfile.setAttr("padding", "" + paddingSize); - } } - private Element readMembers(String kind) throws IOException { - int len = u2(); - Element members = new Element(len); - for (int i = 0; i < len; i++) { - Element member = new Element(kind); - int flags = u2(); - String name = cpRef(); - String type = cpRef(); - member.setAttr("name", name); - member.setAttr("type", type); - member.setAttr("flags", flagString(flags, member)); - readAttributesFor(member); - member.trimToSize(); - members.add(member); + private AccessFlags.Kind getKind(Element e) { + switch(e.getName()) { + case "Class": + return AccessFlags.Kind.Class; + case "InnerClass": + return AccessFlags.Kind.InnerClass; + case "Field": + return AccessFlags.Kind.Field ; + case "Method": + return AccessFlags.Kind.Method; + default: throw new RuntimeException("should not reach here"); } - return members; } protected String flagString(int flags, Element holder) { - // Superset of Modifier.toString. - int kind = 0; - if (holder.getName() == "Field") { - kind = 1; - } - if (holder.getName() == "Method") { - kind = 2; + return flagString(new AccessFlags(flags), holder); + } + protected String flagString(AccessFlags af, Element holder) { + return flagString(af, holder.getName()); + } + protected String flagString(int flags, String kind) { + return flagString(new AccessFlags(flags), kind); + } + protected String flagString(AccessFlags af, String kind) { + Set mods = null; + switch (kind) { + case "Class": + mods = af.getClassFlags(); + break; + case "InnerClass": + mods = af.getInnerClassFlags(); + break; + case "Field": + mods = af.getFieldFlags(); + break; + case "Method": + mods = af.getMethodFlags(); + break; + default: + throw new RuntimeException("should not reach here"); } - StringBuffer sb = new StringBuffer(); - for (int i = 0; flags != 0; i++, flags >>>= 1) { - if ((flags & 1) != 0) { - if (sb.length() > 0) { - sb.append(' '); - } - if (i < modifierNames.length) { - String[] names = modifierNames[i]; - String name = (kind < names.length) ? names[kind] : null; - for (String name2 : names) { - if (name != null) { - break; - } - name = name2; - } - sb.append(name); - } else { - sb.append("#").append(1 << i); - } - } + StringBuilder sb = new StringBuilder(); + for (String x : mods) { + sb.append(x.substring(x.indexOf('_') + 1).toLowerCase()).append(" "); } - return sb.toString(); + return sb.toString().trim(); } - private void readAttributesFor(Element x) throws IOException { - Element prevCurrent; - Element y = new Element(); - if (x.getName() == "Code") { - prevCurrent = currentCode; - currentCode = x; - } else { - prevCurrent = currentMember; - currentMember = x; - } - for (int len = u2(), i = 0; i < len; i++) { - int ref = u2(); - String uname = cpName(ref).intern(); - String refName = uname; - if (!resolveRefs) { - refName = (REF_PREFIX + ref).intern(); - } - String qname = (x.getName() + "." + uname).intern(); - String wname = ("*." + uname).intern(); - String type = attrTypes.get(qname); - if (type == null || "".equals(type)) { - type = attrTypes.get(wname); - } - if ("".equals(type)) { - type = null; - } - int size = u4(); - int[] countVar = attrSizes.get(qname); - if (countVar == null) { - attrSizes.put(qname, countVar = new int[2]); - } - countVar[0] += 1; - countVar[1] += size; - buf.reset(); - for (int j = 0; j < size; j++) { - buf.write(u1()); - } - if (type == null && size == 0) { - y.add(new Element(uname)); // , etc. - } else if (type == null) { - //System.out.println("Warning: No attribute type description: "+qname); - // write cdata attribute - Element a = new Element("Attribute", - new String[]{"Name", refName}, - buf.toString(EIGHT_BIT_CHAR_ENCODING)); - a.addContent(getCPDigest()); - y.add(a); - } else if (type.equals("")) { - // ignore this attribute... - } else { - InputStream in0 = in; - int fileSize0 = fileSize; - ByteArrayInputStream in1 = new ByteArrayInputStream(buf.toByteArray()); - boolean ok = false; - try { - in = in1; - // parse according to type desc. - Element aval; - if (type.equals("...")) { - // delve into Code attribute - aval = readCode(); - } else if (type.equals("...")) { - // delve into StackMap attribute - aval = readStackMap(false); - } else if (type.equals("...")) { - // delve into StackMap attribute - aval = readStackMap(true); - } else if (type.startsWith("[")) { - aval = readAttributeCallables(type); - } else { - aval = readAttribute(type); - } - //System.out.println("attachTo 1 "+y+" <- "+aval); - attachTo(y, aval); - if (false - && in1.available() != 0) { - throw new RuntimeException("extra bytes in " + qname + " :" + in1.available()); - } - ok = true; - } finally { - in = in0; - fileSize = fileSize0; - if (!ok) { - System.out.println("*** Failed to read " + type); - } - } - } - } - if (x.getName() == "Code") { - currentCode = prevCurrent; - } else { - currentMember = prevCurrent; + + protected void readAttributesFor(ClassFile c, Attributes attrs, Element x) { + Element container = new Element(); + AttributeVisitor av = new AttributeVisitor(this, c); + for (Attribute a : attrs) { + av.visit(a, container); } if (!keepOrder) { - y.sort(); - y.sortAttrs(); + container.sort(); } - //System.out.println("attachTo 2 "+x+" <- "+y); - attachTo(x, y); + x.addAll(container); } - private int fileSize = 0; - private int paddingSize = 0; - private HashMap attrSizes = new HashMap(); - private Element formatAttrSizes() { - Element e = new Element("Sizes"); - e.setAttr("fileSize", "" + fileSize); - for (Map.Entry ie : attrSizes.entrySet()) { - int[] countVar = ie.getValue(); - e.add(new Element("AttrSize", - "name", ie.getKey().toString(), - "count", "" + countVar[0], - "size", "" + countVar[1])); - } - return e; - } + private int fileSize = 0; + private HashMap attrSizes = new HashMap<>(); private void attachTo(Element x, Object aval0) { if (aval0 == null) { return; } - //System.out.println("attachTo "+x+" : "+aval0); if (!(aval0 instanceof Element)) { x.add(aval0); return; @@ -589,7 +512,6 @@ } private void attachAttrTo(Element x, String aname, String aval) { - //System.out.println("attachAttrTo "+x+" : "+aname+"="+aval); String aval0 = x.getAttr(aname); if (aval0 != null) { aval = aval0 + " " + aval; @@ -597,407 +519,1003 @@ x.setAttr(aname, aval); } - private Element readAttributeCallables(String type) throws IOException { - assert (callables == null); - callables = getBodies(type); - Element res = readAttribute(callables[0]); - callables = null; - return res; - } - - private Element readAttribute(String type) throws IOException { - //System.out.println("readAttribute "+type); - Element aval = new Element(); - String nextAttrName = null; - for (int len = type.length(), next, i = 0; i < len; i = next) { - String value; - switch (type.charAt(i)) { - case '<': - assert (nextAttrName == null); - next = type.indexOf('>', ++i); - String form = type.substring(i, next++); - if (form.indexOf('=') < 0) { - // elem_placement = '<' elemname '>' - assert (aval.attrSize() == 0); - assert (aval.isAnonymous()); - aval.setName(form.intern()); - } else { - // attr_placement = '<' attrname '=' (value)? '>' - int eqPos = form.indexOf('='); - nextAttrName = form.substring(0, eqPos).intern(); - if (eqPos != form.length() - 1) { - value = form.substring(eqPos + 1); - attachAttrTo(aval, nextAttrName, value); - nextAttrName = null; - } - // ...else subsequent type parsing will find the attr value - // and add it as "nextAttrName". - } - continue; - case '(': - next = type.indexOf(')', ++i); - int callee = Integer.parseInt(type.substring(i, next++)); - attachTo(aval, readAttribute(callables[callee])); - continue; - case 'N': // replication = 'N' int '[' type ... ']' - { - int count = getInt(type.charAt(i + 1), false); - assert (count >= 0); - next = i + 2; - String type1 = getBody(type, next); - next += type1.length() + 2; // skip body and brackets - for (int j = 0; j < count; j++) { - attachTo(aval, readAttribute(type1)); - } - } - continue; - case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']' - int tagValue; - if (type.charAt(++i) == 'S') { - tagValue = getInt(type.charAt(++i), true); - } else { - tagValue = getInt(type.charAt(i), false); - } - attachAttrTo(aval, "tag", "" + tagValue); // always named "tag" - ++i; // skip the int type char - // union_case = '(' uc_tag (',' uc_tag)* ')' '[' body ']' - // uc_tag = ('-')? digit+ - for (boolean foundCase = false;; i = next) { - assert (type.charAt(i) == '('); - next = type.indexOf(')', ++i); - assert (next >= i); - if (type.charAt(next - 1) == '\\' - && type.charAt(next - 2) != '\\') // Skip an escaped paren. - { - next = type.indexOf(')', next + 1); - } - String caseStr = type.substring(i, next++); - String type1 = getBody(type, next); - next += type1.length() + 2; // skip body and brackets - boolean lastCase = (caseStr.length() == 0); - if (!foundCase - && (lastCase || matchTag(tagValue, caseStr))) { - foundCase = true; - // Execute this body. - attachTo(aval, readAttribute(type1)); - } - if (lastCase) { - break; - } - } - continue; - case 'B': - case 'H': - case 'I': // int = oneof "BHI" - next = i + 1; - value = "" + getInt(type.charAt(i), false); - break; - case 'K': - assert ("IJFDLQ".indexOf(type.charAt(i + 1)) >= 0); - assert (type.charAt(i + 2) == 'H'); // only H works for now - next = i + 3; - value = cpRef(); - break; - case 'R': - assert ("CSDFMIU?".indexOf(type.charAt(i + 1)) >= 0); - assert (type.charAt(i + 2) == 'H'); // only H works for now - next = i + 3; - value = cpRef(); - break; - case 'P': // bci = 'P' int - next = i + 2; - value = "" + getInt(type.charAt(i + 1), false); - break; - case 'S': // signed_int = 'S' int - next = i + 2; - value = "" + getInt(type.charAt(i + 1), true); - break; - case 'F': - next = i + 2; - value = flagString(getInt(type.charAt(i + 1), false), currentMember); - break; - default: - throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type); - } - // store the value - if (nextAttrName != null) { - attachAttrTo(aval, nextAttrName, value); - nextAttrName = null; - } else { - attachTo(aval, value); - } - } - //System.out.println("readAttribute => "+aval); - assert (nextAttrName == null); - return aval; - } - - private int getInt(char ch, boolean signed) throws IOException { - if (signed) { - switch (ch) { - case 'B': - return (byte) u1(); - case 'H': - return (short) u2(); - case 'I': - return (int) u4(); - } - } else { - switch (ch) { - case 'B': - return u1(); - case 'H': - return u2(); - case 'I': - return u4(); + private void readCP(ClassFile c) throws IOException { + cpool = new Element("ConstantPool", c.constant_pool.size()); + ConstantPoolVisitor cpv = new ConstantPoolVisitor(cpool, c, + c.constant_pool.size()); + for (int i = 1 ; i < c.constant_pool.size() ; i++) { + try { + cpv.visit(c.constant_pool.get(i), i); + } catch (InvalidIndex ex) { + // can happen periodically when accessing doubles etc. ignore it + // ex.printStackTrace(); } } - assert ("BHIJ".indexOf(ch) >= 0); - return 0; - } - - private Element readCode() throws IOException { - int stack = u2(); - int local = u2(); - int length = u4(); - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - sb.append((char) u1()); - } - String bytecodes = sb.toString(); - Element e = new Element("Code", - "stack", "" + stack, - "local", "" + local); - Element bytes = new Element("Bytes", (String[]) null, bytecodes); - if (keepBytes) { - e.add(bytes); - } - if (parseBytes) { - e.add(parseByteCodes(bytecodes)); - } - for (int len = u2(), i = 0; i < len; i++) { - int start = u2(); - int end = u2(); - int catsh = u2(); - String clasz = cpRef(); - e.add(new Element("Handler", - "start", "" + start, - "end", "" + end, - "catch", "" + catsh, - "class", clasz)); - } - readAttributesFor(e); - e.trimToSize(); - return e; - } - - private Element parseByteCodes(String bytecodes) { - Element e = InstructionSyntax.parse(bytecodes); - for (Element ins : e.elements()) { - Number ref = ins.getAttrNumber("ref"); - if (ref != null && resolveRefs) { - int id = ref.intValue(); - String val = cpName(id); - if (ins.getName().startsWith("ldc")) { - // Yuck: Arb. string cannot be an XML attribute. - ins.add(val); - val = ""; - byte tag = (id >= 0 && id < cpTag.length) ? cpTag[id] : 0; - if (tag != 0) { - ins.setAttrLong("tag", tag); - } - } - if (ins.getName() == "invokeinterface" - && computeInterfaceNum(val) == ins.getAttrLong("num")) { - ins.setAttr("num", null); // garbage bytes - } - ins.setAttr("ref", null); - ins.setAttr("val", val); - } - } - return e; - } - - private Element readStackMap(boolean hasXOption) throws IOException { - Element result = new Element(); - Element bytes = currentCode.findElement("Bytes"); - assert (bytes != null && bytes.size() == 1); - int byteLength = ((String) bytes.get(0)).length(); - boolean uoffsetIsU4 = (byteLength >= (1 << 16)); - boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16); - boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16); - if (hasXOption || uoffsetIsU4 || ulocalvarIsU4 || ustackIsU4) { - Element flags = new Element("StackMapFlags"); - if (hasXOption) { - flags.setAttr("hasXOption", "true"); - } - if (uoffsetIsU4) { - flags.setAttr("uoffsetIsU4", "true"); - } - if (ulocalvarIsU4) { - flags.setAttr("ulocalvarIsU4", "true"); - } - if (ustackIsU4) { - flags.setAttr("ustackIsU4", "true"); - } - currentCode.add(flags); - } - int frame_count = (uoffsetIsU4 ? u4() : u2()); - for (int i = 0; i < frame_count; i++) { - int bci = (uoffsetIsU4 ? u4() : u2()); - int flags = (hasXOption ? u1() : 0); - Element frame = new Element("Frame"); - result.add(frame); - if (flags != 0) { - frame.setAttr("flags", "" + flags); + thePool = cpv.getPoolList(); + if (verbose) { + for (int i = 0; i < thePool.size(); i++) { + System.out.println("[" + i + "]: " + thePool.get(i)); } - frame.setAttr("bci", "" + bci); - // Scan local and stack types in this frame: - final int LOCALS = 0, STACK = 1; - for (int j = LOCALS; j <= STACK; j++) { - int typeSize; - if (j == LOCALS) { - typeSize = (ulocalvarIsU4 ? u4() : u2()); - } else { // STACK - typeSize = (ustackIsU4 ? u4() : u2()); - } - Element types = new Element(j == LOCALS ? "Local" : "Stack"); - for (int k = 0; k < typeSize; k++) { - int tag = u1(); - Element type = new Element(itemTagName(tag)); - types.add(type); - switch (tag) { - case ITEM_Object: - type.setAttr("class", cpRef()); - break; - case ITEM_Uninitialized: - case ITEM_ReturnAddress: - type.setAttr("bci", "" + (uoffsetIsU4 ? u4() : u2())); - break; - } - } - if (types.size() > 0) { - frame.add(types); - } - } - } - return result; - } - - private void readCP() throws IOException { - int cpLen = u2(); - cpTag = new byte[cpLen]; - cpName = new String[cpLen]; - int cpTem[][] = new int[cpLen][]; - for (int i = 1; i < cpLen; i++) { - cpTag[i] = (byte) u1(); - switch (cpTag[i]) { - case CONSTANT_Utf8: - buf.reset(); - for (int len = u2(), j = 0; j < len; j++) { - buf.write(u1()); - } - cpName[i] = buf.toString(UTF8_ENCODING); - break; - case CONSTANT_Integer: - cpName[i] = String.valueOf((int) u4()); - break; - case CONSTANT_Float: - cpName[i] = String.valueOf(Float.intBitsToFloat(u4())); - break; - case CONSTANT_Long: - cpName[i] = String.valueOf(u8()); - i += 1; - break; - case CONSTANT_Double: - cpName[i] = String.valueOf(Double.longBitsToDouble(u8())); - i += 1; - break; - case CONSTANT_Class: - case CONSTANT_String: - cpTem[i] = new int[]{u2()}; - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_NameAndType: - cpTem[i] = new int[]{u2(), u2()}; - break; - } - } - for (int i = 1; i < cpLen; i++) { - switch (cpTag[i]) { - case CONSTANT_Class: - case CONSTANT_String: - cpName[i] = cpName[cpTem[i][0]]; - break; - case CONSTANT_NameAndType: - cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]]; - break; - } - } - // do fieldref et al after nameandtype are all resolved - for (int i = 1; i < cpLen; i++) { - switch (cpTag[i]) { - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - cpName[i] = cpName[cpTem[i][0]] + " " + cpName[cpTem[i][1]]; - break; - } - } - cpool = new Element("ConstantPool", cpName.length); - for (int i = 0; i < cpName.length; i++) { - if (cpName[i] == null) { - continue; - } - cpool.add(new Element(cpTagName(cpTag[i]), - new String[]{"id", "" + i}, - cpName[i])); } if (keepCP) { cfile.add(cpool); } } +} - private String cpRef() throws IOException { - int ref = u2(); - if (resolveRefs) { - return cpName(ref); - } else { - return REF_PREFIX + ref; +class ConstantPoolVisitor implements ConstantPool.Visitor { + final List slist; + final Element xpool; + final ClassFile cf; + final ConstantPool cfpool; + final List bsmlist; + + + public ConstantPoolVisitor(Element xpool, ClassFile cf, int size) { + slist = new ArrayList<>(size); + for (int i = 0 ; i < size; i++) { + slist.add(null); + } + this.xpool = xpool; + this.cf = cf; + this.cfpool = cf.constant_pool; + bsmlist = readBSM(); + } + + public List getPoolList() { + return Collections.unmodifiableList(slist); + } + + public List getBSMList() { + return Collections.unmodifiableList(bsmlist); + } + + public String visit(CPInfo c, int index) { + return c.accept(this, index); + } + + private List readBSM() { + BootstrapMethods_attribute bsmAttr = + (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods); + if (bsmAttr != null) { + List out = + new ArrayList<>(bsmAttr.bootstrap_method_specifiers.length); + for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms : + bsmAttr.bootstrap_method_specifiers) { + int index = bsms.bootstrap_method_ref; + try { + String value = slist.get(index); + String bsmStr = value; + if (value == null) { + value = visit(cfpool.get(index), index); + slist.set(index, value); + } + bsmStr = value; + for (int idx : bsms.bootstrap_arguments) { + value = slist.get(idx); + if (value == null) { + value = visit(cfpool.get(idx), idx); + slist.set(idx, value); + } + bsmStr = bsmStr.concat("," + value); + } + out.add(bsmStr); + } catch (InvalidIndex ex) { + ex.printStackTrace(); + } + } + return out; } + return new ArrayList<>(0); + } + + @Override + public String visitClass(CONSTANT_Class_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.name_index), c.name_index); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Class", + new String[]{"id", p.toString()}, + value)); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitDouble(CONSTANT_Double_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + value = Double.toString(c.value); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Double", + new String[]{"id", p.toString()}, + value)); + } + return value; + } + + @Override + public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Fieldref", + new String[]{"id", p.toString()}, + value)); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitFloat(CONSTANT_Float_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + value = Float.toString(c.value); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Float", + new String[]{"id", p.toString()}, + value)); + } + return value; + } + + @Override + public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) { + String value = slist.get(p); + if (value == null) { + value = Integer.toString(cnstnt.value); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Integer", + new String[]{"id", p.toString()}, + value)); + } + return value; } - private String cpName(int id) { - if (id >= 0 && id < cpName.length) { - return cpName[id]; - } else { - return "[CP#" + Integer.toHexString(id) + "]"; + @Override + public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c, + Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + xpool.add(new Element("CONSTANT_InterfaceMethodref", + new String[]{"id", p.toString()}, + value)); + + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = bsmlist.get(c.bootstrap_method_attr_index) + " " + + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index); + slist.set(p, value); + xpool.add(new Element("CONSTANT_InvokeDynamic", + new String[]{"id", p.toString()}, + value)); + + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitLong(CONSTANT_Long_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + value = Long.toString(c.value); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Long", + new String[]{"id", p.toString()}, + value)); + } + return value; + } + + @Override + public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.name_index), c.name_index); + value = value.concat(" " + + visit(cfpool.get(c.type_index), c.type_index)); + slist.set(p, value); + xpool.add(new Element("CONSTANT_NameAndType", + new String[]{"id", p.toString()}, + value)); + } catch (InvalidIndex ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodref(CONSTANT_Methodref_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + xpool.add(new Element("CONSTANT_Methodref", + new String[]{"id", p.toString()}, + value)); + + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = c.reference_kind.name(); + value = value.concat(" " + + visit(cfpool.get(c.reference_index), c.reference_index)); + slist.set(p, value); + xpool.add(new Element("CONSTANT_MethodHandle", + new String[]{"id", p.toString()}, + value)); + + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodType(CONSTANT_MethodType_info c, Integer p) { + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.descriptor_index), c.descriptor_index); + slist.set(p, value); + xpool.add(new Element("CONSTANT_MethodType", + new String[]{"id", p.toString()}, + value)); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitString(CONSTANT_String_info c, Integer p) { + try { + + String value = slist.get(p); + if (value == null) { + value = c.getString(); + slist.set(p, value); + xpool.add(new Element("CONSTANT_String", + new String[]{"id", p.toString()}, + value)); + } + return value; + } catch (ConstantPoolException ex) { + throw new RuntimeException("Fatal error", ex); } } - private long u8() throws IOException { - return ((long) u4() << 32) + (((long) u4() << 32) >>> 32); - } - - private int u4() throws IOException { - return (u2() << 16) + u2(); - } + @Override + public String visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) { + String value = slist.get(p); + if (value == null) { + value = cnstnt.value; + slist.set(p, value); + xpool.add(new Element("CONSTANT_Utf8", + new String[]{"id", p.toString()}, + value)); + } + return value; - private int u2() throws IOException { - return (u1() << 8) + u1(); - } - - private int u1() throws IOException { - int x = in.read(); - if (x < 0) { - paddingSize++; - return 0; // error recovery - } - fileSize++; - assert (x == (x & 0xFF)); - return x; } } +class AttributeVisitor implements Attribute.Visitor { + final ClassFile cf; + final ClassReader x; + final AnnotationsElementVisitor aev; + final InstructionVisitor iv; + + public AttributeVisitor(ClassReader x, ClassFile cf) { + this.x = x; + this.cf = cf; + iv = new InstructionVisitor(x, cf); + aev = new AnnotationsElementVisitor(x, cf); + } + + public void visit(Attribute a, Element parent) { + a.accept(this, parent); + } + + @Override + public Element visitBootstrapMethods(BootstrapMethods_attribute bm, Element p) { + Element e = new Element(x.getCpString(bm.attribute_name_index)); + for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : bm.bootstrap_method_specifiers) { + Element be = new Element("BootstrapMethodSpecifier"); + be.setAttr("ref", x.getCpString(bsm.bootstrap_method_ref)); + if (bsm.bootstrap_arguments.length > 0) { + Element bme = new Element("MethodArguments"); + for (int index : bsm.bootstrap_arguments) { + bme.add(x.getCpString(index)); + } + bme.trimToSize(); + be.add(bme); + } + be.trimToSize(); + e.add(be); + } + e.trimToSize(); + if (!x.keepOrder) { + e.sort(); + } + p.add(e); + return null; + } + + @Override + public Element visitDefault(DefaultAttribute da, Element p) { + Element e = new Element(x.getCpString(da.attribute_name_index)); + StringBuilder sb = new StringBuilder(); + for (byte x : da.info) { + sb.append("0x").append(Integer.toHexString(x)).append(" "); + } + e.setAttr("bytes", sb.toString().trim()); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitAnnotationDefault(AnnotationDefault_attribute ad, Element p) { + Element e = new Element(x.getCpString(ad.attribute_name_index)); + e.setAttr("tag", "" + ad.default_value.tag); + Element child = aev.visit(ad.default_value, e); + if (child != null) { + e.add(child); + } + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitCharacterRangeTable(CharacterRangeTable_attribute crt, + Element p) { + Element e = new Element(x.getCpString(crt.attribute_name_index)); + for (CharacterRangeTable_attribute.Entry ce : crt.character_range_table) { + e.setAttr("start_pc", "" + ce.start_pc); + e.setAttr("end_pc", "" + ce.end_pc); + e.setAttr("range_start", "" + ce.character_range_start); + e.setAttr("range_end", "" + ce.character_range_end); + e.setAttr("flags", x.flagString(ce.flags, "Method")); + } + e.trimToSize(); + p.add(e); + return null; + } + + private Element instructions(Element code, Code_attribute c) { + Element ielement = new Element("Instructions"); + for (Instruction ins : c.getInstructions()) { + ielement.add(iv.visit(ins)); + } + ielement.trimToSize(); + return ielement; + } + + @Override + public Element visitCode(Code_attribute c, Element p) { + Element e = null; + + e = new Element(x.getCpString(c.attribute_name_index), + "stack", "" + c.max_stack, + "local", "" + c.max_locals); + + e.add(instructions(e, c)); + + for (Code_attribute.Exception_data edata : c.exception_table) { + e.add(new Element("Handler", + "start", "" + edata.start_pc, + "end", "" + edata.end_pc, + "catch", "" + edata.handler_pc, + "class", x.getCpString(edata.catch_type))); + + } + this.x.readAttributesFor(cf, c.attributes, e); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitCompilationID(CompilationID_attribute cid, Element p) { + Element e = new Element(x.getCpString(cid.attribute_name_index), + x.getCpString(cid.compilationID_index)); + p.add(e); + return null; + } + + @Override + public Element visitConstantValue(ConstantValue_attribute cv, Element p) { + Element e = new Element(x.getCpString(cv.attribute_name_index)); + e.add(x.getCpString(cv.constantvalue_index)); + p.add(e); + return null; + } + + @Override + public Element visitDeprecated(Deprecated_attribute d, Element p) { + Element e = new Element(x.getCpString(d.attribute_name_index)); + p.add(e); + return null; + } + + @Override + public Element visitEnclosingMethod(EnclosingMethod_attribute em, Element p) { + Element e = new Element(x.getCpString(em.attribute_name_index)); + e.setAttr("class", x.getCpString(em.class_index)); + e.setAttr("desc", x.getCpString(em.method_index)); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitExceptions(Exceptions_attribute e, Element p) { + Element ee = new Element(x.getCpString(e.attribute_name_index)); + for (int idx : e.exception_index_table) { + Element n = new Element("Item"); + n.setAttr("class", x.getCpString(idx)); + ee.add(n); + } + ee.trimToSize(); + p.add(ee); + return null; + } + + @Override + public Element visitInnerClasses(InnerClasses_attribute ic, Element p) { + for (Info info : ic.classes) { + Element e = new Element(x.getCpString(ic.attribute_name_index)); + e.setAttr("class", x.getCpString(info.inner_class_info_index)); + e.setAttr("outer", x.getCpString(info.outer_class_info_index)); + e.setAttr("name", x.getCpString(info.inner_name_index)); + e.setAttr("flags", x.flagString(info.inner_class_access_flags, + "InnerClass")); + e.trimToSize(); + p.add(e); + } + return null; + } + + @Override + public Element visitLineNumberTable(LineNumberTable_attribute lnt, Element p) { + String name = x.getCpString(lnt.attribute_name_index); + for (LineNumberTable_attribute.Entry e : lnt.line_number_table) { + Element l = new Element(name); + l.setAttr("bci", "" + e.start_pc); + l.setAttr("line", "" + e.line_number); + l.trimToSize(); + p.add(l); + } + return null; // already added to parent + } + + @Override + public Element visitLocalVariableTable(LocalVariableTable_attribute lvt, + Element p) { + String name = x.getCpString(lvt.attribute_name_index); + for (LocalVariableTable_attribute.Entry e : lvt.local_variable_table) { + Element l = new Element(name); + l.setAttr("bci", "" + e.start_pc); + l.setAttr("span", "" + e.length); + l.setAttr("name", x.getCpString(e.name_index)); + l.setAttr("type", x.getCpString(e.descriptor_index)); + l.setAttr("slot", "" + e.index); + l.trimToSize(); + p.add(l); + } + return null; // already added to parent + } + + @Override + public Element visitLocalVariableTypeTable(LocalVariableTypeTable_attribute lvtt, + Element p) { + String name = x.getCpString(lvtt.attribute_name_index); + for (LocalVariableTypeTable_attribute.Entry e : lvtt.local_variable_table) { + Element l = new Element(name); + l.setAttr("bci", "" + e.start_pc); + l.setAttr("span", "" + e.length); + l.setAttr("name", x.getCpString(e.name_index)); + l.setAttr("type", x.getCpString(e.signature_index)); + l.setAttr("slot", "" + e.index); + l.trimToSize(); + p.add(l); + } + return null; // already added to parent + } + + private void parseAnnotations(Annotation[] ra, Element p) { + for (Annotation anno : ra) { + Element ea = new Element("Member"); + ea.setAttr("name", "" + x.getCpString(anno.type_index)); + for (Annotation.element_value_pair evp : anno.element_value_pairs) { + Element evpe = new Element("Element"); + evpe.setAttr("tag", "" + evp.value.tag); + evpe.setAttr("value", x.getCpString(evp.element_name_index)); + Element child = aev.visit(evp.value, evpe); + if (child != null) { + evpe.add(child); + } + ea.add(evpe); + } + ea.trimToSize(); + p.add(ea); + } + } + + @Override + public Element visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute rva, + Element p) { + Element e = new Element(x.getCpString(rva.attribute_name_index)); + parseAnnotations(rva.annotations, e); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute ria, + Element p) { + Element e = new Element(x.getCpString(ria.attribute_name_index)); + parseAnnotations(ria.annotations, e); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute rvpa, + Element p) { + Element e = new Element(x.getCpString(rvpa.attribute_name_index)); + for (Annotation[] pa : rvpa.parameter_annotations) { + parseAnnotations(pa, e); + } + p.add(e); + return null; + } + + @Override + public Element visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute ripa, + Element p) { + Element e = new Element(x.getCpString(ripa.attribute_name_index)); + for (Annotation[] pa : ripa.parameter_annotations) { + parseAnnotations(pa, e); + } + p.add(e); + return null; + } + + @Override + public Element visitSignature(Signature_attribute s, Element p) { + String aname = x.getCpString(s.attribute_name_index); + String sname = x.getCpString(s.signature_index); + Element se = new Element(aname); + se.add(sname); + se.trimToSize(); + p.add(se); + return null; + } + + @Override + public Element visitSourceDebugExtension(SourceDebugExtension_attribute sde, + Element p) { + String aname = x.getCpString(sde.attribute_name_index); + Element se = new Element(aname); + se.setAttr("val", sde.getValue()); + se.trimToSize(); + p.add(se); + return null; + } + + @Override + public Element visitSourceFile(SourceFile_attribute sf, Element p) { + String aname = x.getCpString(sf.attribute_name_index); + String sname = x.getCpString(sf.sourcefile_index); + Element se = new Element(aname); + se.add(sname); + se.trimToSize(); + p.add(se); + return null; + } + + @Override + public Element visitSourceID(SourceID_attribute sid, Element p) { + Element e = new Element(x.getCpString(sid.attribute_name_index)); + e.add(x.getCpString(sid.sourceID_index)); + e.trimToSize(); + p.add(e); + return null; + } + + @Override + public Element visitStackMap(StackMap_attribute sm, Element p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element visitStackMapTable(StackMapTable_attribute smt, Element p) { + Element stackmap = new Element(x.getCpString(smt.attribute_name_index)); + for (StackMapTable_attribute.stack_map_frame f : smt.entries) { + StackMapVisitor smv = new StackMapVisitor(x, cf, stackmap); + stackmap.add(smv.visit(f)); + } + stackmap.trimToSize(); + p.add(stackmap); + return null; + } + + @Override + public Element visitSynthetic(Synthetic_attribute s, Element p) { + Element e = new Element(x.getCpString(s.attribute_name_index)); + e.trimToSize(); + p.add(e); + return null; + } +} + +class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor { + + final ClassFile cf; + final ClassReader x; + final Element parent; + + public StackMapVisitor(ClassReader x, ClassFile cf, Element parent) { + this.x = x; + this.cf = cf; + this.parent = parent; + } + + public Element visit(StackMapTable_attribute.stack_map_frame frame) { + return frame.accept(this, null); + } + + @Override + public Element visit_same_frame(same_frame sm_frm, Void p) { + Element e = new Element("SameFrame"); + e.setAttr("tag", "" + sm_frm.frame_type); + return e; + } + + @Override + public Element visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame s, Void p) { + Element e = new Element("SameLocals1StackItemFrame"); + e.setAttr("tag", "" + s.frame_type); + e.addAll(getVerificationTypeInfo("Stack", s.stack)); + e.trimToSize(); + return e; + } + + @Override + public Element visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended s, Void p) { + Element e = new Element("SameLocals1StackItemFrameExtended"); + e.setAttr("tag", "" + s.frame_type); + e.addAll(getVerificationTypeInfo("Stack", s.stack)); + e.trimToSize(); + return e; + } + + @Override + public Element visit_chop_frame(chop_frame c, Void p) { + Element e = new Element("Chop" + (251 - c.frame_type)); + e.setAttr("tag", "" + c.frame_type); + e.setAttr("offset", "" + c.offset_delta); + return e; + } + + @Override + public Element visit_same_frame_extended(same_frame_extended s, Void p) { + Element e = new Element("SameFrameExtended"); + e.setAttr("tag", "" + s.frame_type); + e.setAttr("offset", "" + s.offset_delta); + return e; + } + + @Override + public Element visit_append_frame(append_frame a, Void p) { + Element e = new Element("AppendFrame" + (a.frame_type - 251)); + e.setAttr("tag", "" + a.frame_type); + e.addAll(getVerificationTypeInfo("Local", a.locals)); + e.trimToSize(); + return e; + } + + @Override + public Element visit_full_frame(full_frame fl_frm, Void p) { + Element e = new Element("FullFrame"); + e.setAttr("tag", "" + fl_frm.frame_type); + e.addAll(getVerificationTypeInfo("Local", fl_frm.locals)); + e.trimToSize(); + return e; + } + + private Element getVerificationTypeInfo(String kind, + StackMapTable_attribute.verification_type_info velems[]) { + Element container = new Element(velems.length); + for (StackMapTable_attribute.verification_type_info v : velems) { + Element ve = null; + int offset = 0; + int index = 0; + switch (v.tag) { + case StackMapTable_attribute.verification_type_info.ITEM_Top: + ve = new Element("ITEM_Top"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Integer: + ve = new Element("ITEM_Integer"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Float: + ve = new Element("ITEM_Float"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Long: + ve = new Element("ITEM_Long"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Double: + ve = new Element("ITEM_Double"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Null: + ve = new Element("ITEM_Null"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: + ve = new Element("ITEM_Uninitialized"); + offset = ((StackMapTable_attribute.Uninitialized_variable_info) v).offset; + ve.setAttr("offset", "" + offset); + break; + case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis: + ve = new Element("ITEM_UnitializedtThis"); + break; + case StackMapTable_attribute.verification_type_info.ITEM_Object: + ve = new Element("ITEM_Object"); + index = ((StackMapTable_attribute.Object_variable_info) v).cpool_index; + ve.setAttr("class", x.getCpString(index)); + break; + default: + ve = new Element("Unknown"); + } + Element kindE = new Element(kind); + kindE.setAttr("tag", "" + v.tag); + container.add(kindE); + kindE.add(ve); + } + container.trimToSize(); + return container; + } +} + +class InstructionVisitor implements Instruction.KindVisitor { + + final ClassReader x; + final ClassFile cf; + + public InstructionVisitor(ClassReader x, ClassFile cf) { + this.x = x; + this.cf = cf; + } + + public Element visit(Instruction i) { + Element ie = i.accept(this, null); + ie.trimToSize(); + return ie; + } + + @Override + public Element visitNoOperands(Instruction i, Void p) { + Opcode o = i.getOpcode(); + Element e = new Element(i.getMnemonic()); + if (o.opcode > 0xab && o.opcode <= 0xb1) { + e.setAttr("pc", "" + i.getPC()); + } + return e; + } + + @Override + public Element visitArrayType(Instruction i, TypeKind tk, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("num", "" + tk.value); + ie.setAttr("val", tk.name); + return ie; + } + + @Override + public Element visitBranch(Instruction i, int i1, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("lab", "" + (i.getPC() + i1)); + return ie; + } + + @Override + public Element visitConstantPoolRef(Instruction i, int i1, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("ref", x.getCpString(i1)); + return ie; + } + + @Override + public Element visitConstantPoolRefAndValue(Instruction i, int i1, int i2, Void p) { + // workaround for a potential bug in classfile + Element ie = new Element(i.getMnemonic()); + if (i.getOpcode().equals(Opcode.IINC_W)) { + ie.setAttr("loc", "" + i1); + ie.setAttr("num", "" + i2); + } else { + ie.setAttr("ref", x.getCpString(i1)); + ie.setAttr("val", "" + i2); + } + return ie; + } + + @Override + public Element visitLocal(Instruction i, int i1, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("loc", "" + i1); + return ie; + } + + @Override + public Element visitLocalAndValue(Instruction i, int i1, int i2, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("loc", "" + i1); + ie.setAttr("num", "" + i2); + return ie; + } + + @Override + public Element visitLookupSwitch(Instruction i, int i1, int i2, int[] ints, + int[] ints1, Void p) { + Element ie = new Element(i.getMnemonic()); + int pc = i.getPC(); + ie.setAttr("lab", "" + (pc + i1)); + for (int k = 0 ; k < i2 ; k++) { + Element c = new Element("Case"); + c.setAttr("num", "" + (ints[k])); + c.setAttr("lab", "" + (pc + ints1[k])); + c.trimToSize(); + ie.add(c); + } + return ie; + } + + @Override + public Element visitTableSwitch(Instruction i, int i1, int i2, int i3, + int[] ints, Void p) { + Element ie = new Element(i.getMnemonic()); + int pc = i.getPC(); + ie.setAttr("lab", "" + (pc + i1)); + for (int k : ints) { + Element c = new Element("Case"); + c.setAttr("num", "" + (k + i2)); + c.setAttr("lab", "" + (pc + k)); + c.trimToSize(); + ie.add(c); + } + return ie; + } + + @Override + public Element visitValue(Instruction i, int i1, Void p) { + Element ie = new Element(i.getMnemonic()); + ie.setAttr("num", "" + i1); + return ie; + } + + @Override + public Element visitUnknown(Instruction i, Void p) { + Element e = new Element(i.getMnemonic()); + e.setAttr("pc", "" + i.getPC()); + e.setAttr("opcode", "" + i.getOpcode().opcode); + return e; + } +} + +class AnnotationsElementVisitor implements Annotation.element_value.Visitor { + final ClassReader x; + final ClassFile cf; + + public AnnotationsElementVisitor(ClassReader x, ClassFile cf) { + this.x = x; + this.cf = cf; + } + + public Element visit(Annotation.element_value v, Element p) { + return v.accept(this, p); + } + + @Override + public Element visitPrimitive(Primitive_element_value e, Element p) { + Element el = new Element("String"); + el.setAttr("val", x.getCpString(e.const_value_index)); + el.trimToSize(); + return el; + } + + @Override + public Element visitEnum(Enum_element_value e, Element p) { + Element el = new Element("Enum"); + el.setAttr("name", x.getCpString(e.const_name_index)); + el.setAttr("type", x.getCpString(e.type_name_index)); + el.trimToSize(); + return el; + } + + @Override + public Element visitClass(Class_element_value c, Element p) { + Element el = new Element("Class"); + el.setAttr("name", x.getCpString(c.class_info_index)); + el.trimToSize(); + return el; + } + + @Override + public Element visitAnnotation(Annotation_element_value a, Element p) { + Element el = new Element("Annotation"); + Annotation anno = a.annotation_value; + for (Annotation.element_value_pair evp : anno.element_value_pairs) { + Element child = visit(evp.value, el); + if (child != null) { + el.add(child); + } + } + el.trimToSize(); + return el; + } + + @Override + public Element visitArray(Array_element_value a, Element p) { + Element el = new Element("Array"); + for (Annotation.element_value v : a.values) { + Element child = visit(v, el); + if (child != null) { + el.add(child); + } + } + el.trimToSize(); + return el; + } +} diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassSyntax.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassSyntax.java Wed May 09 13:07:57 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- -import xmlkit.XMLKit.*; - -import java.util.*; -import java.security.MessageDigest; -import java.nio.ByteBuffer; -import xmlkit.XMLKit.Element; -/* - * @author jrose - */ -public abstract class ClassSyntax { - - public interface GetCPIndex { - - int getCPIndex(int tag, String name); // cp finder - } - public static final int CONSTANT_Utf8 = 1, - CONSTANT_Integer = 3, - CONSTANT_Float = 4, - CONSTANT_Long = 5, - CONSTANT_Double = 6, - CONSTANT_Class = 7, - CONSTANT_String = 8, - CONSTANT_Fieldref = 9, - CONSTANT_Methodref = 10, - CONSTANT_InterfaceMethodref = 11, - CONSTANT_NameAndType = 12; - private static final String[] cpTagName = { - /* 0: */null, - /* 1: */ "Utf8", - /* 2: */ null, - /* 3: */ "Integer", - /* 4: */ "Float", - /* 5: */ "Long", - /* 6: */ "Double", - /* 7: */ "Class", - /* 8: */ "String", - /* 9: */ "Fieldref", - /* 10: */ "Methodref", - /* 11: */ "InterfaceMethodref", - /* 12: */ "NameAndType", - null - }; - private static final Set cpTagNames; - - static { - Set set = new HashSet(Arrays.asList(cpTagName)); - set.remove(null); - cpTagNames = Collections.unmodifiableSet(set); - } - public static final int ITEM_Top = 0, // replicates by [1..4,1..4] - ITEM_Integer = 1, // (ditto) - ITEM_Float = 2, - ITEM_Double = 3, - ITEM_Long = 4, - ITEM_Null = 5, - ITEM_UninitializedThis = 6, - ITEM_Object = 7, - ITEM_Uninitialized = 8, - ITEM_ReturnAddress = 9, - ITEM_LIMIT = 10; - private static final String[] itemTagName = { - "Top", - "Integer", - "Float", - "Double", - "Long", - "Null", - "UninitializedThis", - "Object", - "Uninitialized", - "ReturnAddress",}; - private static final Set itemTagNames; - - static { - Set set = new HashSet(Arrays.asList(itemTagName)); - set.remove(null); - itemTagNames = Collections.unmodifiableSet(set); - } - protected static final HashMap attrTypesBacking; - protected static final Map attrTypesInit; - - static { - HashMap at = new HashMap(); - - //at.put("*.Deprecated", ""); - //at.put("*.Synthetic", ""); - ////at.put("Field.ConstantValue", "KQH"); - //at.put("Class.SourceFile", "RUH"); - at.put("Method.Bridge", ""); - at.put("Method.Varargs", ""); - at.put("Class.Enum", ""); - at.put("*.Signature", "RSH"); - //at.put("*.Deprecated", ""); - //at.put("*.Synthetic", ""); - at.put("Field.ConstantValue", "KQH"); - at.put("Class.SourceFile", "RUH"); - at.put("Class.InnerClasses", "NH[RCHRCHRUHFH]"); - at.put("Code.LineNumberTable", "NH[PHH]"); - at.put("Code.LocalVariableTable", "NH[PHHRUHRSHH]"); - at.put("Code.LocalVariableTypeTable", "NH[PHHRUHRSHH]"); - at.put("Method.Exceptions", "NH[RCH]"); - at.put("Method.Code", "..."); - at.put("Code.StackMapTable", "..."); - //at.put("Code.StkMapX", "..."); - if (true) { - at.put("Code.StackMapTable", - "[NH[(1)]]" - + "[TB" - + "(64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79" - + ",80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95" - + ",96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111" - + ",112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127" - + ")[(4)]" - + "(247)[H(4)]" - + "(248)[H]" - + "(249)[H]" - + "(250)[H]" - + "(251)[H]" - + "(252)[H(4)]" - + "(253)[H(4)(4)]" - + "(254)[H(4)(4)(4)]" - + "(255)[H(2)(3)]" - + "()[]]" - + "[NH[(4)]]" - + "[NH[(4)]]" - + "[TB" - + ("(0)[]" - + "(1)[](2)[](3)[](4)[]" - + "(5)[](6)[]" - + "(7)[RCH]" - + "(8)[PH]" - + "()[]]")); - } - - at.put("Class.EnclosingMethod", "RCHRDH");//RDNH - - // Layouts of metadata attrs: - String vpf = "["; - String ipf = "["; - String apf = "["; - String mdanno2 = "" - + "RSHNH[RUH(3)]]" - + ("[TB" - + "(\\B,\\C,\\I,\\S,\\Z)[KIH]" - + "(\\D)[KDH]" - + "(\\F)[KFH]" - + "(\\J)[KJH]" - + "(\\c)[RSH]" - + "(\\e)[RSHRUH]" - + "(\\s)[RUH]" - + "(\\@)[(2)]" - + "(\\[)[NH[(3)]]" - + "()[]" - + "]"); - String visanno = "[NH[(2)]][(1)]" + vpf + mdanno2; - String invanno = "[NH[(2)]][(1)]" + ipf + mdanno2; - String vparamanno = "" - + "[NB[(1)]][NH[(2)]]" - + apf + mdanno2; - String iparamanno = "" - + "[NB[(1)]][NH[(2)]]" - + apf + mdanno2; - String mdannodef = "[(3)][(1)]" + apf + mdanno2; - String[] mdplaces = {"Class", "Field", "Method"}; - for (String place : mdplaces) { - at.put(place + ".RuntimeVisibleAnnotations", visanno); - at.put(place + ".RuntimeInvisibleAnnotations", invanno); - } - at.put("Method.RuntimeVisibleParameterAnnotations", vparamanno); - at.put("Method.RuntimeInvisibleParameterAnnotations", iparamanno); - at.put("Method.AnnotationDefault", mdannodef); - - attrTypesBacking = at; - attrTypesInit = Collections.unmodifiableMap(at); - } - - ; - private static final String[] jcovAttrTypes = { - "Code.CoverageTable=NH[PHHII]", - "Code.CharacterRangeTable=NH[PHPOHIIH]", - "Class.SourceID=RUH", - "Class.CompilationID=RUH" - }; - protected static final String[][] modifierNames = { - {"public"}, - {"private"}, - {"protected"}, - {"static"}, - {"final"}, - {"synchronized"}, - {null, "volatile", "bridge"}, - {null, "transient", "varargs"}, - {null, null, "native"}, - {"interface"}, - {"abstract"}, - {"strictfp"}, - {"synthetic"}, - {"annotation"}, - {"enum"},}; - protected static final String EIGHT_BIT_CHAR_ENCODING = "ISO8859_1"; - protected static final String UTF8_ENCODING = "UTF8"; - // What XML tags are used by this syntax, apart from attributes? - protected static final Set nonAttrTags; - - static { - HashSet tagSet = new HashSet(); - Collections.addAll(tagSet, new String[]{ - "ConstantPool",// the CP - "Class", // the class - "Interface", // implemented interfaces - "Method", // methods - "Field", // fields - "Handler", // exception handler pseudo-attribute - "Attribute", // unparsed attribute - "Bytes", // bytecodes - "Instructions" // bytecodes, parsed - }); - nonAttrTags = Collections.unmodifiableSet(tagSet); - } - - // Accessors. - public static Set nonAttrTags() { - return nonAttrTags; - } - - public static String cpTagName(int t) { - t &= 0xFF; - String ts = null; - if (t < cpTagName.length) { - ts = cpTagName[t]; - } - if (ts != null) { - return ts; - } - return ("UnknownTag" + (int) t).intern(); - } - - public static int cpTagValue(String name) { - for (int t = 0; t < cpTagName.length; t++) { - if (name.equals(cpTagName[t])) { - return t; - } - } - return 0; - } - - public static String itemTagName(int t) { - t &= 0xFF; - String ts = null; - if (t < itemTagName.length) { - ts = itemTagName[t]; - } - if (ts != null) { - return ts; - } - return ("UnknownItem" + (int) t).intern(); - } - - public static int itemTagValue(String name) { - for (int t = 0; t < itemTagName.length; t++) { - if (name.equals(itemTagName[t])) { - return t; - } - } - return -1; - } - - public void addJcovAttrTypes() { - addAttrTypes(jcovAttrTypes); - } - // Public methods for declaring attribute types. - protected Map attrTypes = attrTypesInit; - - public void addAttrType(String opt) { - int eqpos = opt.indexOf('='); - addAttrType(opt.substring(0, eqpos), opt.substring(eqpos + 1)); - } - - public void addAttrTypes(String[] opts) { - for (String opt : opts) { - addAttrType(opt); - } - } - - private void checkAttr(String attr) { - if (!attr.startsWith("Class.") - && !attr.startsWith("Field.") - && !attr.startsWith("Method.") - && !attr.startsWith("Code.") - && !attr.startsWith("*.")) { - throw new IllegalArgumentException("attr name must start with 'Class.', etc."); - } - String uattr = attr.substring(attr.indexOf('.') + 1); - if (nonAttrTags.contains(uattr)) { - throw new IllegalArgumentException("attr name must not be one of " + nonAttrTags); - } - } - - private void checkAttrs(Map at) { - for (String attr : at.keySet()) { - checkAttr(attr); - } - } - - private void modAttrs() { - if (attrTypes == attrTypesInit) { - // Make modifiable. - attrTypes = new HashMap(attrTypesBacking); - } - } - - public void addAttrType(String attr, String fmt) { - checkAttr(attr); - modAttrs(); - attrTypes.put(attr, fmt); - } - - public void addAttrTypes(Map at) { - checkAttrs(at); - modAttrs(); - attrTypes.putAll(at); - } - - public Map getAttrTypes() { - if (attrTypes == attrTypesInit) { - return attrTypes; - } - return Collections.unmodifiableMap(attrTypes); - } - - public void setAttrTypes(Map at) { - checkAttrs(at); - modAttrs(); - attrTypes.keySet().retainAll(at.keySet()); - attrTypes.putAll(at); - } - - // attr format helpers - protected static boolean matchTag(int tagValue, String caseStr) { - //System.out.println("matchTag "+tagValue+" in "+caseStr); - for (int pos = 0, max = caseStr.length(), comma; - pos < max; - pos = comma + 1) { - int caseValue; - if (caseStr.charAt(pos) == '\\') { - caseValue = caseStr.charAt(pos + 1); - comma = pos + 2; - assert (comma == max || caseStr.charAt(comma) == ','); - } else { - comma = caseStr.indexOf(',', pos); - if (comma < 0) { - comma = max; - } - caseValue = Integer.parseInt(caseStr.substring(pos, comma)); - } - if (tagValue == caseValue) { - return true; - } - } - return false; - } - - protected static String[] getBodies(String type) { - ArrayList bodies = new ArrayList(); - for (int i = 0; i < type.length();) { - String body = getBody(type, i); - bodies.add(body); - i += body.length() + 2; // skip body and brackets - } - return bodies.toArray(new String[bodies.size()]); - } - - protected static String getBody(String type, int i) { - assert (type.charAt(i) == '['); - int next = ++i; // skip bracket - for (int depth = 1; depth > 0; next++) { - switch (type.charAt(next)) { - case '[': - depth++; - break; - case ']': - depth--; - break; - case '(': - next = type.indexOf(')', next); - break; - case '<': - next = type.indexOf('>', next); - break; - } - assert (next > 0); - } - --next; // get before bracket - assert (type.charAt(next) == ']'); - return type.substring(i, next); - } - - public Element makeCPDigest(int length) { - MessageDigest md; - try { - md = MessageDigest.getInstance("MD5"); - } catch (java.security.NoSuchAlgorithmException ee) { - throw new Error(ee); - } - int items = 0; - for (Element e : cpool.elements()) { - if (items == length) { - break; - } - if (cpTagNames.contains(e.getName())) { - items += 1; - md.update((byte) cpTagValue(e.getName())); - try { - md.update(e.getText().toString().getBytes(UTF8_ENCODING)); - } catch (java.io.UnsupportedEncodingException ee) { - throw new Error(ee); - } - } - } - ByteBuffer bb = ByteBuffer.wrap(md.digest()); - String l0 = Long.toHexString(bb.getLong(0)); - String l1 = Long.toHexString(bb.getLong(8)); - while (l0.length() < 16) { - l0 = "0" + l0; - } - while (l1.length() < 16) { - l1 = "0" + l1; - } - return new Element("Digest", - "length", "" + items, - "bytes", l0 + l1); - } - - public Element getCPDigest(int length) { - if (length == -1) { - length = cpool.countAll(XMLKit.elementFilter(cpTagNames)); - } - for (Element md : cpool.findAllElements("Digest").elements()) { - if (md.getAttrLong("length") == length) { - return md; - } - } - Element md = makeCPDigest(length); - cpool.add(md); - return md; - } - - public Element getCPDigest() { - return getCPDigest(-1); - } - - public boolean checkCPDigest(Element md) { - return md.equals(getCPDigest((int) md.getAttrLong("length"))); - } - - public static int computeInterfaceNum(String intMethRef) { - intMethRef = intMethRef.substring(1 + intMethRef.lastIndexOf(' ')); - if (!intMethRef.startsWith("(")) { - return -1; - } - int signum = 1; // start with one for "this" - scanSig: - for (int i = 1; i < intMethRef.length(); i++) { - char ch = intMethRef.charAt(i); - signum++; - switch (ch) { - case ')': - --signum; - break scanSig; - case 'L': - i = intMethRef.indexOf(';', i); - break; - case '[': - while (ch == '[') { - ch = intMethRef.charAt(++i); - } - if (ch == 'L') { - i = intMethRef.indexOf(';', i); - } - break; - } - } - int num = (signum << 8) | 0; - //System.out.println("computeInterfaceNum "+intMethRef+" => "+num); - return num; - } - // Protected state for representing the class file. - protected Element cfile; // - protected Element cpool; // - protected Element klass; // - protected Element currentMember; // varies during scans - protected Element currentCode; // varies during scans -} diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassWriter.java Wed May 09 13:07:57 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,818 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import java.util.*; -import java.lang.reflect.*; -import java.io.*; -import xmlkit.XMLKit.Element; -/* - * @author jrose - */ -public class ClassWriter extends ClassSyntax implements ClassSyntax.GetCPIndex { - - private static final CommandLineParser CLP = new CommandLineParser("" - + "-source: +> = \n" - + "-dest: +> = \n" - + "-encoding: +> = \n" - + "-parseBytes $ \n" - + "- *? \n" - + "\n"); - - public static void main(String[] ava) throws IOException { - ArrayList av = new ArrayList(Arrays.asList(ava)); - HashMap props = new HashMap(); - props.put("-encoding:", "UTF8"); // default - CLP.parse(av, props); - File source = asFile(props.get("-source:")); - File dest = asFile(props.get("-dest:")); - String encoding = props.get("-encoding:"); - boolean parseBytes = props.containsKey("-parseBytes"); - boolean destMade = false; - - for (String a : av) { - File f; - File inf = new File(source, a); - System.out.println("Reading " + inf); - Element e; - if (inf.getName().endsWith(".class")) { - ClassReader cr = new ClassReader(); - cr.parseBytes = parseBytes; - e = cr.readFrom(inf); - f = new File(a); - } else if (inf.getName().endsWith(".xml")) { - InputStream in = new FileInputStream(inf); - Reader inw = ClassReader.makeReader(in, encoding); - e = XMLKit.readFrom(inw); - e.findAllInTree(XMLKit.and(XMLKit.elementFilter(nonAttrTags()), - XMLKit.methodFilter(Element.method("trimText")))); - //System.out.println(e); - inw.close(); - f = new File(a.substring(0, a.length() - ".xml".length()) + ".class"); - } else { - System.out.println("Warning: unknown input " + a); - continue; - } - // Now write it: - if (!destMade) { - destMade = true; - if (dest == null) { - dest = File.createTempFile("TestOut", ".dir", new File(".")); - dest.delete(); - System.out.println("Writing results to " + dest); - } - if (!(dest.isDirectory() || dest.mkdir())) { - throw new RuntimeException("Cannot create " + dest); - } - } - File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath()); - outf.getParentFile().mkdirs(); - new ClassWriter(e).writeTo(outf); - } - } - - private static File asFile(String str) { - return (str == null) ? null : new File(str); - } - - public void writeTo(File file) throws IOException { - OutputStream out = null; - try { - out = new BufferedOutputStream(new FileOutputStream(file)); - writeTo(out); - } finally { - if (out != null) { - out.close(); - } - } - } - protected String[] callables; // varies - protected int cpoolSize = 0; - protected HashMap attrTypesByTag; - protected OutputStream out; - protected HashMap cpMap = new HashMap(); - protected ArrayList attrBufs = new ArrayList(); - - private void setupAttrTypes() { - attrTypesByTag = new HashMap(); - for (String key : attrTypes.keySet()) { - String pfx = key.substring(0, key.indexOf('.') + 1); - String val = attrTypes.get(key); - int pos = val.indexOf('<'); - if (pos >= 0) { - String tag = val.substring(pos + 1, val.indexOf('>', pos)); - attrTypesByTag.put(pfx + tag, key); - } - } - //System.out.println("attrTypesByTag: "+attrTypesByTag); - } - - protected ByteArrayOutputStream getAttrBuf() { - int nab = attrBufs.size(); - if (nab == 0) { - return new ByteArrayOutputStream(1024); - } - ByteArrayOutputStream ab = attrBufs.get(nab - 1); - attrBufs.remove(nab - 1); - return ab; - } - - protected void putAttrBuf(ByteArrayOutputStream ab) { - ab.reset(); - attrBufs.add(ab); - } - - public ClassWriter(Element root) { - this(root, null); - } - - public ClassWriter(Element root, ClassSyntax cr) { - if (cr != null) { - attrTypes = cr.attrTypes; - } - setupAttrTypes(); - if (root.getName() == "ClassFile") { - cfile = root; - cpool = root.findElement("ConstantPool"); - klass = root.findElement("Class"); - } else if (root.getName() == "Class") { - cfile = new Element("ClassFile", - new String[]{ - "magic", String.valueOf(0xCAFEBABE), - "minver", "0", "majver", "46",}); - cpool = new Element("ConstantPool"); - klass = root; - } else { - throw new IllegalArgumentException("bad element type " + root.getName()); - } - if (cpool == null) { - cpool = new Element("ConstantPool"); - } - - int cpLen = 1 + cpool.size(); - for (Element c : cpool.elements()) { - int id = (int) c.getAttrLong("id"); - int tag = cpTagValue(c.getName()); - setCPIndex(tag, c.getText().toString(), id); - switch (tag) { - case CONSTANT_Long: - case CONSTANT_Double: - cpLen += 1; - } - } - cpoolSize = cpLen; - } - - public int findCPIndex(int tag, String name) { - if (name == null) { - return 0; - } - int[] ids = cpMap.get(name.toString()); - return (ids == null) ? 0 : ids[tag]; - } - - public int getCPIndex(int tag, String name) { - //System.out.println("getCPIndex "+cpTagName(tag)+" "+name); - if (name == null) { - return 0; - } - int id = findCPIndex(tag, name); - if (id == 0) { - id = cpoolSize; - cpoolSize += 1; - setCPIndex(tag, name, id); - cpool.add(new Element(cpTagName(tag), - new String[]{"id", "" + id}, - new Object[]{name})); - int pos; - switch (tag) { - case CONSTANT_Long: - case CONSTANT_Double: - cpoolSize += 1; - break; - case CONSTANT_Class: - case CONSTANT_String: - getCPIndex(CONSTANT_Utf8, name); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - pos = name.indexOf(' '); - getCPIndex(CONSTANT_Class, name.substring(0, pos)); - getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1)); - break; - case CONSTANT_NameAndType: - pos = name.indexOf(' '); - getCPIndex(CONSTANT_Utf8, name.substring(0, pos)); - getCPIndex(CONSTANT_Utf8, name.substring(pos + 1)); - break; - } - } - return id; - } - - public void setCPIndex(int tag, String name, int id) { - //System.out.println("setCPIndex id="+id+" tag="+tag+" name="+name); - int[] ids = cpMap.get(name); - if (ids == null) { - cpMap.put(name, ids = new int[13]); - } - if (ids[tag] != 0 && ids[tag] != id) { - System.out.println("Warning: Duplicate CP entries for " + ids[tag] + " and " + id); - } - //assert(ids[tag] == 0 || ids[tag] == id); - ids[tag] = id; - } - - public int parseFlags(String flagString) { - int flags = 0; - int i = -1; - for (String[] names : modifierNames) { - ++i; - for (String name : names) { - if (name == null) { - continue; - } - int pos = flagString.indexOf(name); - if (pos >= 0) { - flags |= (1 << i); - } - } - } - return flags; - } - - public void writeTo(OutputStream realOut) throws IOException { - OutputStream headOut = realOut; - ByteArrayOutputStream tailOut = new ByteArrayOutputStream(); - - // write the body of the class file first - this.out = tailOut; - writeClass(); - - // write the file header last - this.out = headOut; - u4((int) cfile.getAttrLong("magic")); - u2((int) cfile.getAttrLong("minver")); - u2((int) cfile.getAttrLong("majver")); - writeCP(); - - // recopy the file tail - this.out = null; - tailOut.writeTo(realOut); - } - - void writeClass() throws IOException { - int flags = parseFlags(klass.getAttr("flags")); - flags ^= Modifier.SYNCHRONIZED; - u2(flags); - cpRef(CONSTANT_Class, klass.getAttr("name")); - cpRef(CONSTANT_Class, klass.getAttr("super")); - Element interfaces = klass.findAllElements("Interface"); - u2(interfaces.size()); - for (Element e : interfaces.elements()) { - cpRef(CONSTANT_Class, e.getAttr("name")); - } - for (int isMethod = 0; isMethod <= 1; isMethod++) { - Element members = klass.findAllElements(isMethod != 0 ? "Method" : "Field"); - u2(members.size()); - for (Element m : members.elements()) { - writeMember(m, isMethod != 0); - } - } - writeAttributesFor(klass); - } - - private void writeMember(Element member, boolean isMethod) throws IOException { - //System.out.println("writeMember "+member); - u2(parseFlags(member.getAttr("flags"))); - cpRef(CONSTANT_Utf8, member.getAttr("name")); - cpRef(CONSTANT_Utf8, member.getAttr("type")); - writeAttributesFor(member); - } - - protected void writeAttributesFor(Element x) throws IOException { - LinkedHashSet attrNames = new LinkedHashSet(); - for (Element e : x.elements()) { - attrNames.add(e.getName()); // uniquifying - } - attrNames.removeAll(nonAttrTags()); - u2(attrNames.size()); - if (attrNames.isEmpty()) { - return; - } - Element prevCurrent; - if (x.getName() == "Code") { - prevCurrent = currentCode; - currentCode = x; - } else { - prevCurrent = currentMember; - currentMember = x; - } - OutputStream realOut = this.out; - for (String utag : attrNames) { - String qtag = x.getName() + "." + utag; - String wtag = "*." + utag; - String key = attrTypesByTag.get(qtag); - if (key == null) { - key = attrTypesByTag.get(wtag); - } - String type = attrTypes.get(key); - //System.out.println("tag "+qtag+" => key "+key+"; type "+type); - Element attrs = x.findAllElements(utag); - ByteArrayOutputStream attrBuf = getAttrBuf(); - if (type == null) { - if (attrs.size() != 1 || !attrs.get(0).equals(new Element(utag))) { - System.out.println("Warning: No attribute type description: " + qtag); - } - key = wtag; - } else { - try { - this.out = attrBuf; - // unparse according to type desc. - if (type.equals("...")) { - writeCode((Element) attrs.get(0)); // assume only 1 - } else if (type.equals("...")) { - writeStackMap(attrs, false); - } else if (type.equals("...")) { - writeStackMap(attrs, true); - } else if (type.startsWith("[")) { - writeAttributeRecursive(attrs, type); - } else { - writeAttribute(attrs, type); - } - } finally { - //System.out.println("Attr Bytes = \""+attrBuf.toString(EIGHT_BIT_CHAR_ENCODING).replace('"', (char)('"'|0x80))+"\""); - this.out = realOut; - } - } - cpRef(CONSTANT_Utf8, key.substring(key.indexOf('.') + 1)); - u4(attrBuf.size()); - attrBuf.writeTo(out); - putAttrBuf(attrBuf); - } - if (x.getName() == "Code") { - currentCode = prevCurrent; - } else { - currentMember = prevCurrent; - } - } - - private void writeAttributeRecursive(Element aval, String type) throws IOException { - assert (callables == null); - callables = getBodies(type); - writeAttribute(aval, callables[0]); - callables = null; - } - - private void writeAttribute(Element aval, String type) throws IOException { - //System.out.println("writeAttribute "+aval+" using "+type); - String nextAttrName = null; - boolean afterElemHead = false; - for (int len = type.length(), next, i = 0; i < len; i = next) { - int value; - char intKind; - int tag; - int sigChar; - String attrValue; - switch (type.charAt(i)) { - case '<': - assert (nextAttrName == null); - next = type.indexOf('>', i); - String form = type.substring(i + 1, next++); - if (form.indexOf('=') < 0) { - // elem_placement = '<' elemname '>' - if (aval.isAnonymous()) { - assert (aval.size() == 1); - aval = (Element) aval.get(0); - } - assert (aval.getName().equals(form)) : aval + " // " + form; - afterElemHead = true; - } else { - // attr_placement = '(' attrname '=' (value)? ')' - int eqPos = form.indexOf('='); - assert (eqPos >= 0); - nextAttrName = form.substring(0, eqPos).intern(); - if (eqPos != form.length() - 1) { - // value is implicit, not placed in file - nextAttrName = null; - } - afterElemHead = false; - } - continue; - case '(': - next = type.indexOf(')', ++i); - int callee = Integer.parseInt(type.substring(i, next++)); - writeAttribute(aval, callables[callee]); - continue; - case 'N': // replication = 'N' int '[' type ... ']' - { - assert (nextAttrName == null); - afterElemHead = false; - char countType = type.charAt(i + 1); - next = i + 2; - String type1 = getBody(type, next); - Element elems = aval; - if (type1.startsWith("<")) { - // Select only matching members of aval. - String elemName = type1.substring(1, type1.indexOf('>')); - elems = aval.findAllElements(elemName); - } - putInt(elems.size(), countType); - next += type1.length() + 2; // skip body and brackets - for (Element elem : elems.elements()) { - writeAttribute(elem, type1); - } - } - continue; - case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']' - // write the value - value = (int) aval.getAttrLong("tag"); - assert (aval.getAttr("tag") != null) : aval; - intKind = type.charAt(++i); - if (intKind == 'S') { - intKind = type.charAt(++i); - } - putInt(value, intKind); - nextAttrName = null; - afterElemHead = false; - ++i; // skip the int type char - // union_case = '(' ('-')? digit+ ')' '[' body ']' - for (boolean foundCase = false;;) { - assert (type.charAt(i) == '('); - next = type.indexOf(')', ++i); - assert (next >= i); - String caseStr = type.substring(i, next++); - String type1 = getBody(type, next); - next += type1.length() + 2; // skip body and brackets - boolean lastCase = (caseStr.length() == 0); - if (!foundCase - && (lastCase || matchTag(value, caseStr))) { - foundCase = true; - // Execute this body. - writeAttribute(aval, type1); - } - if (lastCase) { - break; - } - } - continue; - case 'B': - case 'H': - case 'I': // int = oneof "BHI" - value = (int) aval.getAttrLong(nextAttrName); - intKind = type.charAt(i); - next = i + 1; - break; - case 'K': - sigChar = type.charAt(i + 1); - if (sigChar == 'Q') { - assert (currentMember.getName() == "Field"); - assert (aval.getName() == "ConstantValue"); - String sig = currentMember.getAttr("type"); - sigChar = sig.charAt(0); - switch (sigChar) { - case 'Z': - case 'B': - case 'C': - case 'S': - sigChar = 'I'; - break; - } - } - switch (sigChar) { - case 'I': - tag = CONSTANT_Integer; - break; - case 'J': - tag = CONSTANT_Long; - break; - case 'F': - tag = CONSTANT_Float; - break; - case 'D': - tag = CONSTANT_Double; - break; - case 'L': - tag = CONSTANT_String; - break; - default: - assert (false); - tag = 0; - } - assert (type.charAt(i + 2) == 'H'); // only H works for now - next = i + 3; - assert (afterElemHead || nextAttrName != null); - //System.out.println("get attr "+nextAttrName+" in "+aval); - if (nextAttrName != null) { - attrValue = aval.getAttr(nextAttrName); - assert (attrValue != null); - } else { - assert (aval.isText()) : aval; - attrValue = aval.getText().toString(); - } - value = getCPIndex(tag, attrValue); - intKind = 'H'; //type.charAt(i+2); - break; - case 'R': - sigChar = type.charAt(i + 1); - switch (sigChar) { - case 'C': - tag = CONSTANT_Class; - break; - case 'S': - tag = CONSTANT_Utf8; - break; - case 'D': - tag = CONSTANT_Class; - break; - case 'F': - tag = CONSTANT_Fieldref; - break; - case 'M': - tag = CONSTANT_Methodref; - break; - case 'I': - tag = CONSTANT_InterfaceMethodref; - break; - case 'U': - tag = CONSTANT_Utf8; - break; - //case 'Q': tag = CONSTANT_Class; break; - default: - assert (false); - tag = 0; - } - assert (type.charAt(i + 2) == 'H'); // only H works for now - next = i + 3; - assert (afterElemHead || nextAttrName != null); - //System.out.println("get attr "+nextAttrName+" in "+aval); - if (nextAttrName != null) { - attrValue = aval.getAttr(nextAttrName); - } else if (aval.hasText()) { - attrValue = aval.getText().toString(); - } else { - attrValue = null; - } - value = getCPIndex(tag, attrValue); - intKind = 'H'; //type.charAt(i+2); - break; - case 'P': // bci = 'P' int - case 'S': // signed_int = 'S' int - next = i + 2; - value = (int) aval.getAttrLong(nextAttrName); - intKind = type.charAt(i + 1); - break; - case 'F': - next = i + 2; - value = parseFlags(aval.getAttr(nextAttrName)); - intKind = type.charAt(i + 1); - break; - default: - throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type); - } - // write the value - putInt(value, intKind); - nextAttrName = null; - afterElemHead = false; - } - assert (nextAttrName == null); - } - - private void putInt(int x, char ch) throws IOException { - switch (ch) { - case 'B': - u1(x); - break; - case 'H': - u2(x); - break; - case 'I': - u4(x); - break; - } - assert ("BHI".indexOf(ch) >= 0); - } - - private void writeCode(Element code) throws IOException { - //System.out.println("writeCode "+code); - //Element m = new Element(currentMember); m.remove(code); - //System.out.println(" in "+m); - int stack = (int) code.getAttrLong("stack"); - int local = (int) code.getAttrLong("local"); - Element bytes = code.findElement("Bytes"); - Element insns = code.findElement("Instructions"); - String bytecodes; - if (insns == null) { - bytecodes = bytes.getText().toString(); - } else { - bytecodes = InstructionSyntax.assemble(insns, this); - // Cache the assembled bytecodes: - bytes = new Element("Bytes", (String[]) null, bytecodes); - code.add(0, bytes); - } - u2(stack); - u2(local); - int length = bytecodes.length(); - u4(length); - for (int i = 0; i < length; i++) { - u1((byte) bytecodes.charAt(i)); - } - Element handlers = code.findAllElements("Handler"); - u2(handlers.size()); - for (Element handler : handlers.elements()) { - int start = (int) handler.getAttrLong("start"); - int end = (int) handler.getAttrLong("end"); - int catsh = (int) handler.getAttrLong("catch"); - u2(start); - u2(end); - u2(catsh); - cpRef(CONSTANT_Class, handler.getAttr("class")); - } - writeAttributesFor(code); - } - - protected void writeStackMap(Element attrs, boolean hasXOption) throws IOException { - Element bytes = currentCode.findElement("Bytes"); - assert (bytes != null && bytes.size() == 1); - int byteLength = ((String) bytes.get(0)).length(); - boolean uoffsetIsU4 = (byteLength >= (1 << 16)); - boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16); - boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16); - if (uoffsetIsU4) { - u4(attrs.size()); - } else { - u2(attrs.size()); - } - for (Element frame : attrs.elements()) { - int bci = (int) frame.getAttrLong("bci"); - if (uoffsetIsU4) { - u4(bci); - } else { - u2(bci); - } - if (hasXOption) { - u1((int) frame.getAttrLong("flags")); - } - // Scan local and stack types in this frame: - final int LOCALS = 0, STACK = 1; - for (int j = LOCALS; j <= STACK; j++) { - Element types = frame.findElement(j == LOCALS ? "Local" : "Stack"); - int typeSize = (types == null) ? 0 : types.size(); - if (j == LOCALS) { - if (ulocalvarIsU4) { - u4(typeSize); - } else { - u2(typeSize); - } - } else { // STACK - if (ustackIsU4) { - u4(typeSize); - } else { - u2(typeSize); - } - } - if (types == null) { - continue; - } - for (Element type : types.elements()) { - int tag = itemTagValue(type.getName()); - u1(tag); - switch (tag) { - case ITEM_Object: - cpRef(CONSTANT_Class, type.getAttr("class")); - break; - case ITEM_Uninitialized: - case ITEM_ReturnAddress: { - int offset = (int) type.getAttrLong("bci"); - if (uoffsetIsU4) { - u4(offset); - } else { - u2(offset); - } - } - break; - } - } - } - } - } - - public void writeCP() throws IOException { - int cpLen = cpoolSize; - u2(cpLen); - ByteArrayOutputStream buf = getAttrBuf(); - for (Element c : cpool.elements()) { - if (!c.isText()) { - System.out.println("## !isText " + c); - } - int id = (int) c.getAttrLong("id"); - int tag = cpTagValue(c.getName()); - String name = c.getText().toString(); - int pos; - u1(tag); - switch (tag) { - case CONSTANT_Utf8: { - int done = 0; - buf.reset(); - int nameLen = name.length(); - while (done < nameLen) { - int next = name.indexOf((char) 0, done); - if (next < 0) { - next = nameLen; - } - if (done < next) { - buf.write(name.substring(done, next).getBytes(UTF8_ENCODING)); - } - if (next < nameLen) { - buf.write(0300); - buf.write(0200); - next++; - } - done = next; - } - u2(buf.size()); - buf.writeTo(out); - } - break; - case CONSTANT_Integer: - u4(Integer.parseInt(name)); - break; - case CONSTANT_Float: - u4(Float.floatToIntBits(Float.parseFloat(name))); - break; - case CONSTANT_Long: - u8(Long.parseLong(name)); - //i += 1; // no need: extra cp slot is implicit - break; - case CONSTANT_Double: - u8(Double.doubleToLongBits(Double.parseDouble(name))); - //i += 1; // no need: extra cp slot is implicit - break; - case CONSTANT_Class: - case CONSTANT_String: - u2(getCPIndex(CONSTANT_Utf8, name)); - break; - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - pos = name.indexOf(' '); - u2(getCPIndex(CONSTANT_Class, name.substring(0, pos))); - u2(getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1))); - break; - case CONSTANT_NameAndType: - pos = name.indexOf(' '); - u2(getCPIndex(CONSTANT_Utf8, name.substring(0, pos))); - u2(getCPIndex(CONSTANT_Utf8, name.substring(pos + 1))); - break; - } - } - putAttrBuf(buf); - } - - public void cpRef(int tag, String name) throws IOException { - u2(getCPIndex(tag, name)); - } - - public void u8(long x) throws IOException { - u4((int) (x >>> 32)); - u4((int) (x >>> 0)); - } - - public void u4(int x) throws IOException { - u2(x >>> 16); - u2(x >>> 0); - } - - public void u2(int x) throws IOException { - u1(x >>> 8); - u1(x >>> 0); - } - - public void u1(int x) throws IOException { - out.write(x & 0xFF); - } -} - diff -r 070b00370cae -r 5904985dac0a jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java --- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/InstructionAssembler.java Wed May 09 13:07:57 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*- - -import xmlkit.XMLKit.Element; -import java.util.HashMap; -/* - * @author jrose - */ -abstract class InstructionAssembler extends InstructionSyntax { - - InstructionAssembler() { - } - - public static String assemble(Element instructions, String pcAttrName, - ClassSyntax.GetCPIndex getCPI) { - int insCount = instructions.size(); - Element[] insElems = new Element[insCount]; - int[] elemToIndexMap; - int[] insLocs; - byte[] ops = new byte[insCount]; - int[] operands = new int[insCount]; - boolean[] isWide = new boolean[insCount]; - int[] branches; - int[] branchInsLocs; - HashMap labels = new HashMap(); - - final int WIDE = 0xc4; - final int GOTO = 0xa7; - final int GOTO_W = 0xc8; - final int GOTO_LEN = 3; - final int GOTO_W_LEN = 5; - assert ("wide".equals(bcNames[WIDE])); - assert ("goto".equals(bcNames[GOTO])); - assert ("goto_w".equals(bcNames[GOTO_W])); - assert (bcFormats[GOTO].length() == GOTO_LEN); - assert (bcFormats[GOTO_W].length() == GOTO_W_LEN); - - // Unpack instructions into temp. arrays, and find branches and labels. - { - elemToIndexMap = (pcAttrName != null) ? new int[insCount] : null; - int[] buffer = operands; - int id = 0; - int branchCount = 0; - for (int i = 0; i < insCount; i++) { - Element ins = (Element) instructions.get(i); - if (elemToIndexMap != null) { - elemToIndexMap[i] = (ins.getAttr(pcAttrName) != null ? id : -1); - } - String lab = ins.getAttr("pc"); - if (lab != null) { - labels.put(lab, String.valueOf(id)); - } - int op = opCode(ins.getName()); - if (op < 0) { - assert (ins.getAttr(pcAttrName) != null - || ins.getName().equals("label")); - continue; // delete PC holder element - } - if (op == WIDE) { //0xc4 - isWide[id] = true; // force wide format - continue; - } - if (bcFormats[op].indexOf('o') >= 0) { - buffer[branchCount++] = id; - } - if (bcFormats[op] == bcWideFormats[op]) { - isWide[id] = false; - } - insElems[id] = ins; - ops[id] = (byte) op; - id++; - } - insCount = id; // maybe we deleted some wide prefixes, etc. - branches = new int[branchCount + 1]; - System.arraycopy(buffer, 0, branches, 0, branchCount); - branches[branchCount] = -1; // sentinel - } - - // Compute instruction sizes. These sizes are final, - // except for branch instructions, which may need lengthening. - // Some instructions (ldc, bipush, iload, iinc) are automagically widened. - insLocs = new int[insCount + 1]; - int loc = 0; - for (int bn = 0, id = 0; id < insCount; id++) { - insLocs[id] = loc; - Element ins = insElems[id]; - int op = ops[id] & 0xFF; - String format = opFormat(op, isWide[id]); - // Make sure operands fit within the given format. - for (int j = 1, jlimit = format.length(); j < jlimit; j++) { - char fc = format.charAt(j); - int x = 0; - switch (fc) { - case 'l': - x = (int) ins.getAttrLong("loc"); - assert (x >= 0); - if (x > 0xFF && !isWide[id]) { - isWide[id] = true; - format = opFormat(op, isWide[id]); - } - assert (x <= 0xFFFF); - break; - case 'k': - char fc2 = format.charAt(Math.min(j + 1, format.length() - 1)); - x = getCPIndex(ins, fc2, getCPI); - if (x > 0xFF && j == jlimit - 1) { - assert (op == 0x12); //ldc - ops[id] = (byte) (op = 0x13); //ldc_w - format = opFormat(op); - } - assert (x <= 0xFFFF); - j++; // skip type-of-constant marker - break; - case 'x': - x = (int) ins.getAttrLong("num"); - assert (x >= 0 && x <= ((j == jlimit - 1) ? 0xFF : 0xFFFF)); - break; - case 's': - x = (int) ins.getAttrLong("num"); - if (x != (byte) x && j == jlimit - 1) { - switch (op) { - case 0x10: //bipush - ops[id] = (byte) (op = 0x11); //sipush - break; - case 0x84: //iinc - isWide[id] = true; - format = opFormat(op, isWide[id]); - break; - default: - assert (false); // cannot lengthen - } - } - // unsign the value now, to make later steps clearer - if (j == jlimit - 1) { - assert (x == (byte) x); - x = x & 0xFF; - } else { - assert (x == (short) x); - x = x & 0xFFFF; - } - break; - case 'o': - assert (branches[bn] == id); - bn++; - // make local copies of the branches, and fix up labels - insElems[id] = ins = new Element(ins); - String newLab = labels.get(ins.getAttr("lab")); - assert (newLab != null); - ins.setAttr("lab", newLab); - int prevCas = 0; - int k = 0; - for (Element cas : ins.elements()) { - assert (cas.getName().equals("Case")); - ins.set(k++, cas = new Element(cas)); - newLab = labels.get(cas.getAttr("lab")); - assert (newLab != null); - cas.setAttr("lab", newLab); - int thisCas = (int) cas.getAttrLong("num"); - assert (op == 0xab - || op == 0xaa && (k == 0 || thisCas == prevCas + 1)); - prevCas = thisCas; - } - break; - case 't': - // switch table is represented as Switch.Case sub-elements - break; - default: - assert (false); - } - operands[id] = x; // record operand (last if there are 2) - // skip redundant chars - while (j + 1 < jlimit && format.charAt(j + 1) == fc) { - ++j; - } - } - - switch (op) { - case 0xaa: //tableswitch - loc = switchBase(loc); - loc += 4 * (3 + ins.size()); - break; - case 0xab: //lookupswitch - loc = switchBase(loc); - loc += 4 * (2 + 2 * ins.size()); - break; - default: - if (isWide[id]) { - loc++; // 'wide' opcode prefix - } - loc += format.length(); - break; - } - } - insLocs[insCount] = loc; - - // compute branch offsets, and see if any branches need expansion - for (int maxTries = 9, tries = 0;; ++tries) { - boolean overflowing = false; - boolean[] branchExpansions = null; - for (int bn = 0; bn < branches.length - 1; bn++) { - int id = branches[bn]; - Element ins = insElems[id]; - int insSize = insLocs[id + 1] - insLocs[id]; - int origin = insLocs[id]; - int target = insLocs[(int) ins.getAttrLong("lab")]; - int offset = target - origin; - operands[id] = offset; - //System.out.println("branch id="+id+" len="+insSize+" to="+target+" offset="+offset); - assert (insSize == GOTO_LEN || insSize == GOTO_W_LEN || ins.getName().indexOf("switch") > 0); - boolean thisOverflow = (insSize == GOTO_LEN && (offset != (short) offset)); - if (thisOverflow && !overflowing) { - overflowing = true; - branchExpansions = new boolean[branches.length]; - } - if (thisOverflow || tries == maxTries - 1) { - // lengthen the branch - assert (!(thisOverflow && isWide[id])); - isWide[id] = true; - branchExpansions[bn] = true; - } - } - if (!overflowing) { - break; // done, usually on first try - } - assert (tries <= maxTries); - - // Walk over all instructions, expanding branches and updating locations. - int fixup = 0; - for (int bn = 0, id = 0; id < insCount; id++) { - insLocs[id] += fixup; - if (branches[bn] == id) { - int op = ops[id] & 0xFF; - int wop; - boolean invert; - if (branchExpansions[bn]) { - switch (op) { - case GOTO: //0xa7 - wop = GOTO_W; //0xc8 - invert = false; - break; - case 0xa8: //jsr - wop = 0xc9; //jsr_w - invert = false; - break; - default: - wop = invertBranchOp(op); - invert = true; - break; - } - assert (op != wop); - ops[id] = (byte) wop; - isWide[id] = invert; - if (invert) { - fixup += GOTO_W_LEN; //branch around a wide goto - } else { - fixup += (GOTO_W_LEN - GOTO_LEN); - } - // done expanding: ops and isWide reflect the decision - } - bn++; - } - } - insLocs[insCount] += fixup; - } - // we know the layout now - - // notify the caller of offsets, if requested - if (elemToIndexMap != null) { - for (int i = 0; i < elemToIndexMap.length; i++) { - int id = elemToIndexMap[i]; - if (id >= 0) { - Element ins = (Element) instructions.get(i); - ins.setAttr(pcAttrName, "" + insLocs[id]); - } - } - elemToIndexMap = null; // release the pointer - } - - // output the bytes - StringBuffer sbuf = new StringBuffer(insLocs[insCount]); - for (int bn = 0, id = 0; id < insCount; id++) { - //System.out.println("output id="+id+" loc="+insLocs[id]+" len="+(insLocs[id+1]-insLocs[id])+" #sbuf="+sbuf.length()); - assert (sbuf.length() == insLocs[id]); - Element ins; - int pc = insLocs[id]; - int nextpc = insLocs[id + 1]; - int op = ops[id] & 0xFF; - int opnd = operands[id]; - String format; - if (branches[bn] == id) { - bn++; - sbuf.append((char) op); - if (isWide[id]) { - // emit